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