1 /* Osi interface for Mosek ver. 7.0
2    Lower versions are not supported
3  -----------------------------------------------------------------------------
4   name:     OSI Interface for MOSEK
5  -----------------------------------------------------------------------------
6 
7   This code is licensed under the terms of the Eclipse Public License (EPL).
8 
9   Originally developed by Bo Jensen from MOSEK ApS.  No longer a maintainer.
10 */
11 
12 #include <iostream>
13 #include <cassert>
14 #include <string>
15 #include <numeric>
16 #include "OsiConfig.h"
17 #include "CoinPragma.hpp"
18 #include "CoinError.hpp"
19 #include "CoinFinite.hpp"
20 #include "OsiMskSolverInterface.hpp"
21 #include "OsiRowCut.hpp"
22 #include "OsiColCut.hpp"
23 #include "CoinPackedMatrix.hpp"
24 #include "CoinWarmStartBasis.hpp"
25 
26 #include "mosek.h"
27 
28 #define MSK_OSI_DEBUG_LEVEL          0
29 #ifndef NDEBUG
30 #define MSK_OSI_ASSERT_LEVEL         0
31 #else
32 #define MSK_OSI_ASSERT_LEVEL         4
33 #endif
34 #define MSK_DO_MOSEK_LOG             0
35 
36 #define debugMessage printf
37 
38 //Choose algorithm to be default in initial solve
39 #define INITIAL_SOLVE MSK_OPTIMIZER_FREE
40 
41 //Choose algorithm to be default in resolve
42 #define RESOLVE_SOLVE MSK_OPTIMIZER_FREE_SIMPLEX
43 
44 // Unset this flag to disable the warnings from interface.
45 
46 #define MSK_WARNING_ON
47 
48 #if MSK_VERSION_MAJOR >= 9
49 #define MSKCONST const
50 #endif
51 
52 #undef getc
53 
54 //#############################################################################
55 // A couple of helper functions
56 //#############################################################################
57 
58 // Free memory pointet to by a double pointer
59 
freeCacheDouble(double * & ptr)60 inline void freeCacheDouble( double*& ptr )
61 {
62   if( ptr != NULL )
63   {
64     delete [] ptr;
65     ptr = NULL;
66   }
67 }
68 
69 // Free memory pointet to by a char pointer
70 
freeCacheChar(char * & ptr)71 inline void freeCacheChar( char*& ptr )
72 {
73   if( ptr != NULL )
74   {
75     delete [] ptr;
76     ptr = NULL;
77   }
78 }
79 
80 // Free memory pointet to by a CoinPackedMatrix pointer
81 
freeCacheMatrix(CoinPackedMatrix * & ptr)82 inline void freeCacheMatrix( CoinPackedMatrix*& ptr )
83 {
84   if( ptr != NULL )
85   {
86     delete ptr;
87     ptr = NULL;
88   }
89 }
90 
91 // Function used to connect MOSEK to stream
92 
93 #if MSK_VERSION_MAJOR >= 7
printlog(void * ptr,const char * s)94 static void MSKAPI printlog(void *ptr, const char* s)
95 #else
96 static void MSKAPI printlog(void *ptr, char* s)
97 #endif
98 {
99   printf("%s",s);
100 }
101 
102 static
handleMessage(CoinMessageHandler * handler,MSKCONST char * str)103 void handleMessage(CoinMessageHandler* handler, MSKCONST char* str)
104 {
105 	size_t len = strlen(str);
106 	if( len == 0 )
107 		return;
108 
109 	if( str[len-1] == '\n')
110 	{
111 		char* str_ = (char*)malloc(len);
112 		memcpy(str_, str, len-1);
113 		str_[len-1] = '\0';
114 		handler->message(0, "MSK", str_, ' ') << CoinMessageEol;
115 		free(str_);
116 	}
117 	else
118 		handler->message(0, "MSK", str, ' ');
119 }
120 
121 static
OsiMskStreamFuncLog(MSKuserhandle_t handle,MSKCONST char * str)122 void MSKAPI OsiMskStreamFuncLog(MSKuserhandle_t handle, MSKCONST char* str) {
123 	CoinMessageHandler* handler = (CoinMessageHandler*)handle;
124 	if (handler != NULL) {
125 		if (handler->logLevel() >= 1)
126 			handleMessage(handler, str);
127 	} else {
128 		printf(str);
129 		printf("\n");
130 	}
131 }
132 
133 static
OsiMskStreamFuncWarning(MSKuserhandle_t handle,MSKCONST char * str)134 void MSKAPI OsiMskStreamFuncWarning(MSKuserhandle_t handle, MSKCONST char* str) {
135 	CoinMessageHandler* handler = (CoinMessageHandler*)handle;
136 	if (handler != NULL) {
137 		if (handler->logLevel() >= 0)
138 			handleMessage(handler, str);
139 	} else {
140 		printf(str);
141 		printf("\n");
142 	}
143 }
144 
145 static
OsiMskStreamFuncError(MSKuserhandle_t handle,MSKCONST char * str)146 void MSKAPI OsiMskStreamFuncError(MSKuserhandle_t handle, MSKCONST char* str) {
147 	CoinMessageHandler* handler = (CoinMessageHandler*)handle;
148 	if (handler != NULL) {
149 		handleMessage(handler, str);
150 	} else {
151 		fprintf(stderr, str);
152 		fprintf(stderr, "\n");
153 	}
154 }
155 
156 // Prints a error message and throws a exception
157 
158 static inline void
checkMSKerror(int err,const char * mskfuncname,const char * osimethod)159 checkMSKerror( int err, const char* mskfuncname, const char* osimethod )
160 {
161   if( err != MSK_RES_OK )
162   {
163     char s[100];
164     sprintf( s, "%s returned error %d", mskfuncname, err );
165     std::cout << "ERROR: " << s << " (" << osimethod <<
166     " in OsiMskSolverInterface)" << std::endl;
167     throw CoinError( s, osimethod, "OsiMskSolverInterface" );
168   }
169 }
170 
171 // Prints a error message and throws a exception
172 
173 static inline void
MSKassert(int assertlevel,int test,const char * assertname,const char * osimethod)174 MSKassert(int assertlevel, int test, const char* assertname, const char* osimethod )
175 {
176   if( assertlevel > MSK_OSI_ASSERT_LEVEL && !test )
177   {
178     std::cout << "Assert: " << assertname << " (" << osimethod <<
179     " in OsiMskSolverInterface)" << std::endl;
180     throw CoinError( assertname, osimethod, "OsiMskSolverInterface" );
181   }
182 }
183 
184 // Converts Range/Sense/Rhs to MSK bound structure
185 
186 static inline void
MskConvertSenseToBound(const char rowsen,const double rowrng,const double rowrhs,double & rlb,double & rub,int & rtag)187 MskConvertSenseToBound(const char rowsen, const double rowrng,
188                          const double rowrhs, double &rlb, double &rub, int &rtag)
189 {
190   switch (rowsen)
191   {
192     case 'E':
193       rlb  = rowrhs;
194       rub  = rowrhs;
195       rtag = MSK_BK_FX;
196     break;
197 
198     case 'L':
199       rlb  = MSK_INFINITY;
200       rub  = rowrhs;
201       rtag = MSK_BK_UP;
202       break;
203     case 'G':
204       rlb  = rowrhs;
205       rub  = MSK_INFINITY;
206       rtag = MSK_BK_LO;
207     break;
208 
209     case 'R':
210       if( rowrng >= 0 )
211       {
212         rlb = rowrhs - rowrng;
213         rub = rowrhs;
214       }
215       else
216       {
217         rlb = rowrhs;
218         rub = rowrhs + rowrng;
219       }
220 
221       rtag = MSK_BK_RA;
222       break;
223     case 'N':
224       rlb  = -MSK_INFINITY;
225       rub  = MSK_INFINITY;
226       rtag = MSK_BK_FR;
227       break;
228 
229     default:
230       MSKassert(3,1,"Unknown rowsen","MskConvertSenseToBound");
231   }
232 }
233 
234 // Converts a set of bounds to MSK boundkeys
235 
236 static inline void
MskConvertColBoundToTag(const double collb,const double colub,double & clb,double & cub,int & ctag)237 MskConvertColBoundToTag(const double collb, const double colub, double &clb, double &cub, int &ctag)
238 {
239   #if MSK_OSI_DEBUG_LEVEL > 3
240   debugMessage("Begin MskConvertColBoundToTag()\n");
241   #endif
242 
243   if(collb > -MSK_INFINITY && colub < MSK_INFINITY)
244   {
245     ctag = MSK_BK_RA;
246     clb = collb;
247     cub = colub;
248   }
249   else if(collb <= - MSK_INFINITY && colub < MSK_INFINITY)
250   {
251     ctag = MSK_BK_UP;
252     clb = -MSK_INFINITY;
253     cub = colub;
254   }
255   else if(collb > - MSK_INFINITY && colub >= MSK_INFINITY)
256   {
257     ctag = MSK_BK_LO;
258     clb = collb;
259     cub = MSK_INFINITY;
260   }
261   else if(collb <= -MSK_INFINITY && colub >= MSK_INFINITY)
262   {
263     ctag = MSK_BK_FR;
264     clb = -MSK_INFINITY;
265     cub = MSK_INFINITY;
266   }
267 
268   #if MSK_OSI_DEBUG_LEVEL > 3
269   debugMessage("End MskConvertColBoundToTag()\n");
270   #endif
271 }
272 
273 // Returns true if "solution" is defined in MOSEK, where solution can be basic, interior or
274 // integer resp. (MSK_SOL_BAS), (MSK_SOL_ITR) or (MSK_SOL_ITG).
275 
definedSolution(int solution) const276 bool OsiMskSolverInterface::definedSolution(int solution) const
277 {
278    #if MSK_OSI_DEBUG_LEVEL > 3
279    debugMessage("Begin OsiMskSolverInterface::definedSolution() %p\n",(void*)this);
280    #endif
281 
282 
283    int err, res;
284    err = MSK_solutiondef(getMutableLpPtr(), (MSKsoltypee) solution, &res);
285    checkMSKerror(err,"MSK_solutiondef","definedSolution");
286 
287    #if MSK_OSI_DEBUG_LEVEL > 3
288    debugMessage("End OsiMskSolverInterface::definedSolution()\n");
289    #endif
290 
291 
292    return ( res != MSK_RES_OK);
293 }
294 
295 // Returns the flag for solver currently switched on in MOSEK resp. (MSK_OPTIMIZER_FREE),
296 // (MSK_OPTIMIZER_INTPNT), (MSK_OPTIMIZER_PRIMAL_SIMPLEX), (MSK_OPTIMIZER_MIXED_INT), or
297 // (MSK_OPTIMIZER_MIXED_INT_CONIC).
298 // MOSEK also has Conic and nonconvex solvers, but these are for obvious reasons not
299 // an option in the Osi interface.
300 
solverUsed() const301 int OsiMskSolverInterface::solverUsed() const
302 {
303   #if MSK_OSI_DEBUG_LEVEL > 3
304   debugMessage("Begin OsiMskSolverInterface::solverUsed()\n");
305   #endif
306 
307   #if MSK_OSI_DEBUG_LEVEL > 3
308   debugMessage("End OsiMskSolverInterface::solverUsed()\n");
309   #endif
310 
311   return MSKsolverused_;
312 }
313 
314 // Switch the MOSEK solver to LP uses default solver specified by 'InitialSolver'
315 
316 void
switchToLP(void)317 OsiMskSolverInterface::switchToLP( void )
318 {
319   #if MSK_OSI_DEBUG_LEVEL > 3
320   debugMessage("Begin OsiMskSolverInterface::switchToLP()\n");
321   #endif
322 
323   int err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_MIO_MODE, MSK_MIO_MODE_IGNORED);
324   checkMSKerror(err,"MSK_putintparam","switchToLp");
325 
326   probtypemip_ = false;
327 
328   #if MSK_OSI_DEBUG_LEVEL > 3
329   debugMessage("End OsiMskSolverInterface::switchToLP()\n");
330   #endif
331 }
332 
333 // Switch the MOSEK solver to MIP.
334 
335 void
switchToMIP(void)336 OsiMskSolverInterface::switchToMIP( void )
337 {
338   #if MSK_OSI_DEBUG_LEVEL > 3
339   debugMessage("Begin OsiMskSolverInterface::switchToMIP()\n");
340   #endif
341 
342   int err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_MIO_MODE, MSK_MIO_MODE_SATISFIED);
343   checkMSKerror(err,"MSK_putintparam","switchToMIP");
344 
345 #if MSK_VERSION_MAJOR == 7
346   err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_MIXED_INT_CONIC);
347 #else
348   err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_MIXED_INT);
349 #endif
350   checkMSKerror(err,"MSK_putintparam","switchToMIP");
351   probtypemip_ = true;
352 
353   #if MSK_OSI_DEBUG_LEVEL > 3
354   debugMessage("End OsiMskSolverInterface::switchToMIP()\n");
355   #endif
356 }
357 
358 // Resize the coltype array.
359 
360 void
resizeColType(int minsize)361 OsiMskSolverInterface::resizeColType( int minsize )
362 {
363   #if MSK_OSI_DEBUG_LEVEL > 3
364   debugMessage("Begin OsiMskSolverInterface::resizeColType()\n");
365   #endif
366 
367   if( minsize > coltypesize_ )
368   {
369      int newcoltypesize = 2*coltypesize_;
370      if( minsize > newcoltypesize )
371         newcoltypesize = minsize;
372      char *newcoltype = new char[newcoltypesize];
373 
374      if( coltype_ != NULL )
375      {
376         CoinDisjointCopyN( coltype_, coltypesize_, newcoltype );
377         delete[] coltype_;
378      }
379 
380      coltype_ = newcoltype;
381      coltypesize_ = newcoltypesize;
382   }
383 
384   MSKassert(3,minsize == 0 || coltype_ != NULL,"Unknown rowsen","MskConvertSenseToBound");
385   MSKassert(3,coltypesize_ >= minsize,"coltypesize_ >= minsize","MskConvertSenseToBound");
386 
387   #if MSK_OSI_DEBUG_LEVEL > 3
388   debugMessage("End OsiMskSolverInterface::resizeColType()\n");
389   #endif
390 }
391 
392 // Free coltype array
393 
394 void
freeColType()395 OsiMskSolverInterface::freeColType()
396 {
397   #if MSK_OSI_DEBUG_LEVEL > 3
398   debugMessage("Begin OsiMskSolverInterface::freeColType()\n");
399   #endif
400 
401   if( coltypesize_ > 0 )
402   {
403     delete[] coltype_;
404 
405     coltype_ = NULL;
406     coltypesize_ = 0;
407   }
408 
409   MSKassert(3,coltype_ == NULL,"coltype_ == NULL","freeColType");
410 
411   #if MSK_OSI_DEBUG_LEVEL > 3
412   debugMessage("End OsiMskSolverInterface::freeColType()\n");
413   #endif
414 }
415 
416 //#############################################################################
417 // Solve methods
418 //#############################################################################
419 
420 //-----------------------------------------------------------------------------
421 // Free cached results and optimize the LP problem in task
422 
initialSolve()423 void OsiMskSolverInterface::initialSolve()
424 {
425   #if MSK_OSI_DEBUG_LEVEL > 1
426   debugMessage("Begin OsiMskSolverInterface::initialSolve() %p\n", (void*)this);
427   #endif
428 
429   if( definedSolution( MSK_SOL_BAS ) == true )
430   {
431     resolve();
432   }
433   else
434   {
435 
436     int err,solver;
437 
438     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_SIM_HOTSTART, MSK_SIM_HOTSTART_STATUS_KEYS);
439     checkMSKerror(err,"MSK_putintparam","initialsolve");
440 
441     err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &solver);
442     checkMSKerror(err,"MSK_getintparam","initialsolve");
443 
444     switchToLP();
445 
446     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, INITIAL_SOLVE);
447     checkMSKerror(err,"MSK_putintparam","initialSolve");
448 
449     err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_);
450     checkMSKerror(err,"MSK_getintparam","initialsolve");
451 
452 #if MSK_DO_MOSEK_LOG > 0
453     err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG,MSK_DO_MOSEK_LOG);
454     checkMSKerror(err,"MSK_putintparam","initialsolve");
455 
456     err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG_SIM,MSK_DO_MOSEK_LOG);
457     checkMSKerror(err,"MSK_putintparam","initialsolve");
458 #endif
459 
460     Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ));
461 
462 #if MSK_DO_MOSEK_LOG > 0
463     err = MSK_solutionsummary( getMutableLpPtr(),MSK_STREAM_LOG);
464     checkMSKerror(err,"MSK_solutionsummary","initialsolve");
465 #endif
466 
467     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, solver);
468     checkMSKerror(err,"MSK_putintparam","initialsolve");
469 
470   }
471 
472   #if MSK_OSI_DEBUG_LEVEL > 1
473   debugMessage("End OsiMskSolverInterface::initialSolve()\n");
474   #endif
475 }
476 
477 //-----------------------------------------------------------------------------
478 // Resolves an LP problem.
479 
resolve()480 void OsiMskSolverInterface::resolve()
481 {
482   #if MSK_OSI_DEBUG_LEVEL > 1
483   debugMessage("Begin OsiMskSolverInterface::resolve %p\n", (void*)this);
484   #endif
485 
486   if( definedSolution( MSK_SOL_BAS ) == true )
487   {
488     int err,solver;
489 
490     err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &solver);
491     checkMSKerror(err,"MSK_getintparam","resolve");
492 
493     switchToLP();
494 
495     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_SIM_HOTSTART, MSK_SIM_HOTSTART_STATUS_KEYS);
496     checkMSKerror(err,"MSK_putintparam","resolve");
497 
498     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, RESOLVE_SOLVE);
499     checkMSKerror(err,"MSK_putintparam","resolve");
500 
501     #if 0
502     err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, 20000000 );
503     #endif
504 
505     err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_);
506     checkMSKerror(err,"MSK_getintparam","resolve");
507 
508 #if MSK_DO_MOSEK_LOG > 0
509     err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG,MSK_DO_MOSEK_LOG);
510     checkMSKerror(err,"MSK_putintparam","resolve");
511 
512     err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG_SIM,MSK_DO_MOSEK_LOG);
513     checkMSKerror(err,"MSK_putintparam","resolve");
514 #endif
515 
516     Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ));
517 
518     #if MSK_DO_MOSEK_LOG > 0
519     err = MSK_solutionsummary( getMutableLpPtr(),MSK_STREAM_LOG);
520     printf("Mskerr : %d\n",Mskerr);
521     #endif
522 
523     err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, solver);
524     checkMSKerror(err,"MSK_putintparam","resolve");
525   }
526   else
527   {
528     initialSolve();
529   }
530 
531   #if MSK_OSI_DEBUG_LEVEL > 1
532   debugMessage("End OsiMskSolverInterface::resolve... press any key to continue\n");
533   getchar();
534   #endif
535 }
536 
537 //-----------------------------------------------------------------------------
538 // Resolves an MIP problem with MOSEK MIP solver.
539 
branchAndBound()540 void OsiMskSolverInterface::branchAndBound()
541 {
542   #if MSK_OSI_DEBUG_LEVEL > 1
543   debugMessage("Begin OsiMskSolverInterface::branchAndBound()\n");
544   #endif
545 
546   switchToMIP();
547 
548   int err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_);
549   checkMSKerror(err,"MSK_getintparam","branchAndBound");
550 
551   Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ));
552 
553   #if MSK_OSI_DEBUG_LEVEL > 1
554   debugMessage("End OsiMskSolverInterface::branchAndBound()\n");
555   #endif
556 }
557 
558 //#############################################################################
559 // Parameter related methods
560 //#############################################################################
561 
562 //-----------------------------------------------------------------------------
563 // Sets a int parameter in MOSEK
564 
565 bool
setIntParam(OsiIntParam key,int value)566 OsiMskSolverInterface::setIntParam(OsiIntParam key, int value)
567 {
568   #if MSK_OSI_DEBUG_LEVEL > 3
569   debugMessage("Begin OsiMskSolverInterface::setIntParam(%d, %d)\n", key, value);
570   #endif
571 
572   bool retval = false;
573 
574   switch (key)
575   {
576     case OsiMaxNumIteration:
577       retval = (MSK_putintparam(getMutableLpPtr(),
578                                 MSK_IPAR_SIM_MAX_ITERATIONS,
579                                 value ) == MSK_RES_OK);
580       break;
581 
582     case OsiMaxNumIterationHotStart:
583       if (value < 0) {
584         retval = false;
585       } else {
586         hotStartMaxIteration_ = value;
587         retval = true;
588       }
589       break;
590     case OsiNameDiscipline:
591       retval = false;
592       break;
593     case OsiLastIntParam:
594       retval = false;
595       break;
596   }
597 
598   #if MSK_OSI_DEBUG_LEVEL > 3
599   debugMessage("End OsiMskSolverInterface::setIntParam(%d, %d)\n", key, value);
600   #endif
601 
602   return retval;
603 }
604 
605 //-----------------------------------------------------------------------------
606 // Sets a double parameter in MOSEK.
607 
608 bool
setDblParam(OsiDblParam key,double value)609 OsiMskSolverInterface::setDblParam(OsiDblParam key, double value)
610 {
611   #if MSK_OSI_DEBUG_LEVEL > 3
612   debugMessage("Begin OsiMskSolverInterface::setDblParam(%d, %g)\n", key, value);
613   #endif
614 
615   bool retval = false;
616   switch (key)
617   {
618     case OsiDualObjectiveLimit:
619       if( getObjSense() == +1 ) // Minimize
620             retval = ( MSK_putdouparam( getMutableLpPtr(),
621                                         MSK_DPAR_UPPER_OBJ_CUT,
622                                         value  ) == MSK_RES_OK ); // min
623       else
624           retval = ( MSK_putdouparam( getMutableLpPtr(),
625                                       MSK_DPAR_LOWER_OBJ_CUT,
626                                       value ) == MSK_RES_OK ); // max
627       break;
628     case OsiPrimalObjectiveLimit:
629       if( getObjSense() == +1 ) // Minimize
630           retval = ( MSK_putdouparam( getMutableLpPtr(),
631                                       MSK_DPAR_LOWER_OBJ_CUT,
632                                       value  ) == MSK_RES_OK ); // min
633       else
634           retval = ( MSK_putdouparam( getMutableLpPtr(),
635                                       MSK_DPAR_UPPER_OBJ_CUT,
636                                       value ) == MSK_RES_OK ); // max
637       break;
638     case OsiDualTolerance:
639       retval = ( MSK_putdouparam( getMutableLpPtr(),
640                                   MSK_DPAR_BASIS_TOL_S,
641                                   value ) == MSK_RES_OK );
642       break;
643     case OsiPrimalTolerance:
644       retval = ( MSK_putdouparam( getMutableLpPtr(),
645                                   MSK_DPAR_BASIS_TOL_X,
646                                   value ) == MSK_RES_OK );
647       break;
648     case OsiObjOffset:
649       ObjOffset_ = value;
650       retval     = true;
651       break;
652     case OsiLastDblParam:
653       retval = false;
654       break;
655    }
656 
657   #if MSK_OSI_DEBUG_LEVEL > 3
658   debugMessage("End OsiMskSolverInterface::setDblParam(%d, %g)\n", key, value);
659   #endif
660 
661   return retval;
662 }
663 
664 
665 //-----------------------------------------------------------------------------
666 // Sets a string parameter in MOSEK.
667 
668 bool
setStrParam(OsiStrParam key,const std::string & value)669 OsiMskSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
670 {
671   #if MSK_OSI_DEBUG_LEVEL > 3
672   debugMessage("Begin OsiMskSolverInterface::setStrParam(%d, %s)\n", key, value.c_str());
673   #endif
674 
675   bool retval=false;
676   switch (key)
677   {
678     case OsiProbName:
679       OsiSolverInterface::setStrParam(key,value);
680       return retval = true;
681     case OsiSolverName:
682       return false;
683     case OsiLastStrParam:
684       return false;
685   }
686 
687   #if MSK_OSI_DEBUG_LEVEL > 3
688   debugMessage("End OsiMskSolverInterface::setStrParam(%d, %s)\n", key, value.c_str());
689   #endif
690 
691   return retval;
692 }
693 
694 //-----------------------------------------------------------------------------
695 // Gets a int parameter in MOSEK.
696 
697 bool
getIntParam(OsiIntParam key,int & value) const698 OsiMskSolverInterface::getIntParam(OsiIntParam key, int& value) const
699 {
700   #if MSK_OSI_DEBUG_LEVEL > 3
701   debugMessage("Begin OsiMskSolverInterface::getIntParam(%d)\n", key);
702   #endif
703 
704   bool retval = false;
705   switch (key)
706   {
707     case OsiMaxNumIteration:
708       retval = (MSK_getintparam(getMutableLpPtr(),
709                                 MSK_IPAR_SIM_MAX_ITERATIONS,
710                                 &value ) == MSK_RES_OK);
711       break;
712     case OsiMaxNumIterationHotStart:
713       value = hotStartMaxIteration_;
714       retval = true;
715       break;
716     case OsiNameDiscipline:
717       value = 0;
718       retval = false;
719       break;
720     case OsiLastIntParam:
721       retval = false;
722       break;
723   }
724 
725   #if MSK_OSI_DEBUG_LEVEL > 3
726   debugMessage("End OsiMskSolverInterface::getIntParam(%d)\n", key);
727   #endif
728 
729   return retval;
730 }
731 
732 //-----------------------------------------------------------------------------
733 // Get a double parameter in MOSEK.
734 
735 bool
getDblParam(OsiDblParam key,double & value) const736 OsiMskSolverInterface::getDblParam(OsiDblParam key, double& value) const
737 {
738   #if MSK_OSI_DEBUG_LEVEL > 3
739   debugMessage("Begin OsiMskSolverInterface::getDblParam(%d)\n", key);
740   #endif
741 
742   bool retval = false;
743 
744   switch (key)
745     {
746     case OsiDualObjectiveLimit:
747       if( getObjSense() == +1 )
748           retval = ( MSK_getdouparam( getMutableLpPtr(),
749                                       MSK_DPAR_UPPER_OBJ_CUT,
750                                       &value  ) == MSK_RES_OK ); // max
751       else
752           retval = ( MSK_getdouparam( getMutableLpPtr(),
753                                       MSK_DPAR_LOWER_OBJ_CUT,
754                                       &value ) == MSK_RES_OK ); // min
755       break;
756     case OsiPrimalObjectiveLimit:
757       if( getObjSense() == +1 )
758           retval = ( MSK_getdouparam( getMutableLpPtr(),
759                                       MSK_DPAR_LOWER_OBJ_CUT,
760                                       &value ) == MSK_RES_OK ); // min
761       else
762           retval = ( MSK_getdouparam( getMutableLpPtr(),
763                                       MSK_DPAR_UPPER_OBJ_CUT,
764                                       &value ) == MSK_RES_OK ); // max
765       break;
766     case OsiDualTolerance:
767       retval = ( MSK_getdouparam( getMutableLpPtr(),
768                                   MSK_DPAR_BASIS_TOL_S,
769                                   &value ) == MSK_RES_OK );
770       break;
771     case OsiPrimalTolerance:
772       retval = ( MSK_getdouparam( getMutableLpPtr(),
773                                   MSK_DPAR_BASIS_TOL_X,
774                                   &value ) == MSK_RES_OK );
775       break;
776     case OsiObjOffset:
777       value = ObjOffset_;
778       retval = true;
779       break;
780     case OsiLastDblParam:
781       retval = false;
782       break;
783     }
784 
785   #if MSK_OSI_DEBUG_LEVEL > 3
786   debugMessage("End OsiMskSolverInterface::getDblParam(%d)\n", key);
787   #endif
788 
789   return retval;
790 }
791 
792 //-----------------------------------------------------------------------------
793 // Gets a string parameter from MOSEK
794 
795 bool
getStrParam(OsiStrParam key,std::string & value) const796 OsiMskSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
797 {
798   #if MSK_OSI_DEBUG_LEVEL > 3
799   debugMessage("Begin OsiMskSolverInterface::getStrParam(%d)\n", key);
800   #endif
801 
802   switch (key)
803   {
804     case OsiProbName:
805       OsiSolverInterface::getStrParam(key, value);
806       break;
807     case OsiSolverName:
808       value = "MOSEK";
809       break;
810     case OsiLastStrParam:
811       return false;
812   }
813 
814   #if MSK_OSI_DEBUG_LEVEL > 3
815   debugMessage("End OsiMskSolverInterface::getStrParam(%d)\n", key);
816   #endif
817 
818   return true;
819 }
820 
821 //#############################################################################
822 // Methods returning info on how the solution process terminated
823 //#############################################################################
824 
825 //-----------------------------------------------------------------------------
826 // Returns true if solver abandoned in last call to solver.
827 // Mosek does not use this functionality
828 
isAbandoned() const829 bool OsiMskSolverInterface::isAbandoned() const
830 {
831   #if MSK_OSI_DEBUG_LEVEL > 3
832   debugMessage("Begin OsiMskSolverInterface::isAbandoned()\n");
833   debugMessage("isAbandoned() %d\n",(Mskerr != MSK_RES_OK));
834   debugMessage("End OsiMskSolverInterface::isAbandoned()\n");
835   #endif
836 
837   return (Mskerr != MSK_RES_OK);
838 }
839 
840 //-----------------------------------------------------------------------------
841 // Returns true if "solution" available is proved to be optimal, where "solution" in LP
842 // could be both interior and basic, checks for both.
843 
isProvenOptimal() const844 bool OsiMskSolverInterface::isProvenOptimal() const
845 {
846   #if MSK_OSI_DEBUG_LEVEL > 3
847   debugMessage("Begin OsiMskSolverInterface::isProvenOptimal()\n");
848   #endif
849 
850   int err;
851   MSKsolstae status;
852   MSKsoltypee solution;
853 
854   if( probtypemip_ == false)
855   {
856     if( definedSolution( MSK_SOL_BAS ) == true )
857       solution = MSK_SOL_BAS;
858     else
859     {
860       if( definedSolution( MSK_SOL_ITR ) == true )
861         solution = MSK_SOL_ITR;
862       else
863         return false;
864     }
865   }
866   else
867   {
868      if( definedSolution( MSK_SOL_ITG ) == true )
869       solution = MSK_SOL_ITG;
870     else
871       return false;
872   }
873 
874   err = MSK_getsolution(getMutableLpPtr(),
875                         solution,
876                         NULL,
877                         &status,
878                         NULL,
879                         NULL,
880                         NULL,
881                         NULL,
882                         NULL,
883                         NULL,
884                         NULL,
885                         NULL,
886                         NULL,
887                         NULL,
888                         NULL);
889 
890   checkMSKerror(err,"MSK_getsolution","isProvenOptimal");
891 
892   #if MSK_OSI_DEBUG_LEVEL > 3
893   debugMessage("Solution type , %d  status %d \n ",(status == MSK_SOL_STA_OPTIMAL), status) ;
894   debugMessage("End OsiMskSolverInterface::isProvenOptimal()\n");
895   #endif
896 
897   return ( status == MSK_SOL_STA_OPTIMAL || status == MSK_SOL_STA_INTEGER_OPTIMAL);
898 }
899 
900 //-----------------------------------------------------------------------------
901 // Returns true if a certificate of primal inf. exits
902 
isProvenPrimalInfeasible() const903 bool OsiMskSolverInterface::isProvenPrimalInfeasible() const
904 {
905   #if MSK_OSI_DEBUG_LEVEL > 3
906   debugMessage("Begin OsiMskSolverInterface::isProvenPrimalInfeasible()\n");
907   #endif
908 
909   int err;
910   MSKsolstae status;
911   MSKsoltypee solution;
912 
913   if( probtypemip_ == false)
914   {
915     if( definedSolution( MSK_SOL_BAS ) == true )
916       solution = MSK_SOL_BAS;
917     else
918     {
919       if( definedSolution( MSK_SOL_ITR ) == true )
920         solution = MSK_SOL_ITR;
921       else
922         return false;
923     }
924   }
925   else
926   {
927     if(  definedSolution( MSK_SOL_ITG ) == true)
928       solution = MSK_SOL_ITG;
929     else
930       return false;
931   }
932 
933   err = MSK_getsolution(getMutableLpPtr(),
934                         solution,
935                         NULL,
936                         &status,
937                         NULL,
938                         NULL,
939                         NULL,
940                         NULL,
941                         NULL,
942                         NULL,
943                         NULL,
944                         NULL,
945                         NULL,
946                         NULL,
947                         NULL);
948 
949   checkMSKerror(err,"MSK_getsolution","isProvenPrimalInfeasible");
950 
951   #if MSK_OSI_DEBUG_LEVEL > 3
952   debugMessage("isProvenPrimalInfeasible %d \n",(status == MSK_SOL_STA_PRIM_INFEAS_CER));
953   debugMessage("End OsiMskSolverInterface::isProvenPrimalInfeasible()\n");
954   #endif
955 
956   return ( status == MSK_SOL_STA_PRIM_INFEAS_CER );
957 }
958 
959 //-----------------------------------------------------------------------------
960 // Should return true if a certificate of dual inf. exits
961 // But COIN does not support this feature thus we return false
962 
isProvenDualInfeasible() const963 bool OsiMskSolverInterface::isProvenDualInfeasible() const
964 {
965   #if MSK_OSI_DEBUG_LEVEL > 3
966   debugMessage("Begin OsiMskSolverInterface::isProvenDualInfeasible()\n");
967   #endif
968 
969   int err;
970   MSKsolstae status;
971   MSKsoltypee solution;
972 
973   if( probtypemip_ == false )
974   {
975     if( definedSolution( MSK_SOL_BAS ) == true )
976       solution = MSK_SOL_BAS;
977     else
978     {
979       if( definedSolution( MSK_SOL_ITR ) == true )
980         solution = MSK_SOL_ITR;
981       else
982         return false;
983     }
984   }
985   else
986   {
987     if(  definedSolution( MSK_SOL_ITG ) == true)
988       solution = MSK_SOL_ITG;
989     else
990       return false;
991   }
992 
993   err = MSK_getsolution(getMutableLpPtr(),
994                         solution,
995                         NULL,
996                         &status,
997                         NULL,
998                         NULL,
999                         NULL,
1000                         NULL,
1001                         NULL,
1002                         NULL,
1003                         NULL,
1004                         NULL,
1005                         NULL,
1006                         NULL,
1007                         NULL
1008                         );
1009 
1010   checkMSKerror(err,"MSK_getsolution","isProvenDualInfeasible");
1011 
1012   #if MSK_OSI_DEBUG_LEVEL > 3
1013   debugMessage("isProvenDualInfeasible %d \n",(status == MSK_SOL_STA_DUAL_INFEAS_CER));
1014   debugMessage("End OsiMskSolverInterface::isProvenDualInfeasible()\n");
1015   #endif
1016 
1017   return ( status == MSK_SOL_STA_DUAL_INFEAS_CER );
1018 }
1019 
1020 //-----------------------------------------------------------------------------
1021 // Returns true if primal objective limit is reached. Checks the objective sense
1022 // first.
1023 
isPrimalObjectiveLimitReached() const1024 bool OsiMskSolverInterface::isPrimalObjectiveLimitReached() const
1025 {
1026   #if MSK_OSI_DEBUG_LEVEL > 3
1027   debugMessage("Begin OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n");
1028   #endif
1029 
1030   if( Mskerr == MSK_RES_TRM_OBJECTIVE_RANGE )
1031   {
1032     int err;
1033     double obj = getObjValue(),value=MSK_INFINITY;
1034     if( getObjSense() == +1 )
1035     {
1036       err = MSK_getdouparam( getMutableLpPtr(),
1037                              MSK_DPAR_LOWER_OBJ_CUT,
1038                              &value);
1039 
1040       checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached");
1041     }
1042     else
1043     {
1044       err = MSK_getdouparam(getMutableLpPtr(),
1045                             MSK_DPAR_UPPER_OBJ_CUT,
1046                             &value );
1047 
1048       checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached");
1049 
1050       obj = -obj;
1051       value = -value;
1052     }
1053 
1054     #if MSK_OSI_DEBUG_LEVEL > 3
1055     debugMessage("primal objective value  %-16.10e , lowerbound %-16.10e , reached %d \n",obj,value,(value <= obj));
1056     debugMessage("End OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n");
1057     #endif
1058 
1059     return ( !( value == MSK_INFINITY || value == -MSK_INFINITY ) && value > obj );
1060   }
1061   else
1062   {
1063     if( Mskerr == MSK_RES_OK )
1064     {
1065       if( definedSolution( MSK_SOL_BAS ) == true  )
1066       {
1067         int err;
1068         double obj = getObjValue(),value=MSK_INFINITY;
1069 
1070         if( getObjSense() == +1 )
1071         {
1072           err = MSK_getdouparam( getMutableLpPtr(),
1073                                  MSK_DPAR_LOWER_OBJ_CUT,
1074                                  &value);
1075 
1076           checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached");
1077 
1078           return (obj < value);
1079         }
1080         else
1081         {
1082           err = MSK_getdouparam(getMutableLpPtr(),
1083                                 MSK_DPAR_UPPER_OBJ_CUT,
1084                                 &value );
1085 
1086           checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached");
1087 
1088           obj = -obj;
1089           value = -value;
1090 
1091           return (obj < value);
1092         }
1093       }
1094     }
1095 
1096     #if MSK_OSI_DEBUG_LEVEL > 3
1097     debugMessage("End OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n");
1098     #endif
1099 
1100     return false;
1101   }
1102 }
1103 
1104 //-----------------------------------------------------------------------------
1105 // Returns true if dual objective limit is reached. Checks the objective sense
1106 // first.
1107 
isDualObjectiveLimitReached() const1108 bool OsiMskSolverInterface::isDualObjectiveLimitReached() const
1109 {
1110   #if MSK_OSI_DEBUG_LEVEL > 3
1111   debugMessage("Begin OsiMskSolverInterface::isDualObjectiveLimitReached()\n");
1112   #endif
1113 
1114   if( Mskerr == MSK_RES_TRM_OBJECTIVE_RANGE )
1115   {
1116     int err;
1117     double obj = getObjValue(),value=MSK_INFINITY;
1118     if( getObjSense() == +1 )
1119     {
1120       err = MSK_getdouparam( getMutableLpPtr(),
1121                              MSK_DPAR_UPPER_OBJ_CUT,
1122                              &value);
1123 
1124       checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached");
1125     }
1126     else
1127     {
1128       err = MSK_getdouparam( getMutableLpPtr(),
1129                              MSK_DPAR_LOWER_OBJ_CUT,
1130                              &value );
1131 
1132       checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached");
1133 
1134       obj = -obj;
1135       value = -value;
1136     }
1137 
1138     checkMSKerror( err, "MSK_getdouparam", "isPrimalObjectiveLimitReached" );
1139 
1140     #if MSK_OSI_DEBUG_LEVEL > 3
1141     debugMessage("dual objective value  %f , lowerbound %f , reached %i \n",obj,value,(value <= obj));
1142     debugMessage("End OsiMskSolverInterface::isDualObjectiveLimitReached()\n");
1143     #endif
1144 
1145     return ( !( value == MSK_INFINITY || value == -MSK_INFINITY ) && value <= obj );
1146   }
1147   else
1148   {
1149     if( Mskerr == MSK_RES_OK )
1150     {
1151       if( definedSolution( MSK_SOL_BAS ) == true  )
1152       {
1153         int err;
1154         double obj = getObjValue(),value=MSK_INFINITY;
1155 
1156         if( getObjSense() == +1 )
1157         {
1158           err = MSK_getdouparam( getMutableLpPtr(),
1159                                  MSK_DPAR_UPPER_OBJ_CUT,
1160                                  &value);
1161 
1162           checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached");
1163 
1164           return (obj > value);
1165         }
1166         else
1167         {
1168           err = MSK_getdouparam(getMutableLpPtr(),
1169                                 MSK_DPAR_LOWER_OBJ_CUT,
1170                                 &value );
1171 
1172           checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached");
1173 
1174           obj = -obj;
1175           value = -value;
1176 
1177           return (obj > value);
1178         }
1179       }
1180     }
1181 
1182     #if MSK_OSI_DEBUG_LEVEL > 3
1183     debugMessage("End OsiMskSolverInterface::isDualObjectiveLimitReached()\n");
1184     #endif
1185 
1186     return false;
1187   }
1188 }
1189 
1190 //-----------------------------------------------------------------------------
1191 // Returns true if iteration number used in last call to optimize eq. max number for
1192 // the solver used.
1193 
isIterationLimitReached() const1194 bool OsiMskSolverInterface::isIterationLimitReached() const
1195 {
1196   #if MSK_OSI_DEBUG_LEVEL > 3
1197   debugMessage("Begin OsiMskSolverInterface::isIterationLimitReached()\n");
1198   #endif
1199 
1200   #if MSK_OSI_DEBUG_LEVEL > 3
1201   debugMessage("iteration limit reached %d \n",Mskerr);
1202   debugMessage("End OsiMskSolverInterface::isIterationLimitReached()\n");
1203   #endif
1204 
1205   return Mskerr == MSK_RES_TRM_MAX_ITERATIONS;
1206 }
1207 
1208 //-----------------------------------------------------------------------------
1209 // Returns true if a license problem occured in last call to optimize.
1210 
isLicenseError() const1211 bool OsiMskSolverInterface::isLicenseError() const
1212 {
1213    #if MSK_OSI_DEBUG_LEVEL > 3
1214    debugMessage("Begin OsiMskSolverInterface::isLicenseError()\n");
1215    #endif
1216 
1217    #if MSK_OSI_DEBUG_LEVEL > 3
1218    debugMessage("license error %d \n",Mskerr);
1219    debugMessage("End OsiMskSolverInterface::isLicenseError()\n");
1220    #endif
1221 
1222    return Mskerr >= MSK_RES_ERR_LICENSE && Mskerr <= MSK_RES_ERR_LICENSE_NO_SERVER_SUPPORT;
1223 }
1224 
1225 
1226 //#############################################################################
1227 // WarmStart related methods
1228 //#############################################################################
1229 
1230 // Get an empty warm start object
getEmptyWarmStart() const1231 CoinWarmStart* OsiMskSolverInterface::getEmptyWarmStart () const
1232 { return (dynamic_cast<CoinWarmStart *>(new CoinWarmStartBasis())) ; }
1233 
1234 //-----------------------------------------------------------------------------
1235 // Get warm start, returns NULL pointer if not available
1236 
getWarmStart() const1237 CoinWarmStart* OsiMskSolverInterface::getWarmStart() const
1238 {
1239 
1240   CoinWarmStartBasis* ws = NULL;
1241   int numbas = 0,numcols = getNumCols(),numrows = getNumRows(),*skx,*skc,
1242       err, i,*bkc,*bkx;
1243   double *blc,*buc,*blx,*bux,*xc,*xx;
1244 
1245   bool skip = false;
1246 
1247   #if MSK_OSI_DEBUG_LEVEL > 1
1248   debugMessage("Begin OsiMskSolverInterface::getWarmStart numcols %d numrows %d %p\n",numcols,numrows, (void*)this);
1249   #endif
1250 
1251   skx = new int[numcols];
1252   skc = new int[numrows];
1253 
1254   bkc = new int[numrows];
1255   blc = new double[numrows];
1256   buc = new double[numrows];
1257   xc  = new double[numrows];
1258 
1259   bkx = new int[numcols];
1260   blx = new double[numcols];
1261   bux = new double[numcols];
1262   xx  = new double[numcols];
1263 
1264 #if MSK_VERSION_MAJOR < 9
1265   err = MSK_getboundslice(getMutableLpPtr(),
1266                           MSK_ACC_CON,
1267                           0,
1268                           numrows,
1269                           (MSKboundkeye*)bkc,
1270                           (MSKrealt*)blc,
1271                           (MSKrealt*)buc);
1272 
1273   checkMSKerror( err, "MSK_getboundslice", "getWarmStart" );
1274 
1275   err = MSK_getboundslice(getMutableLpPtr(),
1276                           MSK_ACC_VAR,
1277                           0,
1278                           numcols,
1279                           (MSKboundkeye*)bkx,
1280                           (MSKrealt*)blx,
1281                           (MSKrealt*)bux);
1282 
1283   checkMSKerror( err, "MSK_getboundslice", "getWarmStart" );
1284 #else
1285   err = MSK_getconboundslice(getMutableLpPtr(),
1286                           0,
1287                           numrows,
1288                           (MSKboundkeye*)bkc,
1289                           (MSKrealt*)blc,
1290                           (MSKrealt*)buc);
1291 
1292   checkMSKerror( err, "getconboundslice", "getWarmStart" );
1293 
1294   err = MSK_getvarboundslice(getMutableLpPtr(),
1295                           0,
1296                           numcols,
1297                           (MSKboundkeye*)bkx,
1298                           (MSKrealt*)blx,
1299                           (MSKrealt*)bux);
1300 
1301   checkMSKerror( err, "MSK_getvarboundslice", "getWarmStart" );
1302 #endif
1303 
1304   MSKassert(3,!probtypemip_,"!probtypemip_","getWarmStart");
1305 
1306   if( definedSolution( MSK_SOL_BAS ) == true )
1307   {
1308     err  =   MSK_getsolution(getMutableLpPtr(),
1309                              MSK_SOL_BAS,
1310                              NULL,
1311                              NULL,
1312                              (MSKstakeye*)skc,
1313                              (MSKstakeye*)skx,
1314                              NULL,
1315                              NULL,
1316                              NULL,
1317                              NULL,
1318                              NULL,
1319                              NULL,
1320                              NULL,
1321                              NULL,
1322                              NULL);
1323 
1324       checkMSKerror( err, "MSK_getsolution", "getWarmStart" );
1325   }
1326   else
1327   {
1328     #if MSK_OSI_DEBUG_LEVEL > 1
1329     debugMessage("No basic solution in OsiMskSolverInterface::getWarmStart()\n");
1330     #endif
1331 
1332     /* No basic solution stored choose slack basis */
1333     /* Otherwise the unittest can not be passed    */
1334     ws = new CoinWarmStartBasis;
1335     ws->setSize( numcols, numrows );
1336 
1337     for( i = 0; i < numrows; ++i )
1338       ws->setArtifStatus( i, CoinWarmStartBasis::basic );
1339 
1340     numbas = numrows;
1341 
1342     for( i = 0; i < numcols; ++i )
1343     {
1344       switch(bkx[i])
1345       {
1346         case MSK_BK_RA:
1347         case MSK_BK_LO:
1348            ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound );
1349         break;
1350         case MSK_BK_FX:
1351         case MSK_BK_UP:
1352            ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound );
1353         break;
1354         case MSK_BK_FR:
1355            ws->setStructStatus( i, CoinWarmStartBasis::isFree );
1356         break;
1357         default:
1358           checkMSKerror( 1, "Wrong bound key", "getWarmStart" );
1359       }
1360     }
1361 
1362     #if MSK_OSI_DEBUG_LEVEL > 1
1363     debugMessage("End OsiMskSolverInterface::getWarmStart()\n");
1364     #endif
1365 
1366     delete[] skc;
1367     delete[] skx;
1368 
1369     delete[] bkc;
1370     delete[] blc;
1371     delete[] buc;
1372     delete[] xc;
1373 
1374     delete[] bkx;
1375     delete[] blx;
1376     delete[] bux;
1377     delete[] xx;
1378 
1379     /* Leave function */
1380     return ws;
1381   }
1382 
1383   if( err == MSK_RES_OK )
1384   {
1385     /* Status keys should be defined  */
1386     ws = new CoinWarmStartBasis;
1387 
1388     MSKassert(3,ws != NULL,"1) ws != NULL","getWarmStart");
1389 
1390     ws->setSize( numcols, numrows );
1391 
1392     for( i = 0; i < numrows && ws != NULL; ++i )
1393     {
1394       switch( skc[i] )
1395       {
1396         case MSK_SK_UNK:
1397         case MSK_SK_BAS:
1398           /* Warning : Slacks in Osi and Mosek er negated */
1399           ws->setArtifStatus( i, CoinWarmStartBasis::basic );
1400           ++numbas;
1401           break;
1402         case MSK_SK_LOW:
1403           /* Warning : Slacks in Osi and Mosek er negated */
1404           ws->setArtifStatus( i, CoinWarmStartBasis::atUpperBound );
1405           break;
1406         case MSK_SK_FIX:
1407         case MSK_SK_UPR:
1408           /* Warning : Slacks in Osi and Mosek er negated */
1409           ws->setArtifStatus( i, CoinWarmStartBasis::atLowerBound );
1410           break;
1411         case MSK_SK_SUPBAS:
1412           ws->setArtifStatus( i, CoinWarmStartBasis::isFree );
1413           break;
1414         default:  // unknown row status
1415           delete ws;
1416           ws   = NULL;
1417           skip = true;
1418           checkMSKerror( 1, "Wrong slack status key", "getWarmStart" );
1419           break;
1420       }
1421     }
1422 
1423     if( skip == false )
1424     {
1425       for( i = 0; i < numcols && ws != NULL; ++i )
1426       {
1427         switch( skx[i] )
1428         {
1429           case MSK_SK_UNK:
1430           case MSK_SK_BAS:
1431             ++numbas;
1432             ws->setStructStatus( i, CoinWarmStartBasis::basic );
1433             break;
1434           case MSK_SK_FIX:
1435           case MSK_SK_LOW:
1436             ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound );
1437             break;
1438           case MSK_SK_UPR:
1439             ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound );
1440             break;
1441           case MSK_SK_SUPBAS:
1442             ws->setStructStatus( i, CoinWarmStartBasis::isFree );
1443             break;
1444           default:  // unknown column status
1445             delete ws;
1446             ws = NULL;
1447             checkMSKerror( 1, "Wrong variable status key", "getWarmStart" );
1448             break;
1449         }
1450       }
1451     }
1452   }
1453 
1454   delete[] skx;
1455   delete[] skc;
1456 
1457   delete[] bkc;
1458   delete[] blc;
1459   delete[] buc;
1460   delete[] xc;
1461 
1462   delete[] bkx;
1463   delete[] blx;
1464   delete[] bux;
1465   delete[] xx;
1466 
1467   MSKassert(3,ws!=NULL,"2) ws!=NULL","getWarmStart");
1468 
1469   #if MSK_OSI_DEBUG_LEVEL > 1
1470   debugMessage("End OsiMskSolverInterface::getWarmStart() (%p) numcols %d numrows %d numbas %d\n",(void*)(ws),numcols,numrows,numbas);
1471   #endif
1472 
1473   return ws;
1474 }
1475 
1476 //-----------------------------------------------------------------------------
1477 // Set warm start
1478 
setWarmStart(const CoinWarmStart * warmstart)1479 bool OsiMskSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
1480 {
1481 
1482   const CoinWarmStartBasis* ws = dynamic_cast<const CoinWarmStartBasis*>(warmstart);
1483   int numcols, numrows, i, restat,numbas=0;
1484   int *skx, *skc, *bkc, *bkx;
1485   bool retval = false, skip = false;
1486 
1487   if( !ws )
1488     return false;
1489 
1490   numcols = ws->getNumStructural();
1491   numrows = ws->getNumArtificial();
1492 
1493   #if MSK_OSI_DEBUG_LEVEL > 1
1494   debugMessage("Begin OsiMskSolverInterface::setWarmStart(%p) this = %p numcols %d numrows %d\n", (void *)warmstart,(void*)this,numcols,numrows);
1495   #endif
1496 
1497   if( numcols != getNumCols() || numrows != getNumRows() )
1498     return false;
1499 
1500   switchToLP();
1501 
1502   skx  = new int[numcols];
1503   skc  = new int[numrows];
1504   bkc  = new int[numrows];
1505 
1506 #if MSK_VERSION_MAJOR < 9
1507   restat = MSK_getboundslice(getMutableLpPtr(),
1508                              MSK_ACC_CON,
1509                              0,
1510                              numrows,
1511                              (MSKboundkeye*) (bkc),
1512                              NULL,
1513                              NULL);
1514 
1515   checkMSKerror( restat, "MSK_getboundslice", "setWarmStart" );
1516 #else
1517   restat = MSK_getconboundslice(getMutableLpPtr(),
1518                              0,
1519                              numrows,
1520                              (MSKboundkeye*) (bkc),
1521                              NULL,
1522                              NULL);
1523 
1524   checkMSKerror( restat, "MSK_getconboundslice", "setWarmStart" );
1525 #endif
1526 
1527   for( i = 0; i < numrows; ++i )
1528   {
1529     switch( ws->getArtifStatus( i ) )
1530     {
1531       case CoinWarmStartBasis::basic:
1532         skc[i] = MSK_SK_BAS;
1533         ++numbas;
1534       break;
1535       /* Warning : Slacks in Osi and Mosek er negated */
1536       case CoinWarmStartBasis::atUpperBound:
1537         switch(bkc[i])
1538         {
1539           case MSK_BK_LO:
1540           case MSK_BK_RA:
1541           skc[i] = MSK_SK_LOW;
1542           break;
1543           case MSK_BK_FX:
1544           skc[i] = MSK_SK_FIX;
1545           break;
1546           default:
1547           skc[i] = MSK_SK_UNK;
1548           break;
1549         }
1550       break;
1551       /* Warning : Slacks in Osi and Mosek er negated */
1552       case CoinWarmStartBasis::atLowerBound:
1553         switch(bkc[i])
1554         {
1555           case MSK_BK_UP:
1556           case MSK_BK_RA:
1557           skc[i] = MSK_SK_UPR;
1558           break;
1559           case MSK_BK_FX:
1560           skc[i] = MSK_SK_FIX;
1561           break;
1562           default:
1563           skc[i] = MSK_SK_UNK;
1564           break;
1565         }
1566         break;
1567       case CoinWarmStartBasis::isFree:
1568        skc[i] = MSK_SK_SUPBAS;
1569        break;
1570       default:  // unknown row status
1571        retval = false;
1572        skip   = true;
1573        MSKassert(3,1,"Unkown rowstatus","setWarmStart");
1574        break;
1575     }
1576   }
1577 
1578   delete[] bkc;
1579 
1580   if( skip == false )
1581   {
1582     bkx = new int[numcols];
1583 
1584 #if MSK_VERSION_MAJOR < 9
1585     restat = MSK_getboundslice(getMutableLpPtr(),
1586                                MSK_ACC_VAR,
1587                                0,
1588                                numcols,
1589                                (MSKboundkeye*) (bkx),
1590                                NULL,
1591                                NULL);
1592 
1593    checkMSKerror( restat, "MSK_getboundslice", "setWarmStart" );
1594 #else
1595    restat = MSK_getvarboundslice(getMutableLpPtr(),
1596                               0,
1597                               numcols,
1598                               (MSKboundkeye*) (bkx),
1599                               NULL,
1600                               NULL);
1601 
1602   checkMSKerror( restat, "MSK_getvarboundslice", "setWarmStart" );
1603 #endif
1604 
1605    for( i = 0; i < numcols; ++i )
1606     {
1607       switch( ws->getStructStatus( i ) )
1608       {
1609         case CoinWarmStartBasis::basic:
1610          skx[i] = MSK_SK_BAS;
1611          ++numbas;
1612          break;
1613         case CoinWarmStartBasis::atLowerBound:
1614           switch(bkx[i])
1615           {
1616             case MSK_BK_LO:
1617             case MSK_BK_RA:
1618               skx[i] = MSK_SK_LOW;
1619             break;
1620             case MSK_BK_FX:
1621               skx[i] = MSK_SK_FIX;
1622             default:
1623             skx[i] = MSK_SK_UNK;
1624             break;
1625           }
1626          break;
1627        case CoinWarmStartBasis::atUpperBound:
1628           switch(bkx[i])
1629           {
1630             case MSK_BK_UP:
1631             case MSK_BK_RA:
1632               skx[i] = MSK_SK_UPR;
1633             break;
1634             case MSK_BK_FX:
1635               skx[i] = MSK_SK_FIX;
1636             default:
1637             skx[i] = MSK_SK_UNK;
1638             break;
1639           }
1640          break;
1641        case CoinWarmStartBasis::isFree:
1642          skx[i] = MSK_SK_SUPBAS;
1643          break;
1644        default:  // unknown col status
1645          retval   = false;
1646          skip     = true;
1647          MSKassert(3,1,"Unkown col status","setWarmStart");
1648        break;
1649       }
1650     }
1651 
1652     delete[] bkx;
1653   }
1654 
1655   #if MSK_OSI_DEBUG_LEVEL > 1
1656   debugMessage("OsiMskSolverInterface::setWarmStart(%p) numcols %d numrows %d numbas %d\n", (void *)warmstart,numcols,numrows,numbas);
1657   #endif
1658 
1659   #if 0
1660   MSKassert(3,numbas == numrows,"Wrong number of basis variables","setWarmStart");
1661   #endif
1662 
1663   if( skip == false )
1664   {
1665     restat = MSK_putsolution( getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ),
1666                               MSK_SOL_BAS,
1667                               (MSKstakeye*) (skc),
1668                               (MSKstakeye*) (skx),
1669                               NULL,
1670                               NULL,
1671                               NULL,
1672                               NULL,
1673                               NULL,
1674                               NULL,
1675                               NULL,
1676                               NULL,
1677                               NULL);
1678 
1679     delete[] skx;
1680     delete[] skc;
1681   }
1682   else
1683   {
1684     #if MSK_OSI_DEBUG_LEVEL > 1
1685     debugMessage("Skipping setting values in OsiMskSolverInterface::setWarmStart()\n");
1686     #endif
1687 
1688     #if MSK_OSI_DEBUG_LEVEL > 1
1689     debugMessage("End OsiMskSolverInterface::setWarmStart(%p)\n", (void *)warmstart);
1690     #endif
1691 
1692     delete[] skx;
1693     delete[] skc;
1694 
1695     return false;
1696   }
1697 
1698   retval = (restat == MSK_RES_OK);
1699 
1700   #if MSK_OSI_DEBUG_LEVEL > 1
1701   debugMessage("End OsiMskSolverInterface::setWarmStart(%p)\n", (void *)warmstart);
1702   #endif
1703 
1704   return retval;
1705 }
1706 
1707 //#############################################################################
1708 // Hotstart related methods (primarily used in strong branching)
1709 //#############################################################################
1710 
1711 //-----------------------------------------------------------------------------
1712 // Mark hot start
1713 
markHotStart()1714 void OsiMskSolverInterface::markHotStart()
1715 {
1716   #if MSK_OSI_DEBUG_LEVEL > 1
1717   debugMessage("Begin OsiMskSolverInterface::markHotStart()\n");
1718   #endif
1719 
1720   int err;
1721   int numcols, numrows;
1722 
1723   MSKassert(3,!probtypemip_,"probtypemip_","markHotStart");
1724 
1725   numcols = getNumCols();
1726   numrows = getNumRows();
1727 
1728   if( numcols > hotStartCStatSize_ )
1729   {
1730     delete[] hotStartCStat_;
1731     hotStartCStatSize_ = static_cast<int>( 1.0 * static_cast<double>( numcols ) );
1732     // get some extra space for future hot starts
1733     hotStartCStat_ = new int[hotStartCStatSize_];
1734   }
1735 
1736   if( numrows > hotStartRStatSize_ )
1737   {
1738     delete[] hotStartRStat_;
1739     hotStartRStatSize_ = static_cast<int>( 1.0 * static_cast<double>( numrows ) );
1740     // get some extra space for future hot starts
1741     hotStartRStat_ = new int[hotStartRStatSize_];
1742   }
1743 
1744   err = MSK_getsolution(getMutableLpPtr(),
1745                         MSK_SOL_BAS,
1746                         NULL,
1747                         NULL,
1748                         (MSKstakeye*) (hotStartRStat_),
1749                         (MSKstakeye*) (hotStartCStat_),
1750                         NULL,
1751                         NULL,
1752                         NULL,
1753                         NULL,
1754                         NULL,
1755                         NULL,
1756                         NULL,
1757                         NULL,
1758                         NULL);
1759 
1760   checkMSKerror( err, "MSK_getsolution", "markHotStart" );
1761 
1762   #if MSK_OSI_DEBUG_LEVEL > 1
1763   debugMessage("End OsiMskSolverInterface::markHotStart()\n");
1764   #endif
1765 }
1766 
1767 //-----------------------------------------------------------------------------
1768 // Solve from a hot start
1769 
solveFromHotStart()1770 void OsiMskSolverInterface::solveFromHotStart()
1771 {
1772   #if MSK_OSI_DEBUG_LEVEL > 1
1773   debugMessage("Begin OsiMskSolverInterface::solveFromHotStart()\n");
1774   #endif
1775 
1776   int err;
1777 
1778   int maxiter;
1779 
1780 
1781   switchToLP();
1782 
1783   MSKassert(3,getNumCols() <= hotStartCStatSize_,"getNumCols() <= hotStartCStatSize_","solveFromHotStart");
1784   MSKassert(3,getNumRows() <= hotStartRStatSize_,"getNumRows() <= hotStartRStatSize_","solveFromHotStart");
1785 
1786   err = MSK_putsolution(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ),
1787                         MSK_SOL_BAS,
1788                         (MSKstakeye*) (hotStartRStat_),
1789                         (MSKstakeye*) (hotStartCStat_),
1790                         NULL,
1791                         NULL,
1792                         NULL,
1793                         NULL,
1794                         NULL,
1795                         NULL,
1796                         NULL,
1797                         NULL,
1798                         NULL);
1799 
1800 
1801   checkMSKerror( err, "MSK_putsolution", "solveFromHotStart" );
1802 
1803   err = MSK_getintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, &maxiter );
1804   checkMSKerror( err, "MSK_getintparam", "solveFromHotStart" );
1805 
1806   err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, hotStartMaxIteration_ );
1807   checkMSKerror( err, "MSK_putintparam", "solveFromHotStart" );
1808 
1809   resolve();
1810 
1811   err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, maxiter );
1812 
1813   checkMSKerror( err, "MSK_putintparam", "solveFromHotStart" );
1814 
1815   #if MSK_OSI_DEBUG_LEVEL > 1
1816   debugMessage("End OsiMskSolverInterface::solveFromHotStart()\n");
1817   #endif
1818 }
1819 
1820 //-----------------------------------------------------------------------------
1821 // Unmark a hot start
1822 
unmarkHotStart()1823 void OsiMskSolverInterface::unmarkHotStart()
1824 {
1825   #if MSK_OSI_DEBUG_LEVEL > 1
1826   debugMessage("Begin OsiMskSolverInterface::unmarkHotStart()\n");
1827   #endif
1828 
1829   freeCachedData();
1830 
1831   if( hotStartCStat_ != NULL )
1832     delete[] hotStartCStat_;
1833 
1834   if( hotStartRStat_ != NULL )
1835     delete[] hotStartRStat_;
1836 
1837   hotStartCStat_     = NULL;
1838   hotStartCStatSize_ = 0;
1839   hotStartRStat_     = NULL;
1840   hotStartRStatSize_ = 0;
1841 
1842   #if MSK_OSI_DEBUG_LEVEL > 1
1843   debugMessage("End OsiMskSolverInterface::unmarkHotStart()\n");
1844   #endif
1845 }
1846 
1847 //#############################################################################
1848 // Problem information methods (original data)
1849 //#############################################################################
1850 
1851 
1852 //-----------------------------------------------------------------------------
1853 // Returns number of columns in MOSEK task
1854 
getNumCols() const1855 int OsiMskSolverInterface::getNumCols() const
1856 {
1857   #if MSK_OSI_DEBUG_LEVEL > 3
1858   debugMessage("Begin OsiMskSolverInterface::getNumCols()\n");
1859   #endif
1860 
1861   int numcol, err;
1862   err = MSK_getnumvar(getMutableLpPtr(),&numcol);
1863   checkMSKerror( err, "MSK_getnumvar", "getNumCols" );
1864 
1865   #if MSK_OSI_DEBUG_LEVEL > 3
1866   debugMessage("End OsiMskSolverInterface::getNumCols()\n");
1867   #endif
1868 
1869   return numcol;
1870 }
1871 
1872 //-----------------------------------------------------------------------------
1873 // Returns number of rows in MOSEK task
1874 
getNumRows() const1875 int OsiMskSolverInterface::getNumRows() const
1876 {
1877   #if MSK_OSI_DEBUG_LEVEL > 3
1878   debugMessage("Begin OsiMskSolverInterface::getNumRows()\n");
1879   #endif
1880 
1881   int numrow, err;
1882   err = MSK_getnumcon(getMutableLpPtr(),&numrow);
1883   checkMSKerror( err, "MSK_getnumcon", "getNumRows" );
1884 
1885   #if MSK_OSI_DEBUG_LEVEL > 3
1886   debugMessage("End OsiMskSolverInterface::getNumRows()\n");
1887   #endif
1888 
1889   return numrow;
1890 }
1891 
1892 //-----------------------------------------------------------------------------
1893 // Returns number of non-zeroes (in matrix) in MOSEK task
1894 
getNumElements() const1895 int OsiMskSolverInterface::getNumElements() const
1896 {
1897   #if MSK_OSI_DEBUG_LEVEL > 3
1898   debugMessage("Begin OsiMskSolverInterface::getNumElements()\n");
1899   #endif
1900 
1901   int numnon, err;
1902   err = MSK_getnumanz(getMutableLpPtr(),&numnon);
1903   checkMSKerror( err, "MSK_getnumanz", "getNumElements" );
1904 
1905   #if MSK_OSI_DEBUG_LEVEL > 3
1906   debugMessage("End OsiMskSolverInterface::getNumElements()\n");
1907   #endif
1908 
1909   return numnon;
1910 }
1911 
1912 
1913 //-----------------------------------------------------------------------------
1914 // Returns lower bounds on columns in MOSEK task
1915 
getColLower() const1916 const double * OsiMskSolverInterface::getColLower() const
1917 {
1918   #if MSK_OSI_DEBUG_LEVEL > 3
1919   debugMessage("Begin OsiMskSolverInterface::getColLower()\n");
1920   #endif
1921 
1922   if(collower_ == NULL )
1923   {
1924     int ncols = getNumCols();
1925 
1926     MSKassert(3,colupper_ == NULL,"colupper_","getColLower");
1927 
1928     if( ncols > 0 )
1929     {
1930       if(colupper_ == NULL)
1931         colupper_       = new double[ncols];
1932 
1933       if(collower_ == NULL)
1934         collower_       = new double[ncols];
1935 
1936       int *dummy_tags = new int[ncols];
1937 
1938 #if MSK_VERSION_MAJOR < 9
1939       int err = MSK_getboundslice(getMutableLpPtr(),
1940                                   MSK_ACC_VAR,
1941                                   (MSKidxt)0,
1942                                   (MSKidxt)ncols,
1943                                   (MSKboundkeye*) (dummy_tags),
1944                                   collower_,
1945                                   colupper_);
1946 
1947       checkMSKerror(err, "MSK_getboundslice","getColUpper");
1948 #else
1949       int err = MSK_getvarboundslice(getMutableLpPtr(),
1950                                   0,
1951                                   ncols,
1952                                   (MSKboundkeye*) (dummy_tags),
1953                                   collower_,
1954                                   colupper_);
1955 
1956       checkMSKerror(err, "MSK_getvarboundslice","getColUpper");
1957 #endif
1958 
1959       for( int k = 0; k < ncols; ++k )
1960       {
1961         if( dummy_tags[k] == MSK_BK_UP ||
1962             dummy_tags[k] == MSK_BK_FR )
1963         {
1964           /* No lower */
1965           collower_[k] = -getInfinity();
1966         }
1967 
1968         if( dummy_tags[k] == MSK_BK_LO ||
1969             dummy_tags[k] == MSK_BK_FR )
1970         {
1971           /* No upper */
1972           colupper_[k] =  getInfinity();
1973         }
1974       }
1975 
1976       delete[] dummy_tags;
1977 
1978     }
1979     else
1980     {
1981       if(colupper_ != NULL)
1982         delete [] colupper_;
1983 
1984       if(collower_ != NULL)
1985         delete [] collower_;
1986 
1987       colupper_ = collower_ = NULL;
1988     }
1989   }
1990 
1991   #if MSK_OSI_DEBUG_LEVEL > 3
1992   debugMessage("End OsiMskSolverInterface::getColLower()\n");
1993   #endif
1994 
1995   return collower_;
1996 }
1997 
1998 //-----------------------------------------------------------------------------
1999 // Returns upper bounds on columns in MOSEK task
2000 
getColUpper() const2001 const double * OsiMskSolverInterface::getColUpper() const
2002 {
2003   #if MSK_OSI_DEBUG_LEVEL > 3
2004   debugMessage("Begin OsiMskSolverInterface::getColUpper()\n");
2005   #endif
2006 
2007   if( colupper_ == NULL )
2008   {
2009     int ncols = getNumCols();
2010 
2011     MSKassert(3,collower_ == NULL,"collower_ == NULL","getColUpper");
2012 
2013     if( ncols > 0 )
2014     {
2015       if(colupper_ == NULL)
2016         colupper_       = new double[ncols];
2017 
2018       if(collower_ == NULL)
2019         collower_       = new double[ncols];
2020 
2021       int *dummy_tags = new int[ncols];
2022 
2023 #if MSK_VERSION_MAJOR < 9
2024       int err = MSK_getboundslice( getMutableLpPtr(),
2025                                    MSK_ACC_VAR,
2026                                    (MSKidxt)0,
2027                                    (MSKidxt)ncols,
2028                                    (MSKboundkeye*) (dummy_tags),
2029                                    collower_,
2030                                    colupper_);
2031 
2032       checkMSKerror(err,"MSK_getboundslice","getColUpper");
2033 #else
2034       int err = MSK_getvarboundslice( getMutableLpPtr(),
2035                                    0,
2036                                    ncols,
2037                                    (MSKboundkeye*) (dummy_tags),
2038                                    collower_,
2039                                    colupper_);
2040 
2041       checkMSKerror(err,"MSK_getvarboundslice","getColUpper");
2042 #endif
2043 
2044       delete[] dummy_tags;
2045     }
2046     else
2047     {
2048       if(colupper_ != NULL)
2049         delete [] colupper_;
2050 
2051       if(collower_ != NULL)
2052         delete [] collower_;
2053 
2054       colupper_ = collower_ = NULL;
2055     }
2056   }
2057 
2058   #if MSK_OSI_DEBUG_LEVEL > 3
2059   debugMessage("End OsiMskSolverInterface::getColUpper()\n");
2060   #endif
2061 
2062   return colupper_;
2063 }
2064 
2065 
2066 //-----------------------------------------------------------------------------
2067 // Returns rowsense in MOSEK task, call getRightHandSide to produce triplets.
2068 
getRowSense() const2069 const char * OsiMskSolverInterface::getRowSense() const
2070 {
2071   #if MSK_OSI_DEBUG_LEVEL > 3
2072   debugMessage("Begin OsiMskSolverInterface::getRowSense()\n");
2073   #endif
2074 
2075   if( rowsense_==NULL )
2076   {
2077     getRightHandSide();
2078 
2079     if( getNumRows() != 0 )
2080       MSKassert(3,rowsense_!=NULL,"rowsense_!=NULL","getRowSense");
2081   }
2082 
2083   #if MSK_OSI_DEBUG_LEVEL > 3
2084   debugMessage("End OsiMskSolverInterface::getRowSense()\n");
2085   #endif
2086 
2087   return rowsense_;
2088 }
2089 
2090 //-----------------------------------------------------------------------------
2091 // Returns the RHS in triplet form. MOSEK uses always boundkeys instead of the
2092 // triplet, so we have to convert back to triplet.
2093 
getRightHandSide() const2094 const double * OsiMskSolverInterface::getRightHandSide() const
2095 {
2096   #if MSK_OSI_DEBUG_LEVEL > 3
2097   debugMessage("Begin OsiMskSolverInterface::getRightHandSide()\n");
2098   #endif
2099 
2100   if(rowsense_ == NULL)
2101   {
2102     int nr = getNumRows();
2103     if ( nr != 0 )
2104     {
2105       MSKassert(3,(rhs_ == NULL) && (rowrange_ == NULL),"(rhs_ == NULL) && (rowrange_ == NULL)","getRightHandSide");
2106 
2107       rowsense_         = new char[nr];
2108       rhs_              = new double[nr];
2109       rowrange_         = new double[nr];
2110       const double * lb = getRowLower();
2111       const double * ub = getRowUpper();
2112       int i;
2113 
2114       for ( i=0; i<nr; i++ )
2115         convertBoundToSense(lb[i], ub[i], rowsense_[i], rhs_[i], rowrange_[i]);
2116     }
2117   }
2118 
2119   #if MSK_OSI_DEBUG_LEVEL > 3
2120   debugMessage("End OsiMskSolverInterface::getRightHandSide()\n");
2121   #endif
2122 
2123   return rhs_;
2124 }
2125 
2126 //-----------------------------------------------------------------------------
2127 // Returns rowrange in MOSEK task, call getRightHandSide to produce triplets.
2128 
getRowRange() const2129 const double * OsiMskSolverInterface::getRowRange() const
2130 {
2131   #if MSK_OSI_DEBUG_LEVEL > 3
2132   debugMessage("Begin OsiMskSolverInterface::getRowRange()\n");
2133   #endif
2134 
2135   if( rowrange_ == NULL )
2136   {
2137     getRightHandSide();
2138     MSKassert(3,rowrange_!=NULL || getNumRows() == 0,"rowrange_!=NULL || getNumRows() == 0","getRowRange");
2139   }
2140 
2141   #if MSK_OSI_DEBUG_LEVEL > 3
2142   debugMessage("End OsiMskSolverInterface::getRowRange()\n");
2143   #endif
2144 
2145   return rowrange_;
2146 }
2147 
2148 
2149 //-----------------------------------------------------------------------------
2150 // Returns lower bounds on rows in MOSEK task.
2151 
getRowLower() const2152 const double * OsiMskSolverInterface::getRowLower() const
2153 {
2154   #if MSK_OSI_DEBUG_LEVEL > 3
2155   debugMessage("Begin OsiMskSolverInterface::getRowLower()\n");
2156   #endif
2157 
2158   if( rowlower_ == NULL )
2159   {
2160     MSKassert(3,rowupper_ == NULL,"rowupper_ == NULL","getRowLower");
2161 
2162     int nrows = getNumRows();
2163 
2164     if( nrows > 0 )
2165     {
2166       rowlower_       = new double[nrows];
2167       rowupper_       = new double[nrows];
2168       int *dummy_tags = new int[nrows];
2169 
2170 #if MSK_VERSION_MAJOR < 9
2171       int err = MSK_getboundslice(getMutableLpPtr(),
2172                                   MSK_ACC_CON,
2173                                   (MSKidxt)0,
2174                                   (MSKidxt)nrows,
2175                                   (MSKboundkeye*) (dummy_tags),
2176                                   rowlower_,
2177                                   rowupper_);
2178 
2179       checkMSKerror(err,"MSK_getboundslice","getRowLower");
2180 #else
2181       int err = MSK_getconboundslice(getMutableLpPtr(),
2182                                   0,
2183                                   nrows,
2184                                   (MSKboundkeye*) (dummy_tags),
2185                                   rowlower_,
2186                                   rowupper_);
2187 
2188       checkMSKerror(err,"MSK_getconboundslice","getRowLower");
2189 #endif
2190       delete[] dummy_tags;
2191     }
2192   }
2193 
2194   #if MSK_OSI_DEBUG_LEVEL > 3
2195   debugMessage("End OsiMskSolverInterface::getRowLower()\n");
2196   #endif
2197 
2198   return rowlower_;
2199 }
2200 
2201 
2202 //-----------------------------------------------------------------------------
2203 // Returns upper bounds on rows in MOSEK task.
2204 
getRowUpper() const2205 const double * OsiMskSolverInterface::getRowUpper() const
2206 {
2207   #if MSK_OSI_DEBUG_LEVEL > 3
2208   debugMessage("Begin OsiMskSolverInterface::getRowUpper()\n");
2209   #endif
2210 
2211   if( rowupper_ == NULL )
2212   {
2213     MSKassert(3,rowlower_ == NULL,"probtypemip_","getRowUpper");
2214 
2215     int nrows = getNumRows();
2216 
2217     if( nrows > 0 )
2218     {
2219       rowupper_       = new double[nrows];
2220       rowlower_       = new double[nrows];
2221       int *dummy_tags = new int[nrows];
2222 
2223 #if MSK_VERSION_MAJOR < 9
2224       int err = MSK_getboundslice(getMutableLpPtr(),
2225                                   MSK_ACC_CON,
2226                                   (MSKidxt)0,
2227                                   (MSKidxt)nrows,
2228                                   (MSKboundkeye*) (dummy_tags),
2229                                   rowlower_,
2230                                   rowupper_);
2231 
2232       checkMSKerror(err,"MSK_getboundslice","getRowUpper");
2233 #else
2234       int err = MSK_getconboundslice(getMutableLpPtr(),
2235                                   0,
2236                                   nrows,
2237                                   (MSKboundkeye*) (dummy_tags),
2238                                   rowlower_,
2239                                   rowupper_);
2240 
2241       checkMSKerror(err,"MSK_getconboundslice","getRowUpper");
2242 #endif
2243 
2244       delete[] dummy_tags;
2245     }
2246   }
2247 
2248   #if MSK_OSI_DEBUG_LEVEL > 3
2249   debugMessage("End OsiMskSolverInterface::getRowUpper()\n");
2250   #endif
2251 
2252   return rowupper_;
2253 }
2254 
2255 
2256 //-----------------------------------------------------------------------------
2257 // Returns objective coefficient in MOSEK task.
2258 
2259 
getObjCoefficients() const2260 const double * OsiMskSolverInterface::getObjCoefficients() const
2261 {
2262   #if MSK_OSI_DEBUG_LEVEL > 3
2263   debugMessage("Begin OsiMskSolverInterface::getObjCoefficients()\n");
2264   #endif
2265 
2266   if( obj_ == NULL )
2267   {
2268     int ncols = getNumCols();
2269 
2270     if( ncols > 0 )
2271     {
2272       obj_    = new double[ncols];
2273       int err = MSK_getc( getMutableLpPtr(), obj_ );
2274 
2275       checkMSKerror( err, "MSK_getc", "getObjCoefficients" );
2276     }
2277   }
2278 
2279   #if MSK_OSI_DEBUG_LEVEL > 3
2280   debugMessage("End OsiMskSolverInterface::getObjCoefficients()\n");
2281   #endif
2282 
2283   return obj_;
2284 }
2285 
2286 
2287 //-----------------------------------------------------------------------------
2288 // Returns the direction of optimization
2289 
getObjSense() const2290 double OsiMskSolverInterface::getObjSense() const
2291 {
2292   #if MSK_OSI_DEBUG_LEVEL > 3
2293   debugMessage("Begin OsiMskSolverInterface::getObjSense()\n");
2294   #endif
2295 
2296   int err;
2297   MSKobjsensee objsen;
2298 
2299   err = MSK_getobjsense(getMutableLpPtr(),
2300                         &objsen);
2301 
2302   checkMSKerror(err,"MSK_getintparam","getObjSense");
2303 
2304   #if MSK_OSI_DEBUG_LEVEL > 3
2305   debugMessage("End OsiMskSolverInterface::getObjSense()\n");
2306   #endif
2307 
2308   if( objsen == MSK_OBJECTIVE_SENSE_MAXIMIZE )
2309     return -1.0;
2310   else
2311     return +1.0;
2312 }
2313 
2314 
2315 //-----------------------------------------------------------------------------
2316 // Returns true if variabel is set to continuous
2317 
isContinuous(int colNumber) const2318 bool OsiMskSolverInterface::isContinuous( int colNumber ) const
2319 {
2320   #if MSK_OSI_DEBUG_LEVEL > 3
2321   debugMessage("Begin OsiMskSolverInterface::isContinuous(%d)\n", colNumber);
2322   debugMessage("End OsiMskSolverInterface::isContinuous(%d)\n", colNumber);
2323   #endif
2324 
2325   return getCtype()[colNumber] == 'C';
2326 }
2327 
2328 
2329 //-----------------------------------------------------------------------------
2330 // Returns a Coin matrix by row
2331 
getMatrixByRow() const2332 const CoinPackedMatrix * OsiMskSolverInterface::getMatrixByRow() const
2333 {
2334   #if MSK_OSI_DEBUG_LEVEL > 3
2335   debugMessage("Begin OsiMskSolverInterface::getMatrixByRow()\n");
2336   #endif
2337 
2338   if ( matrixByRow_ == NULL )
2339   {
2340     int nc, nr, nz, *sub, *ptrb, *ptre, surp, *len;
2341     double *val;
2342     nc       = getNumCols();
2343     nr       = getNumRows();
2344     nz       = surp = getNumElements();
2345     ptrb     = new int[nr+1];
2346     ptre     = new int[nr];
2347     sub      = new int[nz];
2348     val      = new double[nz];
2349     len      = new int[nr];
2350     ptrb[nr] = nz;
2351 
2352 #if MSK_VERSION_MAJOR < 9
2353     int err = MSK_getaslice(getMutableLpPtr(),
2354                             MSK_ACC_CON,
2355                             0,
2356                             nr,
2357                             nz,
2358                             &surp,
2359                             ptrb,
2360                             ptre,
2361                             sub,
2362                             val);
2363 
2364     checkMSKerror(err, "MSK_getaslice", "getMatrixByRow");
2365 #else
2366     int err = MSK_getarowslice(getMutableLpPtr(),
2367                             0,
2368                             nr,
2369                             nz,
2370                             &surp,
2371                             ptrb,
2372                             ptre,
2373                             sub,
2374                             val);
2375 
2376     checkMSKerror(err, "MSK_getarowslice", "getMatrixByRow");
2377 #endif
2378 
2379     for(int i=0; i<nr; i++)
2380       len[i] = ptre[i]-ptrb[i];
2381 
2382     matrixByRow_ = new CoinPackedMatrix();
2383     matrixByRow_->assignMatrix(false , nc, nr, nz, val, sub, ptrb, len);
2384 
2385     MSKassert(3,matrixByRow_->getNumCols()==nc,"matrixByRow_->getNumCols()==nc","getMatrixByRow");
2386     MSKassert(3,matrixByRow_->getNumRows()==nr,"matrixByRow_->getNumRows()==nr","getMatrixByRow");
2387 
2388     delete[] ptrb;
2389     delete[] ptre;
2390     delete[] sub;
2391     delete[] val;
2392     delete[] len;
2393   }
2394 
2395   #if MSK_OSI_DEBUG_LEVEL > 3
2396   debugMessage("End OsiMskSolverInterface::getMatrixByRow()\n");
2397   #endif
2398 
2399   return matrixByRow_;
2400 }
2401 
2402 
2403 //-----------------------------------------------------------------------------
2404 // Returns a Coin matrix by column
2405 
getMatrixByCol() const2406 const CoinPackedMatrix * OsiMskSolverInterface::getMatrixByCol() const
2407 {
2408   #if MSK_OSI_DEBUG_LEVEL > 3
2409   debugMessage("Begin OsiMskSolverInterface::getMatrixByCol()\n");
2410   #endif
2411 
2412   if ( matrixByCol_ == NULL )
2413   {
2414     int nc, nr, nz, *sub, *ptrb, *ptre, surp, *len;
2415     double *val;
2416 
2417     nc       = getNumCols();
2418     nr       = getNumRows();
2419     nz       = surp = getNumElements();
2420     ptrb     = new int[nc+1];
2421     ptre     = new int[nc];
2422     sub      = new int[nz];
2423     val      = new double[nz];
2424     len      = new int[nc];
2425     ptrb[nc] = nz;
2426 
2427 #if MSK_VERSION_MAJOR < 9
2428     int err = MSK_getaslice(getMutableLpPtr(),
2429                             MSK_ACC_VAR,
2430                             0,
2431                             nc,
2432                             nz,
2433                             &surp,
2434                             ptrb,
2435                             ptre,
2436                             sub,
2437                             val);
2438 
2439     checkMSKerror(err, "MSK_getaslice", "getMatrixByCol");
2440 #else
2441     int err = MSK_getacolslice(getMutableLpPtr(),
2442                             0,
2443                             nc,
2444                             nz,
2445                             &surp,
2446                             ptrb,
2447                             ptre,
2448                             sub,
2449                             val);
2450 
2451     checkMSKerror(err, "MSK_getacolslice", "getMatrixByCol");
2452 #endif
2453 
2454     for(int i=0; i<nc; i++)
2455       len[i] = ptre[i]-ptrb[i];
2456 
2457     matrixByCol_ = new CoinPackedMatrix();
2458     matrixByCol_->assignMatrix(true , nr, nc, nz, val, sub, ptrb, len);
2459 
2460     MSKassert(3,matrixByCol_->getNumCols()==nc,"matrixByCol_->getNumCols()==nc","getMatrixByCol");
2461     MSKassert(3,matrixByCol_->getNumRows()==nr,"matrixByCol_->getNumRows()==nr","getMatrixByCol");
2462 
2463     delete[] ptrb;
2464     delete[] ptre;
2465     delete[] sub;
2466     delete[] val;
2467     delete[] len;
2468   }
2469 
2470   #if MSK_OSI_DEBUG_LEVEL > 3
2471   debugMessage("End OsiMskSolverInterface::getMatrixByCol()\n");
2472   #endif
2473 
2474   return matrixByCol_;
2475 }
2476 
2477 
2478 //-----------------------------------------------------------------------------
2479 // Returns the infinity level used in MOSEK.
2480 
getInfinity() const2481 double OsiMskSolverInterface::getInfinity() const
2482 {
2483   #if MSK_OSI_DEBUG_LEVEL > 3
2484   debugMessage("Begin OsiMskSolverInterface::getInfinity()\n");
2485   debugMessage("End OsiMskSolverInterface::getInfinity()\n");
2486   #endif
2487 
2488   return MSK_INFINITY;
2489 }
2490 
2491 //#############################################################################
2492 // Problem information methods (results)
2493 //#############################################################################
2494 
2495 //-----------------------------------------------------------------------------
2496 // Returns the current col solution.
2497 
getColSolution() const2498 const double * OsiMskSolverInterface::getColSolution() const
2499 {
2500   #if MSK_OSI_DEBUG_LEVEL > 3
2501   debugMessage("Begin OsiMskSolverInterface::getColSolution() %p\n",(void*)this);
2502   #endif
2503 
2504   if( colsol_ != NULL )
2505   {
2506     #if MSK_OSI_DEBUG_LEVEL > 3
2507     debugMessage("colsol_ != NULL\n");
2508     #endif
2509 
2510     return colsol_;
2511   }
2512 
2513   int i;
2514   int nc = getNumCols();
2515   if( nc > 0 )
2516   {
2517     MSKsoltypee solution = MSK_SOL_END;
2518 
2519     if(colsol_ == NULL)
2520       colsol_ = new double[nc];
2521 
2522     if( probtypemip_ == false)
2523     {
2524       if( definedSolution( MSK_SOL_BAS ) == true )
2525         solution = MSK_SOL_BAS;
2526       else if( definedSolution( MSK_SOL_ITR) == true )
2527         solution = MSK_SOL_ITR;
2528     }
2529     else if( definedSolution( MSK_SOL_ITG ) == true )
2530       solution = MSK_SOL_ITG;
2531 
2532     if ( solution == MSK_SOL_END )
2533     {
2534       double const *cl=getColLower(),*cu=getColLower();
2535 
2536       /* this is just plain stupid, but needed to pass unit test */
2537       for( i = 0; i < nc; ++i )
2538       {
2539         if( cl[i] > -getInfinity() )
2540         {
2541           colsol_[i] = cl[i];
2542         }
2543         else if( cu[i] < getInfinity() )
2544         {
2545           colsol_[i] = cu[i];
2546         }
2547         else
2548         {
2549           colsol_[i] = 0.0;
2550         }
2551       }
2552 
2553       #if MSK_OSI_DEBUG_LEVEL > 3
2554       debugMessage("colsol_ truncated to zero due to no solution\n");
2555       debugMessage("probtypemip_ %d\n",probtypemip_);
2556       #endif
2557 
2558       return colsol_;
2559     }
2560 
2561     int err = MSK_getsolution(getMutableLpPtr(),
2562                               solution,
2563                               NULL,
2564                               NULL,
2565                               NULL,
2566                               NULL,
2567                               NULL,
2568                               NULL,
2569                               colsol_,
2570                               NULL,
2571                               NULL,
2572                               NULL,
2573                               NULL,
2574                               NULL,
2575                               NULL
2576                               );
2577 
2578     checkMSKerror(err,"MSK_getsolution","getColSolution");
2579   }
2580 
2581   #if MSK_OSI_DEBUG_LEVEL > 3
2582   debugMessage("End OsiMskSolverInterface::getColSolution()\n");
2583   #endif
2584 
2585   return colsol_;
2586 }
2587 
2588 //-----------------------------------------------------------------------------
2589 // Returns the row price / dual variabels in MOSEK task
2590 
getRowPrice() const2591 const double * OsiMskSolverInterface::getRowPrice() const
2592 {
2593   #if MSK_OSI_DEBUG_LEVEL > 3
2594   debugMessage("Begin OsiMskSolverInterface::getRowPrice()\n");
2595   #endif
2596 
2597   if( rowsol_ == NULL )
2598   {
2599     int i;
2600     int nr = getNumRows();
2601 
2602     if( nr > 0 )
2603     {
2604       MSKsoltypee solution = MSK_SOL_END;
2605       rowsol_      = new double[nr];
2606 
2607       if( definedSolution( MSK_SOL_BAS ) == true )
2608         solution = MSK_SOL_BAS;
2609       else if( definedSolution( MSK_SOL_ITR) == true )
2610         solution = MSK_SOL_ITR;
2611 
2612       if ( solution == MSK_SOL_END )
2613       {
2614         for( i = 0; i < nr; ++i )
2615            rowsol_[i] = 0.0;
2616 
2617         return rowsol_;
2618       }
2619 
2620       int err = MSK_getsolution(getMutableLpPtr(),
2621                                 solution,
2622                                 NULL,
2623                                 NULL,
2624                                 NULL,
2625                                 NULL,
2626                                 NULL,
2627                                 NULL,
2628                                 NULL,
2629                                 rowsol_,
2630                                 NULL,
2631                                 NULL,
2632                                 NULL,
2633                                 NULL,
2634                                 NULL);
2635 
2636 
2637       checkMSKerror( err, "MSK_getsolution", "getRowPrice" );
2638     }
2639   }
2640 
2641   #if MSK_OSI_DEBUG_LEVEL > 3
2642   debugMessage("End OsiMskSolverInterface::getRowPrice()\n");
2643   #endif
2644 
2645   return rowsol_;
2646 }
2647 
2648 //-----------------------------------------------------------------------------
2649 // Returns the reduced cost in MOSEK task.
2650 
getReducedCost() const2651 const double * OsiMskSolverInterface::getReducedCost() const
2652 {
2653   #if MSK_OSI_DEBUG_LEVEL > 3
2654   debugMessage("Begin OsiMskSolverInterface::getReducedCost()\n");
2655   #endif
2656 
2657   if( redcost_ == NULL )
2658   {
2659     int ncols = getNumCols();
2660 
2661     if( ncols > 0 )
2662     {
2663       MSKsoltypee solution = MSK_SOL_END;
2664       if( definedSolution( MSK_SOL_BAS ) == true )
2665         solution = MSK_SOL_BAS;
2666       else if( definedSolution( MSK_SOL_ITR) == true )
2667         solution = MSK_SOL_ITR;
2668 
2669       if ( solution == MSK_SOL_END )
2670         return NULL;
2671 
2672       redcost_    = new double[ncols];
2673       double *slx = new double[ncols];
2674       double *sux = new double[ncols];
2675 
2676       int err = MSK_getsolution(getMutableLpPtr(),
2677                                 solution,
2678                                 NULL,
2679                                 NULL,
2680                                 NULL,
2681                                 NULL,
2682                                 NULL,
2683                                 NULL,
2684                                 NULL,
2685                                 NULL,
2686                                 NULL,
2687                                 NULL,
2688                                 slx,
2689                                 sux,
2690                                 NULL);
2691 
2692       // Calculate reduced cost
2693       for(int i = 0; i < ncols; i++)
2694         redcost_[i] = slx[i]-sux[i];
2695 
2696       delete[] slx;
2697       delete[] sux;
2698 
2699       checkMSKerror( err, "MSK_getsolution", "getReducedCost" );
2700     }
2701   }
2702 
2703   #if MSK_OSI_DEBUG_LEVEL > 3
2704   debugMessage("End OsiMskSolverInterface::getReducedCost()\n");
2705   #endif
2706 
2707   return  redcost_;
2708 }
2709 
2710 
2711 //-----------------------------------------------------------------------------
2712 // Returns the rowactivity in MOSEK task.
2713 
getRowActivity() const2714 const double * OsiMskSolverInterface::getRowActivity() const
2715 {
2716   #if MSK_OSI_DEBUG_LEVEL > 3
2717   debugMessage("Begin OsiMskSolverInterface::getRowActivity()\n");
2718   #endif
2719 
2720   if( rowact_ == NULL )
2721   {
2722     int nrows = getNumRows();
2723     if( nrows > 0 )
2724     {
2725       rowact_ = new double[nrows];
2726 
2727       const double *x = getColSolution() ;
2728       const CoinPackedMatrix *mtx = getMatrixByRow() ;
2729       mtx->times(x,rowact_) ;
2730    }
2731  }
2732 
2733  #if MSK_OSI_DEBUG_LEVEL > 3
2734  debugMessage("End OsiMskSolverInterface::getRowActivity()\n");
2735  #endif
2736 
2737  return  rowact_;
2738 }
2739 
2740 //-----------------------------------------------------------------------------
2741 // Returns the objective for defined solution in MOSEK task.
2742 
getObjValue() const2743 double OsiMskSolverInterface::getObjValue() const
2744 {
2745   #if MSK_OSI_DEBUG_LEVEL > 3
2746   debugMessage("Begin OsiMskSolverInterface::getObjValue()\n");
2747   #endif
2748 
2749   double objval = OsiSolverInterface::getObjValue();
2750 
2751   #if MSK_OSI_DEBUG_LEVEL > 3
2752   debugMessage("End OsiMskSolverInterface::getObjValue()\n");
2753   #endif
2754 
2755   return objval;
2756 }
2757 
2758 //-----------------------------------------------------------------------------
2759 // Returns the iteration used in last call to optimize. Notice that the cross
2760 // over phase in interior methods is not returned, when interior point is
2761 // used, only the interior point iterations.
2762 
getIterationCount() const2763 int OsiMskSolverInterface::getIterationCount() const
2764 {
2765   #if MSK_OSI_DEBUG_LEVEL > 3
2766   debugMessage("Begin OsiMskSolverInterface::getIterationCount()\n");
2767   #endif
2768 
2769   int nr = 0, solver, err;
2770   int nrp=0;
2771   solver = solverUsed();
2772 
2773   if( solver == MSK_OPTIMIZER_PRIMAL_SIMPLEX )
2774   {
2775     {
2776       err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_PRIMAL_ITER, &nr);
2777       checkMSKerror(err,"MSK_getintinf","getIterationsCount");
2778     }
2779   }
2780   else if( solver == MSK_OPTIMIZER_DUAL_SIMPLEX  )
2781   {
2782     {
2783       err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_DUAL_ITER, &nr);
2784       checkMSKerror(err,"MSK_getintinf","getIterationsCount");
2785     }
2786   }
2787   else if( solver == MSK_OPTIMIZER_FREE_SIMPLEX  )
2788   {
2789     {
2790       err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_DUAL_ITER, &nr);
2791       checkMSKerror(err,"MSK_getintinf","getIterationsCount");
2792       err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_PRIMAL_ITER, &nrp);
2793       checkMSKerror(err,"MSK_getintinf","getIterationsCount");
2794       nr = nr+nrp;
2795     }
2796   }
2797   else if( solver == MSK_OPTIMIZER_INTPNT )
2798   {
2799     {
2800       err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_INTPNT_ITER, &nr);
2801       checkMSKerror(err,"MSK_getintinf","getIterationsCount");
2802     }
2803   }
2804 
2805   #if MSK_OSI_DEBUG_LEVEL > 3
2806   debugMessage("End OsiMskSolverInterface::getIterationCount()\n");
2807   #endif
2808 
2809   return nr;
2810 }
2811 
2812 //-----------------------------------------------------------------------------
2813 // Returns one dual ray
2814 
getDualRays(int maxNumRays,bool fullRay) const2815 std::vector<double*> OsiMskSolverInterface::getDualRays(int maxNumRays,
2816 							bool fullRay) const
2817 {
2818   #if MSK_OSI_DEBUG_LEVEL > 3
2819   debugMessage("Begin OsiMskSolverInterface::getDualRays(%d,%s)\n", maxNumRays,
2820 	       fullRay?"true":"false");
2821   #endif
2822 
2823   if (fullRay == true) {
2824     throw CoinError("Full dual rays not yet implemented.","getDualRays",
2825 		    "OsiMskSolverInterface");
2826   }
2827 
2828   OsiMskSolverInterface solver(*this);
2829 
2830   int numrows = getNumRows(), r;
2831   MSKsolstae status;
2832   MSKsoltypee solution;
2833 
2834   if( probtypemip_ == false )
2835   {
2836     if( definedSolution( MSK_SOL_BAS ) == true )
2837       solution = MSK_SOL_BAS;
2838     else
2839     {
2840       if( definedSolution( MSK_SOL_ITR ) == true )
2841         solution = MSK_SOL_ITR;
2842       else
2843         return std::vector<double*>();
2844     }
2845   }
2846   else
2847   {
2848     if( definedSolution( MSK_SOL_ITG ) == true )
2849       solution = MSK_SOL_ITG;
2850     else
2851       return std::vector<double*>();
2852   }
2853 
2854   double *farkasray = new double[numrows];
2855   r = MSK_getsolution(getMutableLpPtr(),
2856                       solution,
2857                       NULL,
2858                       &status,
2859                       NULL,
2860                       NULL,
2861                       NULL,
2862                       NULL,
2863                       NULL,
2864                       farkasray,
2865                       NULL,
2866                       NULL,
2867                       NULL,
2868                       NULL,
2869                       NULL);
2870 
2871   checkMSKerror( r, "MSK_getsolution", "getDualRays" );
2872 
2873   #if MSK_OSI_DEBUG_LEVEL > 3
2874   debugMessage("End OsiMskSolverInterface::getDualRays(%d)\n", maxNumRays);
2875   #endif
2876 
2877   if( status != MSK_SOL_STA_PRIM_INFEAS_CER )
2878   {
2879     delete[] farkasray;
2880 
2881     return std::vector<double*>();
2882   }
2883   else
2884     return std::vector<double*>(1, farkasray);
2885 }
2886 
2887 //-----------------------------------------------------------------------------
2888 // Returns one primal ray
2889 
getPrimalRays(int maxNumRays) const2890 std::vector<double*> OsiMskSolverInterface::getPrimalRays(int maxNumRays) const
2891 {
2892   #if MSK_OSI_DEBUG_LEVEL > 3
2893   debugMessage("Begin OsiMskSolverInterface::getPrimalRays(%d)\n", maxNumRays);
2894   #endif
2895 
2896   OsiMskSolverInterface solver(*this);
2897 
2898   int numcols = getNumCols(), r;
2899   MSKsolstae status;
2900   MSKsoltypee solution;
2901 
2902   if( probtypemip_ == false )
2903   {
2904     if( definedSolution( MSK_SOL_BAS ) == true )
2905       solution = MSK_SOL_BAS;
2906     else
2907     {
2908       if( definedSolution( MSK_SOL_ITR ) == true )
2909         solution = MSK_SOL_ITR;
2910       else
2911         return std::vector<double*>();
2912     }
2913   }
2914   else
2915   {
2916     if( definedSolution( MSK_SOL_ITG ) == true )
2917       solution = MSK_SOL_ITG;
2918     else
2919       return std::vector<double*>();
2920   }
2921 
2922   double *farkasray = new double[numcols];
2923 
2924   r = MSK_getsolution(getMutableLpPtr(),
2925                       solution,
2926                       NULL,
2927                       &status,
2928                       NULL,
2929                       NULL,
2930                       NULL,
2931                       NULL,
2932                       farkasray,
2933                       NULL,
2934                       NULL,
2935                       NULL,
2936                       NULL,
2937                       NULL,
2938                       NULL);
2939 
2940   checkMSKerror( r, "MSK_getsolution", "getPrimalRays" );
2941 
2942   #if MSK_OSI_DEBUG_LEVEL > 3
2943   debugMessage("End OsiMskSolverInterface::getPrimalRays(%d)\n", maxNumRays);
2944   #endif
2945 
2946   if( status != MSK_SOL_STA_DUAL_INFEAS_CER )
2947   {
2948     delete[] farkasray;
2949 
2950     return std::vector<double*>();
2951   }
2952   else
2953     return std::vector<double*>(1, farkasray);
2954 }
2955 
2956 //#############################################################################
2957 // Problem modifying methods (rim vectors)
2958 //#############################################################################
2959 
2960 //-----------------------------------------------------------------------------
2961 // Sets a variabels objective coeff.
2962 
setObjCoeff(int elementIndex,double elementValue)2963 void OsiMskSolverInterface::setObjCoeff( int elementIndex, double elementValue )
2964 {
2965   #if MSK_OSI_DEBUG_LEVEL > 3
2966   debugMessage("Begin OsiMskSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue);
2967   #endif
2968 
2969   const double *oldobj;
2970 
2971   if( redcost_  && !obj_ )
2972     oldobj = getObjCoefficients();
2973   else
2974     oldobj = obj_;
2975 
2976   int err = MSK_putclist(getMutableLpPtr(),
2977                           1,
2978                           &elementIndex,
2979                           &elementValue);
2980 
2981   checkMSKerror(err, "MSK_putclist", "setObjCoeff");
2982 
2983   if( obj_  )
2984   {
2985     if( redcost_  )
2986     {
2987       redcost_[elementIndex] += elementValue-oldobj[elementIndex];
2988       obj_[elementIndex]      = elementValue;
2989     }
2990     else
2991     {
2992       obj_[elementIndex] = elementValue;
2993     }
2994   }
2995 
2996   #if MSK_OSI_DEBUG_LEVEL > 3
2997   debugMessage("End OsiMskSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue);
2998   #endif
2999 }
3000 
3001 //-----------------------------------------------------------------------------
3002 // Sets a list of objective coeff.
3003 
setObjCoeffSet(const int * indexFirst,const int * indexLast,const double * coeffList)3004 void OsiMskSolverInterface::setObjCoeffSet(const int* indexFirst,
3005                                            const int* indexLast,
3006                                            const double* coeffList)
3007 {
3008   #if MSK_OSI_DEBUG_LEVEL > 3
3009   debugMessage("Begin OsiMskSolverInterface::setObjCoeffSet(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)coeffList);
3010   #endif
3011 
3012   const double *oldobj;
3013   const long int cnt = indexLast - indexFirst;
3014 
3015   if( redcost_  && !obj_ )
3016     oldobj = getObjCoefficients();
3017   else
3018     oldobj = obj_;
3019 
3020   int err = MSK_putclist(getMutableLpPtr(),
3021                          static_cast<int>(cnt),
3022                          const_cast<int*>(indexFirst),
3023                          const_cast<double*>(coeffList));
3024 
3025   checkMSKerror(err, "MSK_putclist", "setObjCoeffSet");
3026 
3027   if( obj_  )
3028   {
3029     if( redcost_  )
3030     {
3031       for( int j = 0; j < cnt; ++j)
3032       {
3033         redcost_[j] += coeffList[indexFirst[j]]-oldobj[j];
3034         obj_[j]      = coeffList[indexFirst[j]];
3035       }
3036     }
3037     else
3038     {
3039       for( int j = 0; j < cnt; ++j)
3040       {
3041         obj_[j] = coeffList[indexFirst[j]];
3042       }
3043     }
3044   }
3045 
3046 
3047   #if MSK_OSI_DEBUG_LEVEL > 3
3048   debugMessage("End OsiMskSolverInterface::setObjCoeffSet(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)coeffList);
3049   #endif
3050 }
3051 
3052 //-----------------------------------------------------------------------------
3053 // Sets lower bound on one specific column
3054 
setColLower(int elementIndex,double elementValue)3055 void OsiMskSolverInterface::setColLower(int elementIndex, double elementValue)
3056 {
3057   #if MSK_OSI_DEBUG_LEVEL > 3
3058   debugMessage("Begin OsiMskSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue);
3059   #endif
3060 
3061   int finite = 1;
3062 
3063   if( elementValue <= -getInfinity() )
3064     finite = 0;
3065 
3066 #if MSK_VERSION_MAJOR < 9
3067   int err = MSK_chgbound(getMutableLpPtr(),
3068                          MSK_ACC_VAR,
3069                          elementIndex,
3070                          1,       /*It is a lower bound*/
3071                          finite,  /* Is it finite */
3072                          elementValue);
3073 
3074   checkMSKerror( err, "MSK_chgbound", "setColLower" );
3075 #else
3076   int err = MSK_chgvarbound(getMutableLpPtr(),
3077                          elementIndex,
3078                          1,       /*It is a lower bound*/
3079                          finite,  /* Is it finite */
3080                          elementValue);
3081 
3082   checkMSKerror( err, "MSK_chgvarbound", "setColLower" );
3083 #endif
3084 
3085   if( collower_ != NULL )
3086     collower_[elementIndex] = elementValue;
3087 
3088   #if MSK_OSI_DEBUG_LEVEL > 3
3089   debugMessage("End OsiMskSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue);
3090   #endif
3091 }
3092 
3093 //-----------------------------------------------------------------------------
3094 // Sets upper bound on one specific column.
3095 
setColUpper(int elementIndex,double elementValue)3096 void OsiMskSolverInterface::setColUpper(int elementIndex, double elementValue)
3097 {
3098   #if MSK_OSI_DEBUG_LEVEL > 3
3099   debugMessage("Begin OsiMskSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue);
3100   #endif
3101 
3102   int finite = 1;
3103 
3104   if( elementValue >= getInfinity() )
3105     finite = 0;
3106 
3107 #if MSK_VERSION_MAJOR < 9
3108   int err = MSK_chgbound( getMutableLpPtr(),
3109                           MSK_ACC_VAR,
3110                           elementIndex,
3111                           0,       /* It is a upper bound */
3112                           finite,  /* Is it finite */
3113                           elementValue);
3114 
3115   checkMSKerror( err, "MSK_chgbound", "setColUpper" );
3116 #else
3117   int err = MSK_chgvarbound( getMutableLpPtr(),
3118                           elementIndex,
3119                           0,       /* It is a upper bound */
3120                           finite,  /* Is it finite */
3121                           elementValue);
3122 
3123   checkMSKerror( err, "MSK_chgvarbound", "setColUpper" );
3124 #endif
3125 
3126   if( colupper_ != NULL )
3127     colupper_[elementIndex] = elementValue;
3128 
3129   #if MSK_OSI_DEBUG_LEVEL > 3
3130   debugMessage("End OsiMskSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue);
3131   #endif
3132 }
3133 
3134 //-----------------------------------------------------------------------------
3135 // Sets upper and lower bound on one specific column
3136 
setColBounds(int elementIndex,double lower,double upper)3137 void OsiMskSolverInterface::setColBounds( int elementIndex, double lower, double upper )
3138 {
3139   #if MSK_OSI_DEBUG_LEVEL > 3
3140   debugMessage("Begin OsiMskSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper);
3141   #endif
3142 
3143   setColLower(elementIndex, lower);
3144   setColUpper(elementIndex, upper);
3145 
3146   #if MSK_OSI_DEBUG_LEVEL > 3
3147   debugMessage("End OsiMskSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper);
3148   #endif
3149 }
3150 
3151 //-----------------------------------------------------------------------------
3152 // Sets upper and lower bounds on a list of columns. Due to the strange storage of
3153 // boundlist, it is not possible to change all the bounds in one call to MOSEK,
3154 // so the standard method is used.
3155 
setColSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)3156 void OsiMskSolverInterface::setColSetBounds(const int* indexFirst,
3157                                              const int* indexLast,
3158                                              const double* boundList)
3159 {
3160   #if MSK_OSI_DEBUG_LEVEL > 3
3161   debugMessage("Begin OsiMskSolverInterface::setColSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList);
3162   #endif
3163 
3164   OsiSolverInterface::setColSetBounds( indexFirst, indexLast, boundList );
3165 
3166   #if MSK_OSI_DEBUG_LEVEL > 3
3167   debugMessage("End OsiMskSolverInterface::setColSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList);
3168   #endif
3169 }
3170 
3171 //-----------------------------------------------------------------------------
3172 // Sets the lower bound on a row
3173 
3174 void
setRowLower(int i,double elementValue)3175 OsiMskSolverInterface::setRowLower( int i, double elementValue )
3176 {
3177   #if MSK_OSI_DEBUG_LEVEL > 3
3178   debugMessage("Begin OsiMskSolverInterface::setRowLower(%d, %g)\n", i, elementValue);
3179   #endif
3180 
3181   double rhs   = getRightHandSide()[i];
3182   double range = getRowRange()[i];
3183   char   sense = getRowSense()[i];
3184   double lower=-MSK_INFINITY, upper=MSK_INFINITY;
3185 
3186   convertSenseToBound( sense, rhs, range, lower, upper );
3187   if( lower != elementValue )
3188   {
3189     convertBoundToSense( elementValue, upper, sense, rhs, range );
3190     setRowType( i, sense, rhs, range );
3191   }
3192 
3193   #if MSK_OSI_DEBUG_LEVEL > 3
3194   debugMessage("End OsiMskSolverInterface::setRowLower(%d, %g)\n", i, elementValue);
3195   #endif
3196 }
3197 
3198 //-----------------------------------------------------------------------------
3199 // Sets the upper bound on a row
3200 
3201 void
setRowUpper(int i,double elementValue)3202 OsiMskSolverInterface::setRowUpper( int i, double elementValue )
3203 {
3204   #if MSK_OSI_DEBUG_LEVEL > 3
3205   debugMessage("Begin OsiMskSolverInterface::setRowUpper(%d, %g)\n", i, elementValue);
3206   #endif
3207 
3208   double rhs   = getRightHandSide()[i];
3209   double range = getRowRange()[i];
3210   char   sense = getRowSense()[i];
3211   double lower=-MSK_INFINITY, upper=MSK_INFINITY;
3212 
3213   convertSenseToBound( sense, rhs, range, lower, upper );
3214   if( upper != elementValue )
3215   {
3216     convertBoundToSense( lower, elementValue, sense, rhs, range );
3217     setRowType( i, sense, rhs, range );
3218   }
3219 
3220   #if MSK_OSI_DEBUG_LEVEL > 3
3221   debugMessage("End OsiMskSolverInterface::setRowUpper(%d, %g)\n", i, elementValue);
3222   #endif
3223 }
3224 
3225 //-----------------------------------------------------------------------------
3226 // Sets the upper and lower bound on a row
3227 
3228 void
setRowBounds(int elementIndex,double lower,double upper)3229 OsiMskSolverInterface::setRowBounds( int elementIndex, double lower, double upper )
3230 {
3231   #if MSK_OSI_DEBUG_LEVEL > 3
3232   debugMessage("Begin OsiMskSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper);
3233   #endif
3234 
3235   double rhs, range;
3236   char sense;
3237 
3238   convertBoundToSense( lower, upper, sense, rhs, range );
3239   setRowType( elementIndex, sense, rhs, range );
3240 
3241   #if MSK_OSI_DEBUG_LEVEL > 3
3242   debugMessage("End OsiMskSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper);
3243   #endif
3244 }
3245 
3246 //-----------------------------------------------------------------------------
3247 // Sets the triplet on a row
3248 
3249 void
setRowType(int i,char sense,double rightHandSide,double range)3250 OsiMskSolverInterface::setRowType(int i, char sense, double rightHandSide,double range)
3251 {
3252   #if MSK_OSI_DEBUG_LEVEL > 3
3253   debugMessage("Begin OsiMskSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range);
3254   #endif
3255 
3256   double rub=MSK_INFINITY,rlb=-MSK_INFINITY;
3257   int rtag=MSK_BK_FR;
3258 
3259   MskConvertSenseToBound(sense, range, rightHandSide, rlb, rub, rtag);
3260 
3261 #if MSK_VERSION_MAJOR < 9
3262   int err = MSK_putbound(getMutableLpPtr(),
3263                          MSK_ACC_CON,
3264                          i,
3265                          (MSKboundkeye)rtag,
3266                          rlb,
3267                          rub);
3268 
3269   checkMSKerror( err, "MSK_putbound", "setRowType" );
3270 #else
3271   int err = MSK_putconbound(getMutableLpPtr(),
3272                          i,
3273                          (MSKboundkeye)rtag,
3274                          rlb,
3275                          rub);
3276 
3277   checkMSKerror( err, "MSK_putconbound", "setRowType" );
3278 #endif
3279 
3280   if( rowsense_ != NULL )
3281      rowsense_[i] = sense;
3282 
3283   if( rowrange_ != NULL )
3284      rowrange_[i] = range;
3285 
3286   if( rhs_      != NULL )
3287      rhs_[i]      = rightHandSide;
3288 
3289   #if MSK_OSI_DEBUG_LEVEL > 3
3290   debugMessage("End OsiMskSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range);
3291   #endif
3292 }
3293 
3294 //-----------------------------------------------------------------------------
3295 // Set upper og lower bounds for a lisit of rows. Due to the strange storage of
3296 // boundlist, it is not possible to change all the bounds in one call to MOSEK,
3297 // so the standard method is used.
3298 
setRowSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)3299 void OsiMskSolverInterface::setRowSetBounds(const int* indexFirst,
3300                                               const int* indexLast,
3301                                               const double* boundList)
3302 {
3303   #if MSK_OSI_DEBUG_LEVEL > 3
3304   debugMessage("Begin OsiMskSolverInterface::setRowSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList);
3305   #endif
3306 
3307   const long int cnt = indexLast - indexFirst;
3308 
3309   if (cnt <= 0)
3310     return;
3311 
3312   for (int i = 0; i < cnt; ++i)
3313     setRowBounds(indexFirst[i], boundList[2*i], boundList[2*i+1]);
3314 
3315   #if MSK_OSI_DEBUG_LEVEL > 3
3316   debugMessage("End OsiMskSolverInterface::setRowSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList);
3317   #endif
3318 }
3319 
3320 
3321 //-----------------------------------------------------------------------------
3322 // Set triplets for a list of rows
3323 
3324 void
setRowSetTypes(const int * indexFirst,const int * indexLast,const char * senseList,const double * rhsList,const double * rangeList)3325 OsiMskSolverInterface::setRowSetTypes(const int* indexFirst,
3326                                        const int* indexLast,
3327                                        const char* senseList,
3328                                        const double* rhsList,
3329                                        const double* rangeList)
3330 {
3331   #if MSK_OSI_DEBUG_LEVEL > 3
3332   debugMessage("Begin OsiMskSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n",
3333    (void *)indexFirst, (void *)indexLast, (void *)senseList, (void *)rhsList, (void *)rangeList);
3334   #endif
3335 
3336   const long int cnt = indexLast - indexFirst;
3337 
3338   if (cnt <= 0)
3339     return;
3340 
3341   for (int i = 0; i < cnt; ++i)
3342     setRowType(indexFirst[i], senseList[i], rhsList[i], rangeList[i]);
3343 
3344   #if MSK_OSI_DEBUG_LEVEL > 3
3345   debugMessage("End OsiMskSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n",
3346                 (void *)indexFirst, (void *)indexLast, (void *)senseList, (void *)rhsList, (void *)rangeList);
3347   #endif
3348 }
3349 
3350 
3351 //-----------------------------------------------------------------------------
3352 // Sets a variabel to continuous
3353 
3354 void
setContinuous(int index)3355 OsiMskSolverInterface::setContinuous(int index)
3356 {
3357   int numcols = getNumCols();
3358 
3359   #if MSK_OSI_DEBUG_LEVEL > 3
3360   debugMessage("Begin OsiMskSolverInterface::setContinuous(%d)\n", index);
3361   #endif
3362 
3363   MSKassert(3,coltype_ != NULL,"coltype_ != NULL","setContinuous");
3364   MSKassert(3,coltypesize_ >= getNumCols(),"coltypesize_ >= getNumCols()","setContinuous");
3365 
3366   coltype_[index] = 'C';
3367 
3368   if( index < numcols )
3369   {
3370     int err = MSK_putvartype( getMutableLpPtr(), index, MSK_VAR_TYPE_CONT);
3371     checkMSKerror( err, "MSK_putvartype", "setContinuous" );
3372   }
3373 
3374   #if MSK_OSI_DEBUG_LEVEL > 3
3375   debugMessage("End OsiMskSolverInterface::setContinuous(%d)\n", index);
3376   #endif
3377 }
3378 
3379 //-----------------------------------------------------------------------------
3380 // Sets a variabel to integer
3381 
3382 void
setInteger(int index)3383 OsiMskSolverInterface::setInteger(int index)
3384 {
3385   int numcols = getNumCols();
3386 
3387   #if MSK_OSI_DEBUG_LEVEL > 3
3388   debugMessage("Begin OsiMskSolverInterface::setInteger(%d)\n", index);
3389   #endif
3390 
3391   MSKassert(3,coltype_ != NULL,"coltype_ != NULL","setInteger");
3392   MSKassert(3,coltypesize_ >= getNumCols(),"coltypesize_ >= getNumCols()","setInteger");
3393 
3394   coltype_[index] = 'I';
3395 
3396   if( index < numcols )
3397   {
3398     int err = MSK_putvartype( getMutableLpPtr(), index, MSK_VAR_TYPE_INT);
3399 
3400     checkMSKerror( err, "MSK_putvartype", "setInteger" );
3401   }
3402 
3403   #if MSK_OSI_DEBUG_LEVEL > 3
3404   debugMessage("End OsiMskSolverInterface::setInteger(%d)\n", index);
3405   #endif
3406 }
3407 
3408 //-----------------------------------------------------------------------------
3409 // Sets a list of variables to continuous
3410 
3411 void
setContinuous(const int * indices,int len)3412 OsiMskSolverInterface::setContinuous(const int* indices, int len)
3413 {
3414   #if MSK_OSI_DEBUG_LEVEL > 3
3415   debugMessage("Begin OsiMskSolverInterface::setContinuous(%p, %d)\n", (void *)indices, len);
3416   #endif
3417 
3418   for( int i = 0; i < len; ++i )
3419     setContinuous(indices[i]);
3420 
3421   #if MSK_OSI_DEBUG_LEVEL > 3
3422   debugMessage("End OsiMskSolverInterface::setContinuous(%p, %d)\n", (void *)indices, len);
3423   #endif
3424 }
3425 
3426 //-----------------------------------------------------------------------------
3427 // Sets a list of variables to integer
3428 
3429 void
setInteger(const int * indices,int len)3430 OsiMskSolverInterface::setInteger(const int* indices, int len)
3431 {
3432   #if MSK_OSI_DEBUG_LEVEL > 3
3433   debugMessage("Begin OsiMskSolverInterface::setInteger(%p, %d)\n", (void *)indices, len);
3434   #endif
3435 
3436   for( int i = 0; i < len; ++i )
3437      setInteger(indices[i]);
3438 
3439   #if MSK_OSI_DEBUG_LEVEL > 3
3440   debugMessage("End OsiMskSolverInterface::setInteger(%p, %d)\n", (void *)indices, len);
3441   #endif
3442 }
3443 
3444 //-----------------------------------------------------------------------------
3445 // Sets the direction of optimization
3446 
setObjSense(double s)3447 void OsiMskSolverInterface::setObjSense(double s)
3448 {
3449   #if MSK_OSI_DEBUG_LEVEL > 3
3450   debugMessage("Begin OsiMskSolverInterface::setObjSense(%g)\n", s);
3451   #endif
3452 
3453   int err;
3454   double pre;
3455 
3456   pre = getObjSense();
3457 
3458   if( s == +1.0 )
3459   {
3460      err = MSK_putobjsense(getMutableLpPtr(),
3461                            MSK_OBJECTIVE_SENSE_MINIMIZE);
3462   }
3463   else
3464   {
3465     err = MSK_putobjsense(getMutableLpPtr(),
3466                           MSK_OBJECTIVE_SENSE_MAXIMIZE);
3467   }
3468 
3469   checkMSKerror(err,"MSK_putintparam","setObjSense");
3470 
3471   if( pre != s )
3472   {
3473     /* A hack to pass unit test, ugly as hell */
3474     /* When objective sense is changed then reset obj cuts */
3475     if( s > 0 )
3476     {
3477       setDblParam(OsiPrimalObjectiveLimit,-COIN_DBL_MAX) ;
3478       setDblParam(OsiDualObjectiveLimit,COIN_DBL_MAX) ;
3479     }
3480     else
3481     {
3482       setDblParam(OsiPrimalObjectiveLimit,COIN_DBL_MAX) ;
3483       setDblParam(OsiDualObjectiveLimit,-COIN_DBL_MAX) ;
3484     }
3485   }
3486 
3487   #if MSK_OSI_DEBUG_LEVEL > 3
3488   debugMessage("End OsiMskSolverInterface::setObjSense(%g)\n", s);
3489   #endif
3490 }
3491 
3492 //-----------------------------------------------------------------------------
3493 // Sets the col solution. This is very fuzzy WE LIKE STATUS KEYS not numerical values i.e superbasics or basic !!!.
3494 
setColSolution(const double * cs)3495 void OsiMskSolverInterface::setColSolution(const double * cs)
3496 {
3497   #if MSK_OSI_DEBUG_LEVEL > 1
3498   debugMessage("Begin OsiMskSolverInterface::setColSolution %p\n", (void*)this);
3499   #endif
3500 
3501   int err,nc = getNumCols(),nr = getNumRows(), numbas = 0;
3502   MSKstakeye *tskc,*tskx;
3503   MSKboundkeye *tbkx,*tbkc;
3504   MSKrealt *tblx,*tbux,*tblc,*tbuc;
3505   double *txc;
3506 
3507   if( cs == NULL )
3508   {
3509     freeCachedResults();
3510   }
3511   else if( nc > 0 )
3512   {
3513     if( colsol_ != NULL )
3514         delete[] colsol_;
3515 
3516     colsol_ = new double[nc];
3517 
3518     CoinDisjointCopyN( cs, nc, colsol_ );
3519 
3520     tbkx    = new MSKboundkeye[nc];
3521     tskx    = new MSKstakeye[nc];
3522     tblx    = new MSKrealt[nc];
3523     tbux    = new MSKrealt[nc];
3524 
3525     tskc    = new MSKstakeye[nr];
3526     txc     = new double[nr];
3527     tbkc    = new MSKboundkeye[nr];
3528     tblc    = new MSKrealt[nr];
3529     tbuc    = new MSKrealt[nr];
3530 
3531     const CoinPackedMatrix *mtx = getMatrixByCol() ;
3532     assert(mtx->getNumCols() == nc);
3533     assert(mtx->getNumRows() == nr);
3534     mtx->times(cs,txc) ;
3535 
3536     /* Negate due to different Osi and Mosek slack representation */
3537     for( int i = 0; i < nr; ++i )
3538     {
3539       txc[i]  = -txc[i];
3540       tskc[i] = MSK_SK_UNK;
3541     }
3542 
3543 #if MSK_VERSION_MAJOR < 9
3544     err = MSK_getboundslice(getMutableLpPtr(),
3545                             MSK_ACC_CON,
3546                             0,
3547                             nr,
3548                             tbkc,
3549                             tblc,
3550                             tbuc);
3551 
3552     checkMSKerror( err, "MSK_getboundslice", "setColsolution" );
3553 
3554     err = MSK_getboundslice(getMutableLpPtr(),
3555                             MSK_ACC_VAR,
3556                             0,
3557                             nc,
3558                             tbkx,
3559                             tblx,
3560                             tbux);
3561 
3562     checkMSKerror( err, "MSK_getboundslice", "setColsolution" );
3563 #else
3564     err = MSK_getconboundslice(getMutableLpPtr(),
3565                             0,
3566                             nr,
3567                             tbkc,
3568                             tblc,
3569                             tbuc);
3570 
3571     checkMSKerror( err, "MSK_getconboundslice", "setColsolution" );
3572 
3573     err = MSK_getvarboundslice(getMutableLpPtr(),
3574                             0,
3575                             nc,
3576                             tbkx,
3577                             tblx,
3578                             tbux);
3579 
3580     checkMSKerror( err, "MSK_getvarboundslice", "setColsolution" );
3581 #endif
3582 
3583     if( definedSolution( MSK_SOL_BAS ) == true )
3584     {
3585       err = MSK_getsolution(getMutableLpPtr(),
3586                             MSK_SOL_BAS,
3587                             NULL,
3588                             NULL,
3589                             tskc,
3590                             tskx,
3591                             NULL,
3592                             NULL,
3593                             NULL,
3594                             NULL,
3595                             NULL,
3596                             NULL,
3597                             NULL,
3598                             NULL,
3599                             NULL);
3600 
3601       checkMSKerror(err,"MSK_getsolution","setColSol");
3602     }
3603 
3604     for( int i = 0; i < nr; ++i )
3605     {
3606       if( tbkc[i] == MSK_BK_FX && tblc[i] == txc[i] )
3607       {
3608         tskc[i] = MSK_SK_FIX;
3609       }
3610       else if( ( tbkc[i] == MSK_BK_LO || tbkc[i] == MSK_BK_RA ) && tblc[i] == txc[i]   )
3611       {
3612         tskc[i] = MSK_SK_LOW;
3613       }
3614       else if( ( tbkc[i] == MSK_BK_UP || tbkc[i] == MSK_BK_RA ) && tbuc[i] == txc[i]   )
3615       {
3616         tskc[i] = MSK_SK_UPR;
3617       }
3618       else if( tbkc[i] == MSK_BK_FR  && txc[i] == 0.0   )
3619       {
3620         tskc[i] = MSK_SK_SUPBAS;
3621       }
3622       else
3623       {
3624         #if 0
3625         printf("Slack : %d bkc : %d blc : %-16.10e buc : %-16.10e xc : %-16.10e\n",
3626                i,tbkc[i],tblc[i],tbuc[i],txc[i]);
3627         #endif
3628 
3629         ++numbas;
3630 
3631         tskc[i] = MSK_SK_BAS;
3632       }
3633     }
3634 
3635     for( int j = 0; j < nc; ++j )
3636     {
3637       if( tbkx[j] == MSK_BK_FX && tblx[j] == cs[j] )
3638       {
3639         tskx[j] = MSK_SK_FIX;
3640       }
3641       else if( ( tbkx[j] == MSK_BK_LO || tbkx[j] == MSK_BK_RA ) && tblx[j] == cs[j]   )
3642       {
3643         tskx[j] = MSK_SK_LOW;
3644       }
3645       else if( ( tbkx[j] == MSK_BK_UP || tbkx[j] == MSK_BK_RA ) && tbux[j] == cs[j]   )
3646       {
3647         tskx[j] = MSK_SK_UPR;
3648       }
3649       else if( ( tbkx[j] == MSK_BK_FR  && cs[j] == 0.0 ) ||  numbas >= nr   )
3650       {
3651         tskx[j] = MSK_SK_SUPBAS;
3652       }
3653       else
3654       {
3655         #if 0
3656         printf("Org %d : bkx : %d blx : %-16.10e bux : %-16.10e xx : %-16.10e\n",
3657                j,tbkx[j],tblx[j],tbux[j],cs[j]);
3658         #endif
3659 
3660         tskx[j] = MSK_SK_BAS;
3661       }
3662     }
3663 
3664     err = MSK_putsolution(getMutableLpPtr(),
3665                            MSK_SOL_BAS,
3666                            tskc,
3667                            tskx,
3668                            NULL,
3669                            (MSKrealt*) txc,
3670                            const_cast<MSKrealt*>(cs),
3671                            NULL,
3672                            NULL,
3673                            NULL,
3674                            NULL,
3675                            NULL,
3676                            NULL);
3677 
3678     checkMSKerror(err,"MSK_putsolution","setColSol");
3679 
3680 
3681     MSKassert(3,definedSolution( MSK_SOL_BAS ) == true,"definedSolution( MSK_SOL_BAS ) == true","setColSolution");
3682 
3683     delete [] tbkx;
3684     delete [] tblx;
3685     delete [] tbux;
3686     delete [] tskx;
3687     delete [] tskc;
3688     delete [] txc;
3689     delete [] tbkc;
3690     delete [] tblc;
3691     delete [] tbuc;
3692   }
3693 
3694   #if MSK_OSI_DEBUG_LEVEL > 1
3695   debugMessage("End OsiMskSolverInterface::setColSolution(%p)\n", (void *)cs);
3696   #endif
3697 }
3698 
3699 //-----------------------------------------------------------------------------
3700 // Sets the rowprices.
3701 
setRowPrice(const double * rs)3702 void OsiMskSolverInterface::setRowPrice(const double * rs)
3703 {
3704   #if MSK_OSI_DEBUG_LEVEL > 1
3705   debugMessage("Begin OsiMskSolverInterface::setRowPrice(%p)\n", (void *)rs);
3706   #endif
3707 
3708   int err,nr = getNumRows(),nc = getNumCols();
3709   MSKstakeye *tskc,*tskx;
3710   MSKrealt *tslc,*tsuc,*tslx,*tsux,*txc,*txx;
3711   double *redcost;
3712 
3713   if( rs == NULL )
3714     freeCachedResults();
3715   else if( nr > 0 )
3716   {
3717     if ( rowsol_ == NULL )
3718       rowsol_ = new double[nr];
3719 
3720     colsol_ = new double[nc];
3721 
3722     tskc = new MSKstakeye[nr];
3723     tslc = new MSKrealt[nr];
3724     tsuc = new MSKrealt[nr];
3725     txc  = new MSKrealt[nr];
3726 
3727     tskx = new MSKstakeye[nc];
3728     tslx = new MSKrealt[nc];
3729     tsux = new MSKrealt[nc];
3730     txx  = new MSKrealt[nc];
3731 
3732     redcost = new double[nc];
3733 
3734     CoinDisjointCopyN( rs, nr, rowsol_ );
3735 
3736     /* Calc reduced costs  */
3737     const CoinPackedMatrix *mtx = getMatrixByCol() ;
3738     mtx->transposeTimes(rs,redcost) ;
3739 
3740     for( int j = 0; j < nc; ++j )
3741     {
3742       redcost[j] = getObjCoefficients()[j]-redcost[j];
3743 
3744       tslx[j] = CoinMax(0.0,redcost[j]);
3745       tsux[j] = CoinMax(0.0,-redcost[j]);
3746     }
3747 
3748     if( definedSolution( MSK_SOL_BAS ) == true )
3749     {
3750       for( int i = 0; i < nr; ++i )
3751       {
3752 #if MSK_VERSION_MAJOR < 9
3753          MSKrealt sn;
3754         err = MSK_getsolutioni(getMutableLpPtr(),
3755                                MSK_ACC_CON,
3756                                i,
3757                                MSK_SOL_BAS,
3758                                &tskc[i],
3759                                &txc[i],
3760                                &tslc[i],
3761                                &tsuc[i],
3762                                &sn);
3763 
3764         checkMSKerror(err,"MSK_putsolutioni","setRowPrice");
3765 
3766 #else
3767         err = MSK_getskcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tskc[i]);
3768         checkMSKerror(err,"MSK_getskcslice","setRowPrice");
3769         err = MSK_getxcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &txc[i]);
3770         checkMSKerror(err,"MSK_getxcslice","setRowPrice");
3771         err = MSK_getslcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tslc[i]);
3772         checkMSKerror(err,"MSK_getslcslice","setRowPrice");
3773         err = MSK_getsucslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tsuc[i]);
3774         checkMSKerror(err,"MSK_getsucslice","setRowPrice");
3775 #endif
3776 
3777         tslc[i] = CoinMax(0.0,rowsol_[i]);
3778         tsuc[i] = CoinMax(0.0,-rowsol_[i]);
3779       }
3780 
3781       err = MSK_getsolution(getMutableLpPtr(),
3782                             MSK_SOL_BAS,
3783                             NULL,
3784                             NULL,
3785                             NULL,
3786                             tskx,
3787                             NULL,
3788                             NULL,
3789                             txx,
3790                             NULL,
3791                             NULL,
3792                             NULL,
3793                             NULL,
3794                             NULL,
3795                             NULL);
3796 
3797       checkMSKerror(err,"MSK_getsolution","setRowPrice");
3798 
3799 
3800       err = MSK_putsolution(getMutableLpPtr(),
3801                              MSK_SOL_BAS,
3802                              tskc,
3803                              tskx,
3804                              NULL,
3805                              txc,
3806                              txx,
3807                              rowsol_,
3808                              tslc,
3809                              tsuc,
3810                              tslx,
3811                              tsux,
3812                              NULL);
3813 
3814         checkMSKerror(err,"MSK_putsolution","setRowPrice");
3815     }
3816     else
3817     {
3818       for( int i = 0; i < nr; ++i )
3819       {
3820         tslc[i] = CoinMax(0.0,rowsol_[i]);
3821         tsuc[i] = CoinMax(0.0,-rowsol_[i]);
3822         tskc[i] = MSK_SK_UNK;
3823       }
3824 
3825       for( int i = 0; i < nc; ++i )
3826       {
3827         tskx[i] = MSK_SK_UNK;
3828         txx[i]  = 0.0;
3829       }
3830 
3831       err = MSK_putsolution(getMutableLpPtr(),
3832                              MSK_SOL_BAS,
3833                              tskc,
3834                              tskx,
3835                              NULL,
3836                              NULL,
3837                              NULL,
3838                              rowsol_,
3839                              tslc,
3840                              tsuc,
3841                              tslx,
3842                              tsux,
3843                              NULL);
3844 
3845       checkMSKerror(err,"MSK_putsolution","setRowPrice");
3846     }
3847 
3848     for( int i = 0; i < nc; ++i )
3849     {
3850       colsol_[i]  = txx[i];
3851     }
3852 
3853     delete [] tskc;
3854     delete [] tslc;
3855     delete [] tsuc;
3856     delete [] txc;
3857 
3858     delete [] tskx;
3859     delete [] tslx;
3860     delete [] tsux;
3861     delete [] txx;
3862     delete [] redcost;
3863   }
3864 
3865   #if MSK_OSI_DEBUG_LEVEL > 1
3866   debugMessage("End OsiMskSolverInterface::setRowPrice(%p)\n", (void *)rs);
3867   #endif
3868 }
3869 
3870 
3871 //#############################################################################
3872 // Problem modifying methods (matrix)
3873 //#############################################################################
3874 
3875 //-----------------------------------------------------------------------------
3876 // Adds a column to the MOSEK task
3877 
3878 void
addCol(const CoinPackedVectorBase & vec,const double collb,const double colub,const double obj)3879 OsiMskSolverInterface::addCol(const CoinPackedVectorBase& vec,
3880                               const double collb, const double colub,
3881                               const double obj)
3882 {
3883   #if MSK_OSI_DEBUG_LEVEL > 3
3884   debugMessage("Begin OsiMskSolverInterface::addCol(%p, %g, %g, %g)\n", (void *)&vec, collb, colub, obj);
3885   #endif
3886 
3887   int nc = getNumCols();
3888 
3889   MSKassert(3,coltypesize_ >= nc,"coltypesize_ >= nc","addCol");
3890 
3891   resizeColType(nc + 1);
3892   coltype_[nc] = 'C';
3893 
3894   int ends = vec.getNumElements();
3895   MSKboundkeye tag;
3896   MSKtask_t task=getLpPtr();
3897 
3898   double inf = getInfinity();
3899   if(collb > -inf && colub >= inf)
3900     tag = MSK_BK_LO;
3901   else if(collb <= -inf && colub < inf)
3902     tag = MSK_BK_UP;
3903   else if(collb > -inf && colub < inf)
3904     tag = MSK_BK_RA;
3905   else if(collb <= -inf && colub >= inf)
3906     tag = MSK_BK_FR;
3907   else
3908     throw CoinError("Bound error", "addCol", "OsiMSKSolverInterface");
3909 
3910 #if MSK_VERSION_MAJOR >= 7
3911   int       err;
3912   MSKint32t j;
3913 
3914   err = MSK_getnumvar(task,&j);
3915 
3916   if ( err==MSK_RES_OK )
3917     err = MSK_appendvars(task,1);
3918 
3919   if ( err==MSK_RES_OK )
3920     err = MSK_putcj(task,j,obj);
3921 
3922   if ( err==MSK_RES_OK )
3923     err = MSK_putacol(task,j,ends,const_cast<int*>(vec.getIndices()),const_cast<double*>(vec.getElements()));
3924 
3925   if ( err==MSK_RES_OK )
3926     err = MSK_putvarbound(task,j,tag,collb,colub);
3927 
3928 #else
3929   int start = 0;
3930   int err = MSK_appendvars(task,
3931                            1,
3932                            const_cast<double*> (&obj),
3933                            &start,
3934                            &ends,
3935                            const_cast<int*>(vec.getIndices()),
3936                            const_cast<double*>(vec.getElements()),
3937                            (&tag),
3938                            const_cast<double*> (&collb),
3939                            const_cast<double*> (&colub));
3940 
3941 #endif
3942 
3943   checkMSKerror( err, "MSK_appendvars", "addCol" );
3944 
3945   #if MSK_OSI_DEBUG_LEVEL > 3
3946   debugMessage("End OsiMskSolverInterface::addCol(%p, %g, %g, %g)\n", (void *)&vec, collb, colub, obj);
3947   #endif
3948 }
3949 
3950 //-----------------------------------------------------------------------------
3951 // Adds a list of columns to the MOSEK task
3952 
3953 void
addCols(const int numcols,const CoinPackedVectorBase * const * cols,const double * collb,const double * colub,const double * obj)3954 OsiMskSolverInterface::addCols(const int numcols,
3955                                const CoinPackedVectorBase * const * cols,
3956                                const double* collb, const double* colub,
3957                                const double* obj)
3958 {
3959   #if MSK_OSI_DEBUG_LEVEL > 3
3960   debugMessage("Begin OsiMskSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, (void *)cols, (void *)collb, (void *)colub, (void *)obj);
3961   #endif
3962 
3963   int i, nz = 0, err = MSK_RES_OK;
3964 
3965   // For efficiency we put hints on the total future size
3966   err = MSK_getmaxnumanz(getLpPtr(),
3967                          &nz);
3968 
3969   checkMSKerror( err, "MSK_getmaxanz", "addCols" );
3970 
3971   for( i = 0; i < numcols; ++i)
3972     nz += cols[i]->getNumElements();
3973 
3974   err = MSK_putmaxnumanz(getLpPtr(),
3975                          nz);
3976 
3977   checkMSKerror( err, "MSK_putmaxanz", "addCols" );
3978 
3979   err = MSK_putmaxnumvar(getLpPtr(),
3980                          numcols+getNumCols());
3981 
3982   checkMSKerror( err, "MSK_putmaxnumvar", "addCols" );
3983 
3984   for( i = 0; i < numcols; ++i )
3985     addCol( *(cols[i]), collb[i], colub[i], obj[i] );
3986 
3987   #if MSK_OSI_DEBUG_LEVEL > 3
3988   debugMessage("End OsiMskSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, (void *)cols, (void *)collb, (void *)colub, (void *)obj);
3989   #endif
3990 }
3991 
3992 //-----------------------------------------------------------------------------
3993 // Deletes a list of columns from the MOSEK task
3994 
3995 void
deleteCols(const int num,const int * columnIndices)3996 OsiMskSolverInterface::deleteCols(const int num, const int * columnIndices)
3997 {
3998   #if MSK_OSI_DEBUG_LEVEL > 3
3999   debugMessage("Begin OsiMskSolverInterface::deleteCols(%d, %p)\n", num, (void *)columnIndices);
4000   #endif
4001 
4002 #if MSK_VERSION_MAJOR >= 7
4003   int err;
4004   err = MSK_removevars(getLpPtr( OsiMskSolverInterface::KEEPCACHED_ROW ),
4005                        num,
4006                        const_cast<int*>(columnIndices));
4007 
4008   checkMSKerror( err, "MSK_removevars", "deleteCols" );
4009 
4010 #else
4011   int err;
4012   err = MSK_remove(getLpPtr( OsiMskSolverInterface::KEEPCACHED_ROW ),
4013                    MSK_ACC_VAR,
4014                    num,
4015                    const_cast<int*>(columnIndices));
4016 
4017   checkMSKerror( err, "MSK_remove", "deleteCols" );
4018 #endif
4019 
4020   #if MSK_OSI_DEBUG_LEVEL > 3
4021   debugMessage("End OsiMskSolverInterface::deleteCols(%d, %p)\n", num, (void *)columnIndices);
4022   #endif
4023 }
4024 
4025 //-----------------------------------------------------------------------------
4026 // Adds a row in bound form to the MOSEK task
4027 
4028 void
addRow(const CoinPackedVectorBase & vec,const double rowlb,const double rowub)4029 OsiMskSolverInterface::addRow(const CoinPackedVectorBase& vec,
4030                                 const double rowlb, const double rowub)
4031 {
4032   #if MSK_OSI_DEBUG_LEVEL > 3
4033   debugMessage("Begin OsiMskSolverInterface::addRow(%p, %g, %g)\n", (void *)&vec, rowlb, rowub);
4034   #endif
4035 
4036   getNumRows();
4037 
4038   int          ends = vec.getNumElements();
4039   double       inf = getInfinity();
4040   MSKboundkeye tag;
4041   MSKtask_t    task = getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN );
4042 
4043   if(rowlb > -inf && rowub >= inf)
4044     tag = MSK_BK_LO;
4045   else if(rowlb <= -inf && rowub < inf)
4046     tag = MSK_BK_UP;
4047   else if(rowlb > -inf && rowub < inf)
4048     tag = MSK_BK_RA;
4049   else if(rowlb <= -inf && rowub >= inf)
4050     tag = MSK_BK_FR;
4051   else
4052     throw CoinError("Bound error", "addRow", "OsiMSKSolverInterface");
4053 
4054 #if MSK_VERSION_MAJOR >= 7
4055   int       err;
4056   MSKint32t i;
4057 
4058   err = MSK_getnumcon(task,&i);
4059 
4060   if ( err==MSK_RES_OK )
4061     err = MSK_appendcons(task,1);
4062 
4063   if ( err==MSK_RES_OK )
4064     err = MSK_putconbound(task,i,tag,rowlb,rowub);
4065 
4066   if ( err==MSK_RES_OK )
4067     err = MSK_putarow(task,i,ends,
4068                       const_cast<int*>(vec.getIndices()),
4069                       const_cast<double*>(vec.getElements()));
4070 
4071 #else
4072   int start = 0;
4073   int err = MSK_appendcons(task,
4074                            1,
4075                            &start,
4076                            &ends,
4077                            const_cast<int*>(vec.getIndices()),
4078                            const_cast<double*>(vec.getElements()),
4079                            (&tag),
4080                            const_cast<double*> (&rowlb),
4081                            const_cast<double*> (&rowub));
4082 #endif
4083 
4084   checkMSKerror( err, "MSK_appendcons", "addRow" );
4085 
4086   #if MSK_OSI_DEBUG_LEVEL > 3
4087   debugMessage("End OsiMskSolverInterface::addRow(%p, %g, %g)\n", (void *)&vec, rowlb, rowub);
4088   #endif
4089 }
4090 
4091 //-----------------------------------------------------------------------------
4092 // Adds a row in triplet form to the MOSEK task
4093 
4094 void
addRow(const CoinPackedVectorBase & vec,const char rowsen,const double rowrhs,const double rowrng)4095 OsiMskSolverInterface::addRow(const CoinPackedVectorBase& vec,
4096                                const char rowsen, const double rowrhs,
4097                                const double rowrng)
4098 {
4099   #if MSK_OSI_DEBUG_LEVEL > 3
4100   debugMessage("Begin OsiMskSolverInterface::addRow(%p, %c, %g, %g)\n", (void *)&vec, rowsen, rowrhs, rowrng);
4101   #endif
4102 
4103   int rtag=MSK_BK_FR;
4104   double lb=-MSK_INFINITY,ub=MSK_INFINITY;
4105   MskConvertSenseToBound( rowsen, rowrng, rowrhs, lb, ub, rtag );
4106   addRow(vec, lb, ub);
4107 
4108   #if MSK_OSI_DEBUG_LEVEL > 3
4109   debugMessage("End OsiMskSolverInterface::addRow(%p, %c, %g, %g)\n", (void *)&vec, rowsen, rowrhs, rowrng);
4110   #endif
4111 }
4112 
4113 //-----------------------------------------------------------------------------
4114 // Adds a serie of rows in bound form to the MOSEK task
4115 
4116 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const double * rowlb,const double * rowub)4117 OsiMskSolverInterface::addRows(const int numrows,
4118                                  const CoinPackedVectorBase * const * rows,
4119                                  const double* rowlb, const double* rowub)
4120 {
4121   #if MSK_OSI_DEBUG_LEVEL > 3
4122   debugMessage("Begin OsiMskSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowlb, (void *)rowub);
4123   #endif
4124 
4125   int i,nz = 0, err = MSK_RES_OK;
4126 
4127   // For efficiency we put hints on the total future size
4128   err = MSK_getmaxnumanz(
4129                      getLpPtr(),
4130                      &nz);
4131 
4132   checkMSKerror( err, "MSK_getmaxanz", "addRows" );
4133 
4134 
4135   for( i = 0; i < numrows; ++i)
4136     nz += rows[i]->getNumElements();
4137 
4138   err = MSK_putmaxnumanz(getLpPtr(),
4139                          nz);
4140 
4141   checkMSKerror( err, "MSK_putmaxanz", "addRows" );
4142 
4143   err = MSK_putmaxnumcon(getLpPtr(),
4144                         numrows+getNumRows());
4145 
4146   checkMSKerror( err, "MSK_putmaxnumcon", "addRows" );
4147 
4148   for( i = 0; i < numrows; ++i )
4149     addRow( *(rows[i]), rowlb[i], rowub[i] );
4150 
4151   #if MSK_OSI_DEBUG_LEVEL > 3
4152   debugMessage("End OsiMskSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowlb, (void *)rowub);
4153   #endif
4154 }
4155 
4156 //-----------------------------------------------------------------------------
4157 // Adds a list of rows in triplet form to the MOSEK task
4158 
4159 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const char * rowsen,const double * rowrhs,const double * rowrng)4160 OsiMskSolverInterface::addRows(const int numrows,
4161                                  const CoinPackedVectorBase * const * rows,
4162                                  const char* rowsen, const double* rowrhs,
4163                                  const double* rowrng)
4164 {
4165   #if MSK_OSI_DEBUG_LEVEL > 3
4166   debugMessage("Begin OsiMskSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowsen, (void *)rowrhs, (void *)rowrng);
4167   #endif
4168 
4169   int i, err = MSK_RES_OK, nz = 0;
4170 
4171     // For efficiency we put hints on the total future size
4172   for( i = 0; i < numrows; ++i)
4173     nz += rows[i]->getNumElements();
4174 
4175   err = MSK_putmaxnumanz(
4176                      getLpPtr(),
4177                      nz);
4178 
4179   checkMSKerror( err, "MSK_putmaxanz", "addRows" );
4180 
4181   err = MSK_putmaxnumcon(
4182                      getLpPtr(),
4183                      numrows);
4184 
4185   checkMSKerror( err, "MSK_putmaxnumcon", "addRows" );
4186 
4187   for( i = 0; i < numrows; ++i )
4188     addRow( *(rows[i]), rowsen[i], rowrhs[i], rowrng[i] );
4189 
4190   #if MSK_OSI_DEBUG_LEVEL > 3
4191   debugMessage("End OsiMskSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowsen, (void *)rowrhs, (void *)rowrng);
4192   #endif
4193 }
4194 
4195 //-----------------------------------------------------------------------------
4196 // Deletes a list of rows the MOSEK task
4197 
4198 void
deleteRows(const int num,const int * rowIndices)4199 OsiMskSolverInterface::deleteRows(const int num, const int * rowIndices)
4200 {
4201   #if MSK_OSI_DEBUG_LEVEL > 3
4202   debugMessage("Begin OsiMskSolverInterface::deleteRows(%d, %p)\n", num, (void *)rowIndices);
4203   #endif
4204 
4205   int err;
4206 #if MSK_VERSION_MAJOR >= 7
4207   err = MSK_removecons(getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN ),
4208                        num,
4209                        const_cast<int*>(rowIndices));
4210 
4211   checkMSKerror( err, "MSK_removecons", "deleteRows" );
4212 
4213 #else
4214   err = MSK_remove(getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN ),
4215                    MSK_ACC_CON,
4216                    num,
4217                    const_cast<int*>(rowIndices));
4218 
4219   checkMSKerror( err, "MSK_remove", "deleteRows" );
4220 #endif
4221 
4222   #if MSK_OSI_DEBUG_LEVEL > 3
4223   debugMessage("End OsiMskSolverInterface::deleteRows(%d, %p)\n", num, (void *)rowIndices);
4224   #endif
4225 }
4226 
4227 //#############################################################################
4228 // Methods to input a problem
4229 //#############################################################################
4230 
4231 //-----------------------------------------------------------------------------
4232 // Loads a problem. Should have its "own" implementation so we don't have to convert
4233 // to triplet, since this is convertet back in the load function called. But
4234 // for simplicity, this is not done.
4235 
4236 void
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)4237 OsiMskSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
4238                                     const double* collb,
4239                                     const double* colub,
4240                                     const double* obj,
4241                                     const double* rowlb,
4242                                     const double* rowub )
4243 {
4244   #if MSK_OSI_DEBUG_LEVEL > 1
4245   debugMessage("Begin OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p)\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowlb, (void *)rowub);
4246   #endif
4247 
4248   const double inf = getInfinity();
4249 
4250   int nrows = matrix.getNumRows();
4251 
4252   char   * rowSense;
4253   double * rowRhs;
4254   double * rowRange;
4255 
4256   if( nrows )
4257   {
4258     rowSense = new char  [nrows];
4259     rowRhs   = new double[nrows];
4260     rowRange = new double[nrows];
4261   }
4262   else
4263   {
4264     rowSense = NULL;
4265     rowRhs   = NULL;
4266     rowRange = NULL;
4267   }
4268 
4269   int i;
4270   if( rowlb == NULL && rowub == NULL)
4271       for ( i = nrows - 1; i >= 0; --i )
4272           convertBoundToSense( -inf, inf, rowSense[i], rowRhs[i], rowRange[i] );
4273   else if( rowlb == NULL)
4274       for ( i = nrows - 1; i >= 0; --i )
4275           convertBoundToSense( -inf, rowub[i], rowSense[i], rowRhs[i], rowRange[i] );
4276   else if( rowub == NULL)
4277       for ( i = nrows - 1; i >= 0; --i )
4278           convertBoundToSense( rowlb[i], inf, rowSense[i], rowRhs[i], rowRange[i] );
4279   else
4280       for ( i = nrows - 1; i >= 0; --i )
4281           convertBoundToSense( rowlb[i], rowub[i], rowSense[i], rowRhs[i], rowRange[i] );
4282 
4283   loadProblem( matrix, collb, colub, obj, rowSense, rowRhs, rowRange );
4284 
4285   if( nrows )
4286   {
4287     delete [] rowSense;
4288     delete [] rowRhs;
4289     delete [] rowRange;
4290   }
4291 
4292   #if MSK_OSI_DEBUG_LEVEL > 1
4293   debugMessage("End OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p)\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowlb, (void *)rowub);
4294   #endif
4295 }
4296 
4297 //-----------------------------------------------------------------------------
4298 // Loads a problem
4299 
4300 void
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,double * & rowlb,double * & rowub)4301 OsiMskSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
4302                                       double*& collb,
4303                                       double*& colub,
4304                                       double*& obj,
4305                                       double*& rowlb,
4306                                       double*& rowub )
4307 {
4308   #if MSK_OSI_DEBUG_LEVEL > 3
4309   debugMessage("Begin OsiMskSolverInterface::assignProblem()\n");
4310   #endif
4311 
4312   loadProblem( *matrix, collb, colub, obj, rowlb, rowub );
4313 
4314   delete matrix;   matrix = 0;
4315   delete[] collb;  collb  = 0;
4316   delete[] colub;  colub  = 0;
4317   delete[] obj;    obj    = 0;
4318   delete[] rowlb;  rowlb  = 0;
4319   delete[] rowub;  rowub  = 0;
4320 
4321   #if MSK_OSI_DEBUG_LEVEL > 3
4322   debugMessage("End OsiMskSolverInterface::assignProblem()\n");
4323   #endif
4324 }
4325 
4326 //-----------------------------------------------------------------------------
4327 // Loads a problem
4328 
4329 void
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)4330 OsiMskSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
4331                                     const double* collb,
4332                                     const double* colub,
4333                                     const double* obj,
4334                                     const char* rowsen,
4335                                     const double* rowrhs,
4336                                     const double* rowrng )
4337 {
4338   int nc=matrix.getNumCols();
4339   int nr=matrix.getNumRows();
4340 
4341   #if MSK_OSI_DEBUG_LEVEL > 1
4342   debugMessage("Begin OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p, %p) numcols : %d numrows : %d\n",
4343      (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng,nc,nr);
4344   #endif
4345 
4346   if( nr == 0 && nc == 0 )
4347     gutsOfDestructor();
4348   else
4349   {
4350     /* Warning input  pointers can be NULL */
4351 
4352     int i,j;
4353 
4354     double    * ob;
4355     int       * rtag  = NULL;
4356     double    * rlb   = NULL;
4357     double    * rub   = NULL;
4358 
4359     int       * ctag  = NULL;
4360     int       * cends = NULL;
4361     const int *len;
4362     const int *start;
4363     double    * clb   = NULL;
4364     double    * cub   = NULL;
4365 
4366     if( obj != NULL )
4367       ob=const_cast<double*>(obj);
4368     else
4369     {
4370       ob = new double[nc];
4371       CoinFillN(ob, nc, 0.0);
4372     }
4373 
4374     if( nr )
4375     {
4376       rtag = new int[nr];
4377       rlb  = new double[nr];
4378       rub  = new double[nr];
4379     }
4380 
4381     if( rowsen && rowrng && rowrhs )
4382     {
4383       for( i=0; i < nr; i++ )
4384         MskConvertSenseToBound( rowsen[i], rowrng[i], rowrhs[i], rlb[i], rub[i], rtag[i]);
4385     }
4386     else
4387     {
4388       for( i=0; i < nr; i++ )
4389       {
4390         rlb[i]  = 0.0;
4391         rub[i]  = MSK_INFINITY;
4392         rtag[i] = MSK_BK_LO;
4393       }
4394     }
4395 
4396     bool freeMatrixRequired = false;
4397     CoinPackedMatrix * m = NULL;
4398     if( !matrix.isColOrdered() )
4399     {
4400       m = new CoinPackedMatrix();
4401       m->reverseOrderedCopyOf(matrix);
4402       freeMatrixRequired = true;
4403     }
4404     else
4405       m = const_cast<CoinPackedMatrix *>(&matrix);
4406 
4407     MSKassert(3,nc == m->getNumCols(),"nc == m->getNumCols()","loadProblem");
4408     MSKassert(3,nr == m->getNumRows(),"nr == m->getNumRows()","loadProblem");
4409     MSKassert(3,m->isColOrdered(),"m->isColOrdered()","loadProblem");
4410 
4411     double inf =getInfinity();
4412 
4413     if( nc )
4414     {
4415       ctag       = new int[nc];
4416       cends      = new int[nc];
4417       clb        = new double[nc];
4418       cub        = new double[nc];
4419     }
4420 
4421     len        = (m->getVectorLengths());
4422     start      = (m->getVectorStarts());
4423 
4424     if( collb == NULL && colub == NULL )
4425     {
4426       for(j=0; j < nc; j++)
4427       {
4428          cends[j] = start[j] + len[j];
4429          MskConvertColBoundToTag(0, inf, clb[j], cub[j], ctag[j]);
4430       }
4431     }
4432     else if( collb == NULL )
4433     {
4434       for(j=0; j < nc; j++)
4435       {
4436          cends[j] = start[j] + len[j];
4437          MskConvertColBoundToTag( 0, colub[j], clb[j], cub[j], ctag[j]);
4438       }
4439     }
4440     else if( colub == NULL )
4441     {
4442       for(j=0; j < nc; j++)
4443       {
4444          cends[j] = start[j] + len[j];
4445          MskConvertColBoundToTag(collb[j], inf, clb[j], cub[j], ctag[j]);
4446       }
4447     }
4448     else
4449     {
4450       for(j=0; j < nc; j++)
4451       {
4452          cends[j] = start[j] + len[j];
4453          MskConvertColBoundToTag( collb[j], colub[j], clb[j], cub[j], ctag[j]);
4454       }
4455     }
4456 
4457     int err=MSK_inputdata(getLpPtr( OsiMskSolverInterface::KEEPCACHED_NONE ),
4458                           nr,
4459                           nc,
4460                           nr,
4461                           nc,
4462                           ob,
4463                           0.0,
4464                           const_cast<int *>(m->getVectorStarts()),
4465                           cends,
4466                           const_cast<int *>(m->getIndices()),
4467                           const_cast<double *>(m->getElements()),
4468                           (MSKboundkeye*)rtag,
4469                           rlb,
4470                           rub,
4471                           (MSKboundkeye*)ctag,
4472                           clb,
4473                           cub);
4474 
4475     checkMSKerror( err, "MSK_inputdata", "loadProblem" );
4476 
4477     if( obj   == NULL )
4478       delete[] ob;
4479 
4480     if( nr )
4481     {
4482       delete[] rtag;
4483       delete[] rlb;
4484       delete[] rub;
4485     }
4486 
4487     if( nc )
4488     {
4489       delete[] ctag;
4490       delete[] clb;
4491       delete[] cub;
4492       delete[] cends;
4493     }
4494 
4495     if ( freeMatrixRequired )
4496       delete m;
4497 
4498     resizeColType(nc);
4499     CoinFillN(coltype_, nc, 'C');
4500   }
4501 
4502   #if MSK_OSI_DEBUG_LEVEL > 1
4503   debugMessage("End OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p, %p)\n",
4504    (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng);
4505   #endif
4506 }
4507 
4508 //-----------------------------------------------------------------------------
4509 // Assigns a problem
4510 
4511 void
assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,char * & rowsen,double * & rowrhs,double * & rowrng)4512 OsiMskSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
4513                                        double*& collb, double*& colub,
4514                                        double*& obj,
4515                                        char*& rowsen, double*& rowrhs,
4516                                        double*& rowrng )
4517 {
4518   #if MSK_OSI_DEBUG_LEVEL > 3
4519   debugMessage("Begin OsiMskSolverInterface::assignProblem()\n");
4520   #endif
4521 
4522   loadProblem( *matrix, collb, colub, obj, rowsen, rowrhs, rowrng );
4523   delete matrix;   matrix = 0;
4524   delete[] collb;  collb = 0;
4525   delete[] colub;  colub = 0;
4526   delete[] obj;    obj = 0;
4527   delete[] rowsen; rowsen = 0;
4528   delete[] rowrhs; rowrhs = 0;
4529   delete[] rowrng; rowrng = 0;
4530 
4531   #if MSK_OSI_DEBUG_LEVEL > 3
4532   debugMessage("End OsiMskSolverInterface::assignProblem()\n");
4533   #endif
4534 }
4535 
4536 //-----------------------------------------------------------------------------
4537 // Loads a problem
4538 
4539 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)4540 OsiMskSolverInterface::loadProblem(const int numcols,
4541                                     const int numrows,
4542                                     const int* start,
4543                                     const int* index,
4544                                     const double* value,
4545                                     const double* collb,
4546                                     const double* colub,
4547                                     const double* obj,
4548                                     const double* rowlb,
4549                                     const double* rowub )
4550 {
4551   #if MSK_OSI_DEBUG_LEVEL > 1
4552   debugMessage("Begin OsiMskSolverInterface::loadProblem() numcols : %d numrows : %d\n",numcols,numrows);
4553   #endif
4554 
4555   const double inf = getInfinity();
4556 
4557   char   * rowSense = new char  [numrows];
4558   double * rowRhs   = new double[numrows];
4559   double * rowRange = new double[numrows];
4560 
4561   for ( int i = numrows - 1; i >= 0; --i )
4562   {
4563     const double lower = rowlb ? rowlb[i] : -inf;
4564     const double upper = rowub ? rowub[i] : inf;
4565     convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] );
4566   }
4567 
4568   loadProblem(numcols, numrows, start, index, value, collb, colub, obj,
4569               rowSense, rowRhs, rowRange);
4570 
4571   delete [] rowSense;
4572   delete [] rowRhs;
4573   delete [] rowRange;
4574 
4575   #if MSK_OSI_DEBUG_LEVEL > 1
4576   debugMessage("End OsiMskSolverInterface::loadProblem()\n");
4577   #endif
4578 }
4579 
4580 //-----------------------------------------------------------------------------
4581 // Loads a problem
4582 
4583 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)4584 OsiMskSolverInterface::loadProblem(const int numcols,
4585                                     const int numrows,
4586                                     const int* start,
4587                                     const int* index,
4588                                     const double* value,
4589                                     const double* collb,
4590                                     const double* colub,
4591                                     const double* obj,
4592                                     const char* rowsen,
4593                                     const double* rowrhs,
4594                                     const double* rowrng )
4595 {
4596   #if MSK_OSI_DEBUG_LEVEL > 1
4597   debugMessage("Begin OsiMskSolverInterface::loadProblem(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n",
4598      numcols, numrows, (void *)start, (void *)index, (void *)value, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen,(void *)rowrhs, (void *)rowrng);
4599   #endif
4600 
4601   const int nc = numcols;
4602   const int nr = numrows;
4603 
4604   if( nr == 0 && nc == 0 )
4605     gutsOfDestructor();
4606   else
4607   {
4608     MSKassert(3,rowsen != NULL,"rowsen != NULL","loadProblem");
4609     MSKassert(3,rowrhs != NULL,"rowrhs != NULL","loadProblem");
4610 
4611     int i,j;
4612 
4613     double   * ob;
4614     int      * rtag =NULL;
4615     double   * rlb = NULL;
4616     double   * rub = NULL;
4617     int      * ctag =NULL;
4618     int      * cends = NULL;
4619     double   * clb = NULL;
4620     double   * cub = NULL;
4621 
4622     if( obj != NULL )
4623       ob=const_cast<double*>(obj);
4624     else
4625     {
4626       ob = new double[nc];
4627       CoinFillN(ob, nc, 0.0);
4628     }
4629 
4630     if( nr )
4631     {
4632       rtag = new int[nr];
4633       rlb  = new double[nr];
4634       rub  = new double[nr];
4635     }
4636 
4637     for( i=0; i < nr; i++ )
4638       MskConvertSenseToBound( rowsen[i], rowrng != NULL ? rowrng[i] : 0.0, rowrhs[i], rlb[i], rub[i], rtag[i]);
4639 
4640     double inf = getInfinity();
4641 
4642     if( nc )
4643     {
4644       ctag       = new int[nc];
4645       cends      = new int[nc];
4646       clb        = new double[nc];
4647       cub        = new double[nc];
4648     }
4649 
4650     if( collb == NULL && colub == NULL )
4651         for(j=0; j < nc; j++)
4652         {
4653            cends[j] = start[j+1];
4654            MskConvertColBoundToTag(0, inf, clb[j], cub[j], ctag[j]);
4655         }
4656     else if( collb == NULL )
4657         for(j=0; j < nc; j++)
4658         {
4659            cends[j] = start[j+1];
4660            MskConvertColBoundToTag( 0, colub[j], clb[j], cub[j], ctag[j]);
4661         }
4662     else if( colub == NULL )
4663         for(j=0; j < nc; j++)
4664         {
4665            cends[j] = start[j+1];
4666            MskConvertColBoundToTag(collb[j], inf, clb[j], cub[j], ctag[j]);
4667         }
4668     else
4669         for(j=0; j < nc; j++)
4670         {
4671            cends[j] = start[j+1];
4672            MskConvertColBoundToTag( collb[j], colub[j], clb[j], cub[j], ctag[j]);
4673         }
4674 
4675     int err=MSK_inputdata(getLpPtr( OsiMskSolverInterface::KEEPCACHED_NONE ),
4676                           nr,
4677                           nc,
4678                           nr,
4679                           nc,
4680                           ob,
4681                           0.0,
4682                           const_cast<int *>(start),
4683                           cends,
4684                           const_cast<int *>(index),
4685                           const_cast<double *>(value),
4686                           (MSKboundkeye*)rtag,
4687                           rlb,
4688                           rub,
4689                           (MSKboundkeye*)ctag,
4690                           clb,
4691                           cub);
4692 
4693     checkMSKerror( err, "MSK_inputdata", "loadProblem3" );
4694 
4695     if( obj   == NULL )
4696       delete[] ob;
4697 
4698     if( nr )
4699     {
4700       delete[] rtag;
4701       delete[] rlb;
4702       delete[] rub;
4703     }
4704 
4705     if( nc )
4706     {
4707       delete[] ctag;
4708       delete[] cends;
4709       delete[] clb;
4710       delete[] cub;
4711     }
4712 
4713     resizeColType(nc);
4714     CoinFillN(coltype_, nc, 'C');
4715   }
4716 
4717   #if MSK_OSI_DEBUG_LEVEL > 1
4718   debugMessage("End OsiMskSolverInterface::loadProblem(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n",
4719      numcols, numrows, (void *)start, (void *)index, (void *)value, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng);
4720   #endif
4721 }
4722 
4723 //-----------------------------------------------------------------------------
4724 // Reads a MPS file with Coin native MPS reader. If marked code is switch on
4725 // then MOSEK file reader is used, and .gz files can be read aswell.
4726 
readMps(const char * filename,const char * extension)4727 int OsiMskSolverInterface::readMps(const char * filename,
4728                                     const char * extension )
4729 {
4730   #if MSK_OSI_DEBUG_LEVEL > 3
4731   debugMessage("Begin OsiMskSolverInterface::readMps(%s, %s) %p\n", filename, extension,(void*)this);
4732   debugMessage("End OsiMskSolverInterface::readMps(%s, %s)\n", filename, extension);
4733   #endif
4734 
4735   return OsiSolverInterface::readMps(filename,extension);
4736 }
4737 
4738 //-----------------------------------------------------------------------------
4739 // Writes the problem in MPS format, uses MOSEK writer.
4740 
writeMps(const char * filename,const char * extension,double objSense) const4741 void OsiMskSolverInterface::writeMps( const char * filename,
4742                                        const char * extension,
4743                                        double objSense ) const
4744 {
4745   #if MSK_OSI_DEBUG_LEVEL > 3
4746   debugMessage("Begin OsiMskSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense);
4747   #endif
4748 
4749   std::string f(filename);
4750   std::string e(extension);
4751   std::string fullname = f + "." + e;
4752 
4753   OsiSolverInterface::writeMpsNative(fullname.c_str(),NULL, NULL, 0, 2, objSense);
4754 
4755   #if 0
4756   int err = MSK_writedata( getMutableLpPtr(), const_cast<char*>( fullname.c_str() ));
4757   checkMSKerror( err, "MSK_writedatafile", "writeMps" );
4758   #endif
4759 
4760   #if MSK_OSI_DEBUG_LEVEL > 3
4761   debugMessage("End OsiMskSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense);
4762   #endif
4763 }
4764 
passInMessageHandler(CoinMessageHandler * handler)4765 void OsiMskSolverInterface::passInMessageHandler(CoinMessageHandler * handler) {
4766 	OsiSolverInterface::passInMessageHandler(handler);
4767 
4768   MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog);
4769   MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncWarning);
4770   MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncError);
4771 }
4772 
4773 //#############################################################################
4774 // MSK specific public interfaces
4775 //#############################################################################
4776 
4777 //-----------------------------------------------------------------------------
4778 // Returns MOSEK task in the interface object
4779 
getEnvironmentPtr()4780 MSKenv_t OsiMskSolverInterface::getEnvironmentPtr()
4781 {
4782   MSKassert(3,env_ != NULL,"probtypemip_","getEnvironmentPtr");
4783 
4784   return env_;
4785 }
4786 
4787 //-----------------------------------------------------------------------------
4788 // Returns MOSEK task in the interface object
4789 
getLpPtr(int keepCached)4790 MSKtask_t OsiMskSolverInterface::getLpPtr( int keepCached )
4791 {
4792   freeCachedData( keepCached );
4793   return getMutableLpPtr();
4794 }
4795 
4796 //-----------------------------------------------------------------------------
4797 // Returns the coltype_ array
4798 
getCtype() const4799 const char * OsiMskSolverInterface::getCtype() const
4800 {
4801   #if MSK_OSI_DEBUG_LEVEL > 3
4802   debugMessage("Begin OsiMskSolverInterface::getCtype()\n");
4803   debugMessage("End OsiMskSolverInterface::getCtype()\n");
4804   #endif
4805 
4806   return coltype_;
4807 }
4808 
4809 //#############################################################################
4810 // Static instance counter methods
4811 //#############################################################################
4812 
4813 //-----------------------------------------------------------------------------
4814 // Increment the instance count, so we know when to close and open MOSEK.
4815 
incrementInstanceCounter()4816 void OsiMskSolverInterface::incrementInstanceCounter()
4817 {
4818   #if MSK_OSI_DEBUG_LEVEL > 3
4819   debugMessage("Begin OsiMskSolverInterface::incrementInstanceCounter()\n");
4820   #endif
4821 
4822   if ( numInstances_ == 0 )
4823   {
4824     int err=0;
4825 
4826 #if MSK_OSI_DEBUG_LEVEL > 1
4827     debugMessage("creating new Mosek environment\n");
4828 #endif
4829 
4830 #if MSK_VERSION_MAJOR >= 7
4831     err = MSK_makeenv(&env_,NULL);
4832 #else
4833     err = MSK_makeenv(&env_,NULL,NULL,NULL,NULL);
4834 #endif
4835     checkMSKerror( err, "MSK_makeenv", "incrementInstanceCounter" );
4836 
4837     err = MSK_linkfunctoenvstream(env_, MSK_STREAM_LOG, NULL, printlog);
4838 
4839     checkMSKerror( err, "MSK_linkfunctoenvstream", "incrementInstanceCounter" );
4840 
4841 #if MSK_VERSION_MAJOR < 8
4842     err = MSK_initenv(env_);
4843     checkMSKerror( err, "MSK_initenv", "incrementInstanceCounter" );
4844 #endif
4845   }
4846 
4847   numInstances_++;
4848 
4849   #if MSK_OSI_DEBUG_LEVEL > 3
4850   debugMessage("End OsiMskSolverInterface::incrementInstanceCounter()\n");
4851   #endif
4852 }
4853 
4854 //-----------------------------------------------------------------------------
4855 // Decrement the instance count, so we know when to close and open MOSEK.
4856 
decrementInstanceCounter()4857 void OsiMskSolverInterface::decrementInstanceCounter()
4858 {
4859   #if MSK_OSI_DEBUG_LEVEL > 3
4860   debugMessage("Begin OsiMskSolverInterface::decrementInstanceCounter()\n");
4861   #endif
4862 
4863   MSKassert(3,numInstances_ != 0,"numInstances_ != 0","decrementInstanceCounter");
4864 
4865   numInstances_--;
4866   if ( numInstances_ == 0 )
4867   {
4868 #if MSK_OSI_DEBUG_LEVEL > 1
4869      debugMessage("deleting Mosek environment\n");
4870 #endif
4871 
4872      int err = MSK_deleteenv(&env_);
4873      checkMSKerror( err, "MSK_deleteenv", "decrementInstanceCounter" );
4874      env_ = NULL;
4875   }
4876 
4877   #if MSK_OSI_DEBUG_LEVEL > 3
4878   debugMessage("End OsiMskSolverInterface::decrementInstanceCounter()\n");
4879   #endif
4880 }
4881 
4882 //-----------------------------------------------------------------------------
4883 // Returns the number of OsiMskSolverInterface objects in play
4884 
getNumInstances()4885 unsigned int OsiMskSolverInterface::getNumInstances()
4886 {
4887   #if MSK_OSI_DEBUG_LEVEL > 3
4888   debugMessage("Begin OsiMskSolverInterface::getNumInstances()\n");
4889   debugMessage("End OsiMskSolverInterface::getNumInstances()\n");
4890   #endif
4891 
4892   return numInstances_;
4893 }
4894 
4895 //#############################################################################
4896 // Constructors, destructors clone and assignment
4897 //#############################################################################
4898 
4899 //-----------------------------------------------------------------------------
4900 // Constructor
4901 
OsiMskSolverInterface(MSKenv_t mskenv)4902 OsiMskSolverInterface::OsiMskSolverInterface(MSKenv_t mskenv)
4903   : OsiSolverInterface(),
4904     Mskerr(MSK_RES_OK),
4905     ObjOffset_(0.0),
4906     InitialSolver(INITIAL_SOLVE),
4907     task_(NULL),
4908     hotStartCStat_(NULL),
4909     hotStartCStatSize_(0),
4910     hotStartRStat_(NULL),
4911     hotStartRStatSize_(0),
4912     hotStartMaxIteration_(1000000),
4913     obj_(NULL),
4914     collower_(NULL),
4915     colupper_(NULL),
4916     rowsense_(NULL),
4917     rhs_(NULL),
4918     rowrange_(NULL),
4919     rowlower_(NULL),
4920     rowupper_(NULL),
4921     colsol_(NULL),
4922     rowsol_(NULL),
4923     redcost_(NULL),
4924     rowact_(NULL),
4925     matrixByRow_(NULL),
4926     matrixByCol_(NULL),
4927     coltype_(NULL),
4928     coltypesize_(0),
4929     probtypemip_(false)
4930 {
4931   #if MSK_OSI_DEBUG_LEVEL > 3
4932   debugMessage("Begin OsiMskSolverInterface::OsiMskSolverinterface()\n");
4933   #endif
4934 
4935   if (mskenv) {
4936   	if (env_) {
4937   		throw CoinError("Already have a global Mosek environment. Cannot use second one.", "OsiMskSolverInterface", "OsiMskSolverInterface");
4938   	}
4939   	env_ = mskenv;
4940   	++numInstances_;
4941   } else
4942   	incrementInstanceCounter();
4943 
4944   gutsOfConstructor();
4945 
4946   #if MSK_OSI_DEBUG_LEVEL > 3
4947   debugMessage("End OsiMskSolverInterface::OsiMskSolverinterface()\n");
4948   #endif
4949 }
4950 
4951 
4952 
4953 //-----------------------------------------------------------------------------
4954 // Clone from one to another object
4955 
clone(bool copyData) const4956 OsiSolverInterface * OsiMskSolverInterface::clone(bool copyData) const
4957 {
4958   #if MSK_OSI_DEBUG_LEVEL > 3
4959   debugMessage("Begin OsiMskSolverInterface::clone(%d)\n", copyData);
4960   debugMessage("End OsiMskSolverInterface::clone(%d)\n", copyData);
4961   #endif
4962 
4963   return( new OsiMskSolverInterface( *this ) );
4964 }
4965 
4966 
4967 //-----------------------------------------------------------------------------
4968 // Copy constructor
4969 
OsiMskSolverInterface(const OsiMskSolverInterface & source)4970 OsiMskSolverInterface::OsiMskSolverInterface( const OsiMskSolverInterface & source )
4971   : OsiSolverInterface(source),
4972     Mskerr(MSK_RES_OK),
4973     MSKsolverused_(INITIAL_SOLVE),
4974     ObjOffset_(source.ObjOffset_),
4975     InitialSolver(INITIAL_SOLVE),
4976     task_(NULL),
4977     hotStartCStat_(NULL),
4978     hotStartCStatSize_(0),
4979     hotStartRStat_(NULL),
4980     hotStartRStatSize_(0),
4981     hotStartMaxIteration_(source.hotStartMaxIteration_),
4982     obj_(NULL),
4983     collower_(NULL),
4984     colupper_(NULL),
4985     rowsense_(NULL),
4986     rhs_(NULL),
4987     rowrange_(NULL),
4988     rowlower_(NULL),
4989     rowupper_(NULL),
4990     colsol_(NULL),
4991     rowsol_(NULL),
4992     redcost_(NULL),
4993     rowact_(NULL),
4994     matrixByRow_(NULL),
4995     matrixByCol_(NULL),
4996     coltype_(NULL),
4997     coltypesize_(0),
4998     probtypemip_(false)
4999 {
5000   #if MSK_OSI_DEBUG_LEVEL > 3
5001   debugMessage("Begin OsiMskSolverInterface::OsiMskSolverInterface from (%p) to %p\n", (void *)&source,(void*)this);
5002   #endif
5003 
5004   incrementInstanceCounter();
5005   gutsOfConstructor();
5006   gutsOfCopy( source );
5007 
5008   #if MSK_OSI_DEBUG_LEVEL > 3
5009   debugMessage("End OsiMskSolverInterface::OsiMskSolverInterface(%p)\n", (void *)&source);
5010   #endif
5011 }
5012 
5013 //-----------------------------------------------------------------------------
5014 // Destructor
5015 
~OsiMskSolverInterface()5016 OsiMskSolverInterface::~OsiMskSolverInterface()
5017 {
5018   #if MSK_OSI_DEBUG_LEVEL > 3
5019   debugMessage("Begin OsiMskSolverInterface::~OsiMskSolverInterface()\n");
5020   #endif
5021 
5022   gutsOfDestructor();
5023   decrementInstanceCounter();
5024 
5025   #if MSK_OSI_DEBUG_LEVEL > 3
5026   debugMessage("End OsiMskSolverInterface::~OsiMskSolverInterface()\n");
5027   #endif
5028 }
5029 
5030 //-----------------------------------------------------------------------------
5031 // Assign operator
5032 
operator =(const OsiMskSolverInterface & rhs)5033 OsiMskSolverInterface& OsiMskSolverInterface::operator=( const OsiMskSolverInterface& rhs )
5034 {
5035   #if MSK_OSI_DEBUG_LEVEL > 3
5036   debugMessage("Begin OsiMskSolverInterface::operator=(%p)\n", (void *)&rhs);
5037   #endif
5038 
5039   if (this != &rhs)
5040   {
5041     OsiSolverInterface::operator=( rhs );
5042     gutsOfDestructor();
5043     gutsOfConstructor();
5044 
5045     if ( rhs.task_ !=NULL )
5046       gutsOfCopy( rhs );
5047   }
5048 
5049   #if MSK_OSI_DEBUG_LEVEL > 3
5050   debugMessage("End OsiMskSolverInterface::operator=(%p)\n", (void *)&rhs);
5051   #endif
5052 
5053   return *this;
5054 }
5055 
5056 //#############################################################################
5057 // Applying cuts
5058 //#############################################################################
5059 
5060 //-----------------------------------------------------------------------------
5061 // Apply col cut
5062 
applyColCut(const OsiColCut & cc)5063 void OsiMskSolverInterface::applyColCut( const OsiColCut & cc )
5064 {
5065   #if MSK_OSI_DEBUG_LEVEL > 3
5066   debugMessage("Begin OsiMskSolverInterface::applyColCut(%p)\n", (void *)&cc);
5067   #endif
5068 
5069   double * MskColLB = new double[getNumCols()];
5070   double * MskColUB = new double[getNumCols()];
5071   const CoinPackedVector & lbs = cc.lbs();
5072   const CoinPackedVector & ubs = cc.ubs();
5073   int i;
5074 
5075   for( i = 0; i < getNumCols(); ++i )
5076   {
5077     MskColLB[i] = getColLower()[i];
5078     MskColUB[i] = getColUpper()[i];
5079   }
5080 
5081   for( i = 0; i < lbs.getNumElements(); ++i )
5082     if ( lbs.getElements()[i] > MskColLB[lbs.getIndices()[i]] )
5083       setColLower( lbs.getIndices()[i], lbs.getElements()[i] );
5084   for( i = 0; i < ubs.getNumElements(); ++i )
5085     if ( ubs.getElements()[i] < MskColUB[ubs.getIndices()[i]] )
5086       setColUpper( ubs.getIndices()[i], ubs.getElements()[i] );
5087 
5088   delete[] MskColLB;
5089   delete[] MskColUB;
5090 
5091   #if MSK_OSI_DEBUG_LEVEL > 3
5092   debugMessage("End OsiMskSolverInterface::applyColCut(%p)\n", (void *)&cc);
5093   #endif
5094 }
5095 
5096 //-----------------------------------------------------------------------------
5097 // Apply row cut
5098 
applyRowCut(const OsiRowCut & rowCut)5099 void OsiMskSolverInterface::applyRowCut( const OsiRowCut & rowCut )
5100 {
5101   #if MSK_OSI_DEBUG_LEVEL > 3
5102   debugMessage("Begin OsiMskSolverInterface::applyRowCut(%p)\n", (void *)&rowCut);
5103   #endif
5104 
5105   const CoinPackedVector & row=rowCut.row();
5106   addRow(row ,  rowCut.lb(),rowCut.ub());
5107 
5108   #if MSK_OSI_DEBUG_LEVEL > 3
5109   debugMessage("End OsiMskSolverInterface::applyRowCut(%p)\n", (void *)&rowCut);
5110   #endif
5111 }
5112 
5113 //#############################################################################
5114 // Private methods (non-static and static) and static data
5115 //#############################################################################
5116 
5117 unsigned int OsiMskSolverInterface::numInstances_ = 0;
5118 MSKenv_t OsiMskSolverInterface::env_=NULL;
5119 
5120 //-----------------------------------------------------------------------------
5121 // Returns MOSEK task in object
5122 
getMutableLpPtr() const5123 MSKtask_t OsiMskSolverInterface::getMutableLpPtr() const
5124 {
5125   #if MSK_OSI_DEBUG_LEVEL > 3
5126   debugMessage("Begin OsiMskSolverInterface::getMutableLpPtr()\n");
5127   #endif
5128 
5129   if ( task_ == NULL )
5130   {
5131     MSKassert(3,env_ != NULL,"env_ == NULL","getMutableLpPtr");
5132 
5133     int err = MSK_makeemptytask(env_,&task_);
5134     checkMSKerror(err, "MSK_makeemptytask","getMutableLpPtr");
5135 
5136     err = MSK_linkfunctotaskstream(task_, MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog);
5137     checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" );
5138 
5139     err = MSK_linkfunctotaskstream(task_, MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncWarning);
5140     checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" );
5141 
5142     err = MSK_linkfunctotaskstream(task_, MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncError);
5143     checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" );
5144 
5145     err = MSK_putintparam(task_, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON);
5146     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5147 
5148     err = MSK_putintparam(task_, MSK_IPAR_PRESOLVE_USE, MSK_ON);
5149     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5150 
5151 #if MSK_VERSION_MAJOR < 9
5152     err = MSK_putintparam(task_, MSK_IPAR_WRITE_DATA_FORMAT, MSK_DATA_FORMAT_MPS);
5153     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5154 #endif
5155 
5156     err = MSK_putintparam(task_, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON);
5157     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5158 
5159     #if MSK_DO_MOSEK_LOG > 0
5160     char file[] = "MOSEK.log";
5161     err = MSK_linkfiletotaskstream(task_, MSK_STREAM_LOG, file, 0);
5162     checkMSKerror( err, "MSK_linkfiletotaskstream", "getMutableLpPtr" );
5163 
5164     err = MSK_putintparam(task_, MSK_IPAR_LOG, 100);
5165     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5166 
5167     err = MSK_putintparam(task_, MSK_IPAR_LOG_SIM, 100);
5168     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5169 
5170     err = MSK_putintparam(task_, MSK_IPAR_LOG_INTPNT, 100);
5171     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5172     #else
5173     err = MSK_putintparam(task_, MSK_IPAR_LOG, 100);
5174     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5175     #endif
5176 
5177     err =  MSK_putintparam(task_,MSK_IPAR_SIM_SOLVE_FORM,MSK_SOLVE_PRIMAL);
5178     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5179 
5180     err =  MSK_putintparam(task_,MSK_IPAR_SIM_HOTSTART,MSK_SIM_HOTSTART_STATUS_KEYS);
5181     checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()");
5182 
5183     std::string pn;
5184     getStrParam(OsiProbName,pn);
5185     MSK_puttaskname( task_, const_cast<char*>(pn.c_str()) );
5186     checkMSKerror(err,"MSK_puttaskname","getMutableLpPtr()");
5187   }
5188 
5189   #if MSK_OSI_DEBUG_LEVEL > 3
5190   debugMessage("End OsiMskSolverInterface::getMutableLpPtr()\n");
5191   #endif
5192 
5193   return task_;
5194 }
5195 
5196 //-----------------------------------------------------------------------------
5197 // Makes a copy
5198 
gutsOfCopy(const OsiMskSolverInterface & source)5199 void OsiMskSolverInterface::gutsOfCopy( const OsiMskSolverInterface & source )
5200 {
5201   #if MSK_OSI_DEBUG_LEVEL > 1
5202   debugMessage("Begin OsiMskSolverInterface::gutsOfCopy()\n");
5203   #endif
5204 
5205   int err;
5206 
5207   InitialSolver = source.InitialSolver;
5208 
5209   MSKassert(3, task_ == NULL, "task_ == NULL", "gutsOfCopy");
5210   err = MSK_clonetask(source.getMutableLpPtr(),&task_);
5211 
5212   checkMSKerror( err, "MSK_clonetask", "gutsOfCopy" );
5213 
5214   // reinitialize output streams to use message handler of copy, also not sure that MSK_clonetask copied these over
5215   MSK_linkfunctotaskstream(task_, MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog);
5216   MSK_linkfunctotaskstream(task_, MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncWarning);
5217   MSK_linkfunctotaskstream(task_, MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncError);
5218 
5219   // Set MIP information
5220   resizeColType(source.coltypesize_);
5221   CoinDisjointCopyN( source.coltype_, source.coltypesize_, coltype_ );
5222 
5223   // Updates task MIP information
5224   for( int k = 0; k < source.coltypesize_; ++k )
5225   {
5226     switch(coltype_[k])
5227     {
5228       case 'I':
5229       setInteger(k);
5230       break;
5231 
5232       case 'C':
5233       setContinuous(k);
5234       break;
5235     }
5236   }
5237 
5238   #if MSK_OSI_DEBUG_LEVEL > 1
5239   debugMessage("End OsiMskSolverInterface::gutsOfCopy()\n");
5240   #endif
5241 }
5242 
5243 
5244 //-----------------------------------------------------------------------------
5245 // Empty function
5246 
gutsOfConstructor()5247 void OsiMskSolverInterface::gutsOfConstructor()
5248 {
5249   #if MSK_OSI_DEBUG_LEVEL > 3
5250   debugMessage("Begin OsiMskSolverInterface::gutsOfConstructor()\n");
5251   #endif
5252 
5253   #if MSK_OSI_DEBUG_LEVEL > 3
5254   debugMessage("End OsiMskSolverInterface::gutsOfConstructor()\n");
5255   #endif
5256 }
5257 
5258 
5259 //-----------------------------------------------------------------------------
5260 // Function called from destructor
5261 
gutsOfDestructor()5262 void OsiMskSolverInterface::gutsOfDestructor()
5263 {
5264   #if MSK_OSI_DEBUG_LEVEL > 3
5265   debugMessage("Begin OsiMskSolverInterface::gutsOfDestructor()\n");
5266   #endif
5267 
5268   freeCachedData(KEEPCACHED_NONE);
5269 
5270   if ( task_ != NULL )
5271   {
5272   	MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_LOG);
5273   	MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_ERR);
5274   	MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_WRN);
5275 
5276       int err = MSK_deletetask(&task_);
5277       checkMSKerror( err, "MSK_deletetask", "gutsOfDestructor" );
5278       task_ = NULL;
5279       freeAllMemory();
5280   }
5281 
5282   MSKassert(3,task_==NULL,"task_==NULL","gutsOfDestructor");
5283   MSKassert(3,obj_==NULL,"obj_==NULL","gutsOfDestructor");
5284   MSKassert(3,collower_==NULL,"collower_==NULL","gutsOfDestructor");
5285   MSKassert(3,colupper_==NULL,"colupper_==NULL","gutsOfDestructor");
5286   MSKassert(3,rowsense_==NULL,"rowsense_==NULL","gutsOfDestructor");
5287   MSKassert(3,rhs_==NULL,"rhs_==NULL","gutsOfDestructor");
5288   MSKassert(3,rowrange_==NULL,"rowrange_==NULL","gutsOfDestructor");
5289   MSKassert(3,rowlower_==NULL,"rowlower_==NULL","gutsOfDestructor");
5290   MSKassert(3,rowupper_==NULL,"rowupper_==NULL","gutsOfDestructor");
5291   MSKassert(3,colsol_==NULL,"colsol_==NULL","gutsOfDestructor");
5292   MSKassert(3,rowsol_==NULL,"rowsol_==NULL","gutsOfDestructor");
5293   MSKassert(3,redcost_==NULL,"redcost_==NULL","gutsOfDestructor");
5294   MSKassert(3,rowact_==NULL,"rowact_==NULL","gutsOfDestructor");
5295   MSKassert(3,matrixByRow_==NULL,"probtypemip_","gutsOfDestructor");
5296   MSKassert(3,matrixByCol_==NULL,"matrixByCol_==NULL","gutsOfDestructor");
5297   MSKassert(3,coltype_==NULL,"coltype_==NULL","gutsOfDestructor");
5298   MSKassert(3,coltypesize_==0,"coltypesize_==0","gutsOfDestructor");
5299 
5300   #if MSK_OSI_DEBUG_LEVEL > 3
5301   debugMessage("End OsiMskSolverInterface::gutsOfDestructor()\n");
5302   #endif
5303 }
5304 
5305 
5306 //-----------------------------------------------------------------------------
5307 // Free function
5308 
freeCachedColRim()5309 void OsiMskSolverInterface::freeCachedColRim()
5310 {
5311   #if MSK_OSI_DEBUG_LEVEL > 3
5312   debugMessage("Begin OsiMskSolverInterface::freeCachedColRim()\n");
5313   #endif
5314 
5315   freeCacheDouble( obj_ );
5316   freeCacheDouble( collower_ );
5317   freeCacheDouble( colupper_ );
5318 
5319   MSKassert(3,obj_==NULL,"obj_==NULL","freeCachedColRim");
5320   MSKassert(3,collower_==NULL,"collower_==NULL","freeCachedColRim");
5321   MSKassert(3,colupper_==NULL,"colupper_==NULL","freeCachedColRim");
5322 
5323   #if MSK_OSI_DEBUG_LEVEL > 3
5324   debugMessage("End OsiMskSolverInterface::freeCachedColRim()\n");
5325   #endif
5326 }
5327 
5328 //-----------------------------------------------------------------------------
5329 // Free function
5330 
freeCachedRowRim()5331 void OsiMskSolverInterface::freeCachedRowRim()
5332 {
5333   #if MSK_OSI_DEBUG_LEVEL > 3
5334   debugMessage("Begin OsiMskSolverInterface::freeCachedRowRim()\n");
5335   #endif
5336 
5337   freeCacheChar( rowsense_ );
5338   freeCacheDouble( rhs_ );
5339   freeCacheDouble( rowrange_ );
5340   freeCacheDouble( rowlower_ );
5341   freeCacheDouble( rowupper_ );
5342 
5343   MSKassert(3,rowsense_==NULL,"rowsense_==NULL","freeCachedRowRim");
5344   MSKassert(3,rhs_==NULL,"rhs_==NULL","freeCachedRowRim");
5345   MSKassert(3,rowrange_==NULL,"rowrange_==NULL","freeCachedRowRim");
5346   MSKassert(3,rowlower_==NULL,"rowlower_==NULL","freeCachedRowRim");
5347   MSKassert(3,rowupper_==NULL,"rowupper_==NULL","freeCachedRowRim");
5348 
5349   #if MSK_OSI_DEBUG_LEVEL > 3
5350   debugMessage("End OsiMskSolverInterface::freeCachedRowRim()\n");
5351   #endif
5352 }
5353 
5354 //-----------------------------------------------------------------------------
5355 // Free function
5356 
freeCachedMatrix()5357 void OsiMskSolverInterface::freeCachedMatrix()
5358 {
5359   #if MSK_OSI_DEBUG_LEVEL > 3
5360   debugMessage("Begin OsiMskSolverInterface::freeCachedMatrix()\n");
5361   #endif
5362 
5363   freeCacheMatrix( matrixByRow_ );
5364   freeCacheMatrix( matrixByCol_ );
5365   MSKassert(3,matrixByRow_==NULL,"matrixByRow_==NULL","freeCachedMatrix");
5366   MSKassert(3,matrixByCol_==NULL,"matrixByCol_==NULL","freeCachedMatrix");
5367 
5368   #if MSK_OSI_DEBUG_LEVEL > 3
5369   debugMessage("End OsiMskSolverInterface::freeCachedMatrix()\n");
5370   #endif
5371 }
5372 
5373 //-----------------------------------------------------------------------------
5374 //  Free function
5375 
freeCachedResults()5376 void OsiMskSolverInterface::freeCachedResults()
5377 {
5378   #if MSK_OSI_DEBUG_LEVEL > 3
5379   debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n");
5380   #endif
5381 
5382   freeCacheDouble( colsol_ );
5383   freeCacheDouble( rowsol_ );
5384   freeCacheDouble( redcost_ );
5385   freeCacheDouble( rowact_ );
5386 
5387   MSKassert(3,colsol_==NULL,"colsol_==NULL","freeCachedResults");
5388   MSKassert(3,rowsol_==NULL,"rowsol_==NULL","freeCachedResults");
5389   MSKassert(3,redcost_==NULL,"redcost_==NULL","freeCachedResults");
5390   MSKassert(3,rowact_==NULL,"rowact_==NULL","freeCachedResults");
5391 
5392   #if MSK_OSI_DEBUG_LEVEL > 3
5393   debugMessage("End OsiMskSolverInterface::freeCachedResults()\n");
5394   #endif
5395 }
5396 
5397 //-----------------------------------------------------------------------------
5398 //  Free function
5399 
freeCachedData(int keepCached)5400 void OsiMskSolverInterface::freeCachedData( int keepCached )
5401 {
5402   #if MSK_OSI_DEBUG_LEVEL > 3
5403   debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n");
5404   #endif
5405 
5406   if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_COLUMN) )
5407     freeCachedColRim();
5408   if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_ROW) )
5409     freeCachedRowRim();
5410   if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_MATRIX) )
5411     freeCachedMatrix();
5412   if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_RESULTS) )
5413     freeCachedResults();
5414 
5415   #if MSK_OSI_DEBUG_LEVEL > 3
5416   debugMessage("End OsiMskSolverInterface::freeCachedResults()\n");
5417   #endif
5418 }
5419 
5420 //-----------------------------------------------------------------------------
5421 //  Free function
5422 
freeAllMemory()5423 void OsiMskSolverInterface::freeAllMemory()
5424 {
5425   #if MSK_OSI_DEBUG_LEVEL > 3
5426   debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n");
5427   #endif
5428 
5429   freeCachedData();
5430 
5431   if( hotStartCStat_ != NULL )
5432     delete[] hotStartCStat_;
5433 
5434   if( hotStartRStat_ != NULL )
5435     delete[] hotStartRStat_;
5436 
5437   hotStartCStat_     = NULL;
5438   hotStartCStatSize_ = 0;
5439   hotStartRStat_     = NULL;
5440   hotStartRStatSize_ = 0;
5441   freeColType();
5442 
5443   #if MSK_OSI_DEBUG_LEVEL > 3
5444   debugMessage("End OsiMskSolverInterface::freeCachedResults()\n");
5445   #endif
5446 }
5447