1 //-----------------------------------------------------------------------------
2 // name:     OSI Interface for Gurobi
3 // template: OSI Cplex Interface written by T. Achterberg
4 // author:   Stefan Vigerske
5 //           Humboldt University Berlin
6 // date:     09/02/2009
7 // license:  this file may be freely distributed under the terms of EPL
8 // comments: please scan this file for '???' and read the comments
9 //-----------------------------------------------------------------------------
10 // Copyright (C) 2009 Humboldt University Berlin and others.
11 // All Rights Reserved.
12 
13 // $Id: OsiGrbSolverInterface.hpp 2197 2019-01-06 23:00:34Z unxusr $
14 
15 #ifndef OsiGrbSolverInterface_H
16 #define OsiGrbSolverInterface_H
17 
18 #include <string>
19 #include "OsiSolverInterface.hpp"
20 
21 typedef struct _GRBmodel GRBmodel;
22 typedef struct _GRBenv GRBenv;
23 
24 /** Gurobi Solver Interface
25 
26  Instantiation of OsiGrbSolverInterface for Gurobi
27  */
28 
29 class OsiGrbSolverInterface : virtual public OsiSolverInterface {
30   friend void OsiGrbSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir);
31 
32 public:
33   //---------------------------------------------------------------------------
34   /**@name Solve methods */
35   //@{
36   /// Solve initial LP relaxation
37   virtual void initialSolve();
38 
39   /// Resolve an LP relaxation after problem modification
40   virtual void resolve();
41 
42   /// Invoke solver's built-in enumeration algorithm
43   virtual void branchAndBound();
44   //@}
45 
46   //---------------------------------------------------------------------------
47   /**@name Parameter set/get methods
48 
49 	 The set methods return true if the parameter was set to the given value,
50 	 false otherwise. There can be various reasons for failure: the given
51 	 parameter is not applicable for the solver (e.g., refactorization
52 	 frequency for the volume algorithm), the parameter is not yet implemented
53 	 for the solver or simply the value of the parameter is out of the range
54 	 the solver accepts. If a parameter setting call returns false check the
55 	 details of your solver.
56 
57 	 The get methods return true if the given parameter is applicable for the
58 	 solver and is implemented. In this case the value of the parameter is
59 	 returned in the second argument. Otherwise they return false.
60 	 */
61   //@{
62   // Set an integer parameter
63   bool setIntParam(OsiIntParam key, int value);
64   // Set an double parameter
65   bool setDblParam(OsiDblParam key, double value);
66   // Set a string parameter
67   bool setStrParam(OsiStrParam key, const std::string &value);
68   // Set a hint parameter
69   bool setHintParam(OsiHintParam key, bool yesNo = true, OsiHintStrength strength = OsiHintTry, void * = NULL);
70   // Get an integer parameter
71   bool getIntParam(OsiIntParam key, int &value) const;
72   // Get an double parameter
73   bool getDblParam(OsiDblParam key, double &value) const;
74   // Get a string parameter
75   bool getStrParam(OsiStrParam key, std::string &value) const;
76   // Get a hint parameter
77   bool getHintParam(OsiHintParam key, bool &yesNo, OsiHintStrength &strength, void *&otherInformation) const;
78   // Get a hint parameter
79   bool getHintParam(OsiHintParam key, bool &yesNo, OsiHintStrength &strength) const;
80   // Get a hint parameter
81   bool getHintParam(OsiHintParam key, bool &yesNo) const;
82   // Set mipstart option (pass column solution to CPLEX before MIP start)
setMipStart(bool value)83   void setMipStart(bool value) { domipstart = value; }
84   // Get mipstart option value
getMipStart() const85   bool getMipStart() const { return domipstart; }
86   //@}
87 
88   //---------------------------------------------------------------------------
89   ///@name Methods returning info on how the solution process terminated
90   //@{
91   /// Are there a numerical difficulties?
92   virtual bool isAbandoned() const;
93   /// Is optimality proven?
94   virtual bool isProvenOptimal() const;
95   /// Is primal infeasiblity proven?
96   virtual bool isProvenPrimalInfeasible() const;
97   /// Is dual infeasiblity proven?
98   virtual bool isProvenDualInfeasible() const;
99   /// Is the given primal objective limit reached?
100   virtual bool isPrimalObjectiveLimitReached() const;
101   /// Is the given dual objective limit reached?
102   virtual bool isDualObjectiveLimitReached() const;
103   /// Iteration limit reached?
104   virtual bool isIterationLimitReached() const;
105   //@}
106 
107   //---------------------------------------------------------------------------
108   /**@name WarmStart related methods */
109   //@{
110 
111   /*! \brief Get an empty warm start object
112 
113 	 This routine returns an empty CoinWarmStartBasis object. Its purpose is
114 	 to provide a way to give a client a warm start basis object of the
115 	 appropriate type, which can resized and modified as desired.
116 	 */
117   CoinWarmStart *getEmptyWarmStart() const;
118 
119   /// Get warmstarting information
120   virtual CoinWarmStart *getWarmStart() const;
121   /** Set warmstarting information. Return true/false depending on whether
122 	 the warmstart information was accepted or not. */
123   virtual bool setWarmStart(const CoinWarmStart *warmstart);
124   //@}
125 
126   //---------------------------------------------------------------------------
127   /**@name Hotstart related methods (primarily used in strong branching). <br>
128 	 The user can create a hotstart (a snapshot) of the optimization process
129 	 then reoptimize over and over again always starting from there.<br>
130 	 <strong>NOTE</strong>: between hotstarted optimizations only
131 	 bound changes are allowed. */
132   //@{
133   /// Create a hotstart point of the optimization process
134   virtual void markHotStart();
135   /// Optimize starting from the hotstart
136   virtual void solveFromHotStart();
137   /// Delete the snapshot
138   virtual void unmarkHotStart();
139   //@}
140 
141   //---------------------------------------------------------------------------
142   /**@name Problem information methods
143 
144 	 These methods call the solver's query routines to return
145 	 information about the problem referred to by the current object.
146 	 Querying a problem that has no data associated with it result in
147 	 zeros for the number of rows and columns, and NULL pointers from
148 	 the methods that return vectors.
149 
150 	 Const pointers returned from any data-query method are valid as
151 	 long as the data is unchanged and the solver is not called.
152 	 */
153   //@{
154   /**@name Methods related to querying the input data */
155   //@{
156   /// Get number of columns
157   virtual int getNumCols() const;
158 
159   /// Get number of rows
160   virtual int getNumRows() const;
161 
162   /// Get number of nonzero elements
163   virtual int getNumElements() const;
164 
165   /// Get pointer to array[getNumCols()] of column lower bounds
166   virtual const double *getColLower() const;
167 
168   /// Get pointer to array[getNumCols()] of column upper bounds
169   virtual const double *getColUpper() const;
170 
171   /** Get pointer to array[getNumRows()] of row constraint senses.
172 	 <ul>
173 	 <li>'L': <= constraint
174 	 <li>'E': =  constraint
175 	 <li>'G': >= constraint
176 	 <li>'R': ranged constraint
177 	 <li>'N': free constraint
178 	 </ul>
179 	 */
180   virtual const char *getRowSense() const;
181 
182   /** Get pointer to array[getNumRows()] of rows right-hand sides
183 	 <ul>
184 	 <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
185 	 <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
186 	 <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
187 	 <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0
188 	 </ul>
189 	 */
190   virtual const double *getRightHandSide() const;
191 
192   /** Get pointer to array[getNumRows()] of row ranges.
193 	 <ul>
194 	 <li> if rowsense()[i] == 'R' then
195 	 rowrange()[i] == rowupper()[i] - rowlower()[i]
196 	 <li> if rowsense()[i] != 'R' then
197 	 rowrange()[i] is 0.0
198 	 </ul>
199 	 */
200   virtual const double *getRowRange() const;
201 
202   /// Get pointer to array[getNumRows()] of row lower bounds
203   virtual const double *getRowLower() const;
204 
205   /// Get pointer to array[getNumRows()] of row upper bounds
206   virtual const double *getRowUpper() const;
207 
208   /// Get pointer to array[getNumCols()] of objective function coefficients
209   virtual const double *getObjCoefficients() const;
210 
211   /// Get objective function sense (1 for min (default), -1 for max)
212   virtual double getObjSense() const;
213 
214   /// Return true if column is continuous
215   virtual bool isContinuous(int colNumber) const;
216 
217   /// Get pointer to row-wise copy of matrix
218   virtual const CoinPackedMatrix *getMatrixByRow() const;
219 
220   /// Get pointer to column-wise copy of matrix
221   virtual const CoinPackedMatrix *getMatrixByCol() const;
222 
223   /// Get solver's value for infinity
224   virtual double getInfinity() const;
225   //@}
226 
227   /**@name Methods related to querying the solution */
228   //@{
229   /// Get pointer to array[getNumCols()] of primal solution vector
230   virtual const double *getColSolution() const;
231 
232   /// Get pointer to array[getNumRows()] of dual prices
233   virtual const double *getRowPrice() const;
234 
235   /// Get a pointer to array[getNumCols()] of reduced costs
236   virtual const double *getReducedCost() const;
237 
238   /** Get pointer to array[getNumRows()] of row activity levels (constraint
239 	 matrix times the solution vector */
240   virtual const double *getRowActivity() const;
241 
242   /// Get objective function value
243   virtual double getObjValue() const;
244 
245   /** Get how many iterations it took to solve the problem (whatever
246 	 "iteration" mean to the solver. */
247   virtual int getIterationCount() const;
248 
249   /** Get as many dual rays as the solver can provide. (In case of proven
250 	 primal infeasibility there should be at least one.)
251 
252 	 The first getNumRows() ray components will always be associated with
253 	 the row duals (as returned by getRowPrice()). If \c fullRay is true,
254 	 the final getNumCols() entries will correspond to the ray components
255 	 associated with the nonbasic variables. If the full ray is requested
256 	 and the method cannot provide it, it will throw an exception.
257 
258 	 <strong>NOTE for implementers of solver interfaces:</strong> <br>
259 	 The double pointers in the vector should point to arrays of length
260 	 getNumRows() and they should be allocated via new[]. <br>
261 
262 	 <strong>NOTE for users of solver interfaces:</strong> <br>
263 	 It is the user's responsibility to free the double pointers in the
264 	 vector using delete[].
265 	 */
266   virtual std::vector< double * > getDualRays(int maxNumRays,
267     bool fullRay = false) const;
268   /** Get as many primal rays as the solver can provide. (In case of proven
269 	 dual infeasibility there should be at least one.)
270 
271 	 <strong>NOTE for implementers of solver interfaces:</strong> <br>
272 	 The double pointers in the vector should point to arrays of length
273 	 getNumCols() and they should be allocated via new[]. <br>
274 
275 	 <strong>NOTE for users of solver interfaces:</strong> <br>
276 	 It is the user's responsibility to free the double pointers in the
277 	 vector using delete[].
278 	 */
279   virtual std::vector< double * > getPrimalRays(int maxNumRays) const;
280   //@}
281   //@}
282 
283   //---------------------------------------------------------------------------
284 
285   /**@name Problem modifying methods */
286   //@{
287   //-------------------------------------------------------------------------
288   /**@name Changing bounds on variables and constraints */
289   //@{
290   /** Set an objective function coefficient */
291   virtual void setObjCoeff(int elementIndex, double elementValue);
292 
293   /** Set a a set of objective function coefficients */
294   virtual void setObjCoeffSet(const int *indexFirst, const int *indexLast,
295     const double *coeffList);
296 
297   using OsiSolverInterface::setColLower;
298   /** Set a single column lower bound<br>
299 	 Use -COIN_DBL_MAX for -infinity. */
300   virtual void setColLower(int elementIndex, double elementValue);
301 
302   using OsiSolverInterface::setColUpper;
303   /** Set a single column upper bound<br>
304 	 Use COIN_DBL_MAX for infinity. */
305   virtual void setColUpper(int elementIndex, double elementValue);
306 
307   /** Set a single column lower and upper bound<br>
308 	 The default implementation just invokes <code>setColLower()</code> and
309 	 <code>setColUpper()</code> */
310   virtual void setColBounds(int elementIndex, double lower, double upper);
311 
312   /** Set the bounds on a number of columns simultaneously<br>
313 	 The default implementation just invokes <code>setCollower()</code> and
314 	 <code>setColupper()</code> over and over again.
315 	 @param <code>[indexfirst,indexLast]</code> contains the indices of
316 	 the constraints whose </em>either</em> bound changes
317 	 @param boundList the new lower/upper bound pairs for the variables
318 	 */
319   virtual void setColSetBounds(const int *indexFirst, const int *indexLast,
320     const double *boundList);
321 
322   /** Set a single row lower bound<br>
323 	 Use -COIN_DBL_MAX for -infinity. */
324   virtual void setRowLower(int elementIndex, double elementValue);
325 
326   /** Set a single row upper bound<br>
327 	 Use COIN_DBL_MAX for infinity. */
328   virtual void setRowUpper(int elementIndex, double elementValue);
329 
330   /** Set a single row lower and upper bound<br>
331 	 The default implementation just invokes <code>setRowLower()</code> and
332 	 <code>setRowUpper()</code> */
333   virtual void setRowBounds(int elementIndex, double lower, double upper);
334 
335   /** Set the type of a single row<br> */
336   virtual void setRowType(int index, char sense, double rightHandSide,
337     double range);
338 
339   /** Set the bounds on a number of rows simultaneously<br>
340 	 The default implementation just invokes <code>setRowLower()</code> and
341 	 <code>setRowUpper()</code> over and over again.
342 	 @param <code>[indexfirst,indexLast]</code> contains the indices of
343 	 the constraints whose </em>either</em> bound changes
344 	 @param boundList the new lower/upper bound pairs for the constraints
345 	 */
346   virtual void setRowSetBounds(const int *indexFirst, const int *indexLast,
347     const double *boundList);
348 
349   /** Set the type of a number of rows simultaneously<br>
350 	 The default implementation just invokes <code>setRowType()</code> and
351 	 over and over again.
352 	 @param <code>[indexfirst,indexLast]</code> contains the indices of
353 	 the constraints whose type changes
354 	 @param senseList the new senses
355 	 @param rhsList   the new right hand sides
356 	 @param rangeList the new ranges
357 	 */
358   virtual void setRowSetTypes(const int *indexFirst, const int *indexLast,
359     const char *senseList, const double *rhsList, const double *rangeList);
360   //@}
361 
362   //-------------------------------------------------------------------------
363   /**@name Integrality related changing methods */
364   //@{
365   /** Set the index-th variable to be a continuous variable */
366   virtual void setContinuous(int index);
367   /** Set the index-th variable to be an integer variable */
368   virtual void setInteger(int index);
369   /** Set the variables listed in indices (which is of length len) to be
370 	 continuous variables */
371   virtual void setContinuous(const int *indices, int len);
372   /** Set the variables listed in indices (which is of length len) to be
373 	 integer variables */
374   virtual void setInteger(const int *indices, int len);
375   //@}
376 
377   //-------------------------------------------------------------------------
378   /**@name Naming methods */
379   //@{
380   /*! \brief Set a row name */
381   virtual void setRowName(int ndx, std::string name);
382 
383   /*! \brief Set a column name */
384   virtual void setColName(int ndx, std::string name);
385   //@}
386 
387   //-------------------------------------------------------------------------
388   /// Set objective function sense (1 for min (default), -1 for max,)
389   virtual void setObjSense(double s);
390 
391   /** Set the primal solution column values
392 
393 	 colsol[numcols()] is an array of values of the problem column
394 	 variables. These values are copied to memory owned by the
395 	 solver object or the solver.  They will be returned as the
396 	 result of colsol() until changed by another call to
397 	 setColsol() or by a call to any solver routine.  Whether the
398 	 solver makes use of the solution in any way is
399 	 solver-dependent.
400 	 */
401   virtual void setColSolution(const double *colsol);
402 
403   /** Set dual solution vector
404 
405 	 rowprice[numrows()] is an array of values of the problem row
406 	 dual variables. These values are copied to memory owned by the
407 	 solver object or the solver.  They will be returned as the
408 	 result of rowprice() until changed by another call to
409 	 setRowprice() or by a call to any solver routine.  Whether the
410 	 solver makes use of the solution in any way is
411 	 solver-dependent.
412 	 */
413   virtual void setRowPrice(const double *rowprice);
414 
415   //-------------------------------------------------------------------------
416   /**@name Methods to expand a problem.<br>
417 	 Note that if a column is added then by default it will correspond to a
418 	 continuous variable. */
419   //@{
420   using OsiSolverInterface::addCol;
421   /** */
422   virtual void addCol(const CoinPackedVectorBase &vec, const double collb,
423     const double colub, const double obj);
424 
425   using OsiSolverInterface::addCols;
426   /** */
427   virtual void addCols(const int numcols,
428     const CoinPackedVectorBase *const *cols, const double *collb,
429     const double *colub, const double *obj);
430   /** */
431   virtual void deleteCols(const int num, const int *colIndices);
432 
433   using OsiSolverInterface::addRow;
434   /** */
435   virtual void addRow(const CoinPackedVectorBase &vec, const double rowlb,
436     const double rowub);
437   /** */
438   virtual void addRow(const CoinPackedVectorBase &vec, const char rowsen,
439     const double rowrhs, const double rowrng);
440 
441   using OsiSolverInterface::addRows;
442   /** */
443   virtual void addRows(const int numrows,
444     const CoinPackedVectorBase *const *rows, const double *rowlb,
445     const double *rowub);
446   /** */
447   virtual void addRows(const int numrows,
448     const CoinPackedVectorBase *const *rows, const char *rowsen,
449     const double *rowrhs, const double *rowrng);
450   /** */
451   virtual void deleteRows(const int num, const int *rowIndices);
452   //@}
453   //@}
454 
455   //---------------------------------------------------------------------------
456 
457   /**@name Methods to input a problem */
458   //@{
459   /** Load in an problem by copying the arguments (the constraints on the
460 	 rows are given by lower and upper bounds). If a pointer is 0 then the
461 	 following values are the default:
462 	 <ul>
463 	 <li> <code>colub</code>: all columns have upper bound infinity
464 	 <li> <code>collb</code>: all columns have lower bound 0
465 	 <li> <code>rowub</code>: all rows have upper bound infinity
466 	 <li> <code>rowlb</code>: all rows have lower bound -infinity
467 	 <li> <code>obj</code>: all variables have 0 objective coefficient
468 	 </ul>
469 	 */
470   virtual void loadProblem(const CoinPackedMatrix &matrix, const double *collb,
471     const double *colub, const double *obj, const double *rowlb,
472     const double *rowub);
473 
474   /** Load in an problem by assuming ownership of the arguments (the
475 	 constraints on the rows are given by lower and upper bounds). For
476 	 default values see the previous method. <br>
477 	 <strong>WARNING</strong>: The arguments passed to this method will be
478 	 freed using the C++ <code>delete</code> and <code>delete[]</code>
479 	 functions.
480 	 */
481   virtual void assignProblem(CoinPackedMatrix *&matrix, double *&collb,
482     double *&colub, double *&obj, double *&rowlb, double *&rowub);
483 
484   /** Load in an problem by copying the arguments (the constraints on the
485 	 rows are given by sense/rhs/range triplets). If a pointer is 0 then the
486 	 following values are the default:
487 	 <ul>
488 	 <li> <code>colub</code>: all columns have upper bound infinity
489 	 <li> <code>collb</code>: all columns have lower bound 0
490 	 <li> <code>obj</code>: all variables have 0 objective coefficient
491 	 <li> <code>rowsen</code>: all rows are >=
492 	 <li> <code>rowrhs</code>: all right hand sides are 0
493 	 <li> <code>rowrng</code>: 0 for the ranged rows
494 	 </ul>
495 	 */
496   virtual void loadProblem(const CoinPackedMatrix &matrix, const double *collb,
497     const double *colub, const double *obj, const char *rowsen,
498     const double *rowrhs, const double *rowrng);
499 
500   /** Load in an problem by assuming ownership of the arguments (the
501 	 constraints on the rows are given by sense/rhs/range triplets). For
502 	 default values see the previous method. <br>
503 	 <strong>WARNING</strong>: The arguments passed to this method will be
504 	 freed using the C++ <code>delete</code> and <code>delete[]</code>
505 	 functions.
506 	 */
507   virtual void assignProblem(CoinPackedMatrix *&matrix, double *&collb,
508     double *&colub, double *&obj, char *&rowsen, double *&rowrhs,
509     double *&rowrng);
510 
511   /** Just like the other loadProblem() methods except that the matrix is
512 	 given in a standard column major ordered format (without gaps). */
513   virtual void loadProblem(const int numcols, const int numrows,
514     const int *start, const int *index, const double *value,
515     const double *collb, const double *colub, const double *obj,
516     const double *rowlb, const double *rowub);
517 
518   /** Just like the other loadProblem() methods except that the matrix is
519 	 given in a standard column major ordered format (without gaps). */
520   virtual void loadProblem(const int numcols, const int numrows,
521     const int *start, const int *index, const double *value,
522     const double *collb, const double *colub, const double *obj,
523     const char *rowsen, const double *rowrhs, const double *rowrng);
524 
525   using OsiSolverInterface::readMps;
526   /** Read an mps file from the given filename */
527   virtual int readMps(const char *filename, const char *extension = "mps");
528 
529   /** Write the problem into an mps file of the given filename.
530 	 If objSense is non zero then -1.0 forces the code to write a
531 	 maximization objective and +1.0 to write a minimization one.
532 	 If 0.0 then solver can do what it wants */
533   virtual void writeMps(const char *filename, const char *extension = "mps",
534     double objSense = 0.0) const;
535 
536   //@}
537 
538   //---------------------------------------------------------------------------
539 
540   /**@name Gurobi specific public interfaces */
541   //@{
542   /** Get pointer to Gurobi model and free all specified cached data entries
543 	 (combined with logical or-operator '|' ):
544 	 */
545   enum keepCachedFlag {
546     /// discard all cached data (default)
547     KEEPCACHED_NONE = 0,
548     /// column information: objective values, lower and upper bounds, variable types
549     KEEPCACHED_COLUMN = 1,
550     /// row information: right hand sides, ranges and senses, lower and upper bounds for row
551     KEEPCACHED_ROW = 2,
552     /// problem matrix: matrix ordered by column and by row
553     KEEPCACHED_MATRIX = 4,
554     /// LP solution: primal and dual solution, reduced costs, row activities
555     KEEPCACHED_RESULTS = 8,
556     /// only discard cached LP solution
557     KEEPCACHED_PROBLEM = KEEPCACHED_COLUMN | KEEPCACHED_ROW | KEEPCACHED_MATRIX,
558     /// keep all cached data (similar to getMutableLpPtr())
559     KEEPCACHED_ALL = KEEPCACHED_PROBLEM | KEEPCACHED_RESULTS,
560     /// free only cached column and LP solution information
561     FREECACHED_COLUMN = KEEPCACHED_PROBLEM & ~KEEPCACHED_COLUMN,
562     /// free only cached row and LP solution information
563     FREECACHED_ROW = KEEPCACHED_PROBLEM & ~KEEPCACHED_ROW,
564     /// free only cached matrix and LP solution information
565     FREECACHED_MATRIX = KEEPCACHED_PROBLEM & ~KEEPCACHED_MATRIX,
566     /// free only cached LP solution information
567     FREECACHED_RESULTS = KEEPCACHED_ALL & ~KEEPCACHED_RESULTS
568   };
569 
570   GRBmodel *getLpPtr(int keepCached = KEEPCACHED_NONE);
571 
572   //@{
573   /// Method to access Gurobi environment pointer
574   GRBenv *getEnvironmentPtr() const;
575 
576   /// Return whether the current Gurobi environment runs in demo mode.
577   bool isDemoLicense() const;
578   //@}
579 
580   /// return a vector of variable types (continous, binary, integer)
581   const char *getCtype() const;
582 
583   /**@name Static instance counter methods */
584   /** Gurobi has a context which must be created prior to all other Gurobi calls.
585 	 This method:
586 	 <ul>
587 	 <li>Increments by 1 the number of uses of the Gurobi environment.
588 	 <li>Creates the Gurobi context when the number of uses is change to
589 	 1 from 0.
590 	 </ul>
591 	 */
592   static void incrementInstanceCounter();
593 
594   /** Gurobi has a context which should be deleted after Gurobi calls.
595 	 This method:
596 	 <ul>
597 	 <li>Decrements by 1 the number of uses of the Gurobi environment.
598 	 <li>Deletes the Gurobi context when the number of uses is change to
599 	 0 from 1.
600 	 </ul>
601 	 */
602   static void decrementInstanceCounter();
603 
604   /// sets the global gurobi environment to a user given one
605   static void setEnvironment(GRBenv *globalenv);
606 
607   /// Return the number of instances of instantiated objects using Gurobi services.
608   static unsigned int getNumInstances();
609   //@}
610   //@}
611 
612   /**@name Constructors and destructor */
613   //@{
614   /// Default Constructor
615   OsiGrbSolverInterface(bool use_local_env = false);
616 
617   /// Constructor that takes a gurobi environment and assumes membership
618   OsiGrbSolverInterface(GRBenv *localgrbenv);
619 
620   /// Clone
621   virtual OsiSolverInterface *clone(bool copyData = true) const;
622 
623   /// Copy constructor
624   OsiGrbSolverInterface(const OsiGrbSolverInterface &);
625 
626   /// Assignment operator
627   OsiGrbSolverInterface &operator=(const OsiGrbSolverInterface &rhs);
628 
629   /// Destructor
630   virtual ~OsiGrbSolverInterface();
631 
632   /// Resets as if default constructor
633   virtual void reset();
634   //@}
635 
636   /***************************************************************************/
637   /**@name OsiSimplexInterface methods
638 	 Gurobi adds a slack with coeff +1 in "<=" and "=" constraints,
639 	 with coeff -1 in ">=",
640 	 slack being non negative. We switch in order to get a "Clp tableau"
641 	 where all the slacks have coefficient +1 in the original tableau.
642 
643 	 If a slack for ">=" is non basic, invB is not changed;
644 	 column of the slack in the optimal tableau is flipped.
645 
646 	 If a slack for ">=" is basic, corresp. row of invB is flipped;
647 	 whole row of the optimal tableau is flipped;
648 	 then whole column for the slack in opt tableau is flipped.
649 
650 	 Ranged rows are not supported. It might work, but no garantee is given.
651 	 */
652   //@{
653 
654   /** Returns 1 if can just do getBInv etc
655 	 2 if has all OsiSimplex methods
656 	 and 0 if it has none */
657   virtual int canDoSimplexInterface() const;
658 
659   using OsiSolverInterface::enableSimplexInterface;
660   /** Useless function, defined only for compatibility with
661 	 OsiSimplexInterface
662 	 */
enableSimplexInterface(int doingPrimal)663   virtual void enableSimplexInterface(int doingPrimal) {};
664 
665   /** Useless function, defined only for compatibility with
666 	 OsiSimplexInterface
667 	 */
disableSimplexInterface()668   virtual void disableSimplexInterface() {};
669 
670   /** Useless function, defined only for compatibility with
671 	 OsiSimplexInterface
672 	 */
enableFactorization() const673   virtual void enableFactorization() const {};
674 
675   /** Useless function, defined only for compatibility with
676 	 OsiSimplexInterface
677 	 */
disableFactorization() const678   virtual void disableFactorization() const {};
679 
680   ///Returns true if a basis is available
681   virtual bool basisIsAvailable() const;
682 
683   /** Returns a basis status of the structural/artificial variables
684 	 At present as warm start i.e 0: free, 1: basic, 2: upper, 3: lower
685 	 */
686   virtual void getBasisStatus(int *cstat, int *rstat) const;
687 
688   //  ///Get a row of the tableau (slack part in slack if not NULL)
689   //  virtual void getBInvARow(int row, double* z, double * slack=NULL) const;
690   //
691   //  ///Get a row of the basis inverse
692   //  virtual void getBInvRow(int row, double* z) const;
693   //
694   //  ///Get a column of the tableau
695   //  virtual void getBInvACol(int col, double* vec) const;
696   //
697   //  ///Get a column of the basis inverse
698   //  virtual void getBInvCol(int col, double* vec) const;
699   //
700   //  /**  Get indices of the pivot variable in each row
701   //      (order of indices corresponds to the
702   //      order of elements in a vector retured by getBInvACol() and
703   //      getBInvCol()).
704   //  */
705   //  virtual void getBasics(int* index) const;
706   /// switches Gurobi to prob type LP
707   void switchToLP();
708 
709   /// switches Gurobi to prob type MIP
710   void switchToMIP();
711 
712   //@}
713   /***************************************************************************/
714 
715   /***************************************************************************/
716 
717   /** Apply a collection of cuts.
718 
719     Only cuts which have an <code>effectiveness >= effectivenessLb</code>
720     are applied.
721     <ul>
722       <li> ReturnCode.getNumineffective() -- number of cuts which were
723            not applied because they had an
724            <code>effectiveness < effectivenessLb</code>
725       <li> ReturnCode.getNuminconsistent() -- number of invalid cuts
726       <li> ReturnCode.getNuminconsistentWrtIntegerModel() -- number of
727            cuts that are invalid with respect to this integer model
728       <li> ReturnCode.getNuminfeasible() -- number of cuts that would
729            make this integer model infeasible
730       <li> ReturnCode.getNumApplied() -- number of integer cuts which
731            were applied to the integer model
732       <li> cs.size() == getNumineffective() +
733              getNuminconsistent() +
734              getNuminconsistentWrtIntegerModel() +
735              getNuminfeasible() +
736              getNumApplied()
737     </ul>
738     */
739   virtual OsiSolverInterface::ApplyCutsReturnCode applyCuts(const OsiCuts &cs,
740     double effectivenessLb = 0.0);
741 
742 protected:
743   /**@name Protected methods */
744   //@{
745   /// Apply a row cut. Return true if cut was applied.
746   virtual void applyRowCut(const OsiRowCut &rc);
747 
748   /** Apply a column cut (bound adjustment).
749 	 Return true if cut was applied.
750 	 */
751   virtual void applyColCut(const OsiColCut &cc);
752   //@}
753 
754 private:
755   /**@name Private static class functions  */
756   //@{
757   /// resizes coltype_, colmap_O2G, colmap_G2O vectors to be able to store at least minsize elements
758   void resizeColSpace(int minsize);
759 
760   /// frees colsize_ vector
761   void freeColSpace();
762 
763   /// resizes colmap_G2O vector to be able to store at least minsize (auxiliary) elements
764   void resizeAuxColSpace(int minsize);
765 
766   /// resizes auxcolind vector to current number of rows and inits values to -1
767   void resizeAuxColIndSpace();
768   //@}
769 
770   /**@name Private static class data */
771   //@{
772   /// Gurobi environment pointer
773   static GRBenv *globalenv_;
774   /// whether OsiGrb has created the global environment (and thus should free it)
775   static bool globalenv_is_ours;
776   /// Number of instances using the global Gurobi environment
777   static unsigned int numInstances_;
778   //@}
779 
780   /**@name Private methods */
781   //@{
782 
783   /// Get LP Pointer for const methods
784   GRBmodel *getMutableLpPtr() const;
785 
786   /// The real work of a copy constructor (used by copy and assignment)
787   void gutsOfCopy(const OsiGrbSolverInterface &source);
788 
789   /// The real work of the constructor
790   void gutsOfConstructor();
791 
792   /// The real work of the destructor
793   void gutsOfDestructor();
794 
795   /// free cached column rim vectors
796   void freeCachedColRim();
797 
798   /// free cached row rim vectors
799   void freeCachedRowRim();
800 
801   /// free cached result vectors
802   void freeCachedResults();
803 
804   /// free cached matrices
805   void freeCachedMatrix();
806 
807   /// free all cached data (except specified entries, see getLpPtr())
808   void freeCachedData(int keepCached = KEEPCACHED_NONE);
809 
810   /// free all allocated memory
811   void freeAllMemory();
812 
813   /// converts a normal row into a ranged row by adding an auxiliary variable
814   void convertToRangedRow(int rowidx, double rhs, double range);
815 
816   /// converts a ranged row into a normal row by removing its auxiliary variable
817   void convertToNormalRow(int rowidx, char sense, double rhs);
818   //@}
819 
820   /**@name Private member data */
821   //@{
822   /// Gurobi environment used only by this class instance
823   mutable GRBenv *localenv_;
824 
825   /// Gurobi model represented by this class instance
826   mutable GRBmodel *lp_;
827 
828   /// Hotstart information
829   int *hotStartCStat_;
830   int hotStartCStatSize_;
831   int *hotStartRStat_;
832   int hotStartRStatSize_;
833   int hotStartMaxIteration_;
834 
835   /// OSI name discipline
836   int nameDisc_;
837 
838   /**@name Cached information derived from the Gurobi model */
839   //@{
840   /// Pointer to objective vector
841   mutable double *obj_;
842 
843   /// Pointer to dense vector of variable lower bounds
844   mutable double *collower_;
845 
846   /// Pointer to dense vector of variable lower bounds
847   mutable double *colupper_;
848 
849   /// Pointer to dense vector of row sense indicators
850   mutable char *rowsense_;
851 
852   /// Pointer to dense vector of row right-hand side values
853   mutable double *rhs_;
854 
855   /// Pointer to dense vector of slack upper bounds for range constraints (undefined for non-range rows)
856   mutable double *rowrange_;
857 
858   /// Pointer to dense vector of row lower bounds
859   mutable double *rowlower_;
860 
861   /// Pointer to dense vector of row upper bounds
862   mutable double *rowupper_;
863 
864   /// Pointer to primal solution vector
865   mutable double *colsol_;
866 
867   /// Pointer to dual solution vector
868   mutable double *rowsol_;
869 
870   /// Pointer to reduced cost vector
871   mutable double *redcost_;
872 
873   /// Pointer to row activity (slack) vector
874   mutable double *rowact_;
875 
876   /// Pointer to row-wise copy of problem matrix coefficients.
877   mutable CoinPackedMatrix *matrixByRow_;
878 
879   /// Pointer to row-wise copy of problem matrix coefficients.
880   mutable CoinPackedMatrix *matrixByCol_;
881   //@}
882 
883   /**@name Additional information needed for storing MIP problems and handling ranged rows */
884   //@{
885   /// Stores whether we currently see the problem as a MIP
886   mutable bool probtypemip_;
887 
888   /// Whether to pass a column solution to CPLEX before starting MIP solve (copymipstart)
889   bool domipstart;
890 
891   /// Size of allocated memory for coltype_, colmap_O2G, and (with offset auxcolspace) colmap_G2O.
892   int colspace_;
893 
894   /// Pointer to dense vector of variable types (continous, binary, integer)
895   char *coltype_;
896 
897   /// Number of auxiliary columns in Gurobi model for handling of ranged rows
898   int nauxcols;
899 
900   /// Size of allocated memory for colmap_G2O that exceeds colspace_
901   int auxcolspace;
902 
903   /// Maps variable indices from Osi to Gurobi
904   /// Is NULL if there are no ranged rows! (assume identity mapping then)
905   int *colmap_O2G;
906 
907   /// Maps variable indices from Gurobi to Osi
908   /// A negative value indicates that a variable is an auxiliary variable that was added to handle a ranged row
909   /// -colmap_G2O[i]-1 gives the index of the ranged row in this case
910   /// Is NULL if there are no ranged rows! (assume identity mapping then)
911   int *colmap_G2O;
912 
913   /// Current length of auxcolind array.
914   int auxcolindspace;
915 
916   /// Gives for each row the index of the corresponding auxiliary variable, if it is a ranged row.
917   /// Otherwise, gives -1.
918   /// Is NULL if there are no ranged rows! (assume -1 for each row then)
919   int *auxcolind;
920   //@}
921 };
922 
923 //#############################################################################
924 /** A function that tests the methods in the OsiGrbSolverInterface class. */
925 void OsiGrbSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir);
926 
927 #endif
928 
929 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
930 */
931