1 | // $Id$ |
---|
2 | // Copyright (C) 2000, International Business Machines |
---|
3 | // Corporation and others. All Rights Reserved. |
---|
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
---|
5 | |
---|
6 | |
---|
7 | #ifndef OsiClpSolverInterface_H |
---|
8 | #define OsiClpSolverInterface_H |
---|
9 | |
---|
10 | #include <string> |
---|
11 | #include <cfloat> |
---|
12 | #include <map> |
---|
13 | |
---|
14 | #include "ClpSimplex.hpp" |
---|
15 | #include "ClpLinearObjective.hpp" |
---|
16 | #include "CoinPackedMatrix.hpp" |
---|
17 | #include "OsiSolverInterface.hpp" |
---|
18 | #include "CoinWarmStartBasis.hpp" |
---|
19 | #include "ClpEventHandler.hpp" |
---|
20 | #include "ClpNode.hpp" |
---|
21 | #include "CoinIndexedVector.hpp" |
---|
22 | |
---|
23 | class OsiRowCut; |
---|
24 | class OsiClpUserSolver; |
---|
25 | class OsiClpDisasterHandler; |
---|
26 | class CoinSet; |
---|
27 | #ifndef COIN_DBL_MAX |
---|
28 | static const double OsiClpInfinity = DBL_MAX; |
---|
29 | #else |
---|
30 | static const double OsiClpInfinity = COIN_DBL_MAX; |
---|
31 | #endif |
---|
32 | |
---|
33 | //############################################################################# |
---|
34 | |
---|
35 | /** Clp Solver Interface |
---|
36 | |
---|
37 | Instantiation of OsiClpSolverInterface for the Model Algorithm. |
---|
38 | |
---|
39 | */ |
---|
40 | |
---|
41 | class OsiClpSolverInterface : |
---|
42 | virtual public OsiSolverInterface { |
---|
43 | friend int OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); |
---|
44 | |
---|
45 | public: |
---|
46 | //--------------------------------------------------------------------------- |
---|
47 | /**@name Solve methods */ |
---|
48 | //@{ |
---|
49 | /// Solve initial LP relaxation |
---|
50 | virtual void initialSolve(); |
---|
51 | |
---|
52 | /// Resolve an LP relaxation after problem modification |
---|
53 | virtual void resolve(); |
---|
54 | |
---|
55 | /// Invoke solver's built-in enumeration algorithm |
---|
56 | virtual void branchAndBound(); |
---|
57 | |
---|
58 | /** Solve when primal column and dual row solutions are near-optimal |
---|
59 | options - 0 no presolve (use primal and dual) |
---|
60 | 1 presolve (just use primal) |
---|
61 | 2 no presolve (just use primal) |
---|
62 | basis - 0 use all slack basis |
---|
63 | 1 try and put some in basis |
---|
64 | */ |
---|
65 | void crossover(int options,int basis); |
---|
66 | //@} |
---|
67 | |
---|
68 | /*! @name OsiSimplexInterface methods |
---|
69 | \brief Methods for the Osi Simplex API. |
---|
70 | |
---|
71 | The current implementation should work for both minimisation and |
---|
72 | maximisation in mode 1 (tableau access). In mode 2 (single pivot), only |
---|
73 | minimisation is supported as of 100907. |
---|
74 | */ |
---|
75 | //@{ |
---|
76 | /** \brief Simplex API capability. |
---|
77 | |
---|
78 | Returns |
---|
79 | - 0 if no simplex API |
---|
80 | - 1 if can just do getBInv etc |
---|
81 | - 2 if has all OsiSimplex methods |
---|
82 | */ |
---|
83 | virtual int canDoSimplexInterface() const; |
---|
84 | |
---|
85 | /*! \brief Enables simplex mode 1 (tableau access) |
---|
86 | |
---|
87 | Tells solver that calls to getBInv etc are about to take place. |
---|
88 | Underlying code may need mutable as this may be called from |
---|
89 | CglCut::generateCuts which is const. If that is too horrific then |
---|
90 | each solver e.g. BCP or CBC will have to do something outside |
---|
91 | main loop. |
---|
92 | */ |
---|
93 | virtual void enableFactorization() const; |
---|
94 | |
---|
95 | /*! \brief Undo any setting changes made by #enableFactorization */ |
---|
96 | virtual void disableFactorization() const; |
---|
97 | |
---|
98 | /** Returns true if a basis is available |
---|
99 | AND problem is optimal. This should be used to see if |
---|
100 | the BInvARow type operations are possible and meaningful. |
---|
101 | */ |
---|
102 | virtual bool basisIsAvailable() const; |
---|
103 | |
---|
104 | /** The following two methods may be replaced by the |
---|
105 | methods of OsiSolverInterface using OsiWarmStartBasis if: |
---|
106 | 1. OsiWarmStartBasis resize operation is implemented |
---|
107 | more efficiently and |
---|
108 | 2. It is ensured that effects on the solver are the same |
---|
109 | |
---|
110 | Returns a basis status of the structural/artificial variables |
---|
111 | At present as warm start i.e 0 free, 1 basic, 2 upper, 3 lower |
---|
112 | |
---|
113 | NOTE artificials are treated as +1 elements so for <= rhs |
---|
114 | artificial will be at lower bound if constraint is tight |
---|
115 | |
---|
116 | This means that Clpsimplex flips artificials as it works |
---|
117 | in terms of row activities |
---|
118 | */ |
---|
119 | virtual void getBasisStatus(int* cstat, int* rstat) const; |
---|
120 | |
---|
121 | /** Set the status of structural/artificial variables and |
---|
122 | factorize, update solution etc |
---|
123 | |
---|
124 | NOTE artificials are treated as +1 elements so for <= rhs |
---|
125 | artificial will be at lower bound if constraint is tight |
---|
126 | |
---|
127 | This means that Clpsimplex flips artificials as it works |
---|
128 | in terms of row activities |
---|
129 | Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ... |
---|
130 | */ |
---|
131 | virtual int setBasisStatus(const int* cstat, const int* rstat); |
---|
132 | |
---|
133 | ///Get the reduced gradient for the cost vector c |
---|
134 | virtual void getReducedGradient(double* columnReducedCosts, |
---|
135 | double * duals, |
---|
136 | const double * c) const ; |
---|
137 | |
---|
138 | ///Get a row of the tableau (slack part in slack if not NULL) |
---|
139 | virtual void getBInvARow(int row, double* z, double * slack=NULL) const; |
---|
140 | |
---|
141 | /** Get a row of the tableau (slack part in slack if not NULL) |
---|
142 | If keepScaled is true then scale factors not applied after so |
---|
143 | user has to use coding similar to what is in this method |
---|
144 | */ |
---|
145 | virtual void getBInvARow(int row, CoinIndexedVector * z, CoinIndexedVector * slack=NULL, |
---|
146 | bool keepScaled=false) const; |
---|
147 | |
---|
148 | ///Get a row of the basis inverse |
---|
149 | virtual void getBInvRow(int row, double* z) const; |
---|
150 | |
---|
151 | ///Get a column of the tableau |
---|
152 | virtual void getBInvACol(int col, double* vec) const ; |
---|
153 | |
---|
154 | ///Get a column of the tableau |
---|
155 | virtual void getBInvACol(int col, CoinIndexedVector * vec) const ; |
---|
156 | |
---|
157 | /** Update (i.e. ftran) the vector passed in. |
---|
158 | Unscaling is applied after - can't be applied before |
---|
159 | */ |
---|
160 | |
---|
161 | virtual void getBInvACol(CoinIndexedVector * vec) const ; |
---|
162 | |
---|
163 | ///Get a column of the basis inverse |
---|
164 | virtual void getBInvCol(int col, double* vec) const ; |
---|
165 | |
---|
166 | /** Get basic indices (order of indices corresponds to the |
---|
167 | order of elements in a vector retured by getBInvACol() and |
---|
168 | getBInvCol()). |
---|
169 | */ |
---|
170 | virtual void getBasics(int* index) const; |
---|
171 | |
---|
172 | /*! \brief Enables simplex mode 2 (individual pivot control) |
---|
173 | |
---|
174 | This method is supposed to ensure that all typical things (like |
---|
175 | reduced costs, etc.) are updated when individual pivots are executed |
---|
176 | and can be queried by other methods. |
---|
177 | */ |
---|
178 | virtual void enableSimplexInterface(bool doingPrimal); |
---|
179 | |
---|
180 | /*! \brief Undo setting changes made by #enableSimplexInterface */ |
---|
181 | virtual void disableSimplexInterface(); |
---|
182 | |
---|
183 | /** Perform a pivot by substituting a colIn for colOut in the basis. |
---|
184 | The status of the leaving variable is given in statOut. Where |
---|
185 | 1 is to upper bound, -1 to lower bound |
---|
186 | Return code is 0 for okay, |
---|
187 | 1 if inaccuracy forced re-factorization (should be okay) and |
---|
188 | -1 for singular factorization |
---|
189 | */ |
---|
190 | virtual int pivot(int colIn, int colOut, int outStatus); |
---|
191 | |
---|
192 | /** Obtain a result of the primal pivot |
---|
193 | Outputs: colOut -- leaving column, outStatus -- its status, |
---|
194 | t -- step size, and, if dx!=NULL, *dx -- primal ray direction. |
---|
195 | Inputs: colIn -- entering column, sign -- direction of its change (+/-1). |
---|
196 | Both for colIn and colOut, artificial variables are index by |
---|
197 | the negative of the row index minus 1. |
---|
198 | Return code (for now): 0 -- leaving variable found, |
---|
199 | -1 -- everything else? |
---|
200 | Clearly, more informative set of return values is required |
---|
201 | Primal and dual solutions are updated |
---|
202 | */ |
---|
203 | virtual int primalPivotResult(int colIn, int sign, |
---|
204 | int& colOut, int& outStatus, |
---|
205 | double& t, CoinPackedVector* dx); |
---|
206 | |
---|
207 | /** Obtain a result of the dual pivot (similar to the previous method) |
---|
208 | Differences: entering variable and a sign of its change are now |
---|
209 | the outputs, the leaving variable and its statuts -- the inputs |
---|
210 | If dx!=NULL, then *dx contains dual ray |
---|
211 | Return code: same |
---|
212 | */ |
---|
213 | virtual int dualPivotResult(int& colIn, int& sign, |
---|
214 | int colOut, int outStatus, |
---|
215 | double& t, CoinPackedVector* dx); |
---|
216 | |
---|
217 | |
---|
218 | //@} |
---|
219 | //--------------------------------------------------------------------------- |
---|
220 | /**@name Parameter set/get methods |
---|
221 | |
---|
222 | The set methods return true if the parameter was set to the given value, |
---|
223 | false otherwise. There can be various reasons for failure: the given |
---|
224 | parameter is not applicable for the solver (e.g., refactorization |
---|
225 | frequency for the clp algorithm), the parameter is not yet implemented |
---|
226 | for the solver or simply the value of the parameter is out of the range |
---|
227 | the solver accepts. If a parameter setting call returns false check the |
---|
228 | details of your solver. |
---|
229 | |
---|
230 | The get methods return true if the given parameter is applicable for the |
---|
231 | solver and is implemented. In this case the value of the parameter is |
---|
232 | returned in the second argument. Otherwise they return false. |
---|
233 | */ |
---|
234 | //@{ |
---|
235 | // Set an integer parameter |
---|
236 | bool setIntParam(OsiIntParam key, int value); |
---|
237 | // Set an double parameter |
---|
238 | bool setDblParam(OsiDblParam key, double value); |
---|
239 | // Set a string parameter |
---|
240 | bool setStrParam(OsiStrParam key, const std::string & value); |
---|
241 | // Get an integer parameter |
---|
242 | bool getIntParam(OsiIntParam key, int& value) const; |
---|
243 | // Get an double parameter |
---|
244 | bool getDblParam(OsiDblParam key, double& value) const; |
---|
245 | // Get a string parameter |
---|
246 | bool getStrParam(OsiStrParam key, std::string& value) const; |
---|
247 | // Set a hint parameter - overrides OsiSolverInterface |
---|
248 | virtual bool setHintParam(OsiHintParam key, bool yesNo=true, |
---|
249 | OsiHintStrength strength=OsiHintTry, |
---|
250 | void * otherInformation=NULL); |
---|
251 | //@} |
---|
252 | |
---|
253 | //--------------------------------------------------------------------------- |
---|
254 | ///@name Methods returning info on how the solution process terminated |
---|
255 | //@{ |
---|
256 | /// Are there a numerical difficulties? |
---|
257 | virtual bool isAbandoned() const; |
---|
258 | /// Is optimality proven? |
---|
259 | virtual bool isProvenOptimal() const; |
---|
260 | /// Is primal infeasiblity proven? |
---|
261 | virtual bool isProvenPrimalInfeasible() const; |
---|
262 | /// Is dual infeasiblity proven? |
---|
263 | virtual bool isProvenDualInfeasible() const; |
---|
264 | /// Is the given primal objective limit reached? |
---|
265 | virtual bool isPrimalObjectiveLimitReached() const; |
---|
266 | /// Is the given dual objective limit reached? |
---|
267 | virtual bool isDualObjectiveLimitReached() const; |
---|
268 | /// Iteration limit reached? |
---|
269 | virtual bool isIterationLimitReached() const; |
---|
270 | //@} |
---|
271 | |
---|
272 | //--------------------------------------------------------------------------- |
---|
273 | /**@name WarmStart related methods */ |
---|
274 | //@{ |
---|
275 | |
---|
276 | /*! \brief Get an empty warm start object |
---|
277 | |
---|
278 | This routine returns an empty CoinWarmStartBasis object. Its purpose is |
---|
279 | to provide a way to give a client a warm start basis object of the |
---|
280 | appropriate type, which can resized and modified as desired. |
---|
281 | */ |
---|
282 | |
---|
283 | virtual CoinWarmStart *getEmptyWarmStart () const; |
---|
284 | |
---|
285 | /// Get warmstarting information |
---|
286 | virtual CoinWarmStart* getWarmStart() const; |
---|
287 | /// Get warmstarting information |
---|
288 | inline CoinWarmStartBasis* getPointerToWarmStart() |
---|
289 | { return &basis_;} |
---|
290 | /// Get warmstarting information |
---|
291 | inline const CoinWarmStartBasis* getConstPointerToWarmStart() const |
---|
292 | { return &basis_;} |
---|
293 | /** Set warmstarting information. Return true/false depending on whether |
---|
294 | the warmstart information was accepted or not. */ |
---|
295 | virtual bool setWarmStart(const CoinWarmStart* warmstart); |
---|
296 | /** \brief Get warm start information. |
---|
297 | |
---|
298 | Return warm start information for the current state of the solver |
---|
299 | interface. If there is no valid warm start information, an empty warm |
---|
300 | start object wil be returned. This does not necessarily create an |
---|
301 | object - may just point to one. must Delete set true if user |
---|
302 | should delete returned object. |
---|
303 | OsiClp version always returns pointer and false. |
---|
304 | */ |
---|
305 | virtual CoinWarmStart* getPointerToWarmStart(bool & mustDelete) ; |
---|
306 | |
---|
307 | //@} |
---|
308 | |
---|
309 | //--------------------------------------------------------------------------- |
---|
310 | /**@name Hotstart related methods (primarily used in strong branching). |
---|
311 | The user can create a hotstart (a snapshot) of the optimization process |
---|
312 | then reoptimize over and over again always starting from there.<br> |
---|
313 | <strong>NOTE</strong>: between hotstarted optimizations only |
---|
314 | bound changes are allowed. */ |
---|
315 | //@{ |
---|
316 | /// Create a hotstart point of the optimization process |
---|
317 | virtual void markHotStart(); |
---|
318 | /// Optimize starting from the hotstart |
---|
319 | virtual void solveFromHotStart(); |
---|
320 | /// Delete the snapshot |
---|
321 | virtual void unmarkHotStart(); |
---|
322 | /** Start faster dual - returns negative if problems 1 if infeasible, |
---|
323 | Options to pass to solver |
---|
324 | 1 - create external reduced costs for columns |
---|
325 | 2 - create external reduced costs for rows |
---|
326 | 4 - create external row activity (columns always done) |
---|
327 | Above only done if feasible |
---|
328 | When set resolve does less work |
---|
329 | */ |
---|
330 | int startFastDual(int options); |
---|
331 | /// Stop fast dual |
---|
332 | void stopFastDual(); |
---|
333 | /// Sets integer tolerance and increment |
---|
334 | void setStuff(double tolerance,double increment); |
---|
335 | //@} |
---|
336 | |
---|
337 | //--------------------------------------------------------------------------- |
---|
338 | /**@name Problem information methods |
---|
339 | |
---|
340 | These methods call the solver's query routines to return |
---|
341 | information about the problem referred to by the current object. |
---|
342 | Querying a problem that has no data associated with it result in |
---|
343 | zeros for the number of rows and columns, and NULL pointers from |
---|
344 | the methods that return vectors. |
---|
345 | |
---|
346 | Const pointers returned from any data-query method are valid as |
---|
347 | long as the data is unchanged and the solver is not called. |
---|
348 | */ |
---|
349 | //@{ |
---|
350 | /**@name Methods related to querying the input data */ |
---|
351 | //@{ |
---|
352 | /// Get number of columns |
---|
353 | virtual int getNumCols() const { |
---|
354 | return modelPtr_->numberColumns(); } |
---|
355 | |
---|
356 | /// Get number of rows |
---|
357 | virtual int getNumRows() const { |
---|
358 | return modelPtr_->numberRows(); } |
---|
359 | |
---|
360 | /// Get number of nonzero elements |
---|
361 | virtual int getNumElements() const { |
---|
362 | int retVal = 0; |
---|
363 | const CoinPackedMatrix * matrix =modelPtr_->matrix(); |
---|
364 | if ( matrix != NULL ) retVal=matrix->getNumElements(); |
---|
365 | return retVal; } |
---|
366 | |
---|
367 | /// Return name of row if one exists or Rnnnnnnn |
---|
368 | /// maxLen is currently ignored and only there to match the signature from the base class! |
---|
369 | virtual std::string getRowName(int rowIndex, |
---|
370 | unsigned maxLen = std::string::npos) const; |
---|
371 | |
---|
372 | /// Return name of column if one exists or Cnnnnnnn |
---|
373 | /// maxLen is currently ignored and only there to match the signature from the base class! |
---|
374 | virtual std::string getColName(int colIndex, |
---|
375 | unsigned maxLen = std::string::npos) const; |
---|
376 | |
---|
377 | |
---|
378 | /// Get pointer to array[getNumCols()] of column lower bounds |
---|
379 | virtual const double * getColLower() const { return modelPtr_->columnLower(); } |
---|
380 | |
---|
381 | /// Get pointer to array[getNumCols()] of column upper bounds |
---|
382 | virtual const double * getColUpper() const { return modelPtr_->columnUpper(); } |
---|
383 | |
---|
384 | /** Get pointer to array[getNumRows()] of row constraint senses. |
---|
385 | <ul> |
---|
386 | <li>'L' <= constraint |
---|
387 | <li>'E' = constraint |
---|
388 | <li>'G' >= constraint |
---|
389 | <li>'R' ranged constraint |
---|
390 | <li>'N' free constraint |
---|
391 | </ul> |
---|
392 | */ |
---|
393 | virtual const char * getRowSense() const; |
---|
394 | |
---|
395 | /** Get pointer to array[getNumRows()] of rows right-hand sides |
---|
396 | <ul> |
---|
397 | <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] |
---|
398 | <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] |
---|
399 | <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] |
---|
400 | <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 |
---|
401 | </ul> |
---|
402 | */ |
---|
403 | virtual const double * getRightHandSide() const ; |
---|
404 | |
---|
405 | /** Get pointer to array[getNumRows()] of row ranges. |
---|
406 | <ul> |
---|
407 | <li> if rowsense()[i] == 'R' then |
---|
408 | rowrange()[i] == rowupper()[i] - rowlower()[i] |
---|
409 | <li> if rowsense()[i] != 'R' then |
---|
410 | rowrange()[i] is undefined |
---|
411 | </ul> |
---|
412 | */ |
---|
413 | virtual const double * getRowRange() const ; |
---|
414 | |
---|
415 | /// Get pointer to array[getNumRows()] of row lower bounds |
---|
416 | virtual const double * getRowLower() const { return modelPtr_->rowLower(); } |
---|
417 | |
---|
418 | /// Get pointer to array[getNumRows()] of row upper bounds |
---|
419 | virtual const double * getRowUpper() const { return modelPtr_->rowUpper(); } |
---|
420 | |
---|
421 | /// Get pointer to array[getNumCols()] of objective function coefficients |
---|
422 | virtual const double * getObjCoefficients() const |
---|
423 | { if (fakeMinInSimplex_) |
---|
424 | return linearObjective_ ; |
---|
425 | else |
---|
426 | return modelPtr_->objective(); } |
---|
427 | |
---|
428 | /// Get objective function sense (1 for min (default), -1 for max) |
---|
429 | virtual double getObjSense() const |
---|
430 | { return ((fakeMinInSimplex_)?-modelPtr_->optimizationDirection(): |
---|
431 | modelPtr_->optimizationDirection()); } |
---|
432 | |
---|
433 | /// Return true if column is continuous |
---|
434 | virtual bool isContinuous(int colNumber) const; |
---|
435 | /// Return true if variable is binary |
---|
436 | virtual bool isBinary(int colIndex) const; |
---|
437 | |
---|
438 | /** Return true if column is integer. |
---|
439 | Note: This function returns true if the the column |
---|
440 | is binary or a general integer. |
---|
441 | */ |
---|
442 | virtual bool isInteger(int colIndex) const; |
---|
443 | |
---|
444 | /// Return true if variable is general integer |
---|
445 | virtual bool isIntegerNonBinary(int colIndex) const; |
---|
446 | |
---|
447 | /// Return true if variable is binary and not fixed at either bound |
---|
448 | virtual bool isFreeBinary(int colIndex) const; |
---|
449 | /** Return array of column length |
---|
450 | 0 - continuous |
---|
451 | 1 - binary (may get fixed later) |
---|
452 | 2 - general integer (may get fixed later) |
---|
453 | */ |
---|
454 | virtual const char * getColType(bool refresh=false) const; |
---|
455 | |
---|
456 | /** Return true if column is integer but does not have to |
---|
457 | be declared as such. |
---|
458 | Note: This function returns true if the the column |
---|
459 | is binary or a general integer. |
---|
460 | */ |
---|
461 | bool isOptionalInteger(int colIndex) const; |
---|
462 | /** Set the index-th variable to be an optional integer variable */ |
---|
463 | void setOptionalInteger(int index); |
---|
464 | |
---|
465 | /// Get pointer to row-wise copy of matrix |
---|
466 | virtual const CoinPackedMatrix * getMatrixByRow() const; |
---|
467 | |
---|
468 | /// Get pointer to column-wise copy of matrix |
---|
469 | virtual const CoinPackedMatrix * getMatrixByCol() const; |
---|
470 | |
---|
471 | /// Get pointer to mutable column-wise copy of matrix |
---|
472 | virtual CoinPackedMatrix * getMutableMatrixByCol() const; |
---|
473 | |
---|
474 | /// Get solver's value for infinity |
---|
475 | virtual double getInfinity() const { return OsiClpInfinity; } |
---|
476 | //@} |
---|
477 | |
---|
478 | /**@name Methods related to querying the solution */ |
---|
479 | //@{ |
---|
480 | /// Get pointer to array[getNumCols()] of primal solution vector |
---|
481 | virtual const double * getColSolution() const; |
---|
482 | |
---|
483 | /// Get pointer to array[getNumRows()] of dual prices |
---|
484 | virtual const double * getRowPrice() const; |
---|
485 | |
---|
486 | /// Get a pointer to array[getNumCols()] of reduced costs |
---|
487 | virtual const double * getReducedCost() const; |
---|
488 | |
---|
489 | /** Get pointer to array[getNumRows()] of row activity levels (constraint |
---|
490 | matrix times the solution vector */ |
---|
491 | virtual const double * getRowActivity() const; |
---|
492 | |
---|
493 | /// Get objective function value |
---|
494 | virtual double getObjValue() const; |
---|
495 | |
---|
496 | /** Get how many iterations it took to solve the problem (whatever |
---|
497 | "iteration" mean to the solver. */ |
---|
498 | virtual int getIterationCount() const |
---|
499 | { return modelPtr_->numberIterations(); } |
---|
500 | |
---|
501 | /** Get as many dual rays as the solver can provide. (In case of proven |
---|
502 | primal infeasibility there should be at least one.) |
---|
503 | |
---|
504 | The first getNumRows() ray components will always be associated with |
---|
505 | the row duals (as returned by getRowPrice()). If \c fullRay is true, |
---|
506 | the final getNumCols() entries will correspond to the ray components |
---|
507 | associated with the nonbasic variables. If the full ray is requested |
---|
508 | and the method cannot provide it, it will throw an exception. |
---|
509 | |
---|
510 | <strong>NOTE for implementers of solver interfaces:</strong> <br> |
---|
511 | The double pointers in the vector should point to arrays of length |
---|
512 | getNumRows() and they should be allocated via new[]. <br> |
---|
513 | |
---|
514 | <strong>NOTE for users of solver interfaces:</strong> <br> |
---|
515 | It is the user's responsibility to free the double pointers in the |
---|
516 | vector using delete[]. |
---|
517 | */ |
---|
518 | virtual std::vector<double*> getDualRays(int maxNumRays, |
---|
519 | bool fullRay = false) const; |
---|
520 | /** Get as many primal rays as the solver can provide. (In case of proven |
---|
521 | dual infeasibility there should be at least one.) |
---|
522 | |
---|
523 | <strong>NOTE for implementers of solver interfaces:</strong> <br> |
---|
524 | The double pointers in the vector should point to arrays of length |
---|
525 | getNumCols() and they should be allocated via new[]. <br> |
---|
526 | |
---|
527 | <strong>NOTE for users of solver interfaces:</strong> <br> |
---|
528 | It is the user's responsibility to free the double pointers in the |
---|
529 | vector using delete[]. |
---|
530 | */ |
---|
531 | virtual std::vector<double*> getPrimalRays(int maxNumRays) const; |
---|
532 | |
---|
533 | //@} |
---|
534 | //@} |
---|
535 | |
---|
536 | //--------------------------------------------------------------------------- |
---|
537 | |
---|
538 | /**@name Problem modifying methods */ |
---|
539 | //@{ |
---|
540 | //------------------------------------------------------------------------- |
---|
541 | /**@name Changing bounds on variables and constraints */ |
---|
542 | //@{ |
---|
543 | /** Set an objective function coefficient */ |
---|
544 | virtual void setObjCoeff( int elementIndex, double elementValue ); |
---|
545 | |
---|
546 | /** Set a single column lower bound<br> |
---|
547 | Use -DBL_MAX for -infinity. */ |
---|
548 | virtual void setColLower( int elementIndex, double elementValue ); |
---|
549 | |
---|
550 | /** Set a single column upper bound<br> |
---|
551 | Use DBL_MAX for infinity. */ |
---|
552 | virtual void setColUpper( int elementIndex, double elementValue ); |
---|
553 | |
---|
554 | /** Set a single column lower and upper bound */ |
---|
555 | virtual void setColBounds( int elementIndex, |
---|
556 | double lower, double upper ); |
---|
557 | |
---|
558 | /** Set the bounds on a number of columns simultaneously<br> |
---|
559 | The default implementation just invokes setColLower() and |
---|
560 | setColUpper() over and over again. |
---|
561 | @param indexFirst,indexLast pointers to the beginning and after the |
---|
562 | end of the array of the indices of the variables whose |
---|
563 | <em>either</em> bound changes |
---|
564 | @param boundList the new lower/upper bound pairs for the variables |
---|
565 | */ |
---|
566 | virtual void setColSetBounds(const int* indexFirst, |
---|
567 | const int* indexLast, |
---|
568 | const double* boundList); |
---|
569 | |
---|
570 | /** Set a single row lower bound<br> |
---|
571 | Use -DBL_MAX for -infinity. */ |
---|
572 | virtual void setRowLower( int elementIndex, double elementValue ); |
---|
573 | |
---|
574 | /** Set a single row upper bound<br> |
---|
575 | Use DBL_MAX for infinity. */ |
---|
576 | virtual void setRowUpper( int elementIndex, double elementValue ) ; |
---|
577 | |
---|
578 | /** Set a single row lower and upper bound */ |
---|
579 | virtual void setRowBounds( int elementIndex, |
---|
580 | double lower, double upper ) ; |
---|
581 | |
---|
582 | /** Set the type of a single row<br> */ |
---|
583 | virtual void setRowType(int index, char sense, double rightHandSide, |
---|
584 | double range); |
---|
585 | |
---|
586 | /** Set the bounds on a number of rows simultaneously<br> |
---|
587 | The default implementation just invokes setRowLower() and |
---|
588 | setRowUpper() over and over again. |
---|
589 | @param indexFirst,indexLast pointers to the beginning and after the |
---|
590 | end of the array of the indices of the constraints whose |
---|
591 | <em>either</em> bound changes |
---|
592 | @param boundList the new lower/upper bound pairs for the constraints |
---|
593 | */ |
---|
594 | virtual void setRowSetBounds(const int* indexFirst, |
---|
595 | const int* indexLast, |
---|
596 | const double* boundList); |
---|
597 | |
---|
598 | /** Set the type of a number of rows simultaneously<br> |
---|
599 | The default implementation just invokes setRowType() |
---|
600 | over and over again. |
---|
601 | @param indexFirst,indexLast pointers to the beginning and after the |
---|
602 | end of the array of the indices of the constraints whose |
---|
603 | <em>any</em> characteristics changes |
---|
604 | @param senseList the new senses |
---|
605 | @param rhsList the new right hand sides |
---|
606 | @param rangeList the new ranges |
---|
607 | */ |
---|
608 | virtual void setRowSetTypes(const int* indexFirst, |
---|
609 | const int* indexLast, |
---|
610 | const char* senseList, |
---|
611 | const double* rhsList, |
---|
612 | const double* rangeList); |
---|
613 | /** Set the objective coefficients for all columns |
---|
614 | array [getNumCols()] is an array of values for the objective. |
---|
615 | This defaults to a series of set operations and is here for speed. |
---|
616 | */ |
---|
617 | virtual void setObjective(const double * array); |
---|
618 | |
---|
619 | /** Set the lower bounds for all columns |
---|
620 | array [getNumCols()] is an array of values for the objective. |
---|
621 | This defaults to a series of set operations and is here for speed. |
---|
622 | */ |
---|
623 | virtual void setColLower(const double * array); |
---|
624 | |
---|
625 | /** Set the upper bounds for all columns |
---|
626 | array [getNumCols()] is an array of values for the objective. |
---|
627 | This defaults to a series of set operations and is here for speed. |
---|
628 | */ |
---|
629 | virtual void setColUpper(const double * array); |
---|
630 | |
---|
631 | // using OsiSolverInterface::setRowName ; |
---|
632 | /// Set name of row |
---|
633 | // virtual void setRowName(int rowIndex, std::string & name) ; |
---|
634 | virtual void setRowName(int rowIndex, std::string name) ; |
---|
635 | |
---|
636 | // using OsiSolverInterface::setColName ; |
---|
637 | /// Set name of column |
---|
638 | // virtual void setColName(int colIndex, std::string & name) ; |
---|
639 | virtual void setColName(int colIndex, std::string name) ; |
---|
640 | |
---|
641 | //@} |
---|
642 | |
---|
643 | //------------------------------------------------------------------------- |
---|
644 | /**@name Integrality related changing methods */ |
---|
645 | //@{ |
---|
646 | /** Set the index-th variable to be a continuous variable */ |
---|
647 | virtual void setContinuous(int index); |
---|
648 | /** Set the index-th variable to be an integer variable */ |
---|
649 | virtual void setInteger(int index); |
---|
650 | /** Set the variables listed in indices (which is of length len) to be |
---|
651 | continuous variables */ |
---|
652 | virtual void setContinuous(const int* indices, int len); |
---|
653 | /** Set the variables listed in indices (which is of length len) to be |
---|
654 | integer variables */ |
---|
655 | virtual void setInteger(const int* indices, int len); |
---|
656 | /// Number of SOS sets |
---|
657 | inline int numberSOS() const |
---|
658 | { return numberSOS_;} |
---|
659 | /// SOS set info |
---|
660 | inline const CoinSet * setInfo() const |
---|
661 | { return setInfo_;} |
---|
662 | /** \brief Identify integer variables and SOS and create corresponding objects. |
---|
663 | |
---|
664 | Record integer variables and create an OsiSimpleInteger object for each |
---|
665 | one. All existing OsiSimpleInteger objects will be destroyed. |
---|
666 | If the solver supports SOS then do the same for SOS. |
---|
667 | If justCount then no objects created and we just store numberIntegers_ |
---|
668 | Returns number of SOS |
---|
669 | */ |
---|
670 | |
---|
671 | virtual int findIntegersAndSOS(bool justCount); |
---|
672 | //@} |
---|
673 | |
---|
674 | //------------------------------------------------------------------------- |
---|
675 | /// Set objective function sense (1 for min (default), -1 for max,) |
---|
676 | virtual void setObjSense(double s ) |
---|
677 | { modelPtr_->setOptimizationDirection( s < 0 ? -1 : 1); } |
---|
678 | |
---|
679 | /** Set the primal solution column values |
---|
680 | |
---|
681 | colsol[numcols()] is an array of values of the problem column |
---|
682 | variables. These values are copied to memory owned by the |
---|
683 | solver object or the solver. They will be returned as the |
---|
684 | result of colsol() until changed by another call to |
---|
685 | setColsol() or by a call to any solver routine. Whether the |
---|
686 | solver makes use of the solution in any way is |
---|
687 | solver-dependent. |
---|
688 | */ |
---|
689 | virtual void setColSolution(const double * colsol); |
---|
690 | |
---|
691 | /** Set dual solution vector |
---|
692 | |
---|
693 | rowprice[numrows()] is an array of values of the problem row |
---|
694 | dual variables. These values are copied to memory owned by the |
---|
695 | solver object or the solver. They will be returned as the |
---|
696 | result of rowprice() until changed by another call to |
---|
697 | setRowprice() or by a call to any solver routine. Whether the |
---|
698 | solver makes use of the solution in any way is |
---|
699 | solver-dependent. |
---|
700 | */ |
---|
701 | virtual void setRowPrice(const double * rowprice); |
---|
702 | |
---|
703 | //------------------------------------------------------------------------- |
---|
704 | /**@name Methods to expand a problem.<br> |
---|
705 | Note that if a column is added then by default it will correspond to a |
---|
706 | continuous variable. */ |
---|
707 | //@{ |
---|
708 | |
---|
709 | //using OsiSolverInterface::addCol ; |
---|
710 | /** */ |
---|
711 | virtual void addCol(const CoinPackedVectorBase& vec, |
---|
712 | const double collb, const double colub, |
---|
713 | const double obj); |
---|
714 | /*! \brief Add a named column (primal variable) to the problem. |
---|
715 | */ |
---|
716 | virtual void addCol(const CoinPackedVectorBase& vec, |
---|
717 | const double collb, const double colub, |
---|
718 | const double obj, std::string name) ; |
---|
719 | /** Add a column (primal variable) to the problem. */ |
---|
720 | virtual void addCol(int numberElements, const int * rows, const double * elements, |
---|
721 | const double collb, const double colub, |
---|
722 | const double obj) ; |
---|
723 | /*! \brief Add a named column (primal variable) to the problem. |
---|
724 | */ |
---|
725 | virtual void addCol(int numberElements, |
---|
726 | const int* rows, const double* elements, |
---|
727 | const double collb, const double colub, |
---|
728 | const double obj, std::string name) ; |
---|
729 | /** */ |
---|
730 | virtual void addCols(const int numcols, |
---|
731 | const CoinPackedVectorBase * const * cols, |
---|
732 | const double* collb, const double* colub, |
---|
733 | const double* obj); |
---|
734 | /** */ |
---|
735 | virtual void addCols(const int numcols, |
---|
736 | const int * columnStarts, const int * rows, const double * elements, |
---|
737 | const double* collb, const double* colub, |
---|
738 | const double* obj); |
---|
739 | /** */ |
---|
740 | virtual void deleteCols(const int num, const int * colIndices); |
---|
741 | |
---|
742 | /** */ |
---|
743 | virtual void addRow(const CoinPackedVectorBase& vec, |
---|
744 | const double rowlb, const double rowub); |
---|
745 | /** */ |
---|
746 | /*! \brief Add a named row (constraint) to the problem. |
---|
747 | |
---|
748 | The default implementation adds the row, then changes the name. This |
---|
749 | can surely be made more efficient within an OsiXXX class. |
---|
750 | */ |
---|
751 | virtual void addRow(const CoinPackedVectorBase& vec, |
---|
752 | const double rowlb, const double rowub, |
---|
753 | std::string name) ; |
---|
754 | virtual void addRow(const CoinPackedVectorBase& vec, |
---|
755 | const char rowsen, const double rowrhs, |
---|
756 | const double rowrng); |
---|
757 | /** Add a row (constraint) to the problem. */ |
---|
758 | virtual void addRow(int numberElements, const int * columns, const double * element, |
---|
759 | const double rowlb, const double rowub) ; |
---|
760 | /*! \brief Add a named row (constraint) to the problem. |
---|
761 | */ |
---|
762 | virtual void addRow(const CoinPackedVectorBase& vec, |
---|
763 | const char rowsen, const double rowrhs, |
---|
764 | const double rowrng, std::string name) ; |
---|
765 | /** */ |
---|
766 | virtual void addRows(const int numrows, |
---|
767 | const CoinPackedVectorBase * const * rows, |
---|
768 | const double* rowlb, const double* rowub); |
---|
769 | /** */ |
---|
770 | virtual void addRows(const int numrows, |
---|
771 | const CoinPackedVectorBase * const * rows, |
---|
772 | const char* rowsen, const double* rowrhs, |
---|
773 | const double* rowrng); |
---|
774 | |
---|
775 | /** */ |
---|
776 | virtual void addRows(const int numrows, |
---|
777 | const int * rowStarts, const int * columns, const double * element, |
---|
778 | const double* rowlb, const double* rowub); |
---|
779 | /// |
---|
780 | void modifyCoefficient(int row, int column, double newElement, |
---|
781 | bool keepZero=false) |
---|
782 | {modelPtr_->modifyCoefficient(row,column,newElement, keepZero);} |
---|
783 | |
---|
784 | /** */ |
---|
785 | virtual void deleteRows(const int num, const int * rowIndices); |
---|
786 | /** If solver wants it can save a copy of "base" (continuous) model here |
---|
787 | */ |
---|
788 | virtual void saveBaseModel() ; |
---|
789 | /** Strip off rows to get to this number of rows. |
---|
790 | If solver wants it can restore a copy of "base" (continuous) model here |
---|
791 | */ |
---|
792 | virtual void restoreBaseModel(int numberRows); |
---|
793 | |
---|
794 | //----------------------------------------------------------------------- |
---|
795 | /** Apply a collection of row cuts which are all effective. |
---|
796 | applyCuts seems to do one at a time which seems inefficient. |
---|
797 | */ |
---|
798 | virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts); |
---|
799 | /** Apply a collection of row cuts which are all effective. |
---|
800 | applyCuts seems to do one at a time which seems inefficient. |
---|
801 | This uses array of pointers |
---|
802 | */ |
---|
803 | virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts); |
---|
804 | /** Apply a collection of cuts. |
---|
805 | |
---|
806 | Only cuts which have an <code>effectiveness >= effectivenessLb</code> |
---|
807 | are applied. |
---|
808 | <ul> |
---|
809 | <li> ReturnCode.getNumineffective() -- number of cuts which were |
---|
810 | not applied because they had an |
---|
811 | <code>effectiveness < effectivenessLb</code> |
---|
812 | <li> ReturnCode.getNuminconsistent() -- number of invalid cuts |
---|
813 | <li> ReturnCode.getNuminconsistentWrtIntegerModel() -- number of |
---|
814 | cuts that are invalid with respect to this integer model |
---|
815 | <li> ReturnCode.getNuminfeasible() -- number of cuts that would |
---|
816 | make this integer model infeasible |
---|
817 | <li> ReturnCode.getNumApplied() -- number of integer cuts which |
---|
818 | were applied to the integer model |
---|
819 | <li> cs.size() == getNumineffective() + |
---|
820 | getNuminconsistent() + |
---|
821 | getNuminconsistentWrtIntegerModel() + |
---|
822 | getNuminfeasible() + |
---|
823 | getNumApplied() |
---|
824 | </ul> |
---|
825 | */ |
---|
826 | virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs, |
---|
827 | double effectivenessLb = 0.0); |
---|
828 | |
---|
829 | //@} |
---|
830 | //@} |
---|
831 | |
---|
832 | //--------------------------------------------------------------------------- |
---|
833 | |
---|
834 | public: |
---|
835 | |
---|
836 | /**@name Methods to input a problem */ |
---|
837 | //@{ |
---|
838 | /** Load in an problem by copying the arguments (the constraints on the |
---|
839 | rows are given by lower and upper bounds). If a pointer is NULL then the |
---|
840 | following values are the default: |
---|
841 | <ul> |
---|
842 | <li> <code>colub</code>: all columns have upper bound infinity |
---|
843 | <li> <code>collb</code>: all columns have lower bound 0 |
---|
844 | <li> <code>rowub</code>: all rows have upper bound infinity |
---|
845 | <li> <code>rowlb</code>: all rows have lower bound -infinity |
---|
846 | <li> <code>obj</code>: all variables have 0 objective coefficient |
---|
847 | </ul> |
---|
848 | */ |
---|
849 | virtual void loadProblem(const CoinPackedMatrix& matrix, |
---|
850 | const double* collb, const double* colub, |
---|
851 | const double* obj, |
---|
852 | const double* rowlb, const double* rowub); |
---|
853 | |
---|
854 | /** Load in an problem by assuming ownership of the arguments (the |
---|
855 | constraints on the rows are given by lower and upper bounds). For |
---|
856 | default values see the previous method. <br> |
---|
857 | <strong>WARNING</strong>: The arguments passed to this method will be |
---|
858 | freed using the C++ <code>delete</code> and <code>delete[]</code> |
---|
859 | functions. |
---|
860 | */ |
---|
861 | virtual void assignProblem(CoinPackedMatrix*& matrix, |
---|
862 | double*& collb, double*& colub, double*& obj, |
---|
863 | double*& rowlb, double*& rowub); |
---|
864 | |
---|
865 | /** Load in an problem by copying the arguments (the constraints on the |
---|
866 | rows are given by sense/rhs/range triplets). If a pointer is NULL then the |
---|
867 | following values are the default: |
---|
868 | <ul> |
---|
869 | <li> <code>colub</code>: all columns have upper bound infinity |
---|
870 | <li> <code>collb</code>: all columns have lower bound 0 |
---|
871 | <li> <code>obj</code>: all variables have 0 objective coefficient |
---|
872 | <li> <code>rowsen</code>: all rows are >= |
---|
873 | <li> <code>rowrhs</code>: all right hand sides are 0 |
---|
874 | <li> <code>rowrng</code>: 0 for the ranged rows |
---|
875 | </ul> |
---|
876 | */ |
---|
877 | virtual void loadProblem(const CoinPackedMatrix& matrix, |
---|
878 | const double* collb, const double* colub, |
---|
879 | const double* obj, |
---|
880 | const char* rowsen, const double* rowrhs, |
---|
881 | const double* rowrng); |
---|
882 | |
---|
883 | /** Load in an problem by assuming ownership of the arguments (the |
---|
884 | constraints on the rows are given by sense/rhs/range triplets). For |
---|
885 | default values see the previous method. <br> |
---|
886 | <strong>WARNING</strong>: The arguments passed to this method will be |
---|
887 | freed using the C++ <code>delete</code> and <code>delete[]</code> |
---|
888 | functions. |
---|
889 | */ |
---|
890 | virtual void assignProblem(CoinPackedMatrix*& matrix, |
---|
891 | double*& collb, double*& colub, double*& obj, |
---|
892 | char*& rowsen, double*& rowrhs, |
---|
893 | double*& rowrng); |
---|
894 | |
---|
895 | /** Just like the other loadProblem() methods except that the matrix is |
---|
896 | given in a standard column major ordered format (without gaps). */ |
---|
897 | virtual void loadProblem(const int numcols, const int numrows, |
---|
898 | const CoinBigIndex * start, const int* index, |
---|
899 | const double* value, |
---|
900 | const double* collb, const double* colub, |
---|
901 | const double* obj, |
---|
902 | const double* rowlb, const double* rowub); |
---|
903 | |
---|
904 | /** Just like the other loadProblem() methods except that the matrix is |
---|
905 | given in a standard column major ordered format (without gaps). */ |
---|
906 | virtual void loadProblem(const int numcols, const int numrows, |
---|
907 | const CoinBigIndex * start, const int* index, |
---|
908 | const double* value, |
---|
909 | const double* collb, const double* colub, |
---|
910 | const double* obj, |
---|
911 | const char* rowsen, const double* rowrhs, |
---|
912 | const double* rowrng); |
---|
913 | /// This loads a model from a coinModel object - returns number of errors |
---|
914 | virtual int loadFromCoinModel ( CoinModel & modelObject, bool keepSolution=false); |
---|
915 | |
---|
916 | using OsiSolverInterface::readMps ; |
---|
917 | /** Read an mps file from the given filename (defaults to Osi reader) - returns |
---|
918 | number of errors (see OsiMpsReader class) */ |
---|
919 | virtual int readMps(const char *filename, |
---|
920 | const char *extension = "mps") ; |
---|
921 | /** Read an mps file from the given filename returns |
---|
922 | number of errors (see OsiMpsReader class) */ |
---|
923 | int readMps(const char *filename,bool keepNames,bool allowErrors); |
---|
924 | /// Read an mps file |
---|
925 | virtual int readMps (const char *filename, const char*extension, |
---|
926 | int & numberSets, CoinSet ** & sets); |
---|
927 | |
---|
928 | /** Write the problem into an mps file of the given filename. |
---|
929 | If objSense is non zero then -1.0 forces the code to write a |
---|
930 | maximization objective and +1.0 to write a minimization one. |
---|
931 | If 0.0 then solver can do what it wants */ |
---|
932 | virtual void writeMps(const char *filename, |
---|
933 | const char *extension = "mps", |
---|
934 | double objSense=0.0) const; |
---|
935 | /** Write the problem into an mps file of the given filename, |
---|
936 | names may be null. formatType is |
---|
937 | 0 - normal |
---|
938 | 1 - extra accuracy |
---|
939 | 2 - IEEE hex (later) |
---|
940 | |
---|
941 | Returns non-zero on I/O error |
---|
942 | */ |
---|
943 | virtual int writeMpsNative(const char *filename, |
---|
944 | const char ** rowNames, const char ** columnNames, |
---|
945 | int formatType=0,int numberAcross=2, |
---|
946 | double objSense=0.0) const ; |
---|
947 | /// Read file in LP format (with names) |
---|
948 | virtual int readLp(const char *filename, const double epsilon = 1e-5); |
---|
949 | /** Write the problem into an Lp file of the given filename. |
---|
950 | If objSense is non zero then -1.0 forces the code to write a |
---|
951 | maximization objective and +1.0 to write a minimization one. |
---|
952 | If 0.0 then solver can do what it wants. |
---|
953 | This version calls writeLpNative with names */ |
---|
954 | virtual void writeLp(const char *filename, |
---|
955 | const char *extension = "lp", |
---|
956 | double epsilon = 1e-5, |
---|
957 | int numberAcross = 10, |
---|
958 | int decimals = 5, |
---|
959 | double objSense = 0.0, |
---|
960 | bool useRowNames = true) const; |
---|
961 | /** Write the problem into the file pointed to by the parameter fp. |
---|
962 | Other parameters are similar to |
---|
963 | those of writeLp() with first parameter filename. |
---|
964 | */ |
---|
965 | virtual void writeLp(FILE *fp, |
---|
966 | double epsilon = 1e-5, |
---|
967 | int numberAcross = 10, |
---|
968 | int decimals = 5, |
---|
969 | double objSense = 0.0, |
---|
970 | bool useRowNames = true) const; |
---|
971 | /** |
---|
972 | I (JJF) am getting annoyed because I can't just replace a matrix. |
---|
973 | The default behavior of this is do nothing so only use where that would not matter |
---|
974 | e.g. strengthening a matrix for MIP |
---|
975 | */ |
---|
976 | virtual void replaceMatrixOptional(const CoinPackedMatrix & matrix); |
---|
977 | /// And if it does matter (not used at present) |
---|
978 | virtual void replaceMatrix(const CoinPackedMatrix & matrix) ; |
---|
979 | //@} |
---|
980 | |
---|
981 | /**@name Message handling (extra for Clp messages). |
---|
982 | Normally I presume you would want the same language. |
---|
983 | If not then you could use underlying model pointer */ |
---|
984 | //@{ |
---|
985 | /** Pass in a message handler |
---|
986 | |
---|
987 | It is the client's responsibility to destroy a message handler installed |
---|
988 | by this routine; it will not be destroyed when the solver interface is |
---|
989 | destroyed. |
---|
990 | */ |
---|
991 | virtual void passInMessageHandler(CoinMessageHandler * handler); |
---|
992 | /// Set language |
---|
993 | void newLanguage(CoinMessages::Language language); |
---|
994 | void setLanguage(CoinMessages::Language language) |
---|
995 | {newLanguage(language);} |
---|
996 | /// Set log level (will also set underlying solver's log level) |
---|
997 | void setLogLevel(int value); |
---|
998 | /// Create C++ lines to get to current state |
---|
999 | void generateCpp( FILE * fp); |
---|
1000 | //@} |
---|
1001 | //--------------------------------------------------------------------------- |
---|
1002 | |
---|
1003 | /**@name Clp specific public interfaces */ |
---|
1004 | //@{ |
---|
1005 | /// Get pointer to Clp model |
---|
1006 | ClpSimplex * getModelPtr() const ; |
---|
1007 | /// Set pointer to Clp model and return old |
---|
1008 | inline ClpSimplex * swapModelPtr(ClpSimplex * newModel) |
---|
1009 | { ClpSimplex * model = modelPtr_; modelPtr_=newModel;return model;} |
---|
1010 | /// Get special options |
---|
1011 | inline unsigned int specialOptions() const |
---|
1012 | { return specialOptions_;} |
---|
1013 | void setSpecialOptions(unsigned int value); |
---|
1014 | /// Last algorithm used , 1 = primal, 2 = dual |
---|
1015 | inline int lastAlgorithm() const |
---|
1016 | { return lastAlgorithm_;} |
---|
1017 | /// Get scaling action option |
---|
1018 | inline int cleanupScaling() const |
---|
1019 | { return cleanupScaling_;} |
---|
1020 | /** Set Scaling option |
---|
1021 | When scaling is on it is possible that the scaled problem |
---|
1022 | is feasible but the unscaled is not. Clp returns a secondary |
---|
1023 | status code to that effect. This option allows for a cleanup. |
---|
1024 | If you use it I would suggest 1. |
---|
1025 | This only affects actions when scaled optimal |
---|
1026 | 0 - no action |
---|
1027 | 1 - clean up using dual if primal infeasibility |
---|
1028 | 2 - clean up using dual if dual infeasibility |
---|
1029 | 3 - clean up using dual if primal or dual infeasibility |
---|
1030 | 11,12,13 - as 1,2,3 but use primal |
---|
1031 | */ |
---|
1032 | inline void setCleanupScaling(int value) |
---|
1033 | { cleanupScaling_=value;} |
---|
1034 | /** Get smallest allowed element in cut. |
---|
1035 | If smaller than this then ignored */ |
---|
1036 | inline double smallestElementInCut() const |
---|
1037 | { return smallestElementInCut_;} |
---|
1038 | /** Set smallest allowed element in cut. |
---|
1039 | If smaller than this then ignored */ |
---|
1040 | inline void setSmallestElementInCut(double value) |
---|
1041 | { smallestElementInCut_=value;} |
---|
1042 | /** Get smallest change in cut. |
---|
1043 | If (upper-lower)*element < this then element is |
---|
1044 | taken out and cut relaxed. |
---|
1045 | (upper-lower) is taken to be at least 1.0 and |
---|
1046 | this is assumed >= smallestElementInCut_ |
---|
1047 | */ |
---|
1048 | inline double smallestChangeInCut() const |
---|
1049 | { return smallestChangeInCut_;} |
---|
1050 | /** Set smallest change in cut. |
---|
1051 | If (upper-lower)*element < this then element is |
---|
1052 | taken out and cut relaxed. |
---|
1053 | (upper-lower) is taken to be at least 1.0 and |
---|
1054 | this is assumed >= smallestElementInCut_ |
---|
1055 | */ |
---|
1056 | inline void setSmallestChangeInCut(double value) |
---|
1057 | { smallestChangeInCut_=value;} |
---|
1058 | /// Pass in initial solve options |
---|
1059 | inline void setSolveOptions(const ClpSolve & options) |
---|
1060 | { solveOptions_ = options;} |
---|
1061 | /** Tighten bounds - lightweight or very lightweight |
---|
1062 | 0 - normal, 1 lightweight but just integers, 2 lightweight and all |
---|
1063 | */ |
---|
1064 | virtual int tightenBounds(int lightweight=0); |
---|
1065 | /// Return number of entries in L part of current factorization |
---|
1066 | virtual CoinBigIndex getSizeL() const; |
---|
1067 | /// Return number of entries in U part of current factorization |
---|
1068 | virtual CoinBigIndex getSizeU() const; |
---|
1069 | /// Get disaster handler |
---|
1070 | const OsiClpDisasterHandler * disasterHandler() const |
---|
1071 | { return disasterHandler_;} |
---|
1072 | /// Pass in disaster handler |
---|
1073 | void passInDisasterHandler(OsiClpDisasterHandler * handler); |
---|
1074 | /// Get fake objective |
---|
1075 | ClpLinearObjective * fakeObjective() const |
---|
1076 | { return fakeObjective_;} |
---|
1077 | /// Set fake objective (and take ownership) |
---|
1078 | void setFakeObjective(ClpLinearObjective * fakeObjective); |
---|
1079 | /// Set fake objective |
---|
1080 | void setFakeObjective(double * fakeObjective); |
---|
1081 | /*! \brief Set up solver for repeated use by Osi interface. |
---|
1082 | |
---|
1083 | The normal usage does things like keeping factorization around so can be |
---|
1084 | used. Will also do things like keep scaling and row copy of matrix if |
---|
1085 | matrix does not change. |
---|
1086 | |
---|
1087 | \p senseOfAdventure: |
---|
1088 | - 0 - safe stuff as above |
---|
1089 | - 1 - will take more risks - if it does not work then bug which will be |
---|
1090 | fixed |
---|
1091 | - 2 - don't bother doing most extreme termination checks e.g. don't bother |
---|
1092 | re-factorizing if less than 20 iterations. |
---|
1093 | - 3 - Actually safer than 1 (mainly just keeps factorization) |
---|
1094 | |
---|
1095 | \p printOut |
---|
1096 | - -1 always skip round common messages instead of doing some work |
---|
1097 | - 0 skip if normal defaults |
---|
1098 | - 1 leaves |
---|
1099 | */ |
---|
1100 | void setupForRepeatedUse(int senseOfAdventure=0, int printOut=0); |
---|
1101 | /// Synchronize model (really if no cuts in tree) |
---|
1102 | virtual void synchronizeModel(); |
---|
1103 | /*! \brief Set special options in underlying clp solver. |
---|
1104 | |
---|
1105 | Safe as const because #modelPtr_ is mutable. |
---|
1106 | */ |
---|
1107 | void setSpecialOptionsMutable(unsigned int value) const; |
---|
1108 | |
---|
1109 | //@} |
---|
1110 | |
---|
1111 | //--------------------------------------------------------------------------- |
---|
1112 | |
---|
1113 | /**@name Constructors and destructors */ |
---|
1114 | //@{ |
---|
1115 | /// Default Constructor |
---|
1116 | OsiClpSolverInterface (); |
---|
1117 | |
---|
1118 | /// Clone |
---|
1119 | virtual OsiSolverInterface * clone(bool copyData = true) const; |
---|
1120 | |
---|
1121 | /// Copy constructor |
---|
1122 | OsiClpSolverInterface (const OsiClpSolverInterface &); |
---|
1123 | |
---|
1124 | /// Borrow constructor - only delete one copy |
---|
1125 | OsiClpSolverInterface (ClpSimplex * rhs, bool reallyOwn=false); |
---|
1126 | |
---|
1127 | /// Releases so won't error |
---|
1128 | void releaseClp(); |
---|
1129 | |
---|
1130 | /// Assignment operator |
---|
1131 | OsiClpSolverInterface & operator=(const OsiClpSolverInterface& rhs); |
---|
1132 | |
---|
1133 | /// Destructor |
---|
1134 | virtual ~OsiClpSolverInterface (); |
---|
1135 | |
---|
1136 | /// Resets as if default constructor |
---|
1137 | virtual void reset(); |
---|
1138 | //@} |
---|
1139 | |
---|
1140 | //--------------------------------------------------------------------------- |
---|
1141 | |
---|
1142 | protected: |
---|
1143 | ///@name Protected methods |
---|
1144 | //@{ |
---|
1145 | /** Apply a row cut (append to constraint matrix). */ |
---|
1146 | virtual void applyRowCut(const OsiRowCut& rc); |
---|
1147 | |
---|
1148 | /** Apply a column cut (adjust one or more bounds). */ |
---|
1149 | virtual void applyColCut(const OsiColCut& cc); |
---|
1150 | //@} |
---|
1151 | |
---|
1152 | //--------------------------------------------------------------------------- |
---|
1153 | |
---|
1154 | protected: |
---|
1155 | /**@name Protected methods */ |
---|
1156 | //@{ |
---|
1157 | /// The real work of a copy constructor (used by copy and assignment) |
---|
1158 | void gutsOfDestructor(); |
---|
1159 | |
---|
1160 | /// Deletes all mutable stuff |
---|
1161 | void freeCachedResults() const; |
---|
1162 | |
---|
1163 | /// Deletes all mutable stuff for row ranges etc |
---|
1164 | void freeCachedResults0() const; |
---|
1165 | |
---|
1166 | /// Deletes all mutable stuff for matrix etc |
---|
1167 | void freeCachedResults1() const; |
---|
1168 | |
---|
1169 | /// A method that fills up the rowsense_, rhs_ and rowrange_ arrays |
---|
1170 | void extractSenseRhsRange() const; |
---|
1171 | |
---|
1172 | /// |
---|
1173 | void fillParamMaps(); |
---|
1174 | /** Warm start |
---|
1175 | |
---|
1176 | NOTE artificials are treated as +1 elements so for <= rhs |
---|
1177 | artificial will be at lower bound if constraint is tight |
---|
1178 | |
---|
1179 | This means that Clpsimplex flips artificials as it works |
---|
1180 | in terms of row activities |
---|
1181 | */ |
---|
1182 | CoinWarmStartBasis getBasis(ClpSimplex * model) const; |
---|
1183 | /** Sets up working basis as a copy of input |
---|
1184 | |
---|
1185 | NOTE artificials are treated as +1 elements so for <= rhs |
---|
1186 | artificial will be at lower bound if constraint is tight |
---|
1187 | |
---|
1188 | This means that Clpsimplex flips artificials as it works |
---|
1189 | in terms of row activities |
---|
1190 | */ |
---|
1191 | void setBasis( const CoinWarmStartBasis & basis, ClpSimplex * model); |
---|
1192 | /// Crunch down problem a bit |
---|
1193 | void crunch(); |
---|
1194 | /// Extend scale factors |
---|
1195 | void redoScaleFactors(int numberRows,const CoinBigIndex * starts, |
---|
1196 | const int * indices, const double * elements); |
---|
1197 | public: |
---|
1198 | /** Sets up working basis as a copy of input and puts in as basis |
---|
1199 | */ |
---|
1200 | void setBasis( const CoinWarmStartBasis & basis); |
---|
1201 | /// Just puts current basis_ into ClpSimplex model |
---|
1202 | inline void setBasis( ) |
---|
1203 | { setBasis(basis_,modelPtr_);} |
---|
1204 | /// Warm start difference from basis_ to statusArray |
---|
1205 | CoinWarmStartDiff * getBasisDiff(const unsigned char * statusArray) const ; |
---|
1206 | /// Warm start from statusArray |
---|
1207 | CoinWarmStartBasis * getBasis(const unsigned char * statusArray) const ; |
---|
1208 | /// Delete all scale factor stuff and reset option |
---|
1209 | void deleteScaleFactors(); |
---|
1210 | /// If doing fast hot start then ranges are computed |
---|
1211 | inline const double * upRange() const |
---|
1212 | { return rowActivity_;} |
---|
1213 | inline const double * downRange() const |
---|
1214 | { return columnActivity_;} |
---|
1215 | /// Pass in range array |
---|
1216 | inline void passInRanges(int * array) |
---|
1217 | { whichRange_=array;} |
---|
1218 | /// Pass in sos stuff from AMPl |
---|
1219 | void setSOSData(int numberSOS,const char * type, |
---|
1220 | const int * start,const int * indices, const double * weights=NULL); |
---|
1221 | /// Compute largest amount any at continuous away from bound |
---|
1222 | void computeLargestAway(); |
---|
1223 | /// Get largest amount continuous away from bound |
---|
1224 | inline double largestAway() const |
---|
1225 | { return largestAway_;} |
---|
1226 | /// Set largest amount continuous away from bound |
---|
1227 | inline void setLargestAway(double value) |
---|
1228 | { largestAway_ = value;} |
---|
1229 | /// Sort of lexicographic resolve |
---|
1230 | void lexSolve(); |
---|
1231 | //@} |
---|
1232 | |
---|
1233 | protected: |
---|
1234 | /**@name Protected member data */ |
---|
1235 | //@{ |
---|
1236 | /// Clp model represented by this class instance |
---|
1237 | mutable ClpSimplex * modelPtr_; |
---|
1238 | //@} |
---|
1239 | /**@name Cached information derived from the OSL model */ |
---|
1240 | //@{ |
---|
1241 | /// Pointer to dense vector of row sense indicators |
---|
1242 | mutable char *rowsense_; |
---|
1243 | |
---|
1244 | /// Pointer to dense vector of row right-hand side values |
---|
1245 | mutable double *rhs_; |
---|
1246 | |
---|
1247 | /** Pointer to dense vector of slack upper bounds for range |
---|
1248 | constraints (undefined for non-range rows) |
---|
1249 | */ |
---|
1250 | mutable double *rowrange_; |
---|
1251 | |
---|
1252 | /** A pointer to the warmstart information to be used in the hotstarts. |
---|
1253 | This is NOT efficient and more thought should be given to it... */ |
---|
1254 | mutable CoinWarmStartBasis* ws_; |
---|
1255 | /** also save row and column information for hot starts |
---|
1256 | only used in hotstarts so can be casual */ |
---|
1257 | mutable double * rowActivity_; |
---|
1258 | mutable double * columnActivity_; |
---|
1259 | /// Stuff for fast dual |
---|
1260 | ClpNodeStuff stuff_; |
---|
1261 | /// Number of SOS sets |
---|
1262 | int numberSOS_; |
---|
1263 | /// SOS set info |
---|
1264 | CoinSet * setInfo_; |
---|
1265 | /// Alternate model (hot starts) - but also could be permanent and used for crunch |
---|
1266 | ClpSimplex * smallModel_; |
---|
1267 | /// factorization for hot starts |
---|
1268 | ClpFactorization * factorization_; |
---|
1269 | /** Smallest allowed element in cut. |
---|
1270 | If smaller than this then ignored */ |
---|
1271 | double smallestElementInCut_; |
---|
1272 | /** Smallest change in cut. |
---|
1273 | If (upper-lower)*element < this then element is |
---|
1274 | taken out and cut relaxed. */ |
---|
1275 | double smallestChangeInCut_; |
---|
1276 | /// Largest amount continuous away from bound |
---|
1277 | double largestAway_; |
---|
1278 | /// Arrays for hot starts |
---|
1279 | char * spareArrays_; |
---|
1280 | /** Warmstart information to be used in resolves. */ |
---|
1281 | CoinWarmStartBasis basis_; |
---|
1282 | /** The original iteration limit before hotstarts started. */ |
---|
1283 | int itlimOrig_; |
---|
1284 | |
---|
1285 | /*! \brief Last algorithm used |
---|
1286 | |
---|
1287 | Coded as |
---|
1288 | - 0 invalid |
---|
1289 | - 1 primal |
---|
1290 | - 2 dual |
---|
1291 | - -911 disaster in the algorithm that was attempted |
---|
1292 | - 999 current solution no longer optimal due to change in problem or |
---|
1293 | basis |
---|
1294 | */ |
---|
1295 | mutable int lastAlgorithm_; |
---|
1296 | |
---|
1297 | /// To say if destructor should delete underlying model |
---|
1298 | bool notOwned_; |
---|
1299 | |
---|
1300 | /// Pointer to row-wise copy of problem matrix coefficients. |
---|
1301 | mutable CoinPackedMatrix *matrixByRow_; |
---|
1302 | |
---|
1303 | /// Pointer to row-wise copy of continuous problem matrix coefficients. |
---|
1304 | CoinPackedMatrix *matrixByRowAtContinuous_; |
---|
1305 | |
---|
1306 | /// Pointer to integer information |
---|
1307 | char * integerInformation_; |
---|
1308 | |
---|
1309 | /** Pointer to variables for which we want range information |
---|
1310 | The number is in [0] |
---|
1311 | memory is not owned by OsiClp |
---|
1312 | */ |
---|
1313 | int * whichRange_; |
---|
1314 | |
---|
1315 | //std::map<OsiIntParam, ClpIntParam> intParamMap_; |
---|
1316 | //std::map<OsiDblParam, ClpDblParam> dblParamMap_; |
---|
1317 | //std::map<OsiStrParam, ClpStrParam> strParamMap_; |
---|
1318 | |
---|
1319 | /*! \brief Faking min to get proper dual solution signs in simplex API */ |
---|
1320 | mutable bool fakeMinInSimplex_ ; |
---|
1321 | /*! \brief Linear objective |
---|
1322 | |
---|
1323 | Normally a pointer to the linear coefficient array in the clp objective. |
---|
1324 | An independent copy when #fakeMinInSimplex_ is true, because we need |
---|
1325 | something permanent to point to when #getObjCoefficients is called. |
---|
1326 | */ |
---|
1327 | mutable double *linearObjective_; |
---|
1328 | |
---|
1329 | /// To save data in OsiSimplex stuff |
---|
1330 | mutable ClpDataSave saveData_; |
---|
1331 | /// Options for initialSolve |
---|
1332 | ClpSolve solveOptions_; |
---|
1333 | /** Scaling option |
---|
1334 | When scaling is on it is possible that the scaled problem |
---|
1335 | is feasible but the unscaled is not. Clp returns a secondary |
---|
1336 | status code to that effect. This option allows for a cleanup. |
---|
1337 | If you use it I would suggest 1. |
---|
1338 | This only affects actions when scaled optimal |
---|
1339 | 0 - no action |
---|
1340 | 1 - clean up using dual if primal infeasibility |
---|
1341 | 2 - clean up using dual if dual infeasibility |
---|
1342 | 3 - clean up using dual if primal or dual infeasibility |
---|
1343 | 11,12,13 - as 1,2,3 but use primal |
---|
1344 | */ |
---|
1345 | int cleanupScaling_; |
---|
1346 | /** Special options |
---|
1347 | 0x80000000 off |
---|
1348 | 0 simple stuff for branch and bound |
---|
1349 | 1 try and keep work regions as much as possible |
---|
1350 | 2 do not use any perturbation |
---|
1351 | 4 allow exit before re-factorization |
---|
1352 | 8 try and re-use factorization if no cuts |
---|
1353 | 16 use standard strong branching rather than clp's |
---|
1354 | 32 Just go to first factorization in fast dual |
---|
1355 | 64 try and tighten bounds in crunch |
---|
1356 | 128 Model will only change in column bounds |
---|
1357 | 256 Clean up model before hot start |
---|
1358 | 512 Give user direct access to Clp regions in getBInvARow etc (i.e., |
---|
1359 | do not unscale, and do not return result in getBInv parameters; |
---|
1360 | you have to know where to look for the answer) |
---|
1361 | 1024 Don't "borrow" model in initialSolve |
---|
1362 | 2048 Don't crunch |
---|
1363 | 4096 quick check for optimality |
---|
1364 | Bits above 8192 give where called from in Cbc |
---|
1365 | At present 0 is normal, 1 doing fast hotstarts, 2 is can do quick check |
---|
1366 | 65536 Keep simple i.e. no crunch etc |
---|
1367 | 131072 Try and keep scaling factors around |
---|
1368 | 262144 Don't try and tighten bounds (funny global cuts) |
---|
1369 | 524288 Fake objective and 0-1 |
---|
1370 | 1048576 Don't recompute ray after crunch |
---|
1371 | */ |
---|
1372 | mutable unsigned int specialOptions_; |
---|
1373 | /// Copy of model when option 131072 set |
---|
1374 | ClpSimplex * baseModel_; |
---|
1375 | /// Number of rows when last "scaled" |
---|
1376 | int lastNumberRows_; |
---|
1377 | /// Continuous model |
---|
1378 | ClpSimplex * continuousModel_; |
---|
1379 | /// Possible disaster handler |
---|
1380 | OsiClpDisasterHandler * disasterHandler_ ; |
---|
1381 | /// Fake objective |
---|
1382 | ClpLinearObjective * fakeObjective_; |
---|
1383 | /// Row scale factors (has inverse at end) |
---|
1384 | CoinDoubleArrayWithLength rowScale_; |
---|
1385 | /// Column scale factors (has inverse at end) |
---|
1386 | CoinDoubleArrayWithLength columnScale_; |
---|
1387 | //@} |
---|
1388 | }; |
---|
1389 | |
---|
1390 | class OsiClpDisasterHandler : public ClpDisasterHandler { |
---|
1391 | public: |
---|
1392 | /**@name Virtual methods that the derived classe should provide. |
---|
1393 | */ |
---|
1394 | //@{ |
---|
1395 | /// Into simplex |
---|
1396 | virtual void intoSimplex(); |
---|
1397 | /// Checks if disaster |
---|
1398 | virtual bool check() const ; |
---|
1399 | /// saves information for next attempt |
---|
1400 | virtual void saveInfo(); |
---|
1401 | /// Type of disaster 0 can fix, 1 abort |
---|
1402 | virtual int typeOfDisaster(); |
---|
1403 | //@} |
---|
1404 | |
---|
1405 | |
---|
1406 | /**@name Constructors, destructor */ |
---|
1407 | |
---|
1408 | //@{ |
---|
1409 | /** Default constructor. */ |
---|
1410 | OsiClpDisasterHandler(OsiClpSolverInterface * model = NULL); |
---|
1411 | /** Destructor */ |
---|
1412 | virtual ~OsiClpDisasterHandler(); |
---|
1413 | // Copy |
---|
1414 | OsiClpDisasterHandler(const OsiClpDisasterHandler&); |
---|
1415 | // Assignment |
---|
1416 | OsiClpDisasterHandler& operator=(const OsiClpDisasterHandler&); |
---|
1417 | /// Clone |
---|
1418 | virtual ClpDisasterHandler * clone() const; |
---|
1419 | |
---|
1420 | //@} |
---|
1421 | |
---|
1422 | /**@name Sets/gets */ |
---|
1423 | |
---|
1424 | //@{ |
---|
1425 | /** set model. */ |
---|
1426 | void setOsiModel(OsiClpSolverInterface * model); |
---|
1427 | /// Get model |
---|
1428 | inline OsiClpSolverInterface * osiModel() const |
---|
1429 | { return osiModel_;} |
---|
1430 | /// Set where from |
---|
1431 | inline void setWhereFrom(int value) |
---|
1432 | { whereFrom_=value;} |
---|
1433 | /// Get where from |
---|
1434 | inline int whereFrom() const |
---|
1435 | { return whereFrom_;} |
---|
1436 | /// Set phase |
---|
1437 | inline void setPhase(int value) |
---|
1438 | { phase_=value;} |
---|
1439 | /// Get phase |
---|
1440 | inline int phase() const |
---|
1441 | { return phase_;} |
---|
1442 | /// are we in trouble |
---|
1443 | inline bool inTrouble() const |
---|
1444 | { return inTrouble_;} |
---|
1445 | |
---|
1446 | //@} |
---|
1447 | |
---|
1448 | |
---|
1449 | protected: |
---|
1450 | /**@name Data members |
---|
1451 | The data members are protected to allow access for derived classes. */ |
---|
1452 | //@{ |
---|
1453 | /// Pointer to model |
---|
1454 | OsiClpSolverInterface * osiModel_; |
---|
1455 | /** Where from |
---|
1456 | 0 dual (resolve) |
---|
1457 | 1 crunch |
---|
1458 | 2 primal (resolve) |
---|
1459 | 4 dual (initialSolve) |
---|
1460 | 6 primal (initialSolve) |
---|
1461 | */ |
---|
1462 | int whereFrom_; |
---|
1463 | /** phase |
---|
1464 | 0 initial |
---|
1465 | 1 trying continuing with back in and maybe different perturb |
---|
1466 | 2 trying continuing with back in and different scaling |
---|
1467 | 3 trying dual from all slack |
---|
1468 | 4 trying primal from previous stored basis |
---|
1469 | */ |
---|
1470 | int phase_; |
---|
1471 | /// Are we in trouble |
---|
1472 | bool inTrouble_; |
---|
1473 | //@} |
---|
1474 | }; |
---|
1475 | // So unit test can find out if NDEBUG set |
---|
1476 | bool OsiClpHasNDEBUG(); |
---|
1477 | //############################################################################# |
---|
1478 | /** A function that tests the methods in the OsiClpSolverInterface class. The |
---|
1479 | only reason for it not to be a member method is that this way it doesn't |
---|
1480 | have to be compiled into the library. And that's a gain, because the |
---|
1481 | library should be compiled with optimization on, but this method should be |
---|
1482 | compiled with debugging. Also, if this method is compiled with |
---|
1483 | optimization, the compilation takes 10-15 minutes and the machine pages |
---|
1484 | (has 256M core memory!)... */ |
---|
1485 | int |
---|
1486 | OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); |
---|
1487 | #endif |
---|