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