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 // license:  this file may be freely distributed under the terms of EPL
7 // comments: please scan this file for '???' and 'TODO' and read the comments
8 //-----------------------------------------------------------------------------
9 // Copyright (C) 2009 Humboldt University Berlin and others.
10 // All Rights Reserved.
11 
12 // $Id: OsiGrbSolverInterface.cpp 1846 2012-07-25 10:50:01Z stefan $
13 
14 #include <iostream>
15 #include <cassert>
16 #include <string>
17 #include <numeric>
18 
19 #include "CoinPragma.hpp"
20 #include "CoinError.hpp"
21 
22 #include "OsiGrbSolverInterface.hpp"
23 #include "OsiRowCut.hpp"
24 #include "OsiColCut.hpp"
25 #include "CoinPackedMatrix.hpp"
26 #include "CoinWarmStartBasis.hpp"
27 
28 extern "C" {
29 #include "gurobi_c.h"
30 }
31 
32 /* A utility definition which allows for easy suppression of unused variable warnings from GCC.
33 */
34 #ifndef UNUSED
35 # if defined(__GNUC__)
36 #   define UNUSED __attribute__((unused))
37 # else
38 #   define UNUSED
39 # endif
40 #endif
41 
42 //#define DEBUG 1
43 
44 #ifdef DEBUG
45 #define debugMessage printf("line %4d: ", __LINE__) & printf
46 #else
47 #define debugMessage if( false ) printf
48 #endif
49 
50 #define GUROBI_CALL(m, x) do \
51 { \
52   int _retcode; \
53   if( (_retcode = (x)) != 0 ) \
54   { \
55     char s[1001]; \
56     sprintf( s, "Error <%d> from GUROBI function call: ", _retcode ); \
57     if (OsiGrbSolverInterface::globalenv_) \
58       strncat(s, GRBgeterrormsg(OsiGrbSolverInterface::globalenv_), 1000); \
59     debugMessage("%s:%d: %s", __FILE__, __LINE__, s); \
60     throw CoinError( s, m, "OsiGrbSolverInterface", __FILE__, __LINE__ ); \
61   } \
62 } \
63 while( false )
64 
65 template <bool> struct CompileTimeAssert;
66 template<> struct CompileTimeAssert<true> {};
67 
68 #if GRB_VERSION_MAJOR < 4
69 #define GRB_METHOD_DUAL    GRB_LPMETHOD_DUAL
70 #define GRB_METHOD_PRIMAL  GRB_LPMETHOD_PRIMAL
71 #define GRB_INT_PAR_METHOD GRB_INT_PAR_LPMETHOD
72 #endif
73 
74 //#############################################################################
75 // A couple of helper functions
76 //#############################################################################
77 
freeCacheDouble(double * & ptr)78 inline void freeCacheDouble( double*& ptr )
79 {
80   if( ptr != NULL )
81     {
82       delete [] ptr;
83       ptr = NULL;
84     }
85 }
86 
freeCacheChar(char * & ptr)87 inline void freeCacheChar( char*& ptr )
88 {
89   if( ptr != NULL )
90     {
91       delete [] ptr;
92       ptr = NULL;
93     }
94 }
95 
freeCacheMatrix(CoinPackedMatrix * & ptr)96 inline void freeCacheMatrix( CoinPackedMatrix*& ptr )
97 {
98   if( ptr != NULL )
99     {
100       delete ptr;
101       ptr = NULL;
102     }
103 }
104 
105 void
switchToLP(void)106 OsiGrbSolverInterface::switchToLP( void )
107 {
108   debugMessage("OsiGrbSolverInterface::switchToLP()\n");
109 
110   if( probtypemip_ )
111   {
112      GRBmodel* lp = getMutableLpPtr();
113      int nc = getNumCols();
114 
115      char* contattr = new char[nc];
116      CoinFillN(contattr, nc, 'C');
117 
118      GUROBI_CALL( "switchToLP", GRBsetcharattrarray(lp, GRB_CHAR_ATTR_VTYPE, 0, nc, contattr) );
119 
120      delete[] contattr;
121 
122      probtypemip_ = false;
123   }
124 }
125 
126 void
switchToMIP(void)127 OsiGrbSolverInterface::switchToMIP( void )
128 {
129   debugMessage("OsiGrbSolverInterface::switchToMIP()\n");
130 
131   if( !probtypemip_ )
132   {
133      GRBmodel* lp = getMutableLpPtr();
134      int nc = getNumCols();
135 
136      assert(coltype_ != NULL);
137 
138      GUROBI_CALL( "switchToMIP", GRBsetcharattrarray(lp, GRB_CHAR_ATTR_VTYPE, 0, nc, coltype_) );
139 
140      probtypemip_ = true;
141   }
142 }
143 
144 void
resizeColSpace(int minsize)145 OsiGrbSolverInterface::resizeColSpace( int minsize )
146 {
147   debugMessage("OsiGrbSolverInterface::resizeColSpace()\n");
148 
149   if( minsize > colspace_ )
150   {
151      int newcolspace = 2*colspace_;
152      if( minsize > newcolspace )
153         newcolspace = minsize;
154      char* newcoltype = new char[newcolspace];
155 
156      if( coltype_ != NULL )
157      {
158        CoinDisjointCopyN( coltype_, colspace_, newcoltype );
159        delete[] coltype_;
160      }
161      coltype_ = newcoltype;
162 
163      if( colmap_O2G != NULL )
164      {
165        int* newcolmap_O2G = new int[newcolspace];
166        CoinDisjointCopyN( colmap_O2G, colspace_, newcolmap_O2G );
167        delete[] colmap_O2G;
168        colmap_O2G = newcolmap_O2G;
169      }
170 
171      if( colmap_G2O != NULL )
172      {
173        int* newcolmap_G2O = new int[newcolspace + auxcolspace];
174        CoinDisjointCopyN( colmap_G2O, colspace_ + auxcolspace, newcolmap_G2O );
175        delete[] colmap_G2O;
176        colmap_G2O = newcolmap_G2O;
177      }
178 
179      colspace_ = newcolspace;
180   }
181   assert(minsize == 0 || coltype_ != NULL);
182   assert(colspace_ >= minsize);
183 }
184 
185 void
freeColSpace()186 OsiGrbSolverInterface::freeColSpace()
187 {
188   debugMessage("OsiGrbSolverInterface::freeColSpace()\n");
189 
190    if( colspace_ > 0 )
191    {
192       delete[] coltype_;
193       delete[] colmap_O2G;
194       delete[] colmap_G2O;
195       coltype_ = NULL;
196       colmap_O2G = NULL;
197       colmap_G2O = NULL;
198       colspace_ = 0;
199       auxcolspace = 0;
200    }
201    assert(coltype_ == NULL);
202    assert(colmap_O2G == NULL);
203    assert(colmap_G2O == NULL);
204 }
205 
resizeAuxColSpace(int minsize)206 void OsiGrbSolverInterface::resizeAuxColSpace(int minsize)
207 {
208   debugMessage("OsiGrbSolverInterface::resizeAuxColSpace()\n");
209 
210   if( minsize > auxcolspace )
211   {
212      int newauxcolspace = 2*auxcolspace;
213      if( minsize > newauxcolspace )
214         newauxcolspace = minsize;
215 
216      if( colmap_G2O != NULL )
217      {
218        int* newcolmap_G2O = new int[colspace_ + newauxcolspace];
219        CoinDisjointCopyN( colmap_G2O, colspace_ + auxcolspace, newcolmap_G2O );
220        delete[] colmap_G2O;
221        colmap_G2O = newcolmap_G2O;
222      }
223 
224      auxcolspace = newauxcolspace;
225   }
226 }
227 
228 /// resizes auxcolind vector to current number of rows and inits values to -1
resizeAuxColIndSpace()229 void OsiGrbSolverInterface::resizeAuxColIndSpace()
230 {
231   debugMessage("OsiGrbSolverInterface::resizeAuxColIndSpace()\n");
232 
233   int numrows = getNumRows();
234   if( auxcolindspace < numrows )
235   {
236     int newspace = 2*auxcolindspace;
237     if( numrows > newspace )
238        newspace = numrows;
239 
240     int* newauxcolind = new int[newspace];
241 
242     if( auxcolindspace > 0 )
243       CoinDisjointCopyN( auxcolind, auxcolindspace, newauxcolind );
244     for( int i = auxcolindspace; i < newspace; ++i )
245       newauxcolind[i] = -1;
246 
247     delete[] auxcolind;
248     auxcolind = newauxcolind;
249     auxcolindspace = newspace;
250   }
251 }
252 
253 //#############################################################################
254 // Solve methods
255 //#############################################################################
256 
initialSolve()257 void OsiGrbSolverInterface::initialSolve()
258 {
259   debugMessage("OsiGrbSolverInterface::initialSolve()\n");
260   bool takeHint, gotHint;
261   OsiHintStrength strength;
262   int prevalgorithm = -1;
263 
264   switchToLP();
265 
266   GRBmodel* lp = getLpPtr( OsiGrbSolverInterface::FREECACHED_RESULTS );
267 
268   /* set whether dual or primal, if hint has been given */
269   gotHint = getHintParam(OsiDoDualInInitial,takeHint,strength);
270   assert(gotHint);
271   if (strength != OsiHintIgnore) {
272   	GUROBI_CALL( "initialSolve", GRBgetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, &prevalgorithm) );
273   	GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, takeHint ? GRB_METHOD_DUAL : GRB_METHOD_PRIMAL) );
274   }
275 
276 	/* set whether presolve or not */
277   int presolve = GRB_PRESOLVE_AUTO;
278   gotHint = getHintParam(OsiDoPresolveInInitial,takeHint,strength);
279   assert (gotHint);
280   if (strength != OsiHintIgnore)
281   	presolve = takeHint ? GRB_PRESOLVE_AUTO : GRB_PRESOLVE_OFF;
282 
283   GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, presolve) );
284 
285 	/* set whether output or not */
286   GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_OUTPUTFLAG, (messageHandler()->logLevel() > 0)) );
287 
288 	/* optimize */
289   GUROBI_CALL( "initialSolve", GRBoptimize(lp) );
290 
291   /* reoptimize without presolve if status unclear */
292   int stat;
293   GUROBI_CALL( "initialSolve", GRBgetintattr(lp, GRB_INT_ATTR_STATUS, &stat) );
294 
295   if (stat == GRB_INF_OR_UNBD && presolve != GRB_PRESOLVE_OFF) {
296     GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, GRB_PRESOLVE_OFF) );
297     GUROBI_CALL( "initialSolve", GRBoptimize(lp) );
298     GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, presolve) );
299   }
300 
301   /* reset method parameter, if changed */
302   if( prevalgorithm != -1 )
303   	GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, prevalgorithm) );
304 }
305 
306 //-----------------------------------------------------------------------------
resolve()307 void OsiGrbSolverInterface::resolve()
308 {
309   debugMessage("OsiGrbSolverInterface::resolve()\n");
310   bool takeHint, gotHint;
311   OsiHintStrength strength;
312   int prevalgorithm = -1;
313 
314   switchToLP();
315 
316   GRBmodel* lp = getLpPtr( OsiGrbSolverInterface::FREECACHED_RESULTS );
317 
318   /* set whether primal or dual */
319   gotHint = getHintParam(OsiDoDualInResolve,takeHint,strength);
320   assert (gotHint);
321   if (strength != OsiHintIgnore) {
322   	GUROBI_CALL( "resolve", GRBgetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, &prevalgorithm) );
323   	GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, takeHint ? GRB_METHOD_DUAL : GRB_METHOD_PRIMAL) );
324   }
325 
326 	/* set whether presolve or not */
327   int presolve = GRB_PRESOLVE_OFF;
328   gotHint = getHintParam(OsiDoPresolveInResolve,takeHint,strength);
329   assert (gotHint);
330   if (strength != OsiHintIgnore)
331   	presolve = takeHint ? GRB_PRESOLVE_AUTO : GRB_PRESOLVE_OFF;
332 
333   GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, presolve) );
334 
335 	/* set whether output or not */
336   GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_OUTPUTFLAG, (messageHandler()->logLevel() > 0)) );
337 
338 	/* optimize */
339   GUROBI_CALL( "resolve", GRBoptimize(lp) );
340 
341   /* reoptimize if status unclear */
342   int stat;
343   GUROBI_CALL( "resolve", GRBgetintattr(lp, GRB_INT_ATTR_STATUS, &stat) );
344 
345   if (stat == GRB_INF_OR_UNBD && presolve != GRB_PRESOLVE_OFF) {
346     GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, GRB_PRESOLVE_OFF) );
347     GUROBI_CALL( "resolve", GRBoptimize(lp) );
348     GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_PRESOLVE, presolve) );
349   }
350 
351   /* reset method parameter, if changed */
352   if( prevalgorithm != -1 )
353   	GUROBI_CALL( "initialSolve", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_METHOD, prevalgorithm) );
354 }
355 
356 //-----------------------------------------------------------------------------
branchAndBound()357 void OsiGrbSolverInterface::branchAndBound()
358 {
359   debugMessage("OsiGrbSolverInterface::branchAndBound()\n");
360 
361   switchToMIP();
362 
363   if( colsol_ != NULL && domipstart )
364   {
365     int* discridx = new int[getNumIntegers()];
366     double* discrval  = new double[getNumIntegers()];
367 
368     int j = 0;
369     for( int i = 0; i < getNumCols() && j < getNumIntegers(); ++i )
370     {
371        if( !isInteger(i) && !isBinary(i) )
372           continue;
373        discridx[j] = i;
374        discrval[j] = colsol_[i];
375        ++j;
376     }
377     assert(j == getNumIntegers());
378 
379     GUROBI_CALL( "branchAndBound", GRBsetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_START, getNumIntegers(), discridx, discrval) );
380 
381     delete[] discridx;
382     delete[] discrval;
383   }
384 
385   GRBmodel* lp = getLpPtr( OsiGrbSolverInterface::FREECACHED_RESULTS );
386 
387   GUROBI_CALL( "branchAndBound", GRBsetintparam(GRBgetenv(lp), GRB_INT_PAR_OUTPUTFLAG, (messageHandler()->logLevel() > 0)) );
388 
389   GUROBI_CALL( "branchAndBound", GRBoptimize( lp ) );
390 }
391 
392 //#############################################################################
393 // Parameter related methods
394 //#############################################################################
395 
396 bool
setIntParam(OsiIntParam key,int value)397 OsiGrbSolverInterface::setIntParam(OsiIntParam key, int value)
398 {
399   debugMessage("OsiGrbSolverInterface::setIntParam(%d, %d)\n", key, value);
400 
401   switch (key)
402   {
403     case OsiMaxNumIteration:
404       if( GRBsetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_ITERATIONLIMIT, (double)value) != 0 )
405       {
406         *messageHandler() << "Warning: Setting GUROBI iteration limit to" << value << "failed." << CoinMessageEol;
407         if (OsiGrbSolverInterface::globalenv_)
408           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
409         return false;
410       }
411       return true;
412 
413     case OsiMaxNumIterationHotStart:
414     	if( value >= 0 )
415     	{
416     		hotStartMaxIteration_ = value;
417     		return true;
418     	}
419     	return false;
420 
421     case OsiNameDiscipline:
422       if( value < 0 || value > 3 )
423         return false;
424       nameDisc_ = value;
425       return true;
426 
427     case OsiLastIntParam:
428     default:
429       return false;
430   }
431 }
432 
433 //-----------------------------------------------------------------------------
434 
435 bool
setDblParam(OsiDblParam key,double value)436 OsiGrbSolverInterface::setDblParam(OsiDblParam key, double value)
437 {
438   debugMessage("OsiGrbSolverInterface::setDblParam(%d, %g)\n", key, value);
439 
440   switch (key)
441   {
442 // Gurobi does not have primal or dual objective limits
443 //  	case OsiDualObjectiveLimit:
444 //  		break;
445 //  	case OsiPrimalObjectiveLimit:
446 //  	  break;
447   	case OsiDualTolerance:
448   	  if( GRBsetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_OPTIMALITYTOL, value) != 0 )
449       {
450         *messageHandler() << "Warning: Setting GUROBI dual (i.e., optimality) tolerance to" << value << "failed." << CoinMessageEol;
451         if (OsiGrbSolverInterface::globalenv_)
452           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
453         return false;
454       }
455   	  return true;
456   	case OsiPrimalTolerance:
457   	  if( GRBsetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_FEASIBILITYTOL, value) != 0 )
458       {
459         *messageHandler() << "Warning: Setting GUROBI primal (i.e., feasiblity) tolerance to" << value << "failed." << CoinMessageEol;
460         if (OsiGrbSolverInterface::globalenv_)
461           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
462         return false;
463       }
464   	  return true;
465   	case OsiObjOffset:
466   		return OsiSolverInterface::setDblParam(key,value);
467   	case OsiLastDblParam:
468   	default:
469   		return false;
470   }
471 }
472 
473 //-----------------------------------------------------------------------------
474 
475 bool
setStrParam(OsiStrParam key,const std::string & value)476 OsiGrbSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
477 {
478   debugMessage("OsiGrbSolverInterface::setStrParam(%d, %s)\n", key, value.c_str());
479 
480   switch (key) {
481     case OsiProbName:
482       GUROBI_CALL( "setStrParam", GRBsetstrattr(getLpPtr(), GRB_STR_ATTR_MODELNAME, const_cast<char*>(value.c_str())) );
483       return true;
484 
485     case OsiSolverName:
486     case OsiLastStrParam:
487     default:
488       return false;
489   }
490 }
491 
492 // Set a hint parameter
493 bool
setHintParam(OsiHintParam key,bool yesNo,OsiHintStrength strength,void * otherInfo)494 OsiGrbSolverInterface::setHintParam(OsiHintParam key, bool yesNo, OsiHintStrength strength, void* otherInfo)
495 {
496   debugMessage("OsiGrbSolverInterface::setHintParam(%d, %d)\n", key, yesNo);
497 
498   if( key == OsiDoScale )
499   {
500     GUROBI_CALL( "setHintParam", GRBsetintparam(GRBgetenv(getMutableLpPtr()), GRB_INT_PAR_SCALEFLAG, yesNo) );
501     OsiSolverInterface::setHintParam(key, yesNo, strength, otherInfo);
502     return true;
503   }
504 
505   return OsiSolverInterface::setHintParam(key, yesNo, strength, otherInfo);
506 }
507 
508 //-----------------------------------------------------------------------------
509 
510 bool
getIntParam(OsiIntParam key,int & value) const511 OsiGrbSolverInterface::getIntParam(OsiIntParam key, int& value) const
512 {
513   debugMessage("OsiGrbSolverInterface::getIntParam(%d)\n", key);
514 
515   switch (key)
516   {
517     case OsiMaxNumIteration:
518     	double dblval;
519       GUROBI_CALL( "getIntParam", GRBupdatemodel(getMutableLpPtr()) );
520       GUROBI_CALL( "getIntParam", GRBgetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_ITERATIONLIMIT, &dblval) );
521     	value = (int) dblval;
522       return true;
523 
524     case OsiMaxNumIterationHotStart:
525       value = hotStartMaxIteration_;
526       return true;
527 
528     case OsiNameDiscipline:
529       value = nameDisc_;
530       return true;
531 
532     case OsiLastIntParam:
533     default:
534       return false;
535   }
536 }
537 
538 //-----------------------------------------------------------------------------
539 
540 bool
getDblParam(OsiDblParam key,double & value) const541 OsiGrbSolverInterface::getDblParam(OsiDblParam key, double& value) const
542 {
543   debugMessage("OsiGrbSolverInterface::getDblParam(%d)\n", key);
544 
545   GUROBI_CALL( "getDblParam", GRBupdatemodel(getMutableLpPtr()) );
546 
547   switch (key)
548   {
549 // Gurobi does not have primal or dual objective limits
550 //    case OsiDualObjectiveLimit:
551 //      break;
552 //   	case OsiPrimalObjectiveLimit:
553 //   	  break;
554   	case OsiDualTolerance:
555   	  GUROBI_CALL( "getDblParam", GRBgetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_OPTIMALITYTOL, &value) );
556   		return true;
557   	case OsiPrimalTolerance:
558   	  GUROBI_CALL( "getDblParam", GRBgetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_FEASIBILITYTOL, &value) );
559   	  return true;
560     case OsiObjOffset:
561       return OsiSolverInterface::getDblParam(key, value);
562     case OsiLastDblParam:
563     default:
564       return false;
565   }
566 }
567 
568 //-----------------------------------------------------------------------------
569 
570 bool
getStrParam(OsiStrParam key,std::string & value) const571 OsiGrbSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
572 {
573   debugMessage("OsiGrbSolverInterface::getStrParam(%d)\n", key);
574 
575   switch (key) {
576   	case OsiProbName:
577   	{
578   	  char* name = NULL;
579       GUROBI_CALL( "getStrParam", GRBgetstrattr(getMutableLpPtr(), GRB_STR_ATTR_MODELNAME, &name) );
580       assert(name != NULL);
581       value = name;
582   		return true;
583   	}
584 
585   	case OsiSolverName:
586   		value = "gurobi";
587   		return true;
588 
589   	case OsiLastStrParam:
590   	default:
591   		return false;
592   }
593 }
594 
595 // Get a hint parameter
596 bool
getHintParam(OsiHintParam key,bool & yesNo,OsiHintStrength & strength,void * & otherInformation) const597 OsiGrbSolverInterface::getHintParam(OsiHintParam key, bool& yesNo, OsiHintStrength& strength, void*& otherInformation) const
598 {
599   debugMessage("OsiGrbSolverInterface::getHintParam[1](%d)\n", key);
600   if( key == OsiDoScale )
601   {
602     OsiSolverInterface::getHintParam(key, yesNo, strength, otherInformation);
603     GUROBI_CALL( "getHintParam", GRBupdatemodel(getMutableLpPtr()) );
604     int value;
605     GUROBI_CALL( "getHintParam", GRBgetintparam(GRBgetenv(getMutableLpPtr()), GRB_INT_PAR_SCALEFLAG, &value) );
606     yesNo = value;
607     return true;
608   }
609 
610   return OsiSolverInterface::getHintParam(key, yesNo, strength, otherInformation);
611 }
612 
613 // Get a hint parameter
614 bool
getHintParam(OsiHintParam key,bool & yesNo,OsiHintStrength & strength) const615 OsiGrbSolverInterface::getHintParam(OsiHintParam key, bool& yesNo, OsiHintStrength& strength) const
616 {
617   debugMessage("OsiGrbSolverInterface::getHintParam[2](%d)\n", key);
618   if( key == OsiDoScale )
619   {
620     OsiSolverInterface::getHintParam(key, yesNo, strength);
621     GUROBI_CALL( "getHintParam", GRBupdatemodel(getMutableLpPtr()) );
622     int value;
623     GUROBI_CALL( "getHintParam", GRBgetintparam(GRBgetenv(getMutableLpPtr()), GRB_INT_PAR_SCALEFLAG, &value) );
624     yesNo = value;
625     return true;
626   }
627 
628   return OsiSolverInterface::getHintParam(key, yesNo, strength);
629 }
630 
631 // Get a hint parameter
632 bool
getHintParam(OsiHintParam key,bool & yesNo) const633 OsiGrbSolverInterface::getHintParam(OsiHintParam key, bool& yesNo) const
634 {
635   debugMessage("OsiGrbSolverInterface::getHintParam[3](%d)\n", key);
636   if( key == OsiDoScale )
637   {
638     OsiSolverInterface::getHintParam(key, yesNo);
639     GUROBI_CALL( "getHintParam", GRBupdatemodel(getMutableLpPtr()) );
640     int value;
641     GUROBI_CALL( "getHintParam", GRBgetintparam(GRBgetenv(getMutableLpPtr()), GRB_INT_PAR_SCALEFLAG, &value) );
642     yesNo = value;
643     return true;
644   }
645 
646   return OsiSolverInterface::getHintParam(key, yesNo);
647 }
648 
649 //#############################################################################
650 // Methods returning info on how the solution process terminated
651 //#############################################################################
652 
isAbandoned() const653 bool OsiGrbSolverInterface::isAbandoned() const
654 {
655   debugMessage("OsiGrbSolverInterface::isAbandoned()\n");
656 
657   GUROBI_CALL( "isAbandoned", GRBupdatemodel(getMutableLpPtr()) );
658 
659   int stat;
660   GUROBI_CALL( "isAbandoned", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &stat) );
661 
662 	return (
663 			stat == GRB_LOADED ||
664 			stat == GRB_NUMERIC ||
665 			stat == GRB_INTERRUPTED
666 		);
667 }
668 
isProvenOptimal() const669 bool OsiGrbSolverInterface::isProvenOptimal() const
670 {
671   debugMessage("OsiGrbSolverInterface::isProvenOptimal()\n");
672 
673   GUROBI_CALL( "isProvenOptimal", GRBupdatemodel(getMutableLpPtr()) );
674 
675   int stat;
676   GUROBI_CALL( "isProvenOptimal", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &stat) );
677 
678 	return (stat == GRB_OPTIMAL);
679 }
680 
isProvenPrimalInfeasible() const681 bool OsiGrbSolverInterface::isProvenPrimalInfeasible() const
682 {
683   debugMessage("OsiGrbSolverInterface::isProvenPrimalInfeasible()\n");
684 
685   GUROBI_CALL( "isProvenPrimalInfeasible", GRBupdatemodel(getMutableLpPtr()) );
686 
687   int stat;
688   GUROBI_CALL( "isProvenPrimalInfeasible", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &stat) );
689 
690 	return (stat == GRB_INFEASIBLE);
691 }
692 
isProvenDualInfeasible() const693 bool OsiGrbSolverInterface::isProvenDualInfeasible() const
694 {
695   debugMessage("OsiGrbSolverInterface::isProvenDualInfeasible()\n");
696 
697   GUROBI_CALL( "isProvenDualInfeasible", GRBupdatemodel(getMutableLpPtr()) );
698 
699   int stat;
700   GUROBI_CALL( "isProvenDualInfeasible", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &stat) );
701 
702 	return (stat == GRB_UNBOUNDED);
703 }
704 
isPrimalObjectiveLimitReached() const705 bool OsiGrbSolverInterface::isPrimalObjectiveLimitReached() const
706 {
707   debugMessage("OsiGrbSolverInterface::isPrimalObjectiveLimitReached()\n");
708 
709   return false;
710 }
711 
isDualObjectiveLimitReached() const712 bool OsiGrbSolverInterface::isDualObjectiveLimitReached() const
713 {
714   debugMessage("OsiGrbSolverInterface::isDualObjectiveLimitReached()\n");
715 
716   return false;
717 }
718 
isIterationLimitReached() const719 bool OsiGrbSolverInterface::isIterationLimitReached() const
720 {
721   debugMessage("OsiGrbSolverInterface::isIterationLimitReached()\n");
722 
723   GUROBI_CALL( "isIterationLimitReached", GRBupdatemodel(getMutableLpPtr()) );
724 
725   int stat;
726   GUROBI_CALL( "isIterationLimitReached", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &stat) );
727 
728 	return (stat == GRB_ITERATION_LIMIT);
729 }
730 
731 //#############################################################################
732 // WarmStart related methods
733 //#############################################################################
734 
getEmptyWarmStart() const735 CoinWarmStart* OsiGrbSolverInterface::getEmptyWarmStart () const
736 { return (dynamic_cast<CoinWarmStart *>(new CoinWarmStartBasis())) ; }
737 
738 // below we assume that getBasisStatus uses the same values as the warm start enum, i.e. 0: free, 1: basic, 2: upper, 3: lower
739 static CompileTimeAssert<CoinWarmStartBasis::isFree       == 0> UNUSED change_In_Enum_CoinWarmStartBasis_Status_free_breaks_this_function;
740 static CompileTimeAssert<CoinWarmStartBasis::basic        == 1> UNUSED change_In_Enum_CoinWarmStartBasis_Status_basic_breaks_this_function;
741 static CompileTimeAssert<CoinWarmStartBasis::atUpperBound == 2> UNUSED change_In_Enum_CoinWarmStartBasis_Status_upper_breaks_this_function;
742 static CompileTimeAssert<CoinWarmStartBasis::atLowerBound == 3> UNUSED change_In_Enum_CoinWarmStartBasis_Status_lower_breaks_this_function;
743 
getWarmStart() const744 CoinWarmStart* OsiGrbSolverInterface::getWarmStart() const
745 {
746   debugMessage("OsiGrbSolverInterface::getWarmStart()\n");
747 
748   assert(!probtypemip_);
749 
750   if( !basisIsAvailable() )
751     return NULL;
752 
753   CoinWarmStartBasis* ws = NULL;
754   int numcols = getNumCols();
755   int numrows = getNumRows();
756   int *cstat = new int[numcols];
757   int *rstat = new int[numrows];
758   int i;
759 
760 #if 1
761   getBasisStatus(cstat, rstat);
762 
763   ws = new CoinWarmStartBasis;
764   ws->setSize( numcols, numrows );
765 
766   for( i = 0; i < numrows; ++i )
767     ws->setArtifStatus( i, CoinWarmStartBasis::Status(rstat[i]) );
768   for( i = 0; i < numcols; ++i )
769     ws->setStructStatus( i, CoinWarmStartBasis::Status(cstat[i]) );
770 
771 #else
772   GUROBI_CALL( "getWarmStart", GRBupdatemodel(getMutableLpPtr()) );
773 
774   GUROBI_CALL( "getWarmStart", GRBgetintattrarray(getMutableLpPtr(), GRB_INT_ATTR_VBASIS, 0, numcols, cstat) );
775   GUROBI_CALL( "getWarmStart", GRBgetintattrarray(getMutableLpPtr(), GRB_INT_ATTR_CBASIS, 0, numrows, rstat) );
776 
777 	ws = new CoinWarmStartBasis;
778 	ws->setSize( numcols, numrows );
779 
780 	char sense;
781 	for( i = 0; i < numrows; ++i )
782 	{
783 	  switch( rstat[i] )
784 	  {
785 	  	case GRB_BASIC:
786 	  		ws->setArtifStatus( i, CoinWarmStartBasis::basic );
787 	  		break;
788 	  	case GRB_NONBASIC_LOWER:
789 	  	case GRB_NONBASIC_UPPER:
790 	  	  GUROBI_CALL( "getWarmStart", GRBgetcharattrelement(getMutableLpPtr(), GRB_CHAR_ATTR_SENSE, i, &sense) );
791 	  		ws->setArtifStatus( i, (sense == '>' ? CoinWarmStartBasis::atUpperBound : CoinWarmStartBasis::atLowerBound) );
792 	  		break;
793 	  	default:  // unknown row status
794 	  		delete ws;
795 	  		delete[] rstat;
796 	  		delete[] cstat;
797 	  		return NULL;
798 	  }
799 	}
800 
801 	for( i = 0; i < numcols; ++i )
802 	{
803 		switch( cstat[i] )
804 		{
805 			case GRB_BASIC:
806 				ws->setStructStatus( i, CoinWarmStartBasis::basic );
807 				break;
808 			case GRB_NONBASIC_LOWER:
809 				ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound );
810 				break;
811 			case GRB_NONBASIC_UPPER:
812 				ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound );
813 				break;
814 			case GRB_SUPERBASIC:
815 				ws->setStructStatus( i, CoinWarmStartBasis::isFree );
816 				break;
817 			default:  // unknown column status
818 				delete[] rstat;
819 				delete[] cstat;
820 				delete ws;
821 				return NULL;
822 		}
823 	}
824 #endif
825 
826 	delete[] cstat;
827   delete[] rstat;
828 
829   return ws;
830 }
831 
832 //-----------------------------------------------------------------------------
833 
setWarmStart(const CoinWarmStart * warmstart)834 bool OsiGrbSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
835 {
836   debugMessage("OsiGrbSolverInterface::setWarmStart(%p)\n", (void*)warmstart);
837 
838   const CoinWarmStartBasis* ws = dynamic_cast<const CoinWarmStartBasis*>(warmstart);
839   int numcols, numrows, i, oi;
840   int *stat;
841 
842   if( !ws )
843     return false;
844 
845   numcols = ws->getNumStructural();
846   numrows = ws->getNumArtificial();
847 
848   if( numcols != getNumCols() || numrows != getNumRows() )
849     return false;
850 
851   switchToLP();
852 
853   stat = new int[numcols + nauxcols > numrows ? numcols + nauxcols : numrows];
854   for( i = 0; i < numrows; ++i )
855   {
856   	switch( ws->getArtifStatus( i ) )
857   	{
858   		case CoinWarmStartBasis::basic:
859   			stat[i] = GRB_BASIC;
860   			break;
861   		case CoinWarmStartBasis::atLowerBound:
862   		case CoinWarmStartBasis::atUpperBound:
863   			stat[i] = GRB_NONBASIC_LOWER;
864   			break;
865       case CoinWarmStartBasis::isFree:
866          stat[i] = GRB_SUPERBASIC;
867          break;
868   		default:  // unknown row status
869   			delete[] stat;
870   			return false;
871   	}
872   }
873 
874   GUROBI_CALL( "setWarmStart", GRBsetintattrarray(getLpPtr(OsiGrbSolverInterface::FREECACHED_RESULTS), GRB_INT_ATTR_CBASIS, 0, numrows, stat) );
875 
876   for( i = 0; i < numcols + nauxcols; ++i )
877   {
878     oi = colmap_G2O ? colmap_G2O[i] : i;
879     if( oi >= 0 )
880     { /* normal variable */
881       switch( ws->getStructStatus( oi ) )
882       {
883         case CoinWarmStartBasis::basic:
884           stat[i] = GRB_BASIC;
885           break;
886         case CoinWarmStartBasis::atLowerBound:
887           stat[i] = GRB_NONBASIC_LOWER;
888           break;
889         case CoinWarmStartBasis::atUpperBound:
890           stat[i] = GRB_NONBASIC_UPPER;
891           break;
892         case CoinWarmStartBasis::isFree:
893           stat[i] = GRB_SUPERBASIC;
894           break;
895         default:  // unknown col status
896           delete[] stat;
897           return false;
898       }
899     }
900     else
901     { /* auxiliary variable, derive status from status of corresponding ranged row */
902       switch( ws->getArtifStatus( -oi-1 ) )
903       {
904         case CoinWarmStartBasis::basic:
905           stat[i] = GRB_BASIC;
906           break;
907         case CoinWarmStartBasis::atLowerBound:
908           stat[i] = GRB_NONBASIC_LOWER;
909           break;
910         case CoinWarmStartBasis::atUpperBound:
911           stat[i] = GRB_NONBASIC_UPPER;
912           break;
913         case CoinWarmStartBasis::isFree:
914            stat[i] = GRB_SUPERBASIC;
915            break;
916         default:  // unknown col status
917           delete[] stat;
918           return false;
919       }
920     }
921   }
922 
923   GUROBI_CALL( "setWarmStart", GRBsetintattrarray(getLpPtr(OsiGrbSolverInterface::FREECACHED_RESULTS), GRB_INT_ATTR_VBASIS, 0, numcols+nauxcols, stat) );
924 
925   delete[] stat;
926   return true;
927 }
928 
929 //#############################################################################
930 // Hotstart related methods (primarily used in strong branching)
931 //#############################################################################
932 
markHotStart()933 void OsiGrbSolverInterface::markHotStart()
934 {
935   debugMessage("OsiGrbSolverInterface::markHotStart()\n");
936 
937   int numcols, numrows;
938 
939   assert(!probtypemip_);
940 
941   numcols = getNumCols() + nauxcols;
942   numrows = getNumRows();
943   if( numcols > hotStartCStatSize_ )
944   {
945   	delete[] hotStartCStat_;
946   	hotStartCStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numcols + nauxcols ) ); // get some extra space for future hot starts
947   	hotStartCStat_ = new int[hotStartCStatSize_];
948   }
949   if( numrows > hotStartRStatSize_ )
950   {
951   	delete[] hotStartRStat_;
952   	hotStartRStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numrows ) ); // get some extra space for future hot starts
953   	hotStartRStat_ = new int[hotStartRStatSize_];
954   }
955 
956   GUROBI_CALL( "markHotStart", GRBupdatemodel(getMutableLpPtr()) );
957 
958   GUROBI_CALL( "markHotStart", GRBgetintattrarray(getMutableLpPtr(), GRB_INT_ATTR_VBASIS, 0, numcols + nauxcols, hotStartCStat_) );
959   GUROBI_CALL( "markHotStart", GRBgetintattrarray(getMutableLpPtr(), GRB_INT_ATTR_CBASIS, 0, numrows, hotStartRStat_) );
960 }
961 
solveFromHotStart()962 void OsiGrbSolverInterface::solveFromHotStart()
963 {
964   debugMessage("OsiGrbSolverInterface::solveFromHotStart()\n");
965 
966   double maxiter;
967 
968   switchToLP();
969 
970   assert( getNumCols() <= hotStartCStatSize_ );
971   assert( getNumRows() <= hotStartRStatSize_ );
972 
973   GUROBI_CALL( "solveFromHotStart", GRBupdatemodel(getMutableLpPtr()) );
974 
975   GUROBI_CALL( "solveFromHotStart", GRBsetintattrarray(getLpPtr(OsiGrbSolverInterface::FREECACHED_RESULTS), GRB_INT_ATTR_CBASIS, 0, getNumRows(), hotStartRStat_ ) );
976   GUROBI_CALL( "solveFromHotStart", GRBsetintattrarray(getLpPtr(OsiGrbSolverInterface::FREECACHED_RESULTS), GRB_INT_ATTR_VBASIS, 0, getNumCols() + nauxcols, hotStartCStat_ ) );
977 
978   GUROBI_CALL( "solveFromHotStart", GRBgetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_ITERATIONLIMIT, &maxiter) );
979   GUROBI_CALL( "solveFromHotStart", GRBsetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_ITERATIONLIMIT, (double)hotStartMaxIteration_) );
980 
981   resolve();
982 
983   GUROBI_CALL( "solveFromHotStart", GRBsetdblparam(GRBgetenv(getMutableLpPtr()), GRB_DBL_PAR_ITERATIONLIMIT, maxiter) );
984 }
985 
unmarkHotStart()986 void OsiGrbSolverInterface::unmarkHotStart()
987 {
988   debugMessage("OsiGrbSolverInterface::unmarkHotStart()\n");
989 
990   // ??? be lazy with deallocating memory and do nothing here, deallocate memory in the destructor
991 }
992 
993 //#############################################################################
994 // Problem information methods (original data)
995 //#############################################################################
996 
997 //------------------------------------------------------------------
998 // Get number of rows, columns, elements, ...
999 //------------------------------------------------------------------
getNumCols() const1000 int OsiGrbSolverInterface::getNumCols() const
1001 {
1002   debugMessage("OsiGrbSolverInterface::getNumCols()\n");
1003 
1004   int numcols;
1005 
1006   GUROBI_CALL( "getNumCols", GRBupdatemodel(getMutableLpPtr()) );
1007 
1008   GUROBI_CALL( "getNumCols", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_NUMVARS, &numcols) );
1009 
1010   numcols -= nauxcols;
1011 
1012   return numcols;
1013 }
1014 
getNumRows() const1015 int OsiGrbSolverInterface::getNumRows() const
1016 {
1017   debugMessage("OsiGrbSolverInterface::getNumRows()\n");
1018 
1019   int numrows;
1020 
1021   GUROBI_CALL( "getNumRows", GRBupdatemodel(getMutableLpPtr()) );
1022 
1023   GUROBI_CALL( "getNumRows", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_NUMCONSTRS, &numrows) );
1024 
1025   return numrows;
1026 }
1027 
getNumElements() const1028 int OsiGrbSolverInterface::getNumElements() const
1029 {
1030   debugMessage("OsiGrbSolverInterface::getNumElements()\n");
1031 
1032   int numnz;
1033 
1034   GUROBI_CALL( "getNumElements", GRBupdatemodel(getMutableLpPtr()) );
1035 
1036   GUROBI_CALL( "getNumElements", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_NUMNZS, &numnz) );
1037 
1038   /* each auxiliary column contributes one nonzero element to exactly one row */
1039   numnz -= nauxcols;
1040 
1041   return numnz;
1042 }
1043 
1044 //------------------------------------------------------------------
1045 // Get pointer to rim vectors
1046 //------------------------------------------------------------------
1047 
getColLower() const1048 const double * OsiGrbSolverInterface::getColLower() const
1049 {
1050   debugMessage("OsiGrbSolverInterface::getColLower()\n");
1051 
1052   if( collower_ == NULL )
1053   {
1054   	int ncols = getNumCols();
1055   	if( ncols > 0 )
1056   	{
1057   		collower_ = new double[ncols];
1058   		GUROBI_CALL( "getColLower", GRBupdatemodel(getMutableLpPtr()) );
1059 
1060   		if( nauxcols )
1061         GUROBI_CALL( "getColLower", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_LB, ncols, colmap_O2G, collower_) );
1062   		else
1063   		  GUROBI_CALL( "getColLower", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_LB, 0, ncols, collower_) );
1064   	}
1065   }
1066 
1067   return collower_;
1068 }
1069 
1070 //------------------------------------------------------------------
getColUpper() const1071 const double * OsiGrbSolverInterface::getColUpper() const
1072 {
1073   debugMessage("OsiGrbSolverInterface::getColUpper()\n");
1074 
1075   if( colupper_ == NULL )
1076   {
1077   	int ncols = getNumCols();
1078   	if( ncols > 0 )
1079   	{
1080   		colupper_ = new double[ncols];
1081   		GUROBI_CALL( "getColUpper", GRBupdatemodel(getMutableLpPtr()) );
1082 
1083   		if( nauxcols )
1084         GUROBI_CALL( "getColUpper", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_UB, ncols, colmap_O2G, colupper_) );
1085   		else
1086   		  GUROBI_CALL( "getColUpper", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_UB, 0, ncols, colupper_) );
1087   	}
1088   }
1089 
1090   return colupper_;
1091 }
1092 
1093 //------------------------------------------------------------------
getRowSense() const1094 const char * OsiGrbSolverInterface::getRowSense() const
1095 {
1096   debugMessage("OsiGrbSolverInterface::getRowSense()\n");
1097 
1098   if ( rowsense_==NULL )
1099   {
1100   	int nrows = getNumRows();
1101   	if( nrows > 0 )
1102   	{
1103   		rowsense_ = new char[nrows];
1104   		GUROBI_CALL( "getRowSense", GRBupdatemodel(getMutableLpPtr()) );
1105 
1106   		GUROBI_CALL( "getRowSense", GRBgetcharattrarray(getMutableLpPtr(), GRB_CHAR_ATTR_SENSE, 0, nrows, rowsense_) );
1107 
1108   	  for (int i = 0; i < nrows; ++i)
1109   	  {
1110   	    if( auxcolind && auxcolind[i] >= 0 )
1111   	    {
1112   	      assert(rowsense_[i] == GRB_EQUAL);
1113           rowsense_[i] = 'R';
1114           continue;
1115   	    }
1116   	  	switch (rowsense_[i])
1117   	  	{
1118   	  		case GRB_LESS_EQUAL:
1119   	  			rowsense_[i] = 'L';
1120   	  			break;
1121   	  		case GRB_GREATER_EQUAL:
1122   	  			rowsense_[i] = 'G';
1123   	  			break;
1124   	  		case GRB_EQUAL:
1125   	  			rowsense_[i] = 'E';
1126   	  			break;
1127   	  	}
1128   	  }
1129   	}
1130   }
1131 
1132   return rowsense_;
1133 }
1134 
1135 //------------------------------------------------------------------
getRightHandSide() const1136 const double * OsiGrbSolverInterface::getRightHandSide() const
1137 {
1138   debugMessage("OsiGrbSolverInterface::getRightHandSide()\n");
1139 
1140   if ( rhs_ == NULL )
1141   {
1142   	int nrows = getNumRows();
1143   	if( nrows > 0 )
1144   	{
1145   		rhs_ = new double[nrows];
1146   		GUROBI_CALL( "getRightHandSide", GRBupdatemodel(getMutableLpPtr()) );
1147 
1148   		GUROBI_CALL( "getRightHandSide", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_RHS, 0, nrows, rhs_) );
1149 
1150   		/* for ranged rows, we give the rhs of the aux. variable used to represent the range of this row as row rhs */
1151   		if( nauxcols )
1152   		  for( int i = 0; i < nrows; ++i )
1153   		    if( auxcolind[i] >= 0 )
1154   		      GUROBI_CALL( "getRightHandSide", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_UB, auxcolind[i], &rhs_[i]) );
1155   	}
1156   }
1157 
1158   return rhs_;
1159 }
1160 
1161 //------------------------------------------------------------------
getRowRange() const1162 const double * OsiGrbSolverInterface::getRowRange() const
1163 {
1164   debugMessage("OsiGrbSolverInterface::getRowRange()\n");
1165 
1166   if ( rowrange_==NULL )
1167   {
1168   	int nrows = getNumRows();
1169   	if (nrows > 0)
1170     	rowrange_ = CoinCopyOfArrayOrZero((double*)NULL, nrows);
1171 
1172     if( nauxcols )
1173     {
1174       double auxlb, auxub;
1175       for( int i = 0; i < nrows; ++i )
1176         if( auxcolind[i] >= 0 )
1177         {
1178           GUROBI_CALL( "getRowRange", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_LB, auxcolind[i], &auxlb) );
1179           GUROBI_CALL( "getRowRange", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_UB, auxcolind[i], &auxub) );
1180           rowrange_[i] = auxub - auxlb;
1181         }
1182     }
1183   }
1184 
1185   return rowrange_;
1186 }
1187 
1188 //------------------------------------------------------------------
getRowLower() const1189 const double * OsiGrbSolverInterface::getRowLower() const
1190 {
1191   debugMessage("OsiGrbSolverInterface::getRowLower()\n");
1192 
1193   if ( rowlower_ == NULL )
1194   {
1195   	int nrows = getNumRows();
1196   	if ( nrows > 0 )
1197   	{
1198     	const char* rowsense = getRowSense();
1199 
1200   		rowlower_ = new double[nrows];
1201 
1202       double rhs;
1203   		double dum1;
1204   		for ( int i = 0; i < nrows; ++i )
1205   		{
1206   		  if( auxcolind && auxcolind[i] >= 0 )
1207   		  {
1208   		    assert(rowsense[i] == 'R');
1209           GUROBI_CALL( "getRowLower", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_LB, auxcolind[i], &rowlower_[i]) );
1210   		  }
1211   		  else
1212   		  {
1213           GUROBI_CALL( "getRowLower", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_RHS, i, &rhs) );
1214           convertSenseToBound( rowsense[i], rhs, 0.0, rowlower_[i], dum1 );
1215   		  }
1216   		}
1217   	}
1218   }
1219 
1220   return rowlower_;
1221 }
1222 
1223 //------------------------------------------------------------------
getRowUpper() const1224 const double * OsiGrbSolverInterface::getRowUpper() const
1225 {
1226   debugMessage("OsiGrbSolverInterface::getRowUpper()\n");
1227 
1228   if ( rowupper_ == NULL )
1229   {
1230   	int nrows = getNumRows();
1231   	if ( nrows > 0 )
1232   	{
1233   	  const char* rowsense = getRowSense();
1234 
1235       rowupper_ = new double[nrows];
1236 
1237       double rhs;
1238       double dum1;
1239       for ( int i = 0; i < nrows; ++i )
1240       {
1241         if( auxcolind && auxcolind[i] >= 0 )
1242         {
1243           assert(rowsense[i] == 'R');
1244           GUROBI_CALL( "getRowUpper", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_UB, auxcolind[i], &rowupper_[i]) );
1245         }
1246         else
1247         {
1248           GUROBI_CALL( "getRowUpper", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_RHS, i, &rhs) );
1249           convertSenseToBound( rowsense[i], rhs, 0.0, dum1, rowupper_[i] );
1250         }
1251       }
1252   	}
1253   }
1254 
1255   return rowupper_;
1256 }
1257 
1258 //------------------------------------------------------------------
getObjCoefficients() const1259 const double * OsiGrbSolverInterface::getObjCoefficients() const
1260 {
1261   debugMessage("OsiGrbSolverInterface::getObjCoefficients()\n");
1262 
1263   if ( obj_==NULL )
1264   {
1265   	int ncols = getNumCols();
1266   	if( ncols > 0 )
1267   	{
1268   		obj_ = new double[ncols];
1269   		GUROBI_CALL( "getObjCoefficients", GRBupdatemodel(getMutableLpPtr()) );
1270 
1271   		GUROBI_CALL( "getObjCoefficients", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_OBJ, ncols, colmap_O2G, obj_) );
1272   	}
1273   }
1274 
1275   return obj_;
1276 }
1277 
1278 //------------------------------------------------------------------
getObjSense() const1279 double OsiGrbSolverInterface::getObjSense() const
1280 {
1281   debugMessage("OsiGrbSolverInterface::getObjSense()\n");
1282 
1283   int sense;
1284   GUROBI_CALL( "getObjSense", GRBupdatemodel(getMutableLpPtr()) );
1285 
1286   GUROBI_CALL( "getObjSense", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_MODELSENSE, &sense) );
1287 
1288   return (double)sense;
1289 }
1290 
1291 //------------------------------------------------------------------
1292 // Return information on integrality
1293 //------------------------------------------------------------------
1294 
isContinuous(int colNumber) const1295 bool OsiGrbSolverInterface::isContinuous( int colNumber ) const
1296 {
1297   debugMessage("OsiGrbSolverInterface::isContinuous(%d)\n", colNumber);
1298 
1299   return getCtype()[colNumber] == 'C';
1300 }
1301 
1302 //------------------------------------------------------------------
1303 // Row and column copies of the matrix ...
1304 //------------------------------------------------------------------
1305 
getMatrixByRow() const1306 const CoinPackedMatrix * OsiGrbSolverInterface::getMatrixByRow() const
1307 {
1308   debugMessage("OsiGrbSolverInterface::getMatrixByRow()\n");
1309 
1310   if ( matrixByRow_ == NULL )
1311   {
1312   	int nrows = getNumRows();
1313   	int ncols = getNumCols();
1314 
1315     if ( nrows == 0 ) {
1316     	matrixByRow_ = new CoinPackedMatrix();
1317     	matrixByRow_->setDimensions(0, ncols);
1318     	return matrixByRow_;
1319     }
1320 
1321   	int nelems;
1322   	int *starts   = new int   [nrows + 1];
1323   	int *len      = new int   [nrows];
1324 
1325   	GUROBI_CALL( "getMatrixByRow", GRBupdatemodel(getMutableLpPtr()) );
1326 
1327   	GUROBI_CALL( "getMatrixByRow", GRBgetconstrs(getMutableLpPtr(), &nelems, NULL, NULL, NULL, 0, nrows) );
1328 
1329   	assert( nelems == getNumElements() + nauxcols );
1330   	int     *indices  = new int   [nelems];
1331   	double  *elements = new double[nelems];
1332 
1333   	GUROBI_CALL( "getMatrixByRow", GRBgetconstrs(getMutableLpPtr(), &nelems, starts, indices, elements, 0, nrows) );
1334 
1335   	matrixByRow_ = new CoinPackedMatrix();
1336 
1337   	// Should be able to pass null for length of packed matrix,
1338   	// assignMatrix does not seem to allow (even though documentation say it is possible to do this).
1339   	// For now compute the length.
1340   	starts[nrows] = nelems;
1341   	for ( int i = 0; i < nrows; ++i )
1342   		len[i] = starts[i+1] - starts[i];
1343 
1344   	matrixByRow_->assignMatrix( false /* not column ordered */,
1345   			ncols + nauxcols, nrows, nelems,
1346   			elements, indices, starts, len);
1347 
1348   	if( nauxcols )
1349   	{
1350   	  // delete auxiliary columns from matrix
1351   	  int* auxcols = new int[nauxcols];
1352   	  int j = 0;
1353   	  for( int i = 0; i < ncols + nauxcols; ++i )
1354   	    if( colmap_G2O[i] < 0 )
1355   	      auxcols[j++] = i;
1356   	  assert(j == nauxcols);
1357 
1358   	  matrixByRow_->deleteCols(nauxcols, auxcols);
1359 
1360   	  delete[] auxcols;
1361 
1362   	  assert(matrixByRow_->getNumElements() == getNumElements());
1363   	  assert(matrixByRow_->getMinorDim() <= ncols);
1364   	}
1365   }
1366 
1367   return matrixByRow_;
1368 }
1369 
1370 //------------------------------------------------------------------
1371 
getMatrixByCol() const1372 const CoinPackedMatrix * OsiGrbSolverInterface::getMatrixByCol() const
1373 {
1374 	debugMessage("OsiGrbSolverInterface::getMatrixByCol()\n");
1375 
1376 	if ( matrixByCol_ == NULL )
1377 	{
1378 		int nrows = getNumRows();
1379 		int ncols = getNumCols();
1380 
1381     matrixByCol_ = new CoinPackedMatrix();
1382 
1383 		if ( ncols > 0 )
1384 		{
1385 		  int nelems;
1386 		  int *starts = new int   [ncols + nauxcols + 1];
1387 		  int *len    = new int   [ncols + nauxcols];
1388 
1389 		  GUROBI_CALL( "getMatrixByCol", GRBupdatemodel(getMutableLpPtr()) );
1390 
1391 		  GUROBI_CALL( "getMatrixByCol", GRBgetvars(getMutableLpPtr(), &nelems, NULL, NULL, NULL, 0, ncols + nauxcols) );
1392 
1393 		  int     *indices  = new int   [nelems];
1394 		  double  *elements = new double[nelems];
1395 
1396 		  GUROBI_CALL( "getMatrixByCol", GRBgetvars(getMutableLpPtr(), &nelems, starts, indices, elements, 0, ncols + nauxcols) );
1397 
1398 		  // Should be able to pass null for length of packed matrix,
1399 		  // assignMatrix does not seem to allow (even though documentation say it is possible to do this).
1400 		  // For now compute the length.
1401 		  starts[ncols + nauxcols] = nelems;
1402 		  for ( int i = 0; i < ncols + nauxcols; i++ )
1403 		    len[i] = starts[i+1] - starts[i];
1404 
1405 		  matrixByCol_->assignMatrix( true /* column ordered */,
1406 		      nrows, ncols + nauxcols, nelems,
1407 		      elements, indices, starts, len);
1408 
1409 		  assert( matrixByCol_->getNumCols() == ncols + nauxcols );
1410 		  assert( matrixByCol_->getNumRows() == nrows );
1411 
1412 	    if( nauxcols )
1413 	    {
1414 	      // delete auxiliary columns from matrix
1415 	      int* auxcols = new int[nauxcols];
1416 	      int j = 0;
1417 	      for( int i = 0; i < ncols + nauxcols; ++i )
1418 	        if( colmap_G2O[i] < 0 )
1419 	          auxcols[j++] = i;
1420 	      assert(j == nauxcols);
1421 
1422 	      matrixByCol_->deleteCols(nauxcols, auxcols);
1423 
1424 	      delete[] auxcols;
1425 
1426 	      assert(matrixByCol_->getNumElements() == getNumElements());
1427         assert(matrixByCol_->getMajorDim() <= ncols);
1428 	      assert(matrixByCol_->getMinorDim() <= nrows);
1429 	    }
1430 		}
1431 		else
1432 		  matrixByCol_->setDimensions(nrows, ncols);
1433 	}
1434 
1435 	return matrixByCol_;
1436 }
1437 
1438 //------------------------------------------------------------------
1439 // Get solver's value for infinity
1440 //------------------------------------------------------------------
getInfinity() const1441 double OsiGrbSolverInterface::getInfinity() const
1442 {
1443   debugMessage("OsiGrbSolverInterface::getInfinity()\n");
1444 
1445   return GRB_INFINITY;
1446 }
1447 
1448 //#############################################################################
1449 // Problem information methods (results)
1450 //#############################################################################
1451 
1452 // *FIXME*: what should be done if a certain vector doesn't exist???
1453 
getColSolution() const1454 const double * OsiGrbSolverInterface::getColSolution() const
1455 {
1456 	debugMessage("OsiGrbSolverInterface::getColSolution()\n");
1457 
1458 	if( colsol_ == NULL )
1459 	{
1460 		int ncols = getNumCols();
1461 		if( ncols > 0 )
1462 		{
1463 			colsol_ = new double[ncols];
1464 
1465 			GUROBI_CALL( "getColSolution", GRBupdatemodel(getMutableLpPtr()) );
1466 
1467       if ( GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_X, 0, colsol_) == 0 )
1468       { // if a solution is available, get it
1469         if( nauxcols )
1470           GUROBI_CALL( "getColSolution", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_X, ncols, colmap_O2G, colsol_) );
1471         else
1472           GUROBI_CALL( "getColSolution", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_X, 0, ncols, colsol_) );
1473       }
1474       else
1475       {
1476         *messageHandler() << "Warning: OsiGrbSolverInterface::getColSolution() called, but no solution available! Returning lower bounds, but they may be at -infinity. Be aware!" << CoinMessageEol;
1477         if (OsiGrbSolverInterface::globalenv_)
1478           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
1479         if( nauxcols )
1480           GUROBI_CALL( "getColSolution", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_LB, ncols, colmap_O2G, colsol_) );
1481         else
1482           GUROBI_CALL( "getColSolution", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_LB, 0, ncols, colsol_) );
1483       }
1484 		}
1485 	}
1486 
1487 	return colsol_;
1488 }
1489 
1490 //------------------------------------------------------------------
getRowPrice() const1491 const double * OsiGrbSolverInterface::getRowPrice() const
1492 {
1493   debugMessage("OsiGrbSolverInterface::getRowPrice()\n");
1494 
1495   if( rowsol_==NULL )
1496   {
1497   	int nrows = getNumRows();
1498   	if( nrows > 0 )
1499   	{
1500   		rowsol_ = new double[nrows];
1501 
1502   		GUROBI_CALL( "getRowPrice", GRBupdatemodel(getMutableLpPtr()) );
1503 
1504       if ( GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_PI, 0, rowsol_) == 0 )
1505       {
1506     		GUROBI_CALL( "getRowPrice", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_PI, 0, nrows, rowsol_) );
1507       }
1508       else
1509       {
1510         *messageHandler() << "Warning: OsiGrbSolverInterface::getRowPrice() called, but no solution available! Returning 0.0. Be aware!" << CoinMessageEol;
1511         if (OsiGrbSolverInterface::globalenv_)
1512           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
1513         CoinZeroN(rowsol_, nrows);
1514       }
1515 
1516   		//??? what is the dual value for a ranged row?
1517   	}
1518   }
1519 
1520   return rowsol_;
1521 }
1522 
1523 //------------------------------------------------------------------
getReducedCost() const1524 const double * OsiGrbSolverInterface::getReducedCost() const
1525 {
1526   debugMessage("OsiGrbSolverInterface::getReducedCost()\n");
1527 
1528   if( redcost_==NULL )
1529   {
1530   	int ncols = getNumCols();
1531   	if( ncols > 0 )
1532   	{
1533   		redcost_ = new double[ncols];
1534 
1535   		GUROBI_CALL( "getReducedCost", GRBupdatemodel(getMutableLpPtr()) );
1536 
1537       if ( GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_RC, 0, redcost_) == 0 )
1538       { // if reduced costs are available, get them
1539     		if( nauxcols )
1540     		  GUROBI_CALL( "getReducedCost", GRBgetdblattrlist(getMutableLpPtr(), GRB_DBL_ATTR_RC, ncols, colmap_O2G, redcost_) );
1541     		else
1542           GUROBI_CALL( "getReducedCost", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_RC, 0, ncols, redcost_) );
1543       }
1544       else
1545       {
1546         *messageHandler() << "Warning: OsiGrbSolverInterface::getReducedCost() called, but no solution available! Returning 0.0. Be aware!" << CoinMessageEol;
1547         if (OsiGrbSolverInterface::globalenv_)
1548           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
1549         CoinZeroN(redcost_, ncols);
1550       }
1551   	}
1552   }
1553 
1554   return redcost_;
1555 }
1556 
1557 //------------------------------------------------------------------
getRowActivity() const1558 const double * OsiGrbSolverInterface::getRowActivity() const
1559 {
1560   debugMessage("OsiGrbSolverInterface::getRowActivity()\n");
1561 
1562   if( rowact_==NULL )
1563   {
1564   	int nrows = getNumRows();
1565   	if( nrows > 0 )
1566   	{
1567   		rowact_ = new double[nrows];
1568 
1569   		GUROBI_CALL( "getRowActivity", GRBupdatemodel(getMutableLpPtr()) );
1570 
1571   		if ( GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_SLACK, 0, rowact_) == 0 )
1572   		{
1573   			GUROBI_CALL( "getRowActivity", GRBgetdblattrarray(getMutableLpPtr(), GRB_DBL_ATTR_SLACK, 0, nrows, rowact_) );
1574 
1575   			for( int r = 0; r < nrows; ++r )
1576   			{
1577   				if( nauxcols && auxcolind[r] >= 0 )
1578   				{
1579   					GUROBI_CALL( "getRowActivity", GRBgetdblattrelement(getMutableLpPtr(), GRB_DBL_ATTR_X, auxcolind[r], &rowact_[r]) );
1580   				}
1581   				else
1582   					rowact_[r] = getRightHandSide()[r] - rowact_[r];
1583   			}
1584   		}
1585       else
1586       {
1587         *messageHandler() << "Warning: OsiGrbSolverInterface::getRowActivity() called, but no solution available! Returning 0.0. Be aware!" << CoinMessageEol;
1588         if (OsiGrbSolverInterface::globalenv_)
1589           *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
1590         CoinZeroN(rowact_, nrows);
1591       }
1592   	}
1593   }
1594   return rowact_;
1595 }
1596 
1597 //------------------------------------------------------------------
getObjValue() const1598 double OsiGrbSolverInterface::getObjValue() const
1599 {
1600   debugMessage("OsiGrbSolverInterface::getObjValue()\n");
1601 
1602   double objval = 0.0;
1603 
1604   GUROBI_CALL( "getObjValue", GRBupdatemodel(getMutableLpPtr()) );
1605 
1606   if( GRBgetdblattr(getMutableLpPtr(), GRB_DBL_ATTR_OBJVAL, &objval) == 0 )
1607   {
1608     // Adjust objective function value by constant term in objective function
1609     double objOffset;
1610     getDblParam(OsiObjOffset,objOffset);
1611     objval = objval - objOffset;
1612   }
1613   else
1614   {
1615     *messageHandler() << "Warning: OsiGrbSolverInterface::getObjValue() called, but probably no solution available! Returning 0.0. Be aware!" << CoinMessageEol;
1616     if (OsiGrbSolverInterface::globalenv_)
1617       *messageHandler() << "\t GUROBI error message: " << GRBgeterrormsg(OsiGrbSolverInterface::globalenv_) << CoinMessageEol;
1618   }
1619 
1620   return objval;
1621 }
1622 
1623 //------------------------------------------------------------------
getIterationCount() const1624 int OsiGrbSolverInterface::getIterationCount() const
1625 {
1626   debugMessage("OsiGrbSolverInterface::getIterationCount()\n");
1627 
1628   double itercnt;
1629 
1630   GUROBI_CALL( "getIterationCount", GRBupdatemodel(getMutableLpPtr()) );
1631 
1632   GUROBI_CALL( "getIterationCount", GRBgetdblattr(getMutableLpPtr(), GRB_DBL_ATTR_ITERCOUNT, &itercnt) );
1633 
1634   return (int)itercnt;
1635 }
1636 
1637 //------------------------------------------------------------------
getDualRays(int maxNumRays,bool fullRay) const1638 std::vector<double*> OsiGrbSolverInterface::getDualRays(int maxNumRays,
1639 							bool fullRay) const
1640 {
1641   debugMessage("OsiGrbSolverInterface::getDualRays(%d,%s)\n", maxNumRays,
1642 	       fullRay?"true":"false");
1643 
1644   if (fullRay == true) {
1645     throw CoinError("Full dual rays not yet implemented.","getDualRays",
1646 		    "OsiGrbSolverInterface");
1647   }
1648 
1649   OsiGrbSolverInterface solver(*this);
1650 
1651   const int numcols = getNumCols();
1652   const int numrows = getNumRows();
1653   int* index = new int[CoinMax(numcols,numrows)];
1654   int i;
1655   for ( i = CoinMax(numcols,numrows)-1; i >= 0; --i)
1656   {
1657   	index[i] = i;
1658   }
1659   double* obj = new double[CoinMax(numcols,2*numrows)];
1660   CoinFillN(obj, numcols, 0.0);
1661   solver.setObjCoeffSet(index, index+numcols, obj);
1662 
1663   double* clb = new double[2*numrows];
1664   double* cub = new double[2*numrows];
1665 
1666   const double plusone = 1.0;
1667   const double minusone = -1.0;
1668   const char* sense = getRowSense();
1669 
1670   const CoinPackedVectorBase** cols = new const CoinPackedVectorBase*[numrows];
1671   int newcols = 0;
1672   for (i = 0; i < numrows; ++i) {
1673   	switch (sense[i]) {
1674   		case 'L':
1675   			cols[newcols++] = new CoinShallowPackedVector(1, &index[i], &minusone, false);
1676   			break;
1677   		case 'G':
1678   			cols[newcols++] = new CoinShallowPackedVector(1, &index[i], &plusone, false);
1679   			break;
1680   		case 'R':
1681   		  cols[newcols++] = new CoinShallowPackedVector(1, &index[i], &minusone, false);
1682   		  cols[newcols++] = new CoinShallowPackedVector(1, &index[i], &plusone, false);
1683   		  break;
1684   		case 'N':
1685   		case 'E':
1686   			break;
1687   	}
1688   }
1689 
1690   CoinFillN(obj, newcols, 1.0);
1691   CoinFillN(clb, newcols, 0.0);
1692   CoinFillN(cub, newcols, getInfinity());
1693 
1694   solver.addCols(newcols, cols, clb, cub, obj);
1695   delete[] index;
1696   delete[] cols;
1697   delete[] clb;
1698   delete[] cub;
1699   delete[] obj;
1700 
1701   solver.setObjSense(1.0); // minimize
1702   solver.initialSolve();
1703 
1704   const double* solverpi = solver.getRowPrice();
1705   double* pi = new double[numrows];
1706   for ( i = numrows - 1; i >= 0; --i) {
1707   	pi[i] = -solverpi[i];
1708   }
1709   return std::vector<double*>(1, pi);
1710 }
1711 
1712 //------------------------------------------------------------------
getPrimalRays(int maxNumRays) const1713 std::vector<double*> OsiGrbSolverInterface::getPrimalRays(int maxNumRays) const
1714 {
1715   debugMessage("OsiGrbSolverInterface::getPrimalRays(%d)\n", maxNumRays);
1716 
1717   return std::vector<double*>();
1718 }
1719 
1720 //#############################################################################
1721 // Problem modifying methods (rim vectors)
1722 //#############################################################################
1723 
setObjCoeff(int elementIndex,double elementValue)1724 void OsiGrbSolverInterface::setObjCoeff( int elementIndex, double elementValue )
1725 {
1726   debugMessage("OsiGrbSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue);
1727 
1728   GUROBI_CALL( "setObjCoeff", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_OBJ, nauxcols ? colmap_O2G[elementIndex] : elementIndex, elementValue) );
1729 
1730   if(obj_ != NULL)
1731     obj_[elementIndex] = elementValue;
1732 }
1733 
1734 //-----------------------------------------------------------------------------
1735 
setObjCoeffSet(const int * indexFirst,const int * indexLast,const double * coeffList)1736 void OsiGrbSolverInterface::setObjCoeffSet(const int* indexFirst,
1737 					   const int* indexLast,
1738 					   const double* coeffList)
1739 {
1740   debugMessage("OsiGrbSolverInterface::setObjCoeffSet(%p, %p, %p)\n", (void*)indexFirst, (void*)indexLast, (void*)coeffList);
1741 
1742   const int cnt = (int)(indexLast - indexFirst);
1743 
1744   if( cnt == 0 )
1745     return;
1746   if( cnt == 1 )
1747   {
1748     setObjCoeff(*indexFirst, *coeffList);
1749     return;
1750   }
1751   assert(cnt > 1);
1752 
1753   if( nauxcols )
1754   {
1755     int* indices = new int[cnt];
1756     for( int i = 0; i < cnt; ++i )
1757       indices[i] = colmap_O2G[indexFirst[i]];
1758     GUROBI_CALL( "setObjCoeffSet", GRBsetdblattrlist(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_OBJ, cnt, indices, const_cast<double*>(coeffList)) );
1759     delete[] indices;
1760   }
1761   else
1762   {
1763     GUROBI_CALL( "setObjCoeffSet", GRBsetdblattrlist(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_OBJ, cnt, const_cast<int*>(indexFirst), const_cast<double*>(coeffList)) );
1764   }
1765 
1766 	if (obj_ != NULL)
1767 		for (int i = 0; i < cnt; ++i)
1768 			obj_[indexFirst[i]] = coeffList[i];
1769 
1770 }
1771 
1772 //-----------------------------------------------------------------------------
setColLower(int elementIndex,double elementValue)1773 void OsiGrbSolverInterface::setColLower(int elementIndex, double elementValue)
1774 {
1775   debugMessage("OsiGrbSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue);
1776 
1777   GUROBI_CALL( "setColLower", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_LB, nauxcols ? colmap_O2G[elementIndex] : elementIndex, elementValue) );
1778 
1779   if(collower_ != NULL)
1780     collower_[elementIndex] = elementValue;
1781 }
1782 
1783 //-----------------------------------------------------------------------------
setColUpper(int elementIndex,double elementValue)1784 void OsiGrbSolverInterface::setColUpper(int elementIndex, double elementValue)
1785 {
1786   debugMessage("OsiGrbSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue);
1787 
1788   GUROBI_CALL( "setColUpper", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_UB, nauxcols ? colmap_O2G[elementIndex] : elementIndex, elementValue) );
1789 
1790   if(colupper_ != NULL)
1791     colupper_[elementIndex] = elementValue;
1792 }
1793 
1794 //-----------------------------------------------------------------------------
setColBounds(int elementIndex,double lower,double upper)1795 void OsiGrbSolverInterface::setColBounds( int elementIndex, double lower, double upper )
1796 {
1797   debugMessage("OsiGrbSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper);
1798 
1799   setColLower(elementIndex, lower);
1800   setColUpper(elementIndex, upper);
1801 }
1802 
1803 //-----------------------------------------------------------------------------
setColSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)1804 void OsiGrbSolverInterface::setColSetBounds(const int* indexFirst,
1805 					    const int* indexLast,
1806 					    const double* boundList)
1807 {
1808   debugMessage("OsiGrbSolverInterface::setColSetBounds(%p, %p, %p)\n", (void*)indexFirst, (void*)indexLast, (void*)boundList);
1809 
1810   const int cnt = (int)(indexLast - indexFirst);
1811   if (cnt == 0)
1812   	return;
1813   if (cnt == 1)
1814   {
1815     setColLower(*indexFirst, boundList[0]);
1816     setColUpper(*indexFirst, boundList[1]);
1817     return;
1818   }
1819   assert(cnt > 1);
1820 
1821   double* lbList = new double[cnt];
1822   double* ubList = new double[cnt];
1823   int* indices = nauxcols ? new int[cnt] : NULL;
1824 
1825   for (int i = 0; i < cnt; ++i)
1826   {
1827   	lbList[i] = boundList[2*i];
1828   	ubList[i] = boundList[2*i+1];
1829   	if( indices )
1830   	  indices[i] = colmap_O2G[indexFirst[i]];
1831 
1832     if(collower_ != NULL)
1833     	collower_[indexFirst[i]] = boundList[2*i];
1834     if(colupper_ != NULL)
1835     	colupper_[indexFirst[i]] = boundList[2*i+1];
1836   }
1837 
1838   GUROBI_CALL( "setColSetBounds", GRBsetdblattrlist(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_LB, cnt, indices ? indices : const_cast<int*>(indexFirst), lbList) );
1839   GUROBI_CALL( "setColSetBounds", GRBsetdblattrlist(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_UB, cnt, indices ? indices : const_cast<int*>(indexFirst), ubList) );
1840 
1841 	delete[] lbList;
1842 	delete[] ubList;
1843 	delete[] indices;
1844 }
1845 
1846 //-----------------------------------------------------------------------------
1847 void
setRowLower(int i,double elementValue)1848 OsiGrbSolverInterface::setRowLower( int i, double elementValue )
1849 {
1850   debugMessage("OsiGrbSolverInterface::setRowLower(%d, %g)\n", i, elementValue);
1851 
1852   double rhs   = getRightHandSide()[i];
1853   double range = getRowRange()[i];
1854   char   sense = getRowSense()[i];
1855   double lower = 0, upper = 0;
1856 
1857   convertSenseToBound( sense, rhs, range, lower, upper );
1858   if( lower != elementValue )
1859   {
1860   	convertBoundToSense( elementValue, upper, sense, rhs, range );
1861   	setRowType( i, sense, rhs, range );
1862   }
1863 }
1864 
1865 //-----------------------------------------------------------------------------
1866 void
setRowUpper(int i,double elementValue)1867 OsiGrbSolverInterface::setRowUpper( int i, double elementValue )
1868 {
1869   debugMessage("OsiGrbSolverInterface::setRowUpper(%d, %g)\n", i, elementValue);
1870 
1871   double rhs   = getRightHandSide()[i];
1872   double range = getRowRange()[i];
1873   char   sense = getRowSense()[i];
1874   double lower = 0, upper = 0;
1875 
1876   convertSenseToBound( sense, rhs, range, lower, upper );
1877   if( upper != elementValue ) {
1878   	convertBoundToSense( lower, elementValue, sense, rhs, range );
1879   	setRowType( i, sense, rhs, range );
1880   }
1881 }
1882 
1883 //-----------------------------------------------------------------------------
1884 void
setRowBounds(int elementIndex,double lower,double upper)1885 OsiGrbSolverInterface::setRowBounds( int elementIndex, double lower, double upper )
1886 {
1887   debugMessage("OsiGrbSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper);
1888 
1889   double rhs, range;
1890   char sense;
1891 
1892   convertBoundToSense( lower, upper, sense, rhs, range );
1893 
1894   setRowType( elementIndex, sense, rhs, range );
1895 }
1896 
1897 //-----------------------------------------------------------------------------
1898 void
setRowType(int i,char sense,double rightHandSide,double range)1899 OsiGrbSolverInterface::setRowType(int i, char sense, double rightHandSide, double range)
1900 {
1901   debugMessage("OsiGrbSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range);
1902 
1903   GUROBI_CALL( "setRowType", GRBupdatemodel(getMutableLpPtr()) );
1904 
1905   if( nauxcols && auxcolind[i] >= 0 )
1906   { // so far, row i is a ranged row
1907     switch (sense)
1908     {
1909       case 'R':
1910         // row i was ranged row and remains a ranged row
1911         assert(range > 0);
1912         GUROBI_CALL( "setRowType", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_LB, auxcolind[i], rightHandSide - range) );
1913         GUROBI_CALL( "setRowType", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_UB, auxcolind[i], rightHandSide ) );
1914         break;
1915       case 'N':
1916       case 'L':
1917       case 'G':
1918       case 'E':
1919         convertToNormalRow(i, sense, rightHandSide);
1920         break;
1921       default:
1922         std::cerr << "Unknown row sense: " << sense << std::endl;
1923         exit(-1);
1924     }
1925   }
1926   else if (sense == 'R')
1927   {
1928     convertToRangedRow(i, rightHandSide, range);
1929   }
1930   else
1931   {
1932     char grbsense;
1933     switch (sense)
1934     {
1935       case 'N':
1936         grbsense = GRB_LESS_EQUAL;
1937         rightHandSide = getInfinity();
1938         break;
1939 
1940       case 'L':
1941         grbsense = GRB_LESS_EQUAL;
1942         break;
1943 
1944       case 'G':
1945         grbsense = GRB_GREATER_EQUAL;
1946         break;
1947 
1948       case 'E':
1949         grbsense = GRB_EQUAL;
1950         break;
1951 
1952       default:
1953         std::cerr << "Unknown row sense: " << sense << std::endl;
1954         exit(-1);
1955     }
1956     GUROBI_CALL( "setRowType", GRBsetcharattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_CHAR_ATTR_SENSE, i, grbsense ) );
1957     GUROBI_CALL( "setRowType", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_RHS, i, rightHandSide) );
1958   }
1959 
1960   if(rowsense_ != NULL)
1961     rowsense_[i] = sense;
1962 
1963   if(rhs_ != NULL)
1964     rhs_[i] = rightHandSide;
1965 
1966   if (rowlower_ != NULL || rowupper_ != NULL)
1967   {
1968   	double dummy;
1969   	convertSenseToBound(sense, rightHandSide, range,
1970   			rowlower_ ? rowlower_[i] : dummy,
1971   			rowupper_ ? rowupper_[i] : dummy);
1972   }
1973 }
1974 
1975 //-----------------------------------------------------------------------------
setRowSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)1976 void OsiGrbSolverInterface::setRowSetBounds(const int* indexFirst,
1977 					    const int* indexLast,
1978 					    const double* boundList)
1979 {
1980   debugMessage("OsiGrbSolverInterface::setRowSetBounds(%p, %p, %p)\n", (void*)indexFirst, (void*)indexLast, (void*)boundList);
1981 
1982   const long int cnt = indexLast - indexFirst;
1983   if (cnt <= 0)
1984     return;
1985 
1986   char* sense = new char[cnt];
1987   double* rhs = new double[cnt];
1988   double* range = new double[cnt];
1989   for (int i = 0; i < cnt; ++i)
1990     convertBoundToSense(boundList[2*i], boundList[2*i+1], sense[i], rhs[i], range[i]);
1991   setRowSetTypes(indexFirst, indexLast, sense, rhs, range);
1992 
1993   delete[] range;
1994   delete[] rhs;
1995   delete[] sense;
1996 }
1997 
1998 //-----------------------------------------------------------------------------
1999 void
setRowSetTypes(const int * indexFirst,const int * indexLast,const char * senseList,const double * rhsList,const double * rangeList)2000 OsiGrbSolverInterface::setRowSetTypes(const int* indexFirst,
2001 				      const int* indexLast,
2002 				      const char* senseList,
2003 				      const double* rhsList,
2004 				      const double* rangeList)
2005 {
2006   debugMessage("OsiGrbSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n",
2007   		(void*)indexFirst, (void*)indexLast, (void*)senseList, (void*)rhsList, (void*)rangeList);
2008 
2009    const int cnt = (int)(indexLast - indexFirst);
2010    if (cnt == 0)
2011   	 return;
2012    if (cnt == 1)
2013    {
2014      setRowType(*indexFirst, *senseList, *rhsList, *rangeList);
2015      return;
2016    }
2017    assert(cnt > 0);
2018 
2019    GUROBI_CALL( "setRowSetTypes", GRBupdatemodel(getMutableLpPtr()) );
2020 
2021    char* grbsense = new char[cnt];
2022    double* rhs = new double[cnt];
2023    for (int i = 0; i < cnt; ++i)
2024    {
2025      rhs[i] = rhsList[i];
2026      if( nauxcols && auxcolind[indexFirst[i]] >= 0 )
2027      { // so far, row is a ranged row
2028        switch (senseList[i])
2029        {
2030          case 'R':
2031            // row i was ranged row and remains a ranged row
2032            assert(rangeList[i] > 0);
2033            GUROBI_CALL( "setRowSetTypes", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_LB, auxcolind[indexFirst[i]], rhsList[i] - rangeList[i]) );
2034            GUROBI_CALL( "setRowSetTypes", GRBsetdblattrelement(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ), GRB_DBL_ATTR_UB, auxcolind[indexFirst[i]], rhsList[i] ) );
2035            grbsense[i] = GRB_EQUAL;
2036            rhs[i] = 0.0;
2037            break;
2038          case 'N':
2039            convertToNormalRow(indexFirst[i], senseList[i], rhsList[i]);
2040            grbsense[i] = GRB_LESS_EQUAL;
2041            rhs[i] = getInfinity();
2042            break;
2043          case 'L':
2044            convertToNormalRow(indexFirst[i], senseList[i], rhsList[i]);
2045            grbsense[i] = GRB_LESS_EQUAL;
2046            break;
2047          case 'G':
2048            convertToNormalRow(indexFirst[i], senseList[i], rhsList[i]);
2049            grbsense[i] = GRB_GREATER_EQUAL;
2050            break;
2051          case 'E':
2052            convertToNormalRow(indexFirst[i], senseList[i], rhsList[i]);
2053            grbsense[i] = GRB_EQUAL;
2054            break;
2055          default:
2056            std::cerr << "Unknown row sense: " << senseList[i] << std::endl;
2057            exit(-1);
2058        }
2059      }
2060      else if (senseList[i] == 'R')
2061      {
2062        convertToRangedRow(indexFirst[i], rhsList[i], rangeList[i]);
2063        grbsense[i] = GRB_EQUAL;
2064        rhs[i] = 0.0;
2065      }
2066      else
2067      {
2068        switch (senseList[i])
2069        {
2070          case 'N':
2071            grbsense[i] = GRB_LESS_EQUAL;
2072            rhs[i] = getInfinity();
2073            break;
2074 
2075          case 'L':
2076            grbsense[i] = GRB_LESS_EQUAL;
2077            break;
2078 
2079          case 'G':
2080            grbsense[i] = GRB_GREATER_EQUAL;
2081            break;
2082 
2083          case 'E':
2084            grbsense[i] = GRB_EQUAL;
2085            break;
2086 
2087          default:
2088            std::cerr << "Unknown row sense: " << senseList[i] << std::endl;
2089            exit(-1);
2090        }
2091      }
2092 
2093      if(rowsense_ != NULL)
2094   		 rowsense_[indexFirst[i]] = senseList[i];
2095 
2096      if(rhs_ != NULL)
2097     	 rhs_[indexFirst[i]] = senseList[i] == 'N' ? getInfinity() : rhsList[i];
2098    }
2099 
2100    GUROBI_CALL( "setRowSetTypes", GRBsetcharattrlist(getLpPtr(OsiGrbSolverInterface::KEEPCACHED_ROW), GRB_CHAR_ATTR_SENSE, cnt, const_cast<int*>(indexFirst), grbsense) );
2101    GUROBI_CALL( "setRowSetTypes", GRBsetdblattrlist(getLpPtr(OsiGrbSolverInterface::KEEPCACHED_ROW), GRB_DBL_ATTR_RHS, cnt, const_cast<int*>(indexFirst), rhs) );
2102 
2103    delete[] rhs;
2104    delete[] grbsense;
2105 }
2106 
2107 //#############################################################################
2108 void
setContinuous(int index)2109 OsiGrbSolverInterface::setContinuous(int index)
2110 {
2111   debugMessage("OsiGrbSolverInterface::setContinuous(%d)\n", index);
2112 
2113   assert(coltype_ != NULL);
2114   assert(colspace_ >= getNumCols());
2115 
2116   coltype_[index] = GRB_CONTINUOUS;
2117 
2118   if ( probtypemip_ )
2119   {
2120     GUROBI_CALL( "setContinuous", GRBupdatemodel(getMutableLpPtr()) );
2121     GUROBI_CALL( "setContinuous", GRBsetcharattrelement(getMutableLpPtr(), GRB_CHAR_ATTR_VTYPE, nauxcols ? colmap_O2G[index] : index, GRB_CONTINUOUS) );
2122   }
2123 }
2124 
2125 //-----------------------------------------------------------------------------
2126 void
setInteger(int index)2127 OsiGrbSolverInterface::setInteger(int index)
2128 {
2129   debugMessage("OsiGrbSolverInterface::setInteger(%d)\n", index);
2130 
2131   assert(coltype_ != NULL);
2132   assert(colspace_ >= getNumCols());
2133 
2134   if( getColLower()[index] == 0.0 && getColUpper()[index] == 1.0 )
2135      coltype_[index] = GRB_BINARY;
2136   else
2137      coltype_[index] = GRB_INTEGER;
2138 
2139   if ( probtypemip_ )
2140   {
2141     GUROBI_CALL( "setInteger", GRBupdatemodel(getMutableLpPtr()) );
2142     GUROBI_CALL( "setInteger", GRBsetcharattrelement(getMutableLpPtr(), GRB_CHAR_ATTR_VTYPE, nauxcols ? colmap_O2G[index] : index, coltype_[index]) );
2143   }
2144 }
2145 
2146 //-----------------------------------------------------------------------------
2147 void
setContinuous(const int * indices,int len)2148 OsiGrbSolverInterface::setContinuous(const int* indices, int len)
2149 {
2150   debugMessage("OsiGrbSolverInterface::setContinuous(%p, %d)\n", (void*)indices, len);
2151 
2152   for( int i = 0; i < len; ++i )
2153      setContinuous(indices[i]);
2154 }
2155 
2156 //-----------------------------------------------------------------------------
2157 void
setInteger(const int * indices,int len)2158 OsiGrbSolverInterface::setInteger(const int* indices, int len)
2159 {
2160   debugMessage("OsiGrbSolverInterface::setInteger(%p, %d)\n", (void*)indices, len);
2161 
2162   for( int i = 0; i < len; ++i )
2163      setInteger(indices[i]);
2164 }
2165 
2166 //#############################################################################
2167 
2168 void
setRowName(int ndx,std::string name)2169 OsiGrbSolverInterface::setRowName(int ndx, std::string name)
2170 {
2171   debugMessage("OsiGrbSolverInterface::setRowName\n");
2172 
2173   if (ndx < 0 || ndx >= getNumRows())
2174     return;
2175 
2176   int nameDiscipline ;
2177   getIntParam(OsiNameDiscipline, nameDiscipline);
2178   if (nameDiscipline == 0)
2179     return;
2180 
2181   OsiSolverInterface::setRowName(ndx, name);
2182 
2183   GUROBI_CALL( "setRowName", GRBsetstrattrelement(getLpPtr(), GRB_STR_ATTR_CONSTRNAME, ndx, const_cast<char*>(name.c_str())) );
2184 }
2185 
2186 void
setColName(int ndx,std::string name)2187 OsiGrbSolverInterface::setColName(int ndx, std::string name)
2188 {
2189   debugMessage("OsiGrbSolverInterface::setColName\n");
2190 
2191   if (ndx < 0 || ndx >= getNumCols())
2192     return;
2193 
2194   int nameDiscipline ;
2195   getIntParam(OsiNameDiscipline, nameDiscipline);
2196   if (nameDiscipline == 0)
2197     return;
2198 
2199   OsiSolverInterface::setColName(ndx, name);
2200 
2201   GUROBI_CALL( "setColName", GRBsetstrattrelement(getLpPtr(), GRB_STR_ATTR_VARNAME, nauxcols ? colmap_O2G[ndx] : ndx, const_cast<char*>(name.c_str())) );
2202 }
2203 
2204 //#############################################################################
2205 
setObjSense(double s)2206 void OsiGrbSolverInterface::setObjSense(double s)
2207 {
2208   debugMessage("OsiGrbSolverInterface::setObjSense(%g)\n", s);
2209 
2210   GUROBI_CALL( "setObjSense", GRBsetintattr(getLpPtr( OsiGrbSolverInterface::FREECACHED_RESULTS ), GRB_INT_ATTR_MODELSENSE, (int)s) );
2211 }
2212 
2213 //-----------------------------------------------------------------------------
2214 
setColSolution(const double * cs)2215 void OsiGrbSolverInterface::setColSolution(const double * cs)
2216 {
2217   debugMessage("OsiGrbSolverInterface::setColSolution(%p)\n", (void*)cs);
2218 
2219   int nc = getNumCols();
2220 
2221   if( cs == NULL )
2222   	freeCachedResults();
2223   else if( nc > 0 )
2224   {
2225   	// If colsol isn't allocated, then allocate it
2226   	if ( colsol_ == NULL )
2227   		colsol_ = new double[nc];
2228 
2229   	// Copy in new col solution.
2230   	CoinDisjointCopyN( cs, nc, colsol_ );
2231 
2232   	//*messageHandler() << "OsiGrb::setColSolution: Gurobi does not allow setting the column solution. Command is ignored." << CoinMessageEol;
2233   }
2234 }
2235 
2236 //-----------------------------------------------------------------------------
2237 
setRowPrice(const double * rs)2238 void OsiGrbSolverInterface::setRowPrice(const double * rs)
2239 {
2240   debugMessage("OsiGrbSolverInterface::setRowPrice(%p)\n", (void*)rs);
2241 
2242   int nr = getNumRows();
2243 
2244   if( rs == NULL )
2245     freeCachedResults();
2246   else if( nr > 0 )
2247   {
2248   	// If rowsol isn't allocated, then allocate it
2249   	if ( rowsol_ == NULL )
2250   		rowsol_ = new double[nr];
2251 
2252   	// Copy in new row solution.
2253   	CoinDisjointCopyN( rs, nr, rowsol_ );
2254 
2255   	*messageHandler() << "OsiGrb::setRowPrice: Gurobi does not allow setting the row price. Command is ignored." << CoinMessageEol;
2256   }
2257 }
2258 
2259 //#############################################################################
2260 // Problem modifying methods (matrix)
2261 //#############################################################################
2262 void
addCol(const CoinPackedVectorBase & vec,const double collb,const double colub,const double obj)2263 OsiGrbSolverInterface::addCol(const CoinPackedVectorBase& vec,
2264 			      const double collb, const double colub,
2265 			      const double obj)
2266 {
2267   debugMessage("OsiGrbSolverInterface::addCol(%p, %g, %g, %g)\n", (void*)&vec, collb, colub, obj);
2268 
2269   int nc = getNumCols();
2270   assert(colspace_ >= nc);
2271 
2272   resizeColSpace(nc + 1);
2273   coltype_[nc] = GRB_CONTINUOUS;
2274 
2275   GUROBI_CALL( "addCol", GRBupdatemodel(getMutableLpPtr()) );
2276 
2277   GUROBI_CALL( "addCol", GRBaddvar(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_ROW ),
2278   		vec.getNumElements(),
2279   		const_cast<int*>(vec.getIndices()),
2280   		const_cast<double*>(vec.getElements()),
2281   		obj, collb, colub, coltype_[nc], NULL) );
2282 
2283   if( nauxcols )
2284   {
2285     colmap_O2G[nc] = nc + nauxcols;
2286     colmap_G2O[nc + nauxcols] = nc;
2287   }
2288 }
2289 
2290 //-----------------------------------------------------------------------------
2291 void
addCols(const int numcols,const CoinPackedVectorBase * const * cols,const double * collb,const double * colub,const double * obj)2292 OsiGrbSolverInterface::addCols(const int numcols,
2293 			       const CoinPackedVectorBase * const * cols,
2294 			       const double* collb, const double* colub,
2295 			       const double* obj)
2296 {
2297   debugMessage("OsiGrbSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, (void*)cols, (void*)collb, (void*)colub, (void*)obj);
2298 
2299   int nc = getNumCols();
2300   assert(colspace_ >= nc);
2301 
2302   resizeColSpace(nc + numcols);
2303   CoinFillN(&coltype_[nc], numcols, GRB_CONTINUOUS);
2304 
2305   int i;
2306   int nz = 0;
2307   for (i = 0; i < numcols; ++i)
2308     nz += cols[i]->getNumElements();
2309 
2310   int* index = new int[nz];
2311   double* elem = new double[nz];
2312   int* start = new int[numcols+1];
2313 
2314   nz = 0;
2315   start[0] = 0;
2316   for (i = 0; i < numcols; ++i)
2317   {
2318     const CoinPackedVectorBase* col = cols[i];
2319     const int len = col->getNumElements();
2320     CoinDisjointCopyN(col->getIndices(), len, index+nz);
2321     CoinDisjointCopyN(col->getElements(), len, elem+nz);
2322     nz += len;
2323     start[i+1] = nz;
2324   }
2325 
2326   GUROBI_CALL( "addCols", GRBupdatemodel(getMutableLpPtr()) );
2327 
2328   GUROBI_CALL( "addCols", GRBaddvars(getLpPtr(OsiGrbSolverInterface::KEEPCACHED_ROW),
2329   		numcols, nz,
2330   		start, index, elem,
2331   		const_cast<double*>(obj),
2332   		const_cast<double*>(collb), const_cast<double*>(colub),
2333   		NULL, NULL) );
2334 
2335   delete[] start;
2336   delete[] elem;
2337   delete[] index;
2338 
2339   if( nauxcols )
2340     for( i = 0; i < numcols; ++i )
2341     {
2342       colmap_O2G[nc+i] = nc+i + nauxcols;
2343       colmap_G2O[nc+i + nauxcols] = nc+i;
2344     }
2345 }
2346 
intcompare(const void * p1,const void * p2)2347 static int intcompare(const void* p1, const void* p2)
2348 {
2349   return (*(const int*)p1) - (*(const int*)p2);
2350 }
2351 
2352 //-----------------------------------------------------------------------------
2353 void
deleteCols(const int num,const int * columnIndices)2354 OsiGrbSolverInterface::deleteCols(const int num, const int * columnIndices)
2355 {
2356   debugMessage("OsiGrbSolverInterface::deleteCols(%d, %p)\n", num, (void*)columnIndices);
2357 
2358   if( num == 0 )
2359     return;
2360 
2361   GUROBI_CALL( "deleteCols", GRBupdatemodel(getMutableLpPtr()) );
2362 
2363   if( nauxcols )
2364   {
2365     int nc = getNumCols();
2366 
2367     int* ind = new int[num];
2368 
2369     // translate into gurobi indices and sort
2370     for( int i = 0; i < num; ++i )
2371       ind[i] = colmap_O2G[columnIndices[i]];
2372     qsort((void*)ind, num, sizeof(int), intcompare);
2373 
2374     // delete indices in gurobi
2375     GUROBI_CALL( "deleteCols", GRBdelvars(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_ROW ), num, ind) );
2376 
2377     nc -= num;
2378 
2379     // update colmap_G2O and auxcolind
2380     int offset = 0;
2381     int j = 0;
2382     for( int i = ind[0]; i < nc + nauxcols; ++i )
2383     {
2384       if( j < num && i == ind[j] )
2385       { // variable i has been deleted, increase offset by 1
2386         assert(colmap_G2O[i] >= 0);
2387         ++offset;
2388         while( j < num && i == ind[j] )
2389           ++j;
2390       }
2391       // variable from position i+offset has moved to position i
2392       if( colmap_G2O[i+offset] >= 0 )
2393       { // if variable at (hithero) position i+offset was a regular variable, then it is now stored at position i
2394         // substract offset since variable indices also changed in Osi
2395         colmap_G2O[i] = colmap_G2O[i+offset] - offset;
2396         assert(colmap_G2O[i] >= 0);
2397         // update also colmap_O2G
2398         colmap_O2G[colmap_G2O[i]] = i;
2399       }
2400       else
2401       { // if variable at (hithero) position i+offset was an auxiliary variable, then the corresponding row index is now stored at position i
2402         int rngrowidx = -colmap_G2O[i+offset]-1;
2403         assert(auxcolind[rngrowidx] == i+offset);
2404         colmap_G2O[i] = colmap_G2O[i+offset];
2405         // update also auxcolind to point to position i now
2406         auxcolind[rngrowidx] = i;
2407       }
2408     }
2409 
2410     delete[] ind;
2411   }
2412   else
2413   {
2414     GUROBI_CALL( "deleteCols", GRBdelvars(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_ROW ), num, const_cast<int*>(columnIndices)) );
2415   }
2416 
2417 #ifndef NDEBUG
2418   if( nauxcols )
2419   {
2420     int nc = getNumCols();
2421     int nr = getNumRows();
2422     for( int i = 0; i < nc + nauxcols; ++i )
2423     {
2424       assert(i >= nc || colmap_G2O[colmap_O2G[i]] == i);
2425       assert(colmap_G2O[i] <  0 || colmap_O2G[colmap_G2O[i]] == i);
2426       assert(colmap_G2O[i] >= 0 || -colmap_G2O[i]-1 < nr);
2427       assert(colmap_G2O[i] >= 0 || auxcolind[-colmap_G2O[i]-1] == i);
2428     }
2429   }
2430 #endif
2431 
2432   if (coltype_)
2433   {
2434   	delete[] coltype_;
2435   	coltype_ = NULL;
2436   }
2437 
2438   for( int i = 0; i < num; ++i )
2439     deleteColNames(columnIndices[i], 1);
2440 }
2441 
2442 //-----------------------------------------------------------------------------
2443 void
addRow(const CoinPackedVectorBase & vec,const double rowlb,const double rowub)2444 OsiGrbSolverInterface::addRow(const CoinPackedVectorBase& vec,
2445 			      const double rowlb, const double rowub)
2446 {
2447   debugMessage("OsiGrbSolverInterface::addRow(%p, %g, %g)\n", (void*)&vec, rowlb, rowub);
2448 
2449   char sense;
2450   double rhs, range;
2451 
2452   convertBoundToSense( rowlb, rowub, sense, rhs, range );
2453 
2454   addRow( vec, sense, rhs, range );
2455 }
2456 
2457 //-----------------------------------------------------------------------------
2458 void
addRow(const CoinPackedVectorBase & vec,const char rowsen,const double rowrhs,const double rowrng)2459 OsiGrbSolverInterface::addRow(const CoinPackedVectorBase& vec,
2460 			      const char rowsen, const double rowrhs,
2461 			      const double rowrng)
2462 {
2463   debugMessage("OsiGrbSolverInterface::addRow(%p, %c, %g, %g)\n", (void*)&vec, rowsen, rowrhs, rowrng);
2464 
2465   char grbsense;
2466   double rhs = rowrhs;
2467 
2468   switch( rowsen )
2469   {
2470     case 'R':
2471       /* ranged rows are added as equality rows first, and then an auxiliary variable is added */
2472       assert(rowrng > 0.0);
2473       grbsense = GRB_EQUAL;
2474       rhs = 0.0;
2475       break;
2476 
2477   	case 'N':
2478   		grbsense = GRB_LESS_EQUAL;
2479   		rhs   = getInfinity();
2480   		break;
2481 
2482   	case 'L':
2483   		grbsense = GRB_LESS_EQUAL;
2484   		break;
2485 
2486   	case 'G':
2487   		grbsense = GRB_GREATER_EQUAL;
2488   		break;
2489 
2490   	case 'E':
2491   		grbsense = GRB_EQUAL;
2492   		break;
2493 
2494   	default:
2495   	  std::cerr << "Unknown row sense: " << rowsen << std::endl;
2496   	  exit(-1);
2497   }
2498 
2499   GUROBI_CALL( "addRow", GRBupdatemodel(getMutableLpPtr()) );
2500 
2501   GUROBI_CALL( "addRow", GRBaddconstr(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_COLUMN ),
2502   		vec.getNumElements(),
2503   		const_cast<int*>(vec.getIndices()),
2504   		const_cast<double*>(vec.getElements()),
2505   		grbsense, rhs, NULL) );
2506 
2507   if( rowsen == 'R' )
2508     convertToRangedRow(getNumRows()-1, rowrhs, rowrng);
2509   else if( nauxcols )
2510     resizeAuxColIndSpace();
2511 }
2512 
2513 //-----------------------------------------------------------------------------
2514 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const double * rowlb,const double * rowub)2515 OsiGrbSolverInterface::addRows(const int numrows,
2516 			       const CoinPackedVectorBase * const * rows,
2517 			       const double* rowlb, const double* rowub)
2518 {
2519   debugMessage("OsiGrbSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, (void*)rows, (void*)rowlb, (void*)rowub);
2520 
2521   int i;
2522   int nz = 0;
2523   for (i = 0; i < numrows; ++i)
2524     nz += rows[i]->getNumElements();
2525 
2526   int* index = new int[nz];
2527   double* elem = new double[nz];
2528   int* start = new int[numrows+1];
2529   char* grbsense = new char[numrows];
2530   double* rhs = new double[numrows];
2531   double range;
2532 
2533   bool haverangedrows = false;
2534 
2535   nz = 0;
2536   start[0] = 0;
2537   for (i = 0; i < numrows; ++i)
2538   {
2539     const CoinPackedVectorBase* row = rows[i];
2540     const int len = row->getNumElements();
2541     CoinDisjointCopyN(row->getIndices(), len, index+nz);
2542     CoinDisjointCopyN(row->getElements(), len, elem+nz);
2543     nz += len;
2544     start[i+1] = nz;
2545 
2546     convertBoundToSense( rowlb[i], rowub[i], grbsense[i], rhs[i], range );
2547     if (range || grbsense[i] == 'R')
2548     {
2549       grbsense[i] = 'E';
2550       rhs[i] = 0.0;
2551       haverangedrows = true;
2552     }
2553 
2554     switch (grbsense[i])
2555     {
2556     	case 'N':
2557     		grbsense[i] = GRB_LESS_EQUAL;
2558     		rhs[i] = getInfinity();
2559     		break;
2560     	case 'L':
2561     		grbsense[i] = GRB_LESS_EQUAL;
2562     		break;
2563     	case 'G':
2564     		grbsense[i] = GRB_GREATER_EQUAL;
2565     		break;
2566     	case 'E':
2567     		grbsense[i] = GRB_EQUAL;
2568     		break;
2569     }
2570   }
2571 
2572   GUROBI_CALL( "addRows", GRBupdatemodel(getMutableLpPtr()) );
2573 
2574   GUROBI_CALL( "addRows", GRBaddconstrs(getLpPtr(OsiGrbSolverInterface::KEEPCACHED_ROW),
2575   		numrows, nz,
2576   		start, index, elem,
2577   		grbsense, rhs, NULL) );
2578 
2579   delete[] start;
2580   delete[] elem;
2581   delete[] index;
2582   delete[] grbsense;
2583   delete[] rhs;
2584 
2585   if( haverangedrows )
2586   {
2587     int nr = getNumRows() - numrows;
2588     for( i = 0; i < numrows; ++i )
2589       if( rowlb[i] > getInfinity() && rowub[i] < getInfinity() && rowub[i] - rowlb[i] > 0.0 )
2590         convertToRangedRow(nr + i, rowub[i], rowub[i] - rowlb[i]);
2591   }
2592   else if( nauxcols )
2593     resizeAuxColIndSpace();
2594 }
2595 
2596 //-----------------------------------------------------------------------------
2597 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const char * rowsen,const double * rowrhs,const double * rowrng)2598 OsiGrbSolverInterface::addRows(const int numrows,
2599 			       const CoinPackedVectorBase * const * rows,
2600 			       const char* rowsen, const double* rowrhs,
2601 			       const double* rowrng)
2602 {
2603   debugMessage("OsiGrbSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, (void*)rows, (void*)rowsen, (void*)rowrhs, (void*)rowrng);
2604 
2605   int i;
2606   int nz = 0;
2607   for (i = 0; i < numrows; ++i)
2608     nz += rows[i]->getNumElements();
2609 
2610   int* index = new int[nz];
2611   double* elem = new double[nz];
2612   int* start = new int[numrows+1];
2613   char* grbsense = new char[numrows];
2614   double* rhs = new double[numrows];
2615   bool haverangedrows = false;
2616 
2617   nz = 0;
2618   start[0] = 0;
2619   for (i = 0; i < numrows; ++i)
2620   {
2621     const CoinPackedVectorBase* row = rows[i];
2622     const int len = row->getNumElements();
2623     CoinDisjointCopyN(row->getIndices(), len, index+nz);
2624     CoinDisjointCopyN(row->getElements(), len, elem+nz);
2625     nz += len;
2626     start[i+1] = nz;
2627 
2628     rhs[i] = rowrhs[i];
2629 
2630     switch (rowsen[i])
2631     {
2632       case 'R':
2633         assert(rowrng[i] > 0.0);
2634         grbsense[i] = GRB_EQUAL;
2635         rhs[i] = 0.0;
2636         haverangedrows = true;
2637         break;
2638     	case 'N':
2639     		grbsense[i] = GRB_LESS_EQUAL;
2640     		rhs[i] = getInfinity();
2641     		break;
2642     	case 'L':
2643     		grbsense[i] = GRB_LESS_EQUAL;
2644     		break;
2645     	case 'G':
2646     		grbsense[i] = GRB_GREATER_EQUAL;
2647     		break;
2648     	case 'E':
2649     		grbsense[i] = GRB_EQUAL;
2650     		break;
2651     }
2652   }
2653 
2654   GUROBI_CALL( "addRows", GRBupdatemodel(getMutableLpPtr()) );
2655 
2656   GUROBI_CALL( "addRows", GRBaddconstrs(getLpPtr(OsiGrbSolverInterface::KEEPCACHED_ROW),
2657   		numrows, nz,
2658   		start, index, elem,
2659   		grbsense, rhs, NULL) );
2660 
2661   delete[] start;
2662   delete[] elem;
2663   delete[] index;
2664   delete[] grbsense;
2665   delete[] rhs;
2666 
2667   if( haverangedrows )
2668   {
2669     int nr = getNumRows() - numrows;
2670     for( i = 0; i < numrows; ++i )
2671       if( rowsen[i] == 'R' )
2672         convertToRangedRow(nr + i, rowrhs[i], rowrng[i]);
2673   }
2674   else if( nauxcols )
2675     resizeAuxColIndSpace();
2676 }
2677 
2678 //-----------------------------------------------------------------------------
2679 void
deleteRows(const int num,const int * rowIndices)2680 OsiGrbSolverInterface::deleteRows(const int num, const int * rowIndices)
2681 {
2682   debugMessage("OsiGrbSolverInterface::deleteRows(%d, %p)\n", num, (void*)rowIndices);
2683 
2684   if( nauxcols )
2685   { // check if a ranged row should be deleted; if so, then convert it into a normal row first
2686     for( int i = 0; i < num; ++i )
2687     {
2688       if( auxcolind[rowIndices[i]] >= 0 )
2689         convertToNormalRow(rowIndices[i], 'E', 0.0);
2690     }
2691   }
2692 
2693   GUROBI_CALL( "deleteRows", GRBdelconstrs(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_COLUMN ), num, const_cast<int*>(rowIndices)) );
2694 
2695   if( nauxcols )
2696   {
2697     int* ind = CoinCopyOfArray(rowIndices, num);
2698     qsort((void*)ind, num, sizeof(int), intcompare);
2699 
2700     int nr = getNumRows();
2701 
2702     int offset = 0;
2703     int j = 0;
2704     for( int i = 0; i < nr; ++i )
2705     {
2706       if( j < num && i == ind[j] )
2707       {
2708         ++offset;
2709         while( j < num && i == ind[j] )
2710           ++j;
2711       }
2712       auxcolind[i] = auxcolind[i + offset];
2713       if( auxcolind[i] >= 0 )
2714         colmap_G2O[auxcolind[i]] = - i - 1;
2715     }
2716     delete[] ind;
2717   }
2718 
2719 #ifndef NDEBUG
2720   if( nauxcols )
2721   {
2722     int nc = getNumCols();
2723     int nr = getNumRows();
2724     for( int i = 0; i < nc + nauxcols; ++i )
2725     {
2726       assert(i >= nc || colmap_G2O[colmap_O2G[i]] == i);
2727       assert(colmap_G2O[i] <  0 || colmap_O2G[colmap_G2O[i]] == i);
2728       assert(colmap_G2O[i] >= 0 || -colmap_G2O[i]-1 < nr);
2729       assert(colmap_G2O[i] >= 0 || auxcolind[-colmap_G2O[i]-1] == i);
2730     }
2731   }
2732 #endif
2733 
2734   for( int i = 0; i < num; ++i )
2735     deleteRowNames(rowIndices[i], 1);
2736 }
2737 
2738 //#############################################################################
2739 // Methods to input a problem
2740 //#############################################################################
2741 
2742 void
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)2743 OsiGrbSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
2744 				    const double* collb, const double* colub,
2745 				    const double* obj,
2746 				    const double* rowlb, const double* rowub )
2747 {
2748   debugMessage("OsiGrbSolverInterface::loadProblem(1)(%p, %p, %p, %p, %p, %p)\n", (void*)&matrix, (void*)collb, (void*)colub, (void*)obj, (void*)rowlb, (void*)rowub);
2749 
2750   const double inf = getInfinity();
2751 
2752   int nrows = matrix.getNumRows();
2753   char   * rowSense = new char  [nrows];
2754   double * rowRhs   = new double[nrows];
2755   double * rowRange = new double[nrows];
2756 
2757   int i;
2758   for ( i = nrows - 1; i >= 0; --i )
2759   {
2760   	const double lower = rowlb ? rowlb[i] : -inf;
2761   	const double upper = rowub ? rowub[i] : inf;
2762   	convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] );
2763   }
2764 
2765   loadProblem( matrix, collb, colub, obj, rowSense, rowRhs, rowRange );
2766   delete [] rowSense;
2767   delete [] rowRhs;
2768   delete [] rowRange;
2769 }
2770 
2771 //-----------------------------------------------------------------------------
2772 
2773 void
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,double * & rowlb,double * & rowub)2774 OsiGrbSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
2775 				      double*& collb, double*& colub,
2776 				      double*& obj,
2777 				      double*& rowlb, double*& rowub )
2778 {
2779   debugMessage("OsiGrbSolverInterface::assignProblem()\n");
2780 
2781   loadProblem( *matrix, collb, colub, obj, rowlb, rowub );
2782   delete matrix;   matrix = 0;
2783   delete[] collb;  collb = 0;
2784   delete[] colub;  colub = 0;
2785   delete[] obj;    obj = 0;
2786   delete[] rowlb;  rowlb = 0;
2787   delete[] rowub;  rowub = 0;
2788 }
2789 
2790 //-----------------------------------------------------------------------------
2791 
2792 void
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)2793 OsiGrbSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
2794 				    const double* collb, const double* colub,
2795 				    const double* obj,
2796 				    const char* rowsen, const double* rowrhs,
2797 				    const double* rowrng )
2798 {
2799 	debugMessage("OsiGrbSolverInterface::loadProblem(2)(%p, %p, %p, %p, %p, %p, %p)\n",
2800 			(void*)&matrix, (void*)collb, (void*)colub, (void*)obj, (void*)rowsen, (void*)rowrhs, (void*)rowrng);
2801 
2802 	int nc = matrix.getNumCols();
2803 	int nr = matrix.getNumRows();
2804 	int i;
2805 
2806 	char* myrowsen = new char[nr];
2807 	double* myrowrhs = new double[nr];
2808 	bool haverangedrows = false;
2809 
2810 	for ( i = 0; i < nr; ++i )
2811 	{
2812 		if (rowrhs)
2813 			myrowrhs[i] = rowrhs[i];
2814 		else
2815 			myrowrhs[i] = 0.0;
2816 
2817 		if (rowsen)
2818 			switch (rowsen[i])
2819 			{
2820 				case 'R':
2821 				  assert( rowrng && rowrng[i] > 0.0 );
2822 				  myrowsen[i] = GRB_EQUAL;
2823 				  myrowrhs[i] = 0.0;
2824 				  haverangedrows = true;
2825 				  break;
2826 
2827 				case 'N':
2828 					myrowsen[i] = GRB_LESS_EQUAL;
2829 					myrowrhs[i] = getInfinity();
2830 					break;
2831 
2832 				case 'L':
2833 					myrowsen[i] = GRB_LESS_EQUAL;
2834 					break;
2835 
2836 				case 'G':
2837 					myrowsen[i] = GRB_GREATER_EQUAL;
2838 					break;
2839 
2840 				case 'E':
2841 					myrowsen[i] = GRB_EQUAL;
2842 					break;
2843 			}
2844 		else
2845 			myrowsen[i] = 'G';
2846 	}
2847 
2848 	// Set column values to defaults if NULL pointer passed
2849 	double * clb;
2850 	double * cub;
2851 	double * ob;
2852 	if ( collb != NULL )
2853 		clb = const_cast<double*>(collb);
2854 	else
2855 	{
2856 		clb = new double[nc];
2857 		CoinFillN(clb, nc, 0.0);
2858 	}
2859 
2860 	if ( colub!=NULL )
2861 		cub = const_cast<double*>(colub);
2862 	else
2863 	{
2864 		cub = new double[nc];
2865 		CoinFillN(cub, nc, getInfinity());
2866 	}
2867 
2868 	if ( obj!=NULL )
2869 		ob = const_cast<double*>(obj);
2870 	else
2871 	{
2872 		ob = new double[nc];
2873 		CoinFillN(ob, nc, 0.0);
2874 	}
2875 
2876 	bool freeMatrixRequired = false;
2877 	CoinPackedMatrix * m = NULL;
2878 
2879   if( !matrix.isColOrdered() )
2880   {
2881     m = new CoinPackedMatrix();
2882     m->reverseOrderedCopyOf(matrix);
2883     freeMatrixRequired = true;
2884   }
2885   else
2886     m = const_cast<CoinPackedMatrix *>(&matrix);
2887 
2888   // up to GUROBI 2.0.1, GUROBI may give an "Index is out of range" error if the constraint matrix has uninitalized "gaps"
2889 #if (GRB_VERSION_MAJOR < 2) || (GRB_VERSION_MAJOR == 2 && GRB_VERSION_MINOR == 0 && GRB_VERSION_TECHNICAL <= 1)
2890 	if ( m->hasGaps() )
2891 	{
2892 	  if( freeMatrixRequired )
2893 	  {
2894 	    m->removeGaps();
2895 	  }
2896 	  else
2897 	  {
2898       m = new CoinPackedMatrix(matrix);
2899       if( m->hasGaps() )
2900         m->removeGaps();
2901       freeMatrixRequired = true;
2902 	  }
2903 	}
2904 #endif
2905 
2906 	assert( nc == m->getNumCols() );
2907 	assert( nr == m->getNumRows() );
2908 	assert( m->isColOrdered() );
2909 
2910 	int modelsense;
2911 	GUROBI_CALL( "loadProblem", GRBupdatemodel(getMutableLpPtr()) );
2912 
2913 	GUROBI_CALL( "loadProblem", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_MODELSENSE, &modelsense) );
2914 
2915 	std::string pn;
2916 	getStrParam(OsiProbName, pn);
2917 
2918 	gutsOfDestructor(); // kill old LP, if any
2919 
2920 	GUROBI_CALL( "loadProblem", GRBloadmodel(getEnvironmentPtr(), &lp_, const_cast<char*>(pn.c_str()),
2921 			nc, nr,
2922 			modelsense,
2923 			0.0,
2924 			ob,
2925 			const_cast<char *>(myrowsen),
2926 			myrowrhs,
2927 			const_cast<int *>(m->getVectorStarts()),
2928 			const_cast<int *>(m->getVectorLengths()),
2929 			const_cast<int *>(m->getIndices()),
2930 			const_cast<double *>(m->getElements()),
2931 			const_cast<double *>(clb),
2932 			const_cast<double *>(cub),
2933 			NULL, NULL, NULL) );
2934 
2935   // GUROBI up to version 2.0.1 may return a scaled LP after GRBoptimize when requesting it via GRBgetvars
2936 #if (GRB_VERSION_MAJOR < 2) || (GRB_VERSION_MAJOR == 2 && GRB_VERSION_MINOR == 0 && GRB_VERSION_TECHNICAL <= 1)
2937   setHintParam(OsiDoScale, false);
2938 #endif
2939 
2940 	delete[] myrowsen;
2941 	delete[] myrowrhs;
2942 	if ( collb == NULL )
2943 		delete[] clb;
2944 	if ( colub == NULL )
2945 		delete[] cub;
2946 	if ( obj   == NULL )
2947 		delete[] ob;
2948 	if ( freeMatrixRequired )
2949 		delete m;
2950 
2951 	resizeColSpace(nc);
2952 	CoinFillN(coltype_, nc, GRB_CONTINUOUS);
2953 
2954 	if( haverangedrows )
2955 	{
2956 	  assert(rowrhs);
2957 	  assert(rowrng);
2958 	  assert(rowsen);
2959     for ( i = 0; i < nr; ++i )
2960       if( rowsen[i] == 'R' )
2961         convertToRangedRow(i, rowrhs[i], rowrng[i]);
2962 	}
2963 }
2964 
2965 //-----------------------------------------------------------------------------
2966 
2967 void
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,char * & rowsen,double * & rowrhs,double * & rowrng)2968 OsiGrbSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
2969 				      double*& collb, double*& colub,
2970 				      double*& obj,
2971 				      char*& rowsen, double*& rowrhs,
2972 				      double*& rowrng )
2973 {
2974   debugMessage("OsiGrbSolverInterface::assignProblem()\n");
2975 
2976   loadProblem( *matrix, collb, colub, obj, rowsen, rowrhs, rowrng );
2977   delete matrix;   matrix = NULL;
2978   delete[] collb;  collb = NULL;
2979   delete[] colub;  colub = NULL;
2980   delete[] obj;    obj = NULL;
2981   delete[] rowsen; rowsen = NULL;
2982   delete[] rowrhs; rowrhs = NULL;
2983   delete[] rowrng; rowrng = NULL;
2984 }
2985 
2986 //-----------------------------------------------------------------------------
2987 
2988 void
loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)2989 OsiGrbSolverInterface::loadProblem(const int numcols, const int numrows,
2990 				   const int* start, const int* index,
2991 				   const double* value,
2992 				   const double* collb, const double* colub,
2993 				   const double* obj,
2994 				   const double* rowlb, const double* rowub )
2995 {
2996   debugMessage("OsiGrbSolverInterface::loadProblem(3)()\n");
2997 
2998   const double inf = getInfinity();
2999 
3000   char   * rowSense = new char  [numrows];
3001   double * rowRhs   = new double[numrows];
3002   double * rowRange = new double[numrows];
3003 
3004   for ( int i = numrows - 1; i >= 0; --i ) {
3005     const double lower = rowlb ? rowlb[i] : -inf;
3006     const double upper = rowub ? rowub[i] : inf;
3007     convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] );
3008   }
3009 
3010   loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowSense, rowRhs, rowRange);
3011 
3012   delete [] rowSense;
3013   delete [] rowRhs;
3014   delete [] rowRange;
3015 }
3016 
3017 //-----------------------------------------------------------------------------
3018 
3019 void
loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)3020 OsiGrbSolverInterface::loadProblem(const int numcols, const int numrows,
3021 				   const int* start, const int* index,
3022 				   const double* value,
3023 				   const double* collb, const double* colub,
3024 				   const double* obj,
3025 				   const char* rowsen, const double* rowrhs,
3026 				   const double* rowrng )
3027 {
3028   debugMessage("OsiGrbSolverInterface::loadProblem(4)(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n",
3029   		numcols, numrows, (void*)start, (void*)index, (void*)value, (void*)collb, (void*)colub, (void*)obj, (void*)rowsen, (void*)rowrhs, (void*)rowrng);
3030 
3031 	int nc = numcols;
3032 	int nr = numrows;
3033 	int i;
3034 
3035 	char* myrowsen = new char[nr];
3036 	double* myrowrhs = new double[nr];
3037 	bool haverangedrows = false;
3038 
3039 	for ( i=0; i<nr; i++ )
3040 	{
3041 		if (rowrhs)
3042 			myrowrhs[i] = rowrhs[i];
3043 		else
3044 			myrowrhs[i] = 0.0;
3045 
3046 		if (rowsen)
3047 			switch (rowsen[i])
3048 			{
3049 				case 'R':
3050 				  assert(rowrng && rowrng[i] > 0.0);
3051 				  myrowsen[i] = GRB_EQUAL;
3052 				  myrowrhs[i] = 0.0;
3053 				  haverangedrows = true;
3054 				  break;
3055 
3056 				case 'N':
3057 					myrowsen[i] = GRB_LESS_EQUAL;
3058 					myrowrhs[i] = getInfinity();
3059 					break;
3060 
3061 				case 'L':
3062 					myrowsen[i] = GRB_LESS_EQUAL;
3063 					break;
3064 
3065 				case 'G':
3066 					myrowsen[i] = GRB_GREATER_EQUAL;
3067 					break;
3068 
3069 				case 'E':
3070 					myrowsen[i] = GRB_EQUAL;
3071 					break;
3072 			}
3073 		else
3074 			myrowsen[i] = 'G';
3075 	}
3076 
3077 	// Set column values to defaults if NULL pointer passed
3078 	double * clb;
3079 	double * cub;
3080 	double * ob;
3081 	if ( collb != NULL )
3082 		clb = const_cast<double*>(collb);
3083 	else
3084 	{
3085 		clb = new double[nc];
3086 		CoinFillN(clb, nc, 0.0);
3087 	}
3088 
3089 	if ( colub!=NULL )
3090 		cub = const_cast<double*>(colub);
3091 	else
3092 	{
3093 		cub = new double[nc];
3094 		CoinFillN(cub, nc, getInfinity());
3095 	}
3096 
3097 	if ( obj!=NULL )
3098 		ob = const_cast<double*>(obj);
3099 	else
3100 	{
3101 		ob = new double[nc];
3102 		CoinFillN(ob, nc, 0.0);
3103 	}
3104 
3105 	int* len = new int[nc];
3106 	for (i = 0; i < nc; ++i)
3107 		len[i] = start[i+1] - start[i];
3108 
3109 	GUROBI_CALL( "loadProblem", GRBupdatemodel(getMutableLpPtr()) );
3110 
3111 	int modelsense;
3112 	GUROBI_CALL( "loadProblem", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_MODELSENSE, &modelsense) );
3113 
3114 	std::string pn;
3115 	getStrParam(OsiProbName, pn);
3116 
3117 	gutsOfDestructor(); // kill old LP, if any
3118 
3119 	GUROBI_CALL( "loadProblem", GRBloadmodel(getEnvironmentPtr(), &lp_, const_cast<char*>(pn.c_str()),
3120 			nc, nr,
3121 			modelsense,
3122 			0.0,
3123 			ob,
3124 			myrowsen,
3125 			myrowrhs,
3126 			const_cast<int*>(start), len,
3127 			const_cast<int*>(index),
3128 			const_cast<double*>(value),
3129 			const_cast<double *>(clb),
3130 			const_cast<double *>(cub),
3131 			NULL, NULL, NULL) );
3132 
3133   // GUROBI up to version 2.0.1 may return a scaled LP after GRBoptimize when requesting it via GRBgetvars
3134 #if (GRB_VERSION_MAJOR < 2) || (GRB_VERSION_MAJOR == 2 && GRB_VERSION_MINOR == 0 && GRB_VERSION_TECHNICAL <= 1)
3135   setHintParam(OsiDoScale, false);
3136 #endif
3137 
3138 	delete[] myrowsen;
3139 	delete[] myrowrhs;
3140 	if ( collb == NULL )
3141 		delete[] clb;
3142 	if ( colub == NULL )
3143 		delete[] cub;
3144 	if ( obj   == NULL )
3145 		delete[] ob;
3146 	delete[] len;
3147 
3148 	resizeColSpace(nc);
3149 	CoinFillN(coltype_, nc, GRB_CONTINUOUS);
3150 
3151 	if( haverangedrows )
3152 	{
3153 	  assert(rowrhs);
3154 	  assert(rowrng);
3155 	  assert(rowsen);
3156 	  for ( i = 0; i < nr; ++i )
3157 	    if( rowsen[i] == 'R' )
3158 	      convertToRangedRow(i, rowrhs[i], rowrng[i]);
3159 	}
3160 }
3161 
3162 //-----------------------------------------------------------------------------
3163 // Read mps files
3164 //-----------------------------------------------------------------------------
readMps(const char * filename,const char * extension)3165 int OsiGrbSolverInterface::readMps( const char * filename,
3166 				     const char * extension )
3167 {
3168   debugMessage("OsiGrbSolverInterface::readMps(%s, %s)\n", filename, extension);
3169 
3170   // just call base class method
3171   return OsiSolverInterface::readMps(filename,extension);
3172 }
3173 
3174 
3175 //-----------------------------------------------------------------------------
3176 // Write mps files
3177 //-----------------------------------------------------------------------------
writeMps(const char * filename,const char * extension,double objSense) const3178 void OsiGrbSolverInterface::writeMps( const char * filename,
3179 				      const char * extension,
3180 				      double objSense ) const
3181 {
3182   debugMessage("OsiGrbSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense);
3183 
3184   std::string f(filename);
3185   std::string e(extension);
3186   std::string fullname = f + "." + e;
3187 
3188   //TODO give row and column names?
3189   writeMpsNative(fullname.c_str(), NULL, NULL);
3190 
3191   // do not call Gurobi's MPS writer, because
3192   // 1. it only writes mps if the extension is mps
3193   // 2. the instance in Gurobi may have extra columns due to reformulated ranged rows, that may be confusing
3194 //  GUROBI_CALL( "writeMps", GRBwrite(getMutableLpPtr(), const_cast<char*>(fullname.c_str())) );
3195 }
3196 
3197 //#############################################################################
3198 // CPX specific public interfaces
3199 //#############################################################################
3200 
getEnvironmentPtr() const3201 GRBenv* OsiGrbSolverInterface::getEnvironmentPtr() const
3202 {
3203   assert( localenv_ != NULL || globalenv_ != NULL );
3204   return localenv_ ? localenv_ : globalenv_;
3205 }
3206 
getLpPtr(int keepCached)3207 GRBmodel* OsiGrbSolverInterface::getLpPtr( int keepCached )
3208 {
3209   freeCachedData( keepCached );
3210   return getMutableLpPtr();
3211 }
3212 
3213 /// Return whether the current Gurobi environment runs in demo mode.
isDemoLicense() const3214 bool OsiGrbSolverInterface::isDemoLicense() const
3215 {
3216   debugMessage("OsiGrbSolverInterface::isDemoLicense()\n");
3217 
3218   GRBenv* env = getEnvironmentPtr();
3219 
3220   GRBmodel* testlp;
3221 
3222   // a Gurobi demo license allows to solve only models with up to 500 variables
3223   // thus, let's try to create and solve a model with 1000 variables
3224   GUROBI_CALL( "isDemoLicense", GRBnewmodel(env, &testlp, "licensetest", 1000, NULL, NULL, NULL, NULL, NULL) );
3225 //  GUROBI_CALL( "resolve", GRBsetintparam(GRBgetenv(testlp), GRB_INT_PAR_PRESOLVE, presolve) );
3226 
3227   int rc = GRBoptimize(testlp);
3228 
3229   if(rc == GRB_ERROR_SIZE_LIMIT_EXCEEDED)
3230     return true;
3231 
3232   GUROBI_CALL( "isDemoLicense", rc );
3233 
3234   GRBfreemodel(testlp);
3235 
3236   return false;
3237 }
3238 
3239 //-----------------------------------------------------------------------------
3240 
getCtype() const3241 const char * OsiGrbSolverInterface::getCtype() const
3242 {
3243   debugMessage("OsiGrbSolverInterface::getCtype()\n");
3244 
3245   return coltype_;
3246 }
3247 
3248 //#############################################################################
3249 // Static instance counter methods
3250 //#############################################################################
3251 
incrementInstanceCounter()3252 void OsiGrbSolverInterface::incrementInstanceCounter()
3253 {
3254 	if ( numInstances_ == 0 && !globalenv_)
3255 	{
3256 	  GUROBI_CALL( "incrementInstanceCounter", GRBloadenv( &globalenv_, NULL ) );
3257 		assert( globalenv_ != NULL );
3258 		globalenv_is_ours = true;
3259 	}
3260   numInstances_++;
3261 }
3262 
3263 //-----------------------------------------------------------------------------
3264 
decrementInstanceCounter()3265 void OsiGrbSolverInterface::decrementInstanceCounter()
3266 {
3267 	assert( numInstances_ != 0 );
3268 	assert( globalenv_ != NULL );
3269 	numInstances_--;
3270 	if ( numInstances_ == 0 && globalenv_is_ours)
3271 	{
3272 		GRBfreeenv( globalenv_ );
3273 		globalenv_ = NULL;
3274 	}
3275 }
3276 
3277 //-----------------------------------------------------------------------------
3278 
getNumInstances()3279 unsigned int OsiGrbSolverInterface::getNumInstances()
3280 {
3281   return numInstances_;
3282 }
3283 
setEnvironment(GRBenv * globalenv)3284 void OsiGrbSolverInterface::setEnvironment(GRBenv* globalenv)
3285 {
3286 	if (numInstances_)
3287 	{
3288 		assert(globalenv_);
3289 		throw CoinError("Cannot set global GUROBI environment, since some OsiGrb instance is still using it.", "setEnvironment", "OsiGrbSolverInterface", __FILE__, __LINE__);
3290 	}
3291 
3292 	assert(!globalenv_ || !globalenv_is_ours);
3293 
3294 	globalenv_ = globalenv;
3295 	globalenv_is_ours = false;
3296 }
3297 
3298 
3299 //#############################################################################
3300 // Constructors, destructors clone and assignment
3301 //#############################################################################
3302 
3303 //-------------------------------------------------------------------
3304 // Default Constructor
3305 //-------------------------------------------------------------------
OsiGrbSolverInterface(bool use_local_env)3306 OsiGrbSolverInterface::OsiGrbSolverInterface(bool use_local_env)
3307   : OsiSolverInterface(),
3308     localenv_(NULL),
3309     lp_(NULL),
3310     hotStartCStat_(NULL),
3311     hotStartCStatSize_(0),
3312     hotStartRStat_(NULL),
3313     hotStartRStatSize_(0),
3314     hotStartMaxIteration_(1000000), // ??? default iteration limit for strong branching is large
3315     nameDisc_(0),
3316     obj_(NULL),
3317     collower_(NULL),
3318     colupper_(NULL),
3319     rowsense_(NULL),
3320     rhs_(NULL),
3321     rowrange_(NULL),
3322     rowlower_(NULL),
3323     rowupper_(NULL),
3324     colsol_(NULL),
3325     rowsol_(NULL),
3326     redcost_(NULL),
3327     rowact_(NULL),
3328     matrixByRow_(NULL),
3329     matrixByCol_(NULL),
3330     probtypemip_(false),
3331     domipstart(false),
3332     colspace_(0),
3333     coltype_(NULL),
3334     nauxcols(0),
3335     auxcolspace(0),
3336     colmap_O2G(NULL),
3337     colmap_G2O(NULL),
3338     auxcolindspace(0),
3339     auxcolind(NULL)
3340 {
3341   debugMessage("OsiGrbSolverInterface::OsiGrbSolverInterface()\n");
3342 
3343   if (use_local_env)
3344   {
3345     GUROBI_CALL( "OsiGrbSolverInterface", GRBloadenv( &localenv_, NULL ) );
3346 		assert( localenv_ != NULL );
3347   }
3348   else
3349   	incrementInstanceCounter();
3350 
3351   gutsOfConstructor();
3352 
3353   // change Osi default to Gurobi default
3354   setHintParam(OsiDoDualInInitial,true,OsiHintTry);
3355 }
3356 
OsiGrbSolverInterface(GRBenv * localgrbenv)3357 OsiGrbSolverInterface::OsiGrbSolverInterface(GRBenv* localgrbenv)
3358   : OsiSolverInterface(),
3359     localenv_(localgrbenv),
3360     lp_(NULL),
3361     hotStartCStat_(NULL),
3362     hotStartCStatSize_(0),
3363     hotStartRStat_(NULL),
3364     hotStartRStatSize_(0),
3365     hotStartMaxIteration_(1000000), // ??? default iteration limit for strong branching is large
3366     nameDisc_(0),
3367     obj_(NULL),
3368     collower_(NULL),
3369     colupper_(NULL),
3370     rowsense_(NULL),
3371     rhs_(NULL),
3372     rowrange_(NULL),
3373     rowlower_(NULL),
3374     rowupper_(NULL),
3375     colsol_(NULL),
3376     rowsol_(NULL),
3377     redcost_(NULL),
3378     rowact_(NULL),
3379     matrixByRow_(NULL),
3380     matrixByCol_(NULL),
3381     probtypemip_(false),
3382     domipstart(false),
3383     colspace_(0),
3384     coltype_(NULL),
3385     nauxcols(0),
3386     auxcolspace(0),
3387     colmap_O2G(NULL),
3388     colmap_G2O(NULL),
3389     auxcolindspace(0),
3390     auxcolind(NULL)
3391 {
3392   debugMessage("OsiGrbSolverInterface::OsiGrbSolverInterface()\n");
3393 
3394   if (localenv_ == NULL)
3395   { // if user called this constructor with NULL pointer, we assume that he meant that a local environment should be created
3396     GUROBI_CALL( "OsiGrbSolverInterface", GRBloadenv( &localenv_, NULL ) );
3397 		assert( localenv_ != NULL );
3398   }
3399 
3400   gutsOfConstructor();
3401 
3402   // change Osi default to Gurobi default
3403   setHintParam(OsiDoDualInInitial,true,OsiHintTry);
3404 }
3405 
3406 
3407 //----------------------------------------------------------------
3408 // Clone
3409 //----------------------------------------------------------------
clone(bool copyData) const3410 OsiSolverInterface * OsiGrbSolverInterface::clone(bool copyData) const
3411 {
3412   debugMessage("OsiGrbSolverInterface::clone(%d)\n", copyData);
3413 
3414   return( new OsiGrbSolverInterface( *this ) );
3415 }
3416 
3417 //-------------------------------------------------------------------
3418 // Copy constructor
3419 //-------------------------------------------------------------------
OsiGrbSolverInterface(const OsiGrbSolverInterface & source)3420 OsiGrbSolverInterface::OsiGrbSolverInterface( const OsiGrbSolverInterface & source )
3421   : OsiSolverInterface(source),
3422     localenv_(NULL),
3423     lp_(NULL),
3424     hotStartCStat_(NULL),
3425     hotStartCStatSize_(0),
3426     hotStartRStat_(NULL),
3427     hotStartRStatSize_(0),
3428     hotStartMaxIteration_(source.hotStartMaxIteration_),
3429     nameDisc_(source.nameDisc_),
3430     obj_(NULL),
3431     collower_(NULL),
3432     colupper_(NULL),
3433     rowsense_(NULL),
3434     rhs_(NULL),
3435     rowrange_(NULL),
3436     rowlower_(NULL),
3437     rowupper_(NULL),
3438     colsol_(NULL),
3439     rowsol_(NULL),
3440     redcost_(NULL),
3441     rowact_(NULL),
3442     matrixByRow_(NULL),
3443     matrixByCol_(NULL),
3444     probtypemip_(false),
3445     domipstart(false),
3446     colspace_(0),
3447     coltype_(NULL),
3448     nauxcols(0),
3449     auxcolspace(0),
3450     colmap_O2G(NULL),
3451     colmap_G2O(NULL),
3452     auxcolindspace(0),
3453     auxcolind(NULL)
3454 {
3455   debugMessage("OsiGrbSolverInterface::OsiGrbSolverInterface(%p)\n", (void*)&source);
3456 
3457   if (source.localenv_) {
3458     GUROBI_CALL( "OsiGrbSolverInterface", GRBloadenv( &localenv_, NULL ) );
3459 		assert( localenv_ != NULL );
3460   } else
3461   	incrementInstanceCounter();
3462 
3463   gutsOfConstructor();
3464   gutsOfCopy( source );
3465 }
3466 
3467 
3468 //-------------------------------------------------------------------
3469 // Destructor
3470 //-------------------------------------------------------------------
~OsiGrbSolverInterface()3471 OsiGrbSolverInterface::~OsiGrbSolverInterface()
3472 {
3473   debugMessage("OsiGrbSolverInterface::~OsiGrbSolverInterface()\n");
3474 
3475   gutsOfDestructor();
3476   if (localenv_) {
3477 		GRBfreeenv( localenv_ );
3478   } else
3479   	decrementInstanceCounter();
3480 }
3481 
3482 //----------------------------------------------------------------
3483 // Assignment operator
3484 //-------------------------------------------------------------------
operator =(const OsiGrbSolverInterface & rhs)3485 OsiGrbSolverInterface& OsiGrbSolverInterface::operator=( const OsiGrbSolverInterface& rhs )
3486 {
3487   debugMessage("OsiGrbSolverInterface::operator=(%p)\n", (void*)&rhs);
3488 
3489   if (this != &rhs)
3490   {
3491   	OsiSolverInterface::operator=( rhs );
3492   	gutsOfDestructor();
3493   	gutsOfConstructor();
3494   	if ( rhs.lp_ !=NULL )
3495   		gutsOfCopy( rhs );
3496   }
3497 
3498   return *this;
3499 }
3500 
3501 //#############################################################################
3502 // Applying cuts
3503 //#############################################################################
3504 
applyColCut(const OsiColCut & cc)3505 void OsiGrbSolverInterface::applyColCut( const OsiColCut & cc )
3506 {
3507 	debugMessage("OsiGrbSolverInterface::applyColCut(%p)\n", (void*)&cc);
3508 
3509 	const double * gurobiColLB = getColLower();
3510 	const double * gurobiColUB = getColUpper();
3511 	const CoinPackedVector & lbs = cc.lbs();
3512 	const CoinPackedVector & ubs = cc.ubs();
3513 	int i;
3514 
3515 	for( i = 0; i < lbs.getNumElements(); ++i )
3516 		if ( lbs.getElements()[i] > gurobiColLB[lbs.getIndices()[i]] )
3517 			setColLower( lbs.getIndices()[i], lbs.getElements()[i] );
3518 	for( i = 0; i < ubs.getNumElements(); ++i )
3519 		if ( ubs.getElements()[i] < gurobiColUB[ubs.getIndices()[i]] )
3520 			setColUpper( ubs.getIndices()[i], ubs.getElements()[i] );
3521 }
3522 
3523 //-----------------------------------------------------------------------------
3524 
applyRowCut(const OsiRowCut & rowCut)3525 void OsiGrbSolverInterface::applyRowCut( const OsiRowCut & rowCut )
3526 {
3527   debugMessage("OsiGrbSolverInterface::applyRowCut(%p)\n", (void*)&rowCut);
3528 
3529   double rhs = 0.0;
3530   char sns;
3531   double lb = rowCut.lb();
3532   double ub = rowCut.ub();
3533   bool isrange = false;
3534   if( lb <= -getInfinity() && ub >= getInfinity() )   // free constraint
3535   {
3536   	rhs = getInfinity();
3537   	sns = GRB_LESS_EQUAL;
3538   }
3539   else if( lb <= -getInfinity() )  // <= constraint
3540   {
3541   	rhs = ub;
3542   	sns = GRB_LESS_EQUAL;
3543   }
3544   else if( ub >= getInfinity() )  // >= constraint
3545   {
3546   	rhs = lb;
3547   	sns = GRB_GREATER_EQUAL;
3548   }
3549   else if( ub == lb )  // = constraint
3550   {
3551   	rhs = ub;
3552   	sns = GRB_EQUAL;
3553   }
3554   else  // range constraint
3555   {
3556     rhs = 0.0;
3557     sns = GRB_EQUAL;
3558     isrange = true;
3559   }
3560 
3561   GUROBI_CALL( "applyRowCut", GRBaddconstr( getLpPtr( OsiGrbSolverInterface::KEEPCACHED_COLUMN ),
3562   	rowCut.row().getNumElements(),
3563 		const_cast<int*>( rowCut.row().getIndices() ),
3564 		const_cast<double*>( rowCut.row().getElements() ),
3565 		sns, rhs, NULL) );
3566 
3567   if( isrange )
3568   {
3569     convertToRangedRow(getNumRows()-1, ub, ub - lb);
3570   }
3571   else if( nauxcols )
3572     resizeAuxColIndSpace();
3573 }
3574 
3575 //#############################################################################
3576 // Private methods (non-static and static) and static data
3577 //#############################################################################
3578 
3579 //------------------------------------------------------------------
3580 // Static data
3581 //------------------------------------------------------------------
3582 GRBenv* OsiGrbSolverInterface::globalenv_ = NULL;
3583 bool OsiGrbSolverInterface::globalenv_is_ours = true;
3584 unsigned int OsiGrbSolverInterface::numInstances_ = 0;
3585 
3586 //-------------------------------------------------------------------
3587 // Get pointer to GRBmodel*.
3588 // const methods should use getMutableLpPtr().
3589 // non-const methods should use getLpPtr().
3590 //-------------------------------------------------------------------
getMutableLpPtr() const3591 GRBmodel* OsiGrbSolverInterface::getMutableLpPtr() const
3592 {
3593   if ( lp_ == NULL )
3594   {
3595     assert(getEnvironmentPtr() != NULL);
3596 
3597     GUROBI_CALL( "getMutableLpPtr", GRBnewmodel(getEnvironmentPtr(), &lp_, "OsiGrb_problem", 0, NULL, NULL, NULL, NULL, NULL) );
3598     assert( lp_ != NULL );
3599 
3600     // GUROBI up to version 2.0.1 may return a scaled LP after GRBoptimize when requesting it via GRBgetvars
3601 #if (GRB_VERSION_MAJOR < 2) || (GRB_VERSION_MAJOR == 2 && GRB_VERSION_MINOR == 0 && GRB_VERSION_TECHNICAL <= 1)
3602     GUROBI_CALL( "getMutableLpPtr", GRBsetintparam(GRBgetenv(lp_), GRB_INT_PAR_SCALEFLAG, 0) );
3603 #endif
3604   }
3605   return lp_;
3606 }
3607 
3608 //-------------------------------------------------------------------
3609 
gutsOfCopy(const OsiGrbSolverInterface & source)3610 void OsiGrbSolverInterface::gutsOfCopy( const OsiGrbSolverInterface & source )
3611 {
3612   // Set Rim and constraints
3613   const double* obj = source.getObjCoefficients();
3614   const double* rhs = source.getRightHandSide();
3615   const char* sense = source.getRowSense();
3616   const CoinPackedMatrix * cols = source.getMatrixByCol();
3617   const double* lb = source.getColLower();
3618   const double* ub = source.getColUpper();
3619   loadProblem(*cols,lb,ub,obj,sense,rhs,source.getRowRange());
3620 
3621   // Set Objective Sense
3622   setObjSense(source.getObjSense());
3623 
3624   // Set Objective Constant
3625   double dblParam;
3626   source.getDblParam(OsiObjOffset,dblParam) ;
3627   setDblParam(OsiObjOffset,dblParam) ;
3628 
3629   // Set MIP information
3630   resizeColSpace(source.colspace_);
3631   CoinDisjointCopyN( source.coltype_, source.colspace_, coltype_ );
3632 
3633   // Set Problem name
3634   std::string strParam;
3635   source.getStrParam(OsiProbName,strParam) ;
3636   setStrParam(OsiProbName,strParam) ;
3637 
3638   // Set Solution - not supported by Gurobi
3639 //  setColSolution(source.getColSolution());
3640 //  setRowPrice(source.getRowPrice());
3641 }
3642 
3643 //-------------------------------------------------------------------
gutsOfConstructor()3644 void OsiGrbSolverInterface::gutsOfConstructor()
3645 { }
3646 
3647 //-------------------------------------------------------------------
gutsOfDestructor()3648 void OsiGrbSolverInterface::gutsOfDestructor()
3649 {
3650   debugMessage("OsiGrbSolverInterface::gutsOfDestructor()\n");
3651 
3652   if ( lp_ != NULL )
3653   {
3654     GUROBI_CALL( "gutsOfDestructor", GRBfreemodel(lp_) );
3655   	lp_ = NULL;
3656   	freeAllMemory();
3657   }
3658   assert( lp_==NULL );
3659   assert( obj_==NULL );
3660   assert( collower_==NULL );
3661   assert( colupper_==NULL );
3662   assert( rowsense_==NULL );
3663   assert( rhs_==NULL );
3664   assert( rowrange_==NULL );
3665   assert( rowlower_==NULL );
3666   assert( rowupper_==NULL );
3667   assert( colsol_==NULL );
3668   assert( rowsol_==NULL );
3669   assert( redcost_==NULL );
3670   assert( rowact_==NULL );
3671   assert( matrixByRow_==NULL );
3672   assert( matrixByCol_==NULL );
3673   assert( coltype_==NULL );
3674   assert( colspace_==0 );
3675   assert( auxcolspace == 0);
3676   assert( auxcolindspace == 0 );
3677 }
3678 
3679 //-------------------------------------------------------------------
3680 /// free cached vectors
3681 
freeCachedColRim()3682 void OsiGrbSolverInterface::freeCachedColRim()
3683 {
3684   freeCacheDouble( obj_ );
3685   freeCacheDouble( collower_ );
3686   freeCacheDouble( colupper_ );
3687   assert( obj_==NULL );
3688   assert( collower_==NULL );
3689   assert( colupper_==NULL );
3690 }
3691 
freeCachedRowRim()3692 void OsiGrbSolverInterface::freeCachedRowRim()
3693 {
3694   freeCacheChar( rowsense_ );
3695   freeCacheDouble( rhs_ );
3696   freeCacheDouble( rowrange_ );
3697   freeCacheDouble( rowlower_ );
3698   freeCacheDouble( rowupper_ );
3699   assert( rowsense_==NULL );
3700   assert( rhs_==NULL );
3701   assert( rowrange_==NULL );
3702   assert( rowlower_==NULL );
3703   assert( rowupper_==NULL );
3704  }
3705 
freeCachedMatrix()3706 void OsiGrbSolverInterface::freeCachedMatrix()
3707 {
3708   freeCacheMatrix( matrixByRow_ );
3709   freeCacheMatrix( matrixByCol_ );
3710   assert( matrixByRow_==NULL );
3711   assert( matrixByCol_==NULL );
3712 }
3713 
freeCachedResults()3714 void OsiGrbSolverInterface::freeCachedResults()
3715 {
3716   freeCacheDouble( colsol_ );
3717   freeCacheDouble( rowsol_ );
3718   freeCacheDouble( redcost_ );
3719   freeCacheDouble( rowact_ );
3720   assert( colsol_==NULL );
3721   assert( rowsol_==NULL );
3722   assert( redcost_==NULL );
3723   assert( rowact_==NULL );
3724 }
3725 
3726 
freeCachedData(int keepCached)3727 void OsiGrbSolverInterface::freeCachedData( int keepCached )
3728 {
3729   if( !(keepCached & OsiGrbSolverInterface::KEEPCACHED_COLUMN) )
3730     freeCachedColRim();
3731   if( !(keepCached & OsiGrbSolverInterface::KEEPCACHED_ROW) )
3732     freeCachedRowRim();
3733   if( !(keepCached & OsiGrbSolverInterface::KEEPCACHED_MATRIX) )
3734     freeCachedMatrix();
3735   if( !(keepCached & OsiGrbSolverInterface::KEEPCACHED_RESULTS) )
3736     freeCachedResults();
3737 }
3738 
freeAllMemory()3739 void OsiGrbSolverInterface::freeAllMemory()
3740 {
3741   freeCachedData();
3742   if( hotStartCStat_ != NULL )
3743     delete[] hotStartCStat_;
3744   if( hotStartRStat_ != NULL )
3745     delete[] hotStartRStat_;
3746   hotStartCStat_     = NULL;
3747   hotStartCStatSize_ = 0;
3748   hotStartRStat_     = NULL;
3749   hotStartRStatSize_ = 0;
3750   freeColSpace();
3751   delete[] auxcolind;
3752   auxcolind = NULL;
3753   auxcolindspace = 0;
3754 }
3755 
3756 /// converts a normal row into a ranged row by adding an auxiliary variable
convertToRangedRow(int rowidx,double rhs,double range)3757 void OsiGrbSolverInterface::convertToRangedRow(int rowidx, double rhs, double range)
3758 {
3759   debugMessage("OsiGrbSolverInterface::convertToRangedRow()\n");
3760 
3761   assert(rowidx >= 0);
3762   assert(rowidx < getNumRows());
3763   assert(rhs > -getInfinity());
3764   assert(rhs <  getInfinity());
3765   assert(range > 0.0);
3766   assert(range < getInfinity());
3767 
3768   if( nauxcols == 0 )
3769   { // row rowidx is the first ranged row
3770     assert(colmap_O2G == NULL);
3771     assert(colmap_G2O == NULL);
3772 
3773     assert(colspace_ >= getNumCols());
3774 
3775     auxcolspace = 1;
3776     colmap_G2O = new int[colspace_ + auxcolspace];
3777     CoinIotaN(colmap_G2O, colspace_ + auxcolspace, 0);
3778 
3779     colmap_O2G = CoinCopyOfArray(colmap_G2O, colspace_);
3780   }
3781   else
3782   {
3783     assert(colmap_O2G != NULL);
3784     assert(colmap_G2O != NULL);
3785     resizeAuxColSpace( nauxcols + 1);
3786   }
3787 
3788   resizeAuxColIndSpace();
3789   assert(auxcolind[rowidx] == -1); /* not a ranged row yet */
3790 
3791   GUROBI_CALL( "convertToRangedRow", GRBupdatemodel(getMutableLpPtr()) );
3792 
3793   double minusone = -1.0;
3794   GUROBI_CALL( "convertToRangedRow", GRBaddvar(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_PROBLEM ),
3795       1, &rowidx, &minusone,
3796       0.0, rhs-range, rhs, GRB_CONTINUOUS, NULL) );
3797 
3798   auxcolind[rowidx] = getNumCols() + nauxcols - 1;
3799   colmap_G2O[auxcolind[rowidx]] = -rowidx - 1;
3800 
3801   ++nauxcols;
3802 
3803 #ifndef NDEBUG
3804   if( nauxcols )
3805   {
3806     int nc = getNumCols();
3807     int nr = getNumRows();
3808     for( int i = 0; i < nc + nauxcols; ++i )
3809     {
3810       assert(i >= nc || colmap_G2O[colmap_O2G[i]] == i);
3811       assert(colmap_G2O[i] <  0 || colmap_O2G[colmap_G2O[i]] == i);
3812       assert(colmap_G2O[i] >= 0 || -colmap_G2O[i]-1 < nr);
3813       assert(colmap_G2O[i] >= 0 || auxcolind[-colmap_G2O[i]-1] == i);
3814     }
3815   }
3816 #endif
3817 }
3818 
3819 /// converts a ranged row into a normal row by removing its auxiliary variable
convertToNormalRow(int rowidx,char sense,double rhs)3820 void OsiGrbSolverInterface::convertToNormalRow(int rowidx, char sense, double rhs)
3821 {
3822   debugMessage("OsiGrbSolverInterface::convertToNormalRow()\n");
3823 
3824   assert(rowidx >= 0);
3825   assert(rowidx < getNumRows());
3826 
3827   int auxvar = auxcolind[rowidx];
3828 
3829   assert(nauxcols);
3830   assert(auxvar >= 0);
3831   assert(colmap_G2O[auxvar] == -rowidx - 1);
3832 
3833   GUROBI_CALL( "convertToNormalRow", GRBupdatemodel(getMutableLpPtr()) );
3834 
3835   /* row rowidx should be an ordinary equality row with rhs == 0 now */
3836   GUROBI_CALL( "convertToNormalRow", GRBdelvars(getLpPtr( OsiGrbSolverInterface::KEEPCACHED_ROW ), 1, &auxcolind[rowidx]) );
3837 
3838   auxcolind[rowidx] = -1;
3839 
3840   if( nauxcols > 1 )
3841   {
3842     int nc = getNumCols();
3843     for(int i = auxvar; i < nc; ++i)
3844     {
3845       if( colmap_O2G[i] > auxvar )
3846         --colmap_O2G[i];
3847       colmap_G2O[i] = colmap_G2O[i+1];
3848     }
3849     for(int i = nc; i < nc + nauxcols; ++i)
3850       colmap_G2O[i] = colmap_G2O[i+1];
3851 
3852     int nr = getNumRows();
3853     for(int i = 0; i < nr; ++i)
3854       if( auxcolind[i] > auxvar )
3855         --auxcolind[i];
3856     --nauxcols;
3857   }
3858   else
3859   { // no ranged rows left
3860     delete[] colmap_O2G;
3861     delete[] colmap_G2O;
3862     delete[] auxcolind;
3863     auxcolspace = 0;
3864     auxcolindspace = 0;
3865     nauxcols = 0;
3866   }
3867 
3868   setRowType(rowidx, sense, rhs, 0.0);
3869 
3870 #ifndef NDEBUG
3871   if( nauxcols )
3872   {
3873     int nc = getNumCols();
3874     int nr = getNumRows();
3875     for( int i = 0; i < nc + nauxcols; ++i )
3876     {
3877       assert(i >= nc || colmap_G2O[colmap_O2G[i]] == i);
3878       assert(colmap_G2O[i] <  0 || colmap_O2G[colmap_G2O[i]] == i);
3879       assert(colmap_G2O[i] >= 0 || -colmap_G2O[i]-1 < nr);
3880       assert(colmap_G2O[i] >= 0 || auxcolind[-colmap_G2O[i]-1] == i);
3881     }
3882   }
3883 #endif
3884 }
3885 
3886 //#############################################################################
3887 // Resets as if default constructor
3888 void
reset()3889 OsiGrbSolverInterface::reset()
3890 {
3891   setInitialData(); // clear base class
3892   gutsOfDestructor();
3893 }
3894 
3895 /**********************************************************************/
3896 /* Returns 1 if can just do getBInv etc
3897    2 if has all OsiSimplex methods
3898    and 0 if it has none */
canDoSimplexInterface() const3899 int OsiGrbSolverInterface::canDoSimplexInterface() const {
3900   return 0;
3901 }
3902 
3903 /**********************************************************************/
basisIsAvailable() const3904 bool OsiGrbSolverInterface::basisIsAvailable() const {
3905   if (getNumCols() == 0)
3906   	return true;
3907 
3908   GUROBI_CALL( "basisIsAvailable", GRBupdatemodel(getMutableLpPtr()) );
3909 
3910   int status;
3911   GUROBI_CALL( "basisIsAvailable", GRBgetintattr(getMutableLpPtr(), GRB_INT_ATTR_STATUS, &status) );
3912 
3913 	if (status == GRB_LOADED || status == GRB_INFEASIBLE || status == GRB_INF_OR_UNBD || status == GRB_UNBOUNDED)
3914 		return false;
3915 
3916   int dum;
3917   return GRBgetintattrelement(getMutableLpPtr(), GRB_INT_ATTR_VBASIS, 0, &dum) == 0;
3918 }
3919 
3920 /* Osi return codes:
3921 0: free
3922 1: basic
3923 2: upper
3924 3: lower
3925 */
getBasisStatus(int * cstat,int * rstat) const3926 void OsiGrbSolverInterface::getBasisStatus(int* cstat, int* rstat) const {
3927 
3928 	int numcols = getNumCols();
3929 	int numrows = getNumRows();
3930 
3931 	GUROBI_CALL( "getBasisStatus", GRBupdatemodel(getMutableLpPtr()) );
3932 
3933 	GUROBI_CALL( "getBasisStatus", GRBgetintattrlist(getMutableLpPtr(), GRB_INT_ATTR_VBASIS, numcols, colmap_O2G, cstat) );
3934 
3935 	for (int i = 0; i < numcols; ++i)
3936 		switch (cstat[i])
3937 		{
3938 			case GRB_BASIC:
3939 				cstat[i] = 1;
3940 				break;
3941 			case GRB_NONBASIC_LOWER:
3942 				cstat[i] = 3;
3943 				break;
3944 			case GRB_NONBASIC_UPPER:
3945 				cstat[i] = 2;
3946 				break;
3947 			case GRB_SUPERBASIC:
3948 				cstat[i] = 0;
3949 				break;
3950 		}
3951 
3952 	GUROBI_CALL( "getBasisStatus", GRBgetintattrarray(getMutableLpPtr(), GRB_INT_ATTR_CBASIS, 0, numrows, rstat) );
3953 
3954 	char sense;
3955 	for (int i = 0; i < numrows; ++i)
3956 	{
3957 	  if( nauxcols && auxcolind[i] >= 0 )
3958 	  { /* if the row is a ranged row, then we take the basis status from the corresponding auxiliary column
3959 	       is this correct??? */
3960 	    int auxcolstat;
3961 	    GUROBI_CALL( "getBasisStatus", GRBgetintattrelement(getMutableLpPtr(), GRB_INT_ATTR_VBASIS, auxcolind[i], &auxcolstat) );
3962 	    switch( auxcolstat )
3963 	    {
3964 	      case GRB_BASIC:
3965 	        rstat[i] = 1;
3966 	        break;
3967 	      case GRB_NONBASIC_LOWER:
3968 	        rstat[i] = 3;
3969 	        break;
3970 	      case GRB_NONBASIC_UPPER:
3971 	        rstat[i] = 2;
3972 	        break;
3973 	      case GRB_SUPERBASIC:
3974 	        rstat[i] = 0;
3975 	        break;
3976 	    }
3977 	  }
3978 	  else
3979 	  {
3980 	    switch (rstat[i])
3981 	    {
3982          case GRB_SUPERBASIC:
3983 	        rstat[i] = 0;
3984 	        break;
3985 	      case GRB_BASIC:
3986 	        rstat[i] = 1;
3987 	        break;
3988 	      case GRB_NONBASIC_LOWER:
3989 	      case GRB_NONBASIC_UPPER:
3990 	        GUROBI_CALL( "getBasisStatus", GRBgetcharattrelement(getMutableLpPtr(), GRB_CHAR_ATTR_SENSE, i, &sense) );
3991 	        rstat[i] = (sense == '>' ? 2 : 3);
3992 	        break;
3993 	    }
3994 	  }
3995 	}
3996 }
3997