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