/* Osi interface for Mosek ver. 7.0 Lower versions are not supported ----------------------------------------------------------------------------- name: OSI Interface for MOSEK ----------------------------------------------------------------------------- This code is licensed under the terms of the Eclipse Public License (EPL). Originally developed by Bo Jensen from MOSEK ApS. No longer a maintainer. */ #include #include #include #include #include "OsiConfig.h" #include "CoinPragma.hpp" #include "CoinError.hpp" #include "CoinFinite.hpp" #include "OsiMskSolverInterface.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "CoinPackedMatrix.hpp" #include "CoinWarmStartBasis.hpp" #include "mosek.h" #define MSK_OSI_DEBUG_LEVEL 0 #ifndef NDEBUG #define MSK_OSI_ASSERT_LEVEL 0 #else #define MSK_OSI_ASSERT_LEVEL 4 #endif #define MSK_DO_MOSEK_LOG 0 #define debugMessage printf //Choose algorithm to be default in initial solve #define INITIAL_SOLVE MSK_OPTIMIZER_FREE //Choose algorithm to be default in resolve #define RESOLVE_SOLVE MSK_OPTIMIZER_FREE_SIMPLEX // Unset this flag to disable the warnings from interface. #define MSK_WARNING_ON #if MSK_VERSION_MAJOR >= 9 #define MSKCONST const #endif #undef getc //############################################################################# // A couple of helper functions //############################################################################# // Free memory pointet to by a double pointer inline void freeCacheDouble( double*& ptr ) { if( ptr != NULL ) { delete [] ptr; ptr = NULL; } } // Free memory pointet to by a char pointer inline void freeCacheChar( char*& ptr ) { if( ptr != NULL ) { delete [] ptr; ptr = NULL; } } // Free memory pointet to by a CoinPackedMatrix pointer inline void freeCacheMatrix( CoinPackedMatrix*& ptr ) { if( ptr != NULL ) { delete ptr; ptr = NULL; } } // Function used to connect MOSEK to stream #if MSK_VERSION_MAJOR >= 7 static void MSKAPI printlog(void *ptr, const char* s) #else static void MSKAPI printlog(void *ptr, char* s) #endif { printf("%s",s); } static void handleMessage(CoinMessageHandler* handler, MSKCONST char* str) { size_t len = strlen(str); if( len == 0 ) return; if( str[len-1] == '\n') { char* str_ = (char*)malloc(len); memcpy(str_, str, len-1); str_[len-1] = '\0'; handler->message(0, "MSK", str_, ' ') << CoinMessageEol; free(str_); } else handler->message(0, "MSK", str, ' '); } static void MSKAPI OsiMskStreamFuncLog(MSKuserhandle_t handle, MSKCONST char* str) { CoinMessageHandler* handler = (CoinMessageHandler*)handle; if (handler != NULL) { if (handler->logLevel() >= 1) handleMessage(handler, str); } else { printf(str); printf("\n"); } } static void MSKAPI OsiMskStreamFuncWarning(MSKuserhandle_t handle, MSKCONST char* str) { CoinMessageHandler* handler = (CoinMessageHandler*)handle; if (handler != NULL) { if (handler->logLevel() >= 0) handleMessage(handler, str); } else { printf(str); printf("\n"); } } static void MSKAPI OsiMskStreamFuncError(MSKuserhandle_t handle, MSKCONST char* str) { CoinMessageHandler* handler = (CoinMessageHandler*)handle; if (handler != NULL) { handleMessage(handler, str); } else { fprintf(stderr, str); fprintf(stderr, "\n"); } } // Prints a error message and throws a exception static inline void checkMSKerror( int err, const char* mskfuncname, const char* osimethod ) { if( err != MSK_RES_OK ) { char s[100]; sprintf( s, "%s returned error %d", mskfuncname, err ); std::cout << "ERROR: " << s << " (" << osimethod << " in OsiMskSolverInterface)" << std::endl; throw CoinError( s, osimethod, "OsiMskSolverInterface" ); } } // Prints a error message and throws a exception static inline void MSKassert(int assertlevel, int test, const char* assertname, const char* osimethod ) { if( assertlevel > MSK_OSI_ASSERT_LEVEL && !test ) { std::cout << "Assert: " << assertname << " (" << osimethod << " in OsiMskSolverInterface)" << std::endl; throw CoinError( assertname, osimethod, "OsiMskSolverInterface" ); } } // Converts Range/Sense/Rhs to MSK bound structure static inline void MskConvertSenseToBound(const char rowsen, const double rowrng, const double rowrhs, double &rlb, double &rub, int &rtag) { switch (rowsen) { case 'E': rlb = rowrhs; rub = rowrhs; rtag = MSK_BK_FX; break; case 'L': rlb = MSK_INFINITY; rub = rowrhs; rtag = MSK_BK_UP; break; case 'G': rlb = rowrhs; rub = MSK_INFINITY; rtag = MSK_BK_LO; break; case 'R': if( rowrng >= 0 ) { rlb = rowrhs - rowrng; rub = rowrhs; } else { rlb = rowrhs; rub = rowrhs + rowrng; } rtag = MSK_BK_RA; break; case 'N': rlb = -MSK_INFINITY; rub = MSK_INFINITY; rtag = MSK_BK_FR; break; default: MSKassert(3,1,"Unknown rowsen","MskConvertSenseToBound"); } } // Converts a set of bounds to MSK boundkeys static inline void MskConvertColBoundToTag(const double collb, const double colub, double &clb, double &cub, int &ctag) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin MskConvertColBoundToTag()\n"); #endif if(collb > -MSK_INFINITY && colub < MSK_INFINITY) { ctag = MSK_BK_RA; clb = collb; cub = colub; } else if(collb <= - MSK_INFINITY && colub < MSK_INFINITY) { ctag = MSK_BK_UP; clb = -MSK_INFINITY; cub = colub; } else if(collb > - MSK_INFINITY && colub >= MSK_INFINITY) { ctag = MSK_BK_LO; clb = collb; cub = MSK_INFINITY; } else if(collb <= -MSK_INFINITY && colub >= MSK_INFINITY) { ctag = MSK_BK_FR; clb = -MSK_INFINITY; cub = MSK_INFINITY; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End MskConvertColBoundToTag()\n"); #endif } // Returns true if "solution" is defined in MOSEK, where solution can be basic, interior or // integer resp. (MSK_SOL_BAS), (MSK_SOL_ITR) or (MSK_SOL_ITG). bool OsiMskSolverInterface::definedSolution(int solution) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::definedSolution() %p\n",(void*)this); #endif int err, res; err = MSK_solutiondef(getMutableLpPtr(), (MSKsoltypee) solution, &res); checkMSKerror(err,"MSK_solutiondef","definedSolution"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::definedSolution()\n"); #endif return ( res != MSK_RES_OK); } // Returns the flag for solver currently switched on in MOSEK resp. (MSK_OPTIMIZER_FREE), // (MSK_OPTIMIZER_INTPNT), (MSK_OPTIMIZER_PRIMAL_SIMPLEX), (MSK_OPTIMIZER_MIXED_INT), or // (MSK_OPTIMIZER_MIXED_INT_CONIC). // MOSEK also has Conic and nonconvex solvers, but these are for obvious reasons not // an option in the Osi interface. int OsiMskSolverInterface::solverUsed() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::solverUsed()\n"); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::solverUsed()\n"); #endif return MSKsolverused_; } // Switch the MOSEK solver to LP uses default solver specified by 'InitialSolver' void OsiMskSolverInterface::switchToLP( void ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::switchToLP()\n"); #endif int err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_MIO_MODE, MSK_MIO_MODE_IGNORED); checkMSKerror(err,"MSK_putintparam","switchToLp"); probtypemip_ = false; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::switchToLP()\n"); #endif } // Switch the MOSEK solver to MIP. void OsiMskSolverInterface::switchToMIP( void ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::switchToMIP()\n"); #endif int err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_MIO_MODE, MSK_MIO_MODE_SATISFIED); checkMSKerror(err,"MSK_putintparam","switchToMIP"); #if MSK_VERSION_MAJOR == 7 err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_MIXED_INT_CONIC); #else err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_MIXED_INT); #endif checkMSKerror(err,"MSK_putintparam","switchToMIP"); probtypemip_ = true; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::switchToMIP()\n"); #endif } // Resize the coltype array. void OsiMskSolverInterface::resizeColType( int minsize ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::resizeColType()\n"); #endif if( minsize > coltypesize_ ) { int newcoltypesize = 2*coltypesize_; if( minsize > newcoltypesize ) newcoltypesize = minsize; char *newcoltype = new char[newcoltypesize]; if( coltype_ != NULL ) { CoinDisjointCopyN( coltype_, coltypesize_, newcoltype ); delete[] coltype_; } coltype_ = newcoltype; coltypesize_ = newcoltypesize; } MSKassert(3,minsize == 0 || coltype_ != NULL,"Unknown rowsen","MskConvertSenseToBound"); MSKassert(3,coltypesize_ >= minsize,"coltypesize_ >= minsize","MskConvertSenseToBound"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::resizeColType()\n"); #endif } // Free coltype array void OsiMskSolverInterface::freeColType() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeColType()\n"); #endif if( coltypesize_ > 0 ) { delete[] coltype_; coltype_ = NULL; coltypesize_ = 0; } MSKassert(3,coltype_ == NULL,"coltype_ == NULL","freeColType"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeColType()\n"); #endif } //############################################################################# // Solve methods //############################################################################# //----------------------------------------------------------------------------- // Free cached results and optimize the LP problem in task void OsiMskSolverInterface::initialSolve() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::initialSolve() %p\n", (void*)this); #endif if( definedSolution( MSK_SOL_BAS ) == true ) { resolve(); } else { int err,solver; err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_SIM_HOTSTART, MSK_SIM_HOTSTART_STATUS_KEYS); checkMSKerror(err,"MSK_putintparam","initialsolve"); err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &solver); checkMSKerror(err,"MSK_getintparam","initialsolve"); switchToLP(); err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, INITIAL_SOLVE); checkMSKerror(err,"MSK_putintparam","initialSolve"); err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_); checkMSKerror(err,"MSK_getintparam","initialsolve"); #if MSK_DO_MOSEK_LOG > 0 err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG,MSK_DO_MOSEK_LOG); checkMSKerror(err,"MSK_putintparam","initialsolve"); err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG_SIM,MSK_DO_MOSEK_LOG); checkMSKerror(err,"MSK_putintparam","initialsolve"); #endif Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS )); #if MSK_DO_MOSEK_LOG > 0 err = MSK_solutionsummary( getMutableLpPtr(),MSK_STREAM_LOG); checkMSKerror(err,"MSK_solutionsummary","initialsolve"); #endif err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, solver); checkMSKerror(err,"MSK_putintparam","initialsolve"); } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::initialSolve()\n"); #endif } //----------------------------------------------------------------------------- // Resolves an LP problem. void OsiMskSolverInterface::resolve() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::resolve %p\n", (void*)this); #endif if( definedSolution( MSK_SOL_BAS ) == true ) { int err,solver; err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &solver); checkMSKerror(err,"MSK_getintparam","resolve"); switchToLP(); err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_SIM_HOTSTART, MSK_SIM_HOTSTART_STATUS_KEYS); checkMSKerror(err,"MSK_putintparam","resolve"); err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, RESOLVE_SOLVE); checkMSKerror(err,"MSK_putintparam","resolve"); #if 0 err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, 20000000 ); #endif err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_); checkMSKerror(err,"MSK_getintparam","resolve"); #if MSK_DO_MOSEK_LOG > 0 err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG,MSK_DO_MOSEK_LOG); checkMSKerror(err,"MSK_putintparam","resolve"); err = MSK_putintparam( getMutableLpPtr(),MSK_IPAR_LOG_SIM,MSK_DO_MOSEK_LOG); checkMSKerror(err,"MSK_putintparam","resolve"); #endif Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS )); #if MSK_DO_MOSEK_LOG > 0 err = MSK_solutionsummary( getMutableLpPtr(),MSK_STREAM_LOG); printf("Mskerr : %d\n",Mskerr); #endif err = MSK_putintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, solver); checkMSKerror(err,"MSK_putintparam","resolve"); } else { initialSolve(); } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::resolve... press any key to continue\n"); getchar(); #endif } //----------------------------------------------------------------------------- // Resolves an MIP problem with MOSEK MIP solver. void OsiMskSolverInterface::branchAndBound() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::branchAndBound()\n"); #endif switchToMIP(); int err = MSK_getintparam(getMutableLpPtr(), MSK_IPAR_OPTIMIZER, &MSKsolverused_); checkMSKerror(err,"MSK_getintparam","branchAndBound"); Mskerr = MSK_optimize(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS )); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::branchAndBound()\n"); #endif } //############################################################################# // Parameter related methods //############################################################################# //----------------------------------------------------------------------------- // Sets a int parameter in MOSEK bool OsiMskSolverInterface::setIntParam(OsiIntParam key, int value) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setIntParam(%d, %d)\n", key, value); #endif bool retval = false; switch (key) { case OsiMaxNumIteration: retval = (MSK_putintparam(getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, value ) == MSK_RES_OK); break; case OsiMaxNumIterationHotStart: if (value < 0) { retval = false; } else { hotStartMaxIteration_ = value; retval = true; } break; case OsiNameDiscipline: retval = false; break; case OsiLastIntParam: retval = false; break; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setIntParam(%d, %d)\n", key, value); #endif return retval; } //----------------------------------------------------------------------------- // Sets a double parameter in MOSEK. bool OsiMskSolverInterface::setDblParam(OsiDblParam key, double value) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setDblParam(%d, %g)\n", key, value); #endif bool retval = false; switch (key) { case OsiDualObjectiveLimit: if( getObjSense() == +1 ) // Minimize retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, value ) == MSK_RES_OK ); // min else retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, value ) == MSK_RES_OK ); // max break; case OsiPrimalObjectiveLimit: if( getObjSense() == +1 ) // Minimize retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, value ) == MSK_RES_OK ); // min else retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, value ) == MSK_RES_OK ); // max break; case OsiDualTolerance: retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_BASIS_TOL_S, value ) == MSK_RES_OK ); break; case OsiPrimalTolerance: retval = ( MSK_putdouparam( getMutableLpPtr(), MSK_DPAR_BASIS_TOL_X, value ) == MSK_RES_OK ); break; case OsiObjOffset: ObjOffset_ = value; retval = true; break; case OsiLastDblParam: retval = false; break; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setDblParam(%d, %g)\n", key, value); #endif return retval; } //----------------------------------------------------------------------------- // Sets a string parameter in MOSEK. bool OsiMskSolverInterface::setStrParam(OsiStrParam key, const std::string & value) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setStrParam(%d, %s)\n", key, value.c_str()); #endif bool retval=false; switch (key) { case OsiProbName: OsiSolverInterface::setStrParam(key,value); return retval = true; case OsiSolverName: return false; case OsiLastStrParam: return false; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setStrParam(%d, %s)\n", key, value.c_str()); #endif return retval; } //----------------------------------------------------------------------------- // Gets a int parameter in MOSEK. bool OsiMskSolverInterface::getIntParam(OsiIntParam key, int& value) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getIntParam(%d)\n", key); #endif bool retval = false; switch (key) { case OsiMaxNumIteration: retval = (MSK_getintparam(getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, &value ) == MSK_RES_OK); break; case OsiMaxNumIterationHotStart: value = hotStartMaxIteration_; retval = true; break; case OsiNameDiscipline: value = 0; retval = false; break; case OsiLastIntParam: retval = false; break; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getIntParam(%d)\n", key); #endif return retval; } //----------------------------------------------------------------------------- // Get a double parameter in MOSEK. bool OsiMskSolverInterface::getDblParam(OsiDblParam key, double& value) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getDblParam(%d)\n", key); #endif bool retval = false; switch (key) { case OsiDualObjectiveLimit: if( getObjSense() == +1 ) retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value ) == MSK_RES_OK ); // max else retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value ) == MSK_RES_OK ); // min break; case OsiPrimalObjectiveLimit: if( getObjSense() == +1 ) retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value ) == MSK_RES_OK ); // min else retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value ) == MSK_RES_OK ); // max break; case OsiDualTolerance: retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_BASIS_TOL_S, &value ) == MSK_RES_OK ); break; case OsiPrimalTolerance: retval = ( MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_BASIS_TOL_X, &value ) == MSK_RES_OK ); break; case OsiObjOffset: value = ObjOffset_; retval = true; break; case OsiLastDblParam: retval = false; break; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getDblParam(%d)\n", key); #endif return retval; } //----------------------------------------------------------------------------- // Gets a string parameter from MOSEK bool OsiMskSolverInterface::getStrParam(OsiStrParam key, std::string & value) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getStrParam(%d)\n", key); #endif switch (key) { case OsiProbName: OsiSolverInterface::getStrParam(key, value); break; case OsiSolverName: value = "MOSEK"; break; case OsiLastStrParam: return false; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getStrParam(%d)\n", key); #endif return true; } //############################################################################# // Methods returning info on how the solution process terminated //############################################################################# //----------------------------------------------------------------------------- // Returns true if solver abandoned in last call to solver. // Mosek does not use this functionality bool OsiMskSolverInterface::isAbandoned() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isAbandoned()\n"); debugMessage("isAbandoned() %d\n",(Mskerr != MSK_RES_OK)); debugMessage("End OsiMskSolverInterface::isAbandoned()\n"); #endif return (Mskerr != MSK_RES_OK); } //----------------------------------------------------------------------------- // Returns true if "solution" available is proved to be optimal, where "solution" in LP // could be both interior and basic, checks for both. bool OsiMskSolverInterface::isProvenOptimal() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isProvenOptimal()\n"); #endif int err; MSKsolstae status; MSKsoltypee solution; if( probtypemip_ == false) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else { if( definedSolution( MSK_SOL_ITR ) == true ) solution = MSK_SOL_ITR; else return false; } } else { if( definedSolution( MSK_SOL_ITG ) == true ) solution = MSK_SOL_ITG; else return false; } err = MSK_getsolution(getMutableLpPtr(), solution, NULL, &status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror(err,"MSK_getsolution","isProvenOptimal"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Solution type , %d status %d \n ",(status == MSK_SOL_STA_OPTIMAL), status) ; debugMessage("End OsiMskSolverInterface::isProvenOptimal()\n"); #endif return ( status == MSK_SOL_STA_OPTIMAL || status == MSK_SOL_STA_INTEGER_OPTIMAL); } //----------------------------------------------------------------------------- // Returns true if a certificate of primal inf. exits bool OsiMskSolverInterface::isProvenPrimalInfeasible() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isProvenPrimalInfeasible()\n"); #endif int err; MSKsolstae status; MSKsoltypee solution; if( probtypemip_ == false) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else { if( definedSolution( MSK_SOL_ITR ) == true ) solution = MSK_SOL_ITR; else return false; } } else { if( definedSolution( MSK_SOL_ITG ) == true) solution = MSK_SOL_ITG; else return false; } err = MSK_getsolution(getMutableLpPtr(), solution, NULL, &status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror(err,"MSK_getsolution","isProvenPrimalInfeasible"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("isProvenPrimalInfeasible %d \n",(status == MSK_SOL_STA_PRIM_INFEAS_CER)); debugMessage("End OsiMskSolverInterface::isProvenPrimalInfeasible()\n"); #endif return ( status == MSK_SOL_STA_PRIM_INFEAS_CER ); } //----------------------------------------------------------------------------- // Should return true if a certificate of dual inf. exits // But COIN does not support this feature thus we return false bool OsiMskSolverInterface::isProvenDualInfeasible() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isProvenDualInfeasible()\n"); #endif int err; MSKsolstae status; MSKsoltypee solution; if( probtypemip_ == false ) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else { if( definedSolution( MSK_SOL_ITR ) == true ) solution = MSK_SOL_ITR; else return false; } } else { if( definedSolution( MSK_SOL_ITG ) == true) solution = MSK_SOL_ITG; else return false; } err = MSK_getsolution(getMutableLpPtr(), solution, NULL, &status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); checkMSKerror(err,"MSK_getsolution","isProvenDualInfeasible"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("isProvenDualInfeasible %d \n",(status == MSK_SOL_STA_DUAL_INFEAS_CER)); debugMessage("End OsiMskSolverInterface::isProvenDualInfeasible()\n"); #endif return ( status == MSK_SOL_STA_DUAL_INFEAS_CER ); } //----------------------------------------------------------------------------- // Returns true if primal objective limit is reached. Checks the objective sense // first. bool OsiMskSolverInterface::isPrimalObjectiveLimitReached() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n"); #endif if( Mskerr == MSK_RES_TRM_OBJECTIVE_RANGE ) { int err; double obj = getObjValue(),value=MSK_INFINITY; if( getObjSense() == +1 ) { err = MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value); checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached"); } else { err = MSK_getdouparam(getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value ); checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached"); obj = -obj; value = -value; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("primal objective value %-16.10e , lowerbound %-16.10e , reached %d \n",obj,value,(value <= obj)); debugMessage("End OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n"); #endif return ( !( value == MSK_INFINITY || value == -MSK_INFINITY ) && value > obj ); } else { if( Mskerr == MSK_RES_OK ) { if( definedSolution( MSK_SOL_BAS ) == true ) { int err; double obj = getObjValue(),value=MSK_INFINITY; if( getObjSense() == +1 ) { err = MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value); checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached"); return (obj < value); } else { err = MSK_getdouparam(getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value ); checkMSKerror(err,"MSK_getdouparam","isPrimalObjectiveLimitReached"); obj = -obj; value = -value; return (obj < value); } } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::isPrimalObjectiveLimitReached()\n"); #endif return false; } } //----------------------------------------------------------------------------- // Returns true if dual objective limit is reached. Checks the objective sense // first. bool OsiMskSolverInterface::isDualObjectiveLimitReached() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isDualObjectiveLimitReached()\n"); #endif if( Mskerr == MSK_RES_TRM_OBJECTIVE_RANGE ) { int err; double obj = getObjValue(),value=MSK_INFINITY; if( getObjSense() == +1 ) { err = MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value); checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached"); } else { err = MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value ); checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached"); obj = -obj; value = -value; } checkMSKerror( err, "MSK_getdouparam", "isPrimalObjectiveLimitReached" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("dual objective value %f , lowerbound %f , reached %i \n",obj,value,(value <= obj)); debugMessage("End OsiMskSolverInterface::isDualObjectiveLimitReached()\n"); #endif return ( !( value == MSK_INFINITY || value == -MSK_INFINITY ) && value <= obj ); } else { if( Mskerr == MSK_RES_OK ) { if( definedSolution( MSK_SOL_BAS ) == true ) { int err; double obj = getObjValue(),value=MSK_INFINITY; if( getObjSense() == +1 ) { err = MSK_getdouparam( getMutableLpPtr(), MSK_DPAR_UPPER_OBJ_CUT, &value); checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached"); return (obj > value); } else { err = MSK_getdouparam(getMutableLpPtr(), MSK_DPAR_LOWER_OBJ_CUT, &value ); checkMSKerror(err,"MSK_getdouparam","isDualObjectiveLimitReached"); obj = -obj; value = -value; return (obj > value); } } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::isDualObjectiveLimitReached()\n"); #endif return false; } } //----------------------------------------------------------------------------- // Returns true if iteration number used in last call to optimize eq. max number for // the solver used. bool OsiMskSolverInterface::isIterationLimitReached() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isIterationLimitReached()\n"); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("iteration limit reached %d \n",Mskerr); debugMessage("End OsiMskSolverInterface::isIterationLimitReached()\n"); #endif return Mskerr == MSK_RES_TRM_MAX_ITERATIONS; } //----------------------------------------------------------------------------- // Returns true if a license problem occured in last call to optimize. bool OsiMskSolverInterface::isLicenseError() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isLicenseError()\n"); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("license error %d \n",Mskerr); debugMessage("End OsiMskSolverInterface::isLicenseError()\n"); #endif return Mskerr >= MSK_RES_ERR_LICENSE && Mskerr <= MSK_RES_ERR_LICENSE_NO_SERVER_SUPPORT; } //############################################################################# // WarmStart related methods //############################################################################# // Get an empty warm start object CoinWarmStart* OsiMskSolverInterface::getEmptyWarmStart () const { return (dynamic_cast(new CoinWarmStartBasis())) ; } //----------------------------------------------------------------------------- // Get warm start, returns NULL pointer if not available CoinWarmStart* OsiMskSolverInterface::getWarmStart() const { CoinWarmStartBasis* ws = NULL; int numbas = 0,numcols = getNumCols(),numrows = getNumRows(),*skx,*skc, err, i,*bkc,*bkx; double *blc,*buc,*blx,*bux,*xc,*xx; bool skip = false; #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::getWarmStart numcols %d numrows %d %p\n",numcols,numrows, (void*)this); #endif skx = new int[numcols]; skc = new int[numrows]; bkc = new int[numrows]; blc = new double[numrows]; buc = new double[numrows]; xc = new double[numrows]; bkx = new int[numcols]; blx = new double[numcols]; bux = new double[numcols]; xx = new double[numcols]; #if MSK_VERSION_MAJOR < 9 err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_CON, 0, numrows, (MSKboundkeye*)bkc, (MSKrealt*)blc, (MSKrealt*)buc); checkMSKerror( err, "MSK_getboundslice", "getWarmStart" ); err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_VAR, 0, numcols, (MSKboundkeye*)bkx, (MSKrealt*)blx, (MSKrealt*)bux); checkMSKerror( err, "MSK_getboundslice", "getWarmStart" ); #else err = MSK_getconboundslice(getMutableLpPtr(), 0, numrows, (MSKboundkeye*)bkc, (MSKrealt*)blc, (MSKrealt*)buc); checkMSKerror( err, "getconboundslice", "getWarmStart" ); err = MSK_getvarboundslice(getMutableLpPtr(), 0, numcols, (MSKboundkeye*)bkx, (MSKrealt*)blx, (MSKrealt*)bux); checkMSKerror( err, "MSK_getvarboundslice", "getWarmStart" ); #endif MSKassert(3,!probtypemip_,"!probtypemip_","getWarmStart"); if( definedSolution( MSK_SOL_BAS ) == true ) { err = MSK_getsolution(getMutableLpPtr(), MSK_SOL_BAS, NULL, NULL, (MSKstakeye*)skc, (MSKstakeye*)skx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror( err, "MSK_getsolution", "getWarmStart" ); } else { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("No basic solution in OsiMskSolverInterface::getWarmStart()\n"); #endif /* No basic solution stored choose slack basis */ /* Otherwise the unittest can not be passed */ ws = new CoinWarmStartBasis; ws->setSize( numcols, numrows ); for( i = 0; i < numrows; ++i ) ws->setArtifStatus( i, CoinWarmStartBasis::basic ); numbas = numrows; for( i = 0; i < numcols; ++i ) { switch(bkx[i]) { case MSK_BK_RA: case MSK_BK_LO: ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound ); break; case MSK_BK_FX: case MSK_BK_UP: ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound ); break; case MSK_BK_FR: ws->setStructStatus( i, CoinWarmStartBasis::isFree ); break; default: checkMSKerror( 1, "Wrong bound key", "getWarmStart" ); } } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::getWarmStart()\n"); #endif delete[] skc; delete[] skx; delete[] bkc; delete[] blc; delete[] buc; delete[] xc; delete[] bkx; delete[] blx; delete[] bux; delete[] xx; /* Leave function */ return ws; } if( err == MSK_RES_OK ) { /* Status keys should be defined */ ws = new CoinWarmStartBasis; MSKassert(3,ws != NULL,"1) ws != NULL","getWarmStart"); ws->setSize( numcols, numrows ); for( i = 0; i < numrows && ws != NULL; ++i ) { switch( skc[i] ) { case MSK_SK_UNK: case MSK_SK_BAS: /* Warning : Slacks in Osi and Mosek er negated */ ws->setArtifStatus( i, CoinWarmStartBasis::basic ); ++numbas; break; case MSK_SK_LOW: /* Warning : Slacks in Osi and Mosek er negated */ ws->setArtifStatus( i, CoinWarmStartBasis::atUpperBound ); break; case MSK_SK_FIX: case MSK_SK_UPR: /* Warning : Slacks in Osi and Mosek er negated */ ws->setArtifStatus( i, CoinWarmStartBasis::atLowerBound ); break; case MSK_SK_SUPBAS: ws->setArtifStatus( i, CoinWarmStartBasis::isFree ); break; default: // unknown row status delete ws; ws = NULL; skip = true; checkMSKerror( 1, "Wrong slack status key", "getWarmStart" ); break; } } if( skip == false ) { for( i = 0; i < numcols && ws != NULL; ++i ) { switch( skx[i] ) { case MSK_SK_UNK: case MSK_SK_BAS: ++numbas; ws->setStructStatus( i, CoinWarmStartBasis::basic ); break; case MSK_SK_FIX: case MSK_SK_LOW: ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound ); break; case MSK_SK_UPR: ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound ); break; case MSK_SK_SUPBAS: ws->setStructStatus( i, CoinWarmStartBasis::isFree ); break; default: // unknown column status delete ws; ws = NULL; checkMSKerror( 1, "Wrong variable status key", "getWarmStart" ); break; } } } } delete[] skx; delete[] skc; delete[] bkc; delete[] blc; delete[] buc; delete[] xc; delete[] bkx; delete[] blx; delete[] bux; delete[] xx; MSKassert(3,ws!=NULL,"2) ws!=NULL","getWarmStart"); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::getWarmStart() (%p) numcols %d numrows %d numbas %d\n",(void*)(ws),numcols,numrows,numbas); #endif return ws; } //----------------------------------------------------------------------------- // Set warm start bool OsiMskSolverInterface::setWarmStart(const CoinWarmStart* warmstart) { const CoinWarmStartBasis* ws = dynamic_cast(warmstart); int numcols, numrows, i, restat,numbas=0; int *skx, *skc, *bkc, *bkx; bool retval = false, skip = false; if( !ws ) return false; numcols = ws->getNumStructural(); numrows = ws->getNumArtificial(); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::setWarmStart(%p) this = %p numcols %d numrows %d\n", (void *)warmstart,(void*)this,numcols,numrows); #endif if( numcols != getNumCols() || numrows != getNumRows() ) return false; switchToLP(); skx = new int[numcols]; skc = new int[numrows]; bkc = new int[numrows]; #if MSK_VERSION_MAJOR < 9 restat = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_CON, 0, numrows, (MSKboundkeye*) (bkc), NULL, NULL); checkMSKerror( restat, "MSK_getboundslice", "setWarmStart" ); #else restat = MSK_getconboundslice(getMutableLpPtr(), 0, numrows, (MSKboundkeye*) (bkc), NULL, NULL); checkMSKerror( restat, "MSK_getconboundslice", "setWarmStart" ); #endif for( i = 0; i < numrows; ++i ) { switch( ws->getArtifStatus( i ) ) { case CoinWarmStartBasis::basic: skc[i] = MSK_SK_BAS; ++numbas; break; /* Warning : Slacks in Osi and Mosek er negated */ case CoinWarmStartBasis::atUpperBound: switch(bkc[i]) { case MSK_BK_LO: case MSK_BK_RA: skc[i] = MSK_SK_LOW; break; case MSK_BK_FX: skc[i] = MSK_SK_FIX; break; default: skc[i] = MSK_SK_UNK; break; } break; /* Warning : Slacks in Osi and Mosek er negated */ case CoinWarmStartBasis::atLowerBound: switch(bkc[i]) { case MSK_BK_UP: case MSK_BK_RA: skc[i] = MSK_SK_UPR; break; case MSK_BK_FX: skc[i] = MSK_SK_FIX; break; default: skc[i] = MSK_SK_UNK; break; } break; case CoinWarmStartBasis::isFree: skc[i] = MSK_SK_SUPBAS; break; default: // unknown row status retval = false; skip = true; MSKassert(3,1,"Unkown rowstatus","setWarmStart"); break; } } delete[] bkc; if( skip == false ) { bkx = new int[numcols]; #if MSK_VERSION_MAJOR < 9 restat = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_VAR, 0, numcols, (MSKboundkeye*) (bkx), NULL, NULL); checkMSKerror( restat, "MSK_getboundslice", "setWarmStart" ); #else restat = MSK_getvarboundslice(getMutableLpPtr(), 0, numcols, (MSKboundkeye*) (bkx), NULL, NULL); checkMSKerror( restat, "MSK_getvarboundslice", "setWarmStart" ); #endif for( i = 0; i < numcols; ++i ) { switch( ws->getStructStatus( i ) ) { case CoinWarmStartBasis::basic: skx[i] = MSK_SK_BAS; ++numbas; break; case CoinWarmStartBasis::atLowerBound: switch(bkx[i]) { case MSK_BK_LO: case MSK_BK_RA: skx[i] = MSK_SK_LOW; break; case MSK_BK_FX: skx[i] = MSK_SK_FIX; default: skx[i] = MSK_SK_UNK; break; } break; case CoinWarmStartBasis::atUpperBound: switch(bkx[i]) { case MSK_BK_UP: case MSK_BK_RA: skx[i] = MSK_SK_UPR; break; case MSK_BK_FX: skx[i] = MSK_SK_FIX; default: skx[i] = MSK_SK_UNK; break; } break; case CoinWarmStartBasis::isFree: skx[i] = MSK_SK_SUPBAS; break; default: // unknown col status retval = false; skip = true; MSKassert(3,1,"Unkown col status","setWarmStart"); break; } } delete[] bkx; } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("OsiMskSolverInterface::setWarmStart(%p) numcols %d numrows %d numbas %d\n", (void *)warmstart,numcols,numrows,numbas); #endif #if 0 MSKassert(3,numbas == numrows,"Wrong number of basis variables","setWarmStart"); #endif if( skip == false ) { restat = MSK_putsolution( getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ), MSK_SOL_BAS, (MSKstakeye*) (skc), (MSKstakeye*) (skx), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); delete[] skx; delete[] skc; } else { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Skipping setting values in OsiMskSolverInterface::setWarmStart()\n"); #endif #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::setWarmStart(%p)\n", (void *)warmstart); #endif delete[] skx; delete[] skc; return false; } retval = (restat == MSK_RES_OK); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::setWarmStart(%p)\n", (void *)warmstart); #endif return retval; } //############################################################################# // Hotstart related methods (primarily used in strong branching) //############################################################################# //----------------------------------------------------------------------------- // Mark hot start void OsiMskSolverInterface::markHotStart() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::markHotStart()\n"); #endif int err; int numcols, numrows; MSKassert(3,!probtypemip_,"probtypemip_","markHotStart"); numcols = getNumCols(); numrows = getNumRows(); if( numcols > hotStartCStatSize_ ) { delete[] hotStartCStat_; hotStartCStatSize_ = static_cast( 1.0 * static_cast( numcols ) ); // get some extra space for future hot starts hotStartCStat_ = new int[hotStartCStatSize_]; } if( numrows > hotStartRStatSize_ ) { delete[] hotStartRStat_; hotStartRStatSize_ = static_cast( 1.0 * static_cast( numrows ) ); // get some extra space for future hot starts hotStartRStat_ = new int[hotStartRStatSize_]; } err = MSK_getsolution(getMutableLpPtr(), MSK_SOL_BAS, NULL, NULL, (MSKstakeye*) (hotStartRStat_), (MSKstakeye*) (hotStartCStat_), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror( err, "MSK_getsolution", "markHotStart" ); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::markHotStart()\n"); #endif } //----------------------------------------------------------------------------- // Solve from a hot start void OsiMskSolverInterface::solveFromHotStart() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::solveFromHotStart()\n"); #endif int err; int maxiter; switchToLP(); MSKassert(3,getNumCols() <= hotStartCStatSize_,"getNumCols() <= hotStartCStatSize_","solveFromHotStart"); MSKassert(3,getNumRows() <= hotStartRStatSize_,"getNumRows() <= hotStartRStatSize_","solveFromHotStart"); err = MSK_putsolution(getLpPtr( OsiMskSolverInterface::FREECACHED_RESULTS ), MSK_SOL_BAS, (MSKstakeye*) (hotStartRStat_), (MSKstakeye*) (hotStartCStat_), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror( err, "MSK_putsolution", "solveFromHotStart" ); err = MSK_getintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, &maxiter ); checkMSKerror( err, "MSK_getintparam", "solveFromHotStart" ); err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, hotStartMaxIteration_ ); checkMSKerror( err, "MSK_putintparam", "solveFromHotStart" ); resolve(); err = MSK_putintparam( getMutableLpPtr(), MSK_IPAR_SIM_MAX_ITERATIONS, maxiter ); checkMSKerror( err, "MSK_putintparam", "solveFromHotStart" ); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::solveFromHotStart()\n"); #endif } //----------------------------------------------------------------------------- // Unmark a hot start void OsiMskSolverInterface::unmarkHotStart() { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::unmarkHotStart()\n"); #endif freeCachedData(); if( hotStartCStat_ != NULL ) delete[] hotStartCStat_; if( hotStartRStat_ != NULL ) delete[] hotStartRStat_; hotStartCStat_ = NULL; hotStartCStatSize_ = 0; hotStartRStat_ = NULL; hotStartRStatSize_ = 0; #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::unmarkHotStart()\n"); #endif } //############################################################################# // Problem information methods (original data) //############################################################################# //----------------------------------------------------------------------------- // Returns number of columns in MOSEK task int OsiMskSolverInterface::getNumCols() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getNumCols()\n"); #endif int numcol, err; err = MSK_getnumvar(getMutableLpPtr(),&numcol); checkMSKerror( err, "MSK_getnumvar", "getNumCols" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getNumCols()\n"); #endif return numcol; } //----------------------------------------------------------------------------- // Returns number of rows in MOSEK task int OsiMskSolverInterface::getNumRows() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getNumRows()\n"); #endif int numrow, err; err = MSK_getnumcon(getMutableLpPtr(),&numrow); checkMSKerror( err, "MSK_getnumcon", "getNumRows" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getNumRows()\n"); #endif return numrow; } //----------------------------------------------------------------------------- // Returns number of non-zeroes (in matrix) in MOSEK task int OsiMskSolverInterface::getNumElements() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getNumElements()\n"); #endif int numnon, err; err = MSK_getnumanz(getMutableLpPtr(),&numnon); checkMSKerror( err, "MSK_getnumanz", "getNumElements" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getNumElements()\n"); #endif return numnon; } //----------------------------------------------------------------------------- // Returns lower bounds on columns in MOSEK task const double * OsiMskSolverInterface::getColLower() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getColLower()\n"); #endif if(collower_ == NULL ) { int ncols = getNumCols(); MSKassert(3,colupper_ == NULL,"colupper_","getColLower"); if( ncols > 0 ) { if(colupper_ == NULL) colupper_ = new double[ncols]; if(collower_ == NULL) collower_ = new double[ncols]; int *dummy_tags = new int[ncols]; #if MSK_VERSION_MAJOR < 9 int err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_VAR, (MSKidxt)0, (MSKidxt)ncols, (MSKboundkeye*) (dummy_tags), collower_, colupper_); checkMSKerror(err, "MSK_getboundslice","getColUpper"); #else int err = MSK_getvarboundslice(getMutableLpPtr(), 0, ncols, (MSKboundkeye*) (dummy_tags), collower_, colupper_); checkMSKerror(err, "MSK_getvarboundslice","getColUpper"); #endif for( int k = 0; k < ncols; ++k ) { if( dummy_tags[k] == MSK_BK_UP || dummy_tags[k] == MSK_BK_FR ) { /* No lower */ collower_[k] = -getInfinity(); } if( dummy_tags[k] == MSK_BK_LO || dummy_tags[k] == MSK_BK_FR ) { /* No upper */ colupper_[k] = getInfinity(); } } delete[] dummy_tags; } else { if(colupper_ != NULL) delete [] colupper_; if(collower_ != NULL) delete [] collower_; colupper_ = collower_ = NULL; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getColLower()\n"); #endif return collower_; } //----------------------------------------------------------------------------- // Returns upper bounds on columns in MOSEK task const double * OsiMskSolverInterface::getColUpper() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getColUpper()\n"); #endif if( colupper_ == NULL ) { int ncols = getNumCols(); MSKassert(3,collower_ == NULL,"collower_ == NULL","getColUpper"); if( ncols > 0 ) { if(colupper_ == NULL) colupper_ = new double[ncols]; if(collower_ == NULL) collower_ = new double[ncols]; int *dummy_tags = new int[ncols]; #if MSK_VERSION_MAJOR < 9 int err = MSK_getboundslice( getMutableLpPtr(), MSK_ACC_VAR, (MSKidxt)0, (MSKidxt)ncols, (MSKboundkeye*) (dummy_tags), collower_, colupper_); checkMSKerror(err,"MSK_getboundslice","getColUpper"); #else int err = MSK_getvarboundslice( getMutableLpPtr(), 0, ncols, (MSKboundkeye*) (dummy_tags), collower_, colupper_); checkMSKerror(err,"MSK_getvarboundslice","getColUpper"); #endif delete[] dummy_tags; } else { if(colupper_ != NULL) delete [] colupper_; if(collower_ != NULL) delete [] collower_; colupper_ = collower_ = NULL; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getColUpper()\n"); #endif return colupper_; } //----------------------------------------------------------------------------- // Returns rowsense in MOSEK task, call getRightHandSide to produce triplets. const char * OsiMskSolverInterface::getRowSense() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowSense()\n"); #endif if( rowsense_==NULL ) { getRightHandSide(); if( getNumRows() != 0 ) MSKassert(3,rowsense_!=NULL,"rowsense_!=NULL","getRowSense"); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowSense()\n"); #endif return rowsense_; } //----------------------------------------------------------------------------- // Returns the RHS in triplet form. MOSEK uses always boundkeys instead of the // triplet, so we have to convert back to triplet. const double * OsiMskSolverInterface::getRightHandSide() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRightHandSide()\n"); #endif if(rowsense_ == NULL) { int nr = getNumRows(); if ( nr != 0 ) { MSKassert(3,(rhs_ == NULL) && (rowrange_ == NULL),"(rhs_ == NULL) && (rowrange_ == NULL)","getRightHandSide"); rowsense_ = new char[nr]; rhs_ = new double[nr]; rowrange_ = new double[nr]; const double * lb = getRowLower(); const double * ub = getRowUpper(); int i; for ( i=0; i 3 debugMessage("End OsiMskSolverInterface::getRightHandSide()\n"); #endif return rhs_; } //----------------------------------------------------------------------------- // Returns rowrange in MOSEK task, call getRightHandSide to produce triplets. const double * OsiMskSolverInterface::getRowRange() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowRange()\n"); #endif if( rowrange_ == NULL ) { getRightHandSide(); MSKassert(3,rowrange_!=NULL || getNumRows() == 0,"rowrange_!=NULL || getNumRows() == 0","getRowRange"); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowRange()\n"); #endif return rowrange_; } //----------------------------------------------------------------------------- // Returns lower bounds on rows in MOSEK task. const double * OsiMskSolverInterface::getRowLower() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowLower()\n"); #endif if( rowlower_ == NULL ) { MSKassert(3,rowupper_ == NULL,"rowupper_ == NULL","getRowLower"); int nrows = getNumRows(); if( nrows > 0 ) { rowlower_ = new double[nrows]; rowupper_ = new double[nrows]; int *dummy_tags = new int[nrows]; #if MSK_VERSION_MAJOR < 9 int err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_CON, (MSKidxt)0, (MSKidxt)nrows, (MSKboundkeye*) (dummy_tags), rowlower_, rowupper_); checkMSKerror(err,"MSK_getboundslice","getRowLower"); #else int err = MSK_getconboundslice(getMutableLpPtr(), 0, nrows, (MSKboundkeye*) (dummy_tags), rowlower_, rowupper_); checkMSKerror(err,"MSK_getconboundslice","getRowLower"); #endif delete[] dummy_tags; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowLower()\n"); #endif return rowlower_; } //----------------------------------------------------------------------------- // Returns upper bounds on rows in MOSEK task. const double * OsiMskSolverInterface::getRowUpper() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowUpper()\n"); #endif if( rowupper_ == NULL ) { MSKassert(3,rowlower_ == NULL,"probtypemip_","getRowUpper"); int nrows = getNumRows(); if( nrows > 0 ) { rowupper_ = new double[nrows]; rowlower_ = new double[nrows]; int *dummy_tags = new int[nrows]; #if MSK_VERSION_MAJOR < 9 int err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_CON, (MSKidxt)0, (MSKidxt)nrows, (MSKboundkeye*) (dummy_tags), rowlower_, rowupper_); checkMSKerror(err,"MSK_getboundslice","getRowUpper"); #else int err = MSK_getconboundslice(getMutableLpPtr(), 0, nrows, (MSKboundkeye*) (dummy_tags), rowlower_, rowupper_); checkMSKerror(err,"MSK_getconboundslice","getRowUpper"); #endif delete[] dummy_tags; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowUpper()\n"); #endif return rowupper_; } //----------------------------------------------------------------------------- // Returns objective coefficient in MOSEK task. const double * OsiMskSolverInterface::getObjCoefficients() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getObjCoefficients()\n"); #endif if( obj_ == NULL ) { int ncols = getNumCols(); if( ncols > 0 ) { obj_ = new double[ncols]; int err = MSK_getc( getMutableLpPtr(), obj_ ); checkMSKerror( err, "MSK_getc", "getObjCoefficients" ); } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getObjCoefficients()\n"); #endif return obj_; } //----------------------------------------------------------------------------- // Returns the direction of optimization double OsiMskSolverInterface::getObjSense() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getObjSense()\n"); #endif int err; MSKobjsensee objsen; err = MSK_getobjsense(getMutableLpPtr(), &objsen); checkMSKerror(err,"MSK_getintparam","getObjSense"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getObjSense()\n"); #endif if( objsen == MSK_OBJECTIVE_SENSE_MAXIMIZE ) return -1.0; else return +1.0; } //----------------------------------------------------------------------------- // Returns true if variabel is set to continuous bool OsiMskSolverInterface::isContinuous( int colNumber ) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::isContinuous(%d)\n", colNumber); debugMessage("End OsiMskSolverInterface::isContinuous(%d)\n", colNumber); #endif return getCtype()[colNumber] == 'C'; } //----------------------------------------------------------------------------- // Returns a Coin matrix by row const CoinPackedMatrix * OsiMskSolverInterface::getMatrixByRow() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getMatrixByRow()\n"); #endif if ( matrixByRow_ == NULL ) { int nc, nr, nz, *sub, *ptrb, *ptre, surp, *len; double *val; nc = getNumCols(); nr = getNumRows(); nz = surp = getNumElements(); ptrb = new int[nr+1]; ptre = new int[nr]; sub = new int[nz]; val = new double[nz]; len = new int[nr]; ptrb[nr] = nz; #if MSK_VERSION_MAJOR < 9 int err = MSK_getaslice(getMutableLpPtr(), MSK_ACC_CON, 0, nr, nz, &surp, ptrb, ptre, sub, val); checkMSKerror(err, "MSK_getaslice", "getMatrixByRow"); #else int err = MSK_getarowslice(getMutableLpPtr(), 0, nr, nz, &surp, ptrb, ptre, sub, val); checkMSKerror(err, "MSK_getarowslice", "getMatrixByRow"); #endif for(int i=0; iassignMatrix(false , nc, nr, nz, val, sub, ptrb, len); MSKassert(3,matrixByRow_->getNumCols()==nc,"matrixByRow_->getNumCols()==nc","getMatrixByRow"); MSKassert(3,matrixByRow_->getNumRows()==nr,"matrixByRow_->getNumRows()==nr","getMatrixByRow"); delete[] ptrb; delete[] ptre; delete[] sub; delete[] val; delete[] len; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getMatrixByRow()\n"); #endif return matrixByRow_; } //----------------------------------------------------------------------------- // Returns a Coin matrix by column const CoinPackedMatrix * OsiMskSolverInterface::getMatrixByCol() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getMatrixByCol()\n"); #endif if ( matrixByCol_ == NULL ) { int nc, nr, nz, *sub, *ptrb, *ptre, surp, *len; double *val; nc = getNumCols(); nr = getNumRows(); nz = surp = getNumElements(); ptrb = new int[nc+1]; ptre = new int[nc]; sub = new int[nz]; val = new double[nz]; len = new int[nc]; ptrb[nc] = nz; #if MSK_VERSION_MAJOR < 9 int err = MSK_getaslice(getMutableLpPtr(), MSK_ACC_VAR, 0, nc, nz, &surp, ptrb, ptre, sub, val); checkMSKerror(err, "MSK_getaslice", "getMatrixByCol"); #else int err = MSK_getacolslice(getMutableLpPtr(), 0, nc, nz, &surp, ptrb, ptre, sub, val); checkMSKerror(err, "MSK_getacolslice", "getMatrixByCol"); #endif for(int i=0; iassignMatrix(true , nr, nc, nz, val, sub, ptrb, len); MSKassert(3,matrixByCol_->getNumCols()==nc,"matrixByCol_->getNumCols()==nc","getMatrixByCol"); MSKassert(3,matrixByCol_->getNumRows()==nr,"matrixByCol_->getNumRows()==nr","getMatrixByCol"); delete[] ptrb; delete[] ptre; delete[] sub; delete[] val; delete[] len; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getMatrixByCol()\n"); #endif return matrixByCol_; } //----------------------------------------------------------------------------- // Returns the infinity level used in MOSEK. double OsiMskSolverInterface::getInfinity() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getInfinity()\n"); debugMessage("End OsiMskSolverInterface::getInfinity()\n"); #endif return MSK_INFINITY; } //############################################################################# // Problem information methods (results) //############################################################################# //----------------------------------------------------------------------------- // Returns the current col solution. const double * OsiMskSolverInterface::getColSolution() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getColSolution() %p\n",(void*)this); #endif if( colsol_ != NULL ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("colsol_ != NULL\n"); #endif return colsol_; } int i; int nc = getNumCols(); if( nc > 0 ) { MSKsoltypee solution = MSK_SOL_END; if(colsol_ == NULL) colsol_ = new double[nc]; if( probtypemip_ == false) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else if( definedSolution( MSK_SOL_ITR) == true ) solution = MSK_SOL_ITR; } else if( definedSolution( MSK_SOL_ITG ) == true ) solution = MSK_SOL_ITG; if ( solution == MSK_SOL_END ) { double const *cl=getColLower(),*cu=getColLower(); /* this is just plain stupid, but needed to pass unit test */ for( i = 0; i < nc; ++i ) { if( cl[i] > -getInfinity() ) { colsol_[i] = cl[i]; } else if( cu[i] < getInfinity() ) { colsol_[i] = cu[i]; } else { colsol_[i] = 0.0; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("colsol_ truncated to zero due to no solution\n"); debugMessage("probtypemip_ %d\n",probtypemip_); #endif return colsol_; } int err = MSK_getsolution(getMutableLpPtr(), solution, NULL, NULL, NULL, NULL, NULL, NULL, colsol_, NULL, NULL, NULL, NULL, NULL, NULL ); checkMSKerror(err,"MSK_getsolution","getColSolution"); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getColSolution()\n"); #endif return colsol_; } //----------------------------------------------------------------------------- // Returns the row price / dual variabels in MOSEK task const double * OsiMskSolverInterface::getRowPrice() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowPrice()\n"); #endif if( rowsol_ == NULL ) { int i; int nr = getNumRows(); if( nr > 0 ) { MSKsoltypee solution = MSK_SOL_END; rowsol_ = new double[nr]; if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else if( definedSolution( MSK_SOL_ITR) == true ) solution = MSK_SOL_ITR; if ( solution == MSK_SOL_END ) { for( i = 0; i < nr; ++i ) rowsol_[i] = 0.0; return rowsol_; } int err = MSK_getsolution(getMutableLpPtr(), solution, NULL, NULL, NULL, NULL, NULL, NULL, NULL, rowsol_, NULL, NULL, NULL, NULL, NULL); checkMSKerror( err, "MSK_getsolution", "getRowPrice" ); } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowPrice()\n"); #endif return rowsol_; } //----------------------------------------------------------------------------- // Returns the reduced cost in MOSEK task. const double * OsiMskSolverInterface::getReducedCost() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getReducedCost()\n"); #endif if( redcost_ == NULL ) { int ncols = getNumCols(); if( ncols > 0 ) { MSKsoltypee solution = MSK_SOL_END; if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else if( definedSolution( MSK_SOL_ITR) == true ) solution = MSK_SOL_ITR; if ( solution == MSK_SOL_END ) return NULL; redcost_ = new double[ncols]; double *slx = new double[ncols]; double *sux = new double[ncols]; int err = MSK_getsolution(getMutableLpPtr(), solution, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, slx, sux, NULL); // Calculate reduced cost for(int i = 0; i < ncols; i++) redcost_[i] = slx[i]-sux[i]; delete[] slx; delete[] sux; checkMSKerror( err, "MSK_getsolution", "getReducedCost" ); } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getReducedCost()\n"); #endif return redcost_; } //----------------------------------------------------------------------------- // Returns the rowactivity in MOSEK task. const double * OsiMskSolverInterface::getRowActivity() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getRowActivity()\n"); #endif if( rowact_ == NULL ) { int nrows = getNumRows(); if( nrows > 0 ) { rowact_ = new double[nrows]; const double *x = getColSolution() ; const CoinPackedMatrix *mtx = getMatrixByRow() ; mtx->times(x,rowact_) ; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getRowActivity()\n"); #endif return rowact_; } //----------------------------------------------------------------------------- // Returns the objective for defined solution in MOSEK task. double OsiMskSolverInterface::getObjValue() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getObjValue()\n"); #endif double objval = OsiSolverInterface::getObjValue(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getObjValue()\n"); #endif return objval; } //----------------------------------------------------------------------------- // Returns the iteration used in last call to optimize. Notice that the cross // over phase in interior methods is not returned, when interior point is // used, only the interior point iterations. int OsiMskSolverInterface::getIterationCount() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getIterationCount()\n"); #endif int nr = 0, solver, err; int nrp=0; solver = solverUsed(); if( solver == MSK_OPTIMIZER_PRIMAL_SIMPLEX ) { { err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_PRIMAL_ITER, &nr); checkMSKerror(err,"MSK_getintinf","getIterationsCount"); } } else if( solver == MSK_OPTIMIZER_DUAL_SIMPLEX ) { { err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_DUAL_ITER, &nr); checkMSKerror(err,"MSK_getintinf","getIterationsCount"); } } else if( solver == MSK_OPTIMIZER_FREE_SIMPLEX ) { { err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_DUAL_ITER, &nr); checkMSKerror(err,"MSK_getintinf","getIterationsCount"); err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_SIM_PRIMAL_ITER, &nrp); checkMSKerror(err,"MSK_getintinf","getIterationsCount"); nr = nr+nrp; } } else if( solver == MSK_OPTIMIZER_INTPNT ) { { err = MSK_getintinf(getMutableLpPtr(), MSK_IINF_INTPNT_ITER, &nr); checkMSKerror(err,"MSK_getintinf","getIterationsCount"); } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getIterationCount()\n"); #endif return nr; } //----------------------------------------------------------------------------- // Returns one dual ray std::vector OsiMskSolverInterface::getDualRays(int maxNumRays, bool fullRay) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getDualRays(%d,%s)\n", maxNumRays, fullRay?"true":"false"); #endif if (fullRay == true) { throw CoinError("Full dual rays not yet implemented.","getDualRays", "OsiMskSolverInterface"); } OsiMskSolverInterface solver(*this); int numrows = getNumRows(), r; MSKsolstae status; MSKsoltypee solution; if( probtypemip_ == false ) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else { if( definedSolution( MSK_SOL_ITR ) == true ) solution = MSK_SOL_ITR; else return std::vector(); } } else { if( definedSolution( MSK_SOL_ITG ) == true ) solution = MSK_SOL_ITG; else return std::vector(); } double *farkasray = new double[numrows]; r = MSK_getsolution(getMutableLpPtr(), solution, NULL, &status, NULL, NULL, NULL, NULL, NULL, farkasray, NULL, NULL, NULL, NULL, NULL); checkMSKerror( r, "MSK_getsolution", "getDualRays" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getDualRays(%d)\n", maxNumRays); #endif if( status != MSK_SOL_STA_PRIM_INFEAS_CER ) { delete[] farkasray; return std::vector(); } else return std::vector(1, farkasray); } //----------------------------------------------------------------------------- // Returns one primal ray std::vector OsiMskSolverInterface::getPrimalRays(int maxNumRays) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getPrimalRays(%d)\n", maxNumRays); #endif OsiMskSolverInterface solver(*this); int numcols = getNumCols(), r; MSKsolstae status; MSKsoltypee solution; if( probtypemip_ == false ) { if( definedSolution( MSK_SOL_BAS ) == true ) solution = MSK_SOL_BAS; else { if( definedSolution( MSK_SOL_ITR ) == true ) solution = MSK_SOL_ITR; else return std::vector(); } } else { if( definedSolution( MSK_SOL_ITG ) == true ) solution = MSK_SOL_ITG; else return std::vector(); } double *farkasray = new double[numcols]; r = MSK_getsolution(getMutableLpPtr(), solution, NULL, &status, NULL, NULL, NULL, NULL, farkasray, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror( r, "MSK_getsolution", "getPrimalRays" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getPrimalRays(%d)\n", maxNumRays); #endif if( status != MSK_SOL_STA_DUAL_INFEAS_CER ) { delete[] farkasray; return std::vector(); } else return std::vector(1, farkasray); } //############################################################################# // Problem modifying methods (rim vectors) //############################################################################# //----------------------------------------------------------------------------- // Sets a variabels objective coeff. void OsiMskSolverInterface::setObjCoeff( int elementIndex, double elementValue ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue); #endif const double *oldobj; if( redcost_ && !obj_ ) oldobj = getObjCoefficients(); else oldobj = obj_; int err = MSK_putclist(getMutableLpPtr(), 1, &elementIndex, &elementValue); checkMSKerror(err, "MSK_putclist", "setObjCoeff"); if( obj_ ) { if( redcost_ ) { redcost_[elementIndex] += elementValue-oldobj[elementIndex]; obj_[elementIndex] = elementValue; } else { obj_[elementIndex] = elementValue; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue); #endif } //----------------------------------------------------------------------------- // Sets a list of objective coeff. void OsiMskSolverInterface::setObjCoeffSet(const int* indexFirst, const int* indexLast, const double* coeffList) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setObjCoeffSet(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)coeffList); #endif const double *oldobj; const long int cnt = indexLast - indexFirst; if( redcost_ && !obj_ ) oldobj = getObjCoefficients(); else oldobj = obj_; int err = MSK_putclist(getMutableLpPtr(), static_cast(cnt), const_cast(indexFirst), const_cast(coeffList)); checkMSKerror(err, "MSK_putclist", "setObjCoeffSet"); if( obj_ ) { if( redcost_ ) { for( int j = 0; j < cnt; ++j) { redcost_[j] += coeffList[indexFirst[j]]-oldobj[j]; obj_[j] = coeffList[indexFirst[j]]; } } else { for( int j = 0; j < cnt; ++j) { obj_[j] = coeffList[indexFirst[j]]; } } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setObjCoeffSet(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)coeffList); #endif } //----------------------------------------------------------------------------- // Sets lower bound on one specific column void OsiMskSolverInterface::setColLower(int elementIndex, double elementValue) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue); #endif int finite = 1; if( elementValue <= -getInfinity() ) finite = 0; #if MSK_VERSION_MAJOR < 9 int err = MSK_chgbound(getMutableLpPtr(), MSK_ACC_VAR, elementIndex, 1, /*It is a lower bound*/ finite, /* Is it finite */ elementValue); checkMSKerror( err, "MSK_chgbound", "setColLower" ); #else int err = MSK_chgvarbound(getMutableLpPtr(), elementIndex, 1, /*It is a lower bound*/ finite, /* Is it finite */ elementValue); checkMSKerror( err, "MSK_chgvarbound", "setColLower" ); #endif if( collower_ != NULL ) collower_[elementIndex] = elementValue; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue); #endif } //----------------------------------------------------------------------------- // Sets upper bound on one specific column. void OsiMskSolverInterface::setColUpper(int elementIndex, double elementValue) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue); #endif int finite = 1; if( elementValue >= getInfinity() ) finite = 0; #if MSK_VERSION_MAJOR < 9 int err = MSK_chgbound( getMutableLpPtr(), MSK_ACC_VAR, elementIndex, 0, /* It is a upper bound */ finite, /* Is it finite */ elementValue); checkMSKerror( err, "MSK_chgbound", "setColUpper" ); #else int err = MSK_chgvarbound( getMutableLpPtr(), elementIndex, 0, /* It is a upper bound */ finite, /* Is it finite */ elementValue); checkMSKerror( err, "MSK_chgvarbound", "setColUpper" ); #endif if( colupper_ != NULL ) colupper_[elementIndex] = elementValue; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue); #endif } //----------------------------------------------------------------------------- // Sets upper and lower bound on one specific column void OsiMskSolverInterface::setColBounds( int elementIndex, double lower, double upper ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper); #endif setColLower(elementIndex, lower); setColUpper(elementIndex, upper); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper); #endif } //----------------------------------------------------------------------------- // Sets upper and lower bounds on a list of columns. Due to the strange storage of // boundlist, it is not possible to change all the bounds in one call to MOSEK, // so the standard method is used. void OsiMskSolverInterface::setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setColSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList); #endif OsiSolverInterface::setColSetBounds( indexFirst, indexLast, boundList ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setColSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList); #endif } //----------------------------------------------------------------------------- // Sets the lower bound on a row void OsiMskSolverInterface::setRowLower( int i, double elementValue ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowLower(%d, %g)\n", i, elementValue); #endif double rhs = getRightHandSide()[i]; double range = getRowRange()[i]; char sense = getRowSense()[i]; double lower=-MSK_INFINITY, upper=MSK_INFINITY; convertSenseToBound( sense, rhs, range, lower, upper ); if( lower != elementValue ) { convertBoundToSense( elementValue, upper, sense, rhs, range ); setRowType( i, sense, rhs, range ); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowLower(%d, %g)\n", i, elementValue); #endif } //----------------------------------------------------------------------------- // Sets the upper bound on a row void OsiMskSolverInterface::setRowUpper( int i, double elementValue ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowUpper(%d, %g)\n", i, elementValue); #endif double rhs = getRightHandSide()[i]; double range = getRowRange()[i]; char sense = getRowSense()[i]; double lower=-MSK_INFINITY, upper=MSK_INFINITY; convertSenseToBound( sense, rhs, range, lower, upper ); if( upper != elementValue ) { convertBoundToSense( lower, elementValue, sense, rhs, range ); setRowType( i, sense, rhs, range ); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowUpper(%d, %g)\n", i, elementValue); #endif } //----------------------------------------------------------------------------- // Sets the upper and lower bound on a row void OsiMskSolverInterface::setRowBounds( int elementIndex, double lower, double upper ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper); #endif double rhs, range; char sense; convertBoundToSense( lower, upper, sense, rhs, range ); setRowType( elementIndex, sense, rhs, range ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper); #endif } //----------------------------------------------------------------------------- // Sets the triplet on a row void OsiMskSolverInterface::setRowType(int i, char sense, double rightHandSide,double range) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range); #endif double rub=MSK_INFINITY,rlb=-MSK_INFINITY; int rtag=MSK_BK_FR; MskConvertSenseToBound(sense, range, rightHandSide, rlb, rub, rtag); #if MSK_VERSION_MAJOR < 9 int err = MSK_putbound(getMutableLpPtr(), MSK_ACC_CON, i, (MSKboundkeye)rtag, rlb, rub); checkMSKerror( err, "MSK_putbound", "setRowType" ); #else int err = MSK_putconbound(getMutableLpPtr(), i, (MSKboundkeye)rtag, rlb, rub); checkMSKerror( err, "MSK_putconbound", "setRowType" ); #endif if( rowsense_ != NULL ) rowsense_[i] = sense; if( rowrange_ != NULL ) rowrange_[i] = range; if( rhs_ != NULL ) rhs_[i] = rightHandSide; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range); #endif } //----------------------------------------------------------------------------- // Set upper og lower bounds for a lisit of rows. Due to the strange storage of // boundlist, it is not possible to change all the bounds in one call to MOSEK, // so the standard method is used. void OsiMskSolverInterface::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList); #endif const long int cnt = indexLast - indexFirst; if (cnt <= 0) return; for (int i = 0; i < cnt; ++i) setRowBounds(indexFirst[i], boundList[2*i], boundList[2*i+1]); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowSetBounds(%p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)boundList); #endif } //----------------------------------------------------------------------------- // Set triplets for a list of rows void OsiMskSolverInterface::setRowSetTypes(const int* indexFirst, const int* indexLast, const char* senseList, const double* rhsList, const double* rangeList) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)senseList, (void *)rhsList, (void *)rangeList); #endif const long int cnt = indexLast - indexFirst; if (cnt <= 0) return; for (int i = 0; i < cnt; ++i) setRowType(indexFirst[i], senseList[i], rhsList[i], rangeList[i]); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n", (void *)indexFirst, (void *)indexLast, (void *)senseList, (void *)rhsList, (void *)rangeList); #endif } //----------------------------------------------------------------------------- // Sets a variabel to continuous void OsiMskSolverInterface::setContinuous(int index) { int numcols = getNumCols(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setContinuous(%d)\n", index); #endif MSKassert(3,coltype_ != NULL,"coltype_ != NULL","setContinuous"); MSKassert(3,coltypesize_ >= getNumCols(),"coltypesize_ >= getNumCols()","setContinuous"); coltype_[index] = 'C'; if( index < numcols ) { int err = MSK_putvartype( getMutableLpPtr(), index, MSK_VAR_TYPE_CONT); checkMSKerror( err, "MSK_putvartype", "setContinuous" ); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setContinuous(%d)\n", index); #endif } //----------------------------------------------------------------------------- // Sets a variabel to integer void OsiMskSolverInterface::setInteger(int index) { int numcols = getNumCols(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setInteger(%d)\n", index); #endif MSKassert(3,coltype_ != NULL,"coltype_ != NULL","setInteger"); MSKassert(3,coltypesize_ >= getNumCols(),"coltypesize_ >= getNumCols()","setInteger"); coltype_[index] = 'I'; if( index < numcols ) { int err = MSK_putvartype( getMutableLpPtr(), index, MSK_VAR_TYPE_INT); checkMSKerror( err, "MSK_putvartype", "setInteger" ); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setInteger(%d)\n", index); #endif } //----------------------------------------------------------------------------- // Sets a list of variables to continuous void OsiMskSolverInterface::setContinuous(const int* indices, int len) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setContinuous(%p, %d)\n", (void *)indices, len); #endif for( int i = 0; i < len; ++i ) setContinuous(indices[i]); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setContinuous(%p, %d)\n", (void *)indices, len); #endif } //----------------------------------------------------------------------------- // Sets a list of variables to integer void OsiMskSolverInterface::setInteger(const int* indices, int len) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setInteger(%p, %d)\n", (void *)indices, len); #endif for( int i = 0; i < len; ++i ) setInteger(indices[i]); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setInteger(%p, %d)\n", (void *)indices, len); #endif } //----------------------------------------------------------------------------- // Sets the direction of optimization void OsiMskSolverInterface::setObjSense(double s) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::setObjSense(%g)\n", s); #endif int err; double pre; pre = getObjSense(); if( s == +1.0 ) { err = MSK_putobjsense(getMutableLpPtr(), MSK_OBJECTIVE_SENSE_MINIMIZE); } else { err = MSK_putobjsense(getMutableLpPtr(), MSK_OBJECTIVE_SENSE_MAXIMIZE); } checkMSKerror(err,"MSK_putintparam","setObjSense"); if( pre != s ) { /* A hack to pass unit test, ugly as hell */ /* When objective sense is changed then reset obj cuts */ if( s > 0 ) { setDblParam(OsiPrimalObjectiveLimit,-COIN_DBL_MAX) ; setDblParam(OsiDualObjectiveLimit,COIN_DBL_MAX) ; } else { setDblParam(OsiPrimalObjectiveLimit,COIN_DBL_MAX) ; setDblParam(OsiDualObjectiveLimit,-COIN_DBL_MAX) ; } } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::setObjSense(%g)\n", s); #endif } //----------------------------------------------------------------------------- // Sets the col solution. This is very fuzzy WE LIKE STATUS KEYS not numerical values i.e superbasics or basic !!!. void OsiMskSolverInterface::setColSolution(const double * cs) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::setColSolution %p\n", (void*)this); #endif int err,nc = getNumCols(),nr = getNumRows(), numbas = 0; MSKstakeye *tskc,*tskx; MSKboundkeye *tbkx,*tbkc; MSKrealt *tblx,*tbux,*tblc,*tbuc; double *txc; if( cs == NULL ) { freeCachedResults(); } else if( nc > 0 ) { if( colsol_ != NULL ) delete[] colsol_; colsol_ = new double[nc]; CoinDisjointCopyN( cs, nc, colsol_ ); tbkx = new MSKboundkeye[nc]; tskx = new MSKstakeye[nc]; tblx = new MSKrealt[nc]; tbux = new MSKrealt[nc]; tskc = new MSKstakeye[nr]; txc = new double[nr]; tbkc = new MSKboundkeye[nr]; tblc = new MSKrealt[nr]; tbuc = new MSKrealt[nr]; const CoinPackedMatrix *mtx = getMatrixByCol() ; assert(mtx->getNumCols() == nc); assert(mtx->getNumRows() == nr); mtx->times(cs,txc) ; /* Negate due to different Osi and Mosek slack representation */ for( int i = 0; i < nr; ++i ) { txc[i] = -txc[i]; tskc[i] = MSK_SK_UNK; } #if MSK_VERSION_MAJOR < 9 err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_CON, 0, nr, tbkc, tblc, tbuc); checkMSKerror( err, "MSK_getboundslice", "setColsolution" ); err = MSK_getboundslice(getMutableLpPtr(), MSK_ACC_VAR, 0, nc, tbkx, tblx, tbux); checkMSKerror( err, "MSK_getboundslice", "setColsolution" ); #else err = MSK_getconboundslice(getMutableLpPtr(), 0, nr, tbkc, tblc, tbuc); checkMSKerror( err, "MSK_getconboundslice", "setColsolution" ); err = MSK_getvarboundslice(getMutableLpPtr(), 0, nc, tbkx, tblx, tbux); checkMSKerror( err, "MSK_getvarboundslice", "setColsolution" ); #endif if( definedSolution( MSK_SOL_BAS ) == true ) { err = MSK_getsolution(getMutableLpPtr(), MSK_SOL_BAS, NULL, NULL, tskc, tskx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror(err,"MSK_getsolution","setColSol"); } for( int i = 0; i < nr; ++i ) { if( tbkc[i] == MSK_BK_FX && tblc[i] == txc[i] ) { tskc[i] = MSK_SK_FIX; } else if( ( tbkc[i] == MSK_BK_LO || tbkc[i] == MSK_BK_RA ) && tblc[i] == txc[i] ) { tskc[i] = MSK_SK_LOW; } else if( ( tbkc[i] == MSK_BK_UP || tbkc[i] == MSK_BK_RA ) && tbuc[i] == txc[i] ) { tskc[i] = MSK_SK_UPR; } else if( tbkc[i] == MSK_BK_FR && txc[i] == 0.0 ) { tskc[i] = MSK_SK_SUPBAS; } else { #if 0 printf("Slack : %d bkc : %d blc : %-16.10e buc : %-16.10e xc : %-16.10e\n", i,tbkc[i],tblc[i],tbuc[i],txc[i]); #endif ++numbas; tskc[i] = MSK_SK_BAS; } } for( int j = 0; j < nc; ++j ) { if( tbkx[j] == MSK_BK_FX && tblx[j] == cs[j] ) { tskx[j] = MSK_SK_FIX; } else if( ( tbkx[j] == MSK_BK_LO || tbkx[j] == MSK_BK_RA ) && tblx[j] == cs[j] ) { tskx[j] = MSK_SK_LOW; } else if( ( tbkx[j] == MSK_BK_UP || tbkx[j] == MSK_BK_RA ) && tbux[j] == cs[j] ) { tskx[j] = MSK_SK_UPR; } else if( ( tbkx[j] == MSK_BK_FR && cs[j] == 0.0 ) || numbas >= nr ) { tskx[j] = MSK_SK_SUPBAS; } else { #if 0 printf("Org %d : bkx : %d blx : %-16.10e bux : %-16.10e xx : %-16.10e\n", j,tbkx[j],tblx[j],tbux[j],cs[j]); #endif tskx[j] = MSK_SK_BAS; } } err = MSK_putsolution(getMutableLpPtr(), MSK_SOL_BAS, tskc, tskx, NULL, (MSKrealt*) txc, const_cast(cs), NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror(err,"MSK_putsolution","setColSol"); MSKassert(3,definedSolution( MSK_SOL_BAS ) == true,"definedSolution( MSK_SOL_BAS ) == true","setColSolution"); delete [] tbkx; delete [] tblx; delete [] tbux; delete [] tskx; delete [] tskc; delete [] txc; delete [] tbkc; delete [] tblc; delete [] tbuc; } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::setColSolution(%p)\n", (void *)cs); #endif } //----------------------------------------------------------------------------- // Sets the rowprices. void OsiMskSolverInterface::setRowPrice(const double * rs) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::setRowPrice(%p)\n", (void *)rs); #endif int err,nr = getNumRows(),nc = getNumCols(); MSKstakeye *tskc,*tskx; MSKrealt *tslc,*tsuc,*tslx,*tsux,*txc,*txx; double *redcost; if( rs == NULL ) freeCachedResults(); else if( nr > 0 ) { if ( rowsol_ == NULL ) rowsol_ = new double[nr]; colsol_ = new double[nc]; tskc = new MSKstakeye[nr]; tslc = new MSKrealt[nr]; tsuc = new MSKrealt[nr]; txc = new MSKrealt[nr]; tskx = new MSKstakeye[nc]; tslx = new MSKrealt[nc]; tsux = new MSKrealt[nc]; txx = new MSKrealt[nc]; redcost = new double[nc]; CoinDisjointCopyN( rs, nr, rowsol_ ); /* Calc reduced costs */ const CoinPackedMatrix *mtx = getMatrixByCol() ; mtx->transposeTimes(rs,redcost) ; for( int j = 0; j < nc; ++j ) { redcost[j] = getObjCoefficients()[j]-redcost[j]; tslx[j] = CoinMax(0.0,redcost[j]); tsux[j] = CoinMax(0.0,-redcost[j]); } if( definedSolution( MSK_SOL_BAS ) == true ) { for( int i = 0; i < nr; ++i ) { #if MSK_VERSION_MAJOR < 9 MSKrealt sn; err = MSK_getsolutioni(getMutableLpPtr(), MSK_ACC_CON, i, MSK_SOL_BAS, &tskc[i], &txc[i], &tslc[i], &tsuc[i], &sn); checkMSKerror(err,"MSK_putsolutioni","setRowPrice"); #else err = MSK_getskcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tskc[i]); checkMSKerror(err,"MSK_getskcslice","setRowPrice"); err = MSK_getxcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &txc[i]); checkMSKerror(err,"MSK_getxcslice","setRowPrice"); err = MSK_getslcslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tslc[i]); checkMSKerror(err,"MSK_getslcslice","setRowPrice"); err = MSK_getsucslice(getMutableLpPtr(), MSK_SOL_BAS, i, i+1, &tsuc[i]); checkMSKerror(err,"MSK_getsucslice","setRowPrice"); #endif tslc[i] = CoinMax(0.0,rowsol_[i]); tsuc[i] = CoinMax(0.0,-rowsol_[i]); } err = MSK_getsolution(getMutableLpPtr(), MSK_SOL_BAS, NULL, NULL, NULL, tskx, NULL, NULL, txx, NULL, NULL, NULL, NULL, NULL, NULL); checkMSKerror(err,"MSK_getsolution","setRowPrice"); err = MSK_putsolution(getMutableLpPtr(), MSK_SOL_BAS, tskc, tskx, NULL, txc, txx, rowsol_, tslc, tsuc, tslx, tsux, NULL); checkMSKerror(err,"MSK_putsolution","setRowPrice"); } else { for( int i = 0; i < nr; ++i ) { tslc[i] = CoinMax(0.0,rowsol_[i]); tsuc[i] = CoinMax(0.0,-rowsol_[i]); tskc[i] = MSK_SK_UNK; } for( int i = 0; i < nc; ++i ) { tskx[i] = MSK_SK_UNK; txx[i] = 0.0; } err = MSK_putsolution(getMutableLpPtr(), MSK_SOL_BAS, tskc, tskx, NULL, NULL, NULL, rowsol_, tslc, tsuc, tslx, tsux, NULL); checkMSKerror(err,"MSK_putsolution","setRowPrice"); } for( int i = 0; i < nc; ++i ) { colsol_[i] = txx[i]; } delete [] tskc; delete [] tslc; delete [] tsuc; delete [] txc; delete [] tskx; delete [] tslx; delete [] tsux; delete [] txx; delete [] redcost; } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::setRowPrice(%p)\n", (void *)rs); #endif } //############################################################################# // Problem modifying methods (matrix) //############################################################################# //----------------------------------------------------------------------------- // Adds a column to the MOSEK task void OsiMskSolverInterface::addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addCol(%p, %g, %g, %g)\n", (void *)&vec, collb, colub, obj); #endif int nc = getNumCols(); MSKassert(3,coltypesize_ >= nc,"coltypesize_ >= nc","addCol"); resizeColType(nc + 1); coltype_[nc] = 'C'; int ends = vec.getNumElements(); MSKboundkeye tag; MSKtask_t task=getLpPtr(); double inf = getInfinity(); if(collb > -inf && colub >= inf) tag = MSK_BK_LO; else if(collb <= -inf && colub < inf) tag = MSK_BK_UP; else if(collb > -inf && colub < inf) tag = MSK_BK_RA; else if(collb <= -inf && colub >= inf) tag = MSK_BK_FR; else throw CoinError("Bound error", "addCol", "OsiMSKSolverInterface"); #if MSK_VERSION_MAJOR >= 7 int err; MSKint32t j; err = MSK_getnumvar(task,&j); if ( err==MSK_RES_OK ) err = MSK_appendvars(task,1); if ( err==MSK_RES_OK ) err = MSK_putcj(task,j,obj); if ( err==MSK_RES_OK ) err = MSK_putacol(task,j,ends,const_cast(vec.getIndices()),const_cast(vec.getElements())); if ( err==MSK_RES_OK ) err = MSK_putvarbound(task,j,tag,collb,colub); #else int start = 0; int err = MSK_appendvars(task, 1, const_cast (&obj), &start, &ends, const_cast(vec.getIndices()), const_cast(vec.getElements()), (&tag), const_cast (&collb), const_cast (&colub)); #endif checkMSKerror( err, "MSK_appendvars", "addCol" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addCol(%p, %g, %g, %g)\n", (void *)&vec, collb, colub, obj); #endif } //----------------------------------------------------------------------------- // Adds a list of columns to the MOSEK task void OsiMskSolverInterface::addCols(const int numcols, const CoinPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, (void *)cols, (void *)collb, (void *)colub, (void *)obj); #endif int i, nz = 0, maxnz, err = MSK_RES_OK; // For efficiency we put hints on the total future size err = MSK_getmaxnumanz(getLpPtr(), &maxnz); checkMSKerror( err, "MSK_getmaxnumanz", "addCols" ); err = MSK_getnumanz(getLpPtr(), &nz); checkMSKerror( err, "MSK_getnumanz", "addCols" ); for( i = 0; i < numcols; ++i) nz += cols[i]->getNumElements(); if( nz > maxnz ) { err = MSK_putmaxnumanz(getLpPtr(), nz); checkMSKerror( err, "MSK_putmaxanz", "addRows" ); } err = MSK_putmaxnumvar(getLpPtr(), numcols+getNumCols()); checkMSKerror( err, "MSK_putmaxnumvar", "addCols" ); for( i = 0; i < numcols; ++i ) addCol( *(cols[i]), collb[i], colub[i], obj[i] ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, (void *)cols, (void *)collb, (void *)colub, (void *)obj); #endif } //----------------------------------------------------------------------------- // Deletes a list of columns from the MOSEK task void OsiMskSolverInterface::deleteCols(const int num, const int * columnIndices) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::deleteCols(%d, %p)\n", num, (void *)columnIndices); #endif #if MSK_VERSION_MAJOR >= 7 int err; err = MSK_removevars(getLpPtr( OsiMskSolverInterface::KEEPCACHED_ROW ), num, const_cast(columnIndices)); checkMSKerror( err, "MSK_removevars", "deleteCols" ); #else int err; err = MSK_remove(getLpPtr( OsiMskSolverInterface::KEEPCACHED_ROW ), MSK_ACC_VAR, num, const_cast(columnIndices)); checkMSKerror( err, "MSK_remove", "deleteCols" ); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::deleteCols(%d, %p)\n", num, (void *)columnIndices); #endif } //----------------------------------------------------------------------------- // Adds a row in bound form to the MOSEK task void OsiMskSolverInterface::addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addRow(%p, %g, %g)\n", (void *)&vec, rowlb, rowub); #endif getNumRows(); int ends = vec.getNumElements(); double inf = getInfinity(); MSKboundkeye tag; MSKtask_t task = getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN ); if(rowlb > -inf && rowub >= inf) tag = MSK_BK_LO; else if(rowlb <= -inf && rowub < inf) tag = MSK_BK_UP; else if(rowlb > -inf && rowub < inf) tag = MSK_BK_RA; else if(rowlb <= -inf && rowub >= inf) tag = MSK_BK_FR; else throw CoinError("Bound error", "addRow", "OsiMSKSolverInterface"); #if MSK_VERSION_MAJOR >= 7 int err; MSKint32t i; err = MSK_getnumcon(task,&i); if ( err==MSK_RES_OK ) err = MSK_appendcons(task,1); if ( err==MSK_RES_OK ) err = MSK_putconbound(task,i,tag,rowlb,rowub); if ( err==MSK_RES_OK ) err = MSK_putarow(task,i,ends, const_cast(vec.getIndices()), const_cast(vec.getElements())); #else int start = 0; int err = MSK_appendcons(task, 1, &start, &ends, const_cast(vec.getIndices()), const_cast(vec.getElements()), (&tag), const_cast (&rowlb), const_cast (&rowub)); #endif checkMSKerror( err, "MSK_appendcons", "addRow" ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addRow(%p, %g, %g)\n", (void *)&vec, rowlb, rowub); #endif } //----------------------------------------------------------------------------- // Adds a row in triplet form to the MOSEK task void OsiMskSolverInterface::addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addRow(%p, %c, %g, %g)\n", (void *)&vec, rowsen, rowrhs, rowrng); #endif int rtag=MSK_BK_FR; double lb=-MSK_INFINITY,ub=MSK_INFINITY; MskConvertSenseToBound( rowsen, rowrng, rowrhs, lb, ub, rtag ); addRow(vec, lb, ub); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addRow(%p, %c, %g, %g)\n", (void *)&vec, rowsen, rowrhs, rowrng); #endif } //----------------------------------------------------------------------------- // Adds a serie of rows in bound form to the MOSEK task void OsiMskSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowlb, (void *)rowub); #endif int i,nz = 0, maxnz, err = MSK_RES_OK; // For efficiency we put hints on the total future size err = MSK_getmaxnumanz(getLpPtr(), &maxnz); checkMSKerror( err, "MSK_getmaxnumanz", "addRows" ); err = MSK_getnumanz( getLpPtr(), &nz); checkMSKerror( err, "MSK_getnumanz", "addRows" ); for( i = 0; i < numrows; ++i) nz += rows[i]->getNumElements(); if( nz > maxnz ) { err = MSK_putmaxnumanz(getLpPtr(), nz); checkMSKerror( err, "MSK_putmaxanz", "addRows" ); } err = MSK_putmaxnumcon(getLpPtr(), numrows+getNumRows()); checkMSKerror( err, "MSK_putmaxnumcon", "addRows" ); for( i = 0; i < numrows; ++i ) addRow( *(rows[i]), rowlb[i], rowub[i] ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowlb, (void *)rowub); #endif } //----------------------------------------------------------------------------- // Adds a list of rows in triplet form to the MOSEK task void OsiMskSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowsen, (void *)rowrhs, (void *)rowrng); #endif int i, err = MSK_RES_OK, nz = 0, maxnz; // For efficiency we put hints on the total future size err = MSK_getmaxnumanz(getLpPtr(), &maxnz); checkMSKerror( err, "MSK_getmaxnumanz", "addRows" ); err = MSK_getnumanz( getLpPtr(), &nz); checkMSKerror( err, "MSK_getnumanz", "addRows" ); for( i = 0; i < numrows; ++i) nz += rows[i]->getNumElements(); if( nz > maxnz ) { err = MSK_putmaxnumanz(getLpPtr(), nz); checkMSKerror( err, "MSK_putmaxanz", "addRows" ); } err = MSK_putmaxnumcon( getLpPtr(), numrows); checkMSKerror( err, "MSK_putmaxnumcon", "addRows" ); for( i = 0; i < numrows; ++i ) addRow( *(rows[i]), rowsen[i], rowrhs[i], rowrng[i] ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, (void *)rows, (void *)rowsen, (void *)rowrhs, (void *)rowrng); #endif } //----------------------------------------------------------------------------- // Deletes a list of rows the MOSEK task void OsiMskSolverInterface::deleteRows(const int num, const int * rowIndices) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::deleteRows(%d, %p)\n", num, (void *)rowIndices); #endif int err; #if MSK_VERSION_MAJOR >= 7 err = MSK_removecons(getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN ), num, const_cast(rowIndices)); checkMSKerror( err, "MSK_removecons", "deleteRows" ); #else err = MSK_remove(getLpPtr( OsiMskSolverInterface::KEEPCACHED_COLUMN ), MSK_ACC_CON, num, const_cast(rowIndices)); checkMSKerror( err, "MSK_remove", "deleteRows" ); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::deleteRows(%d, %p)\n", num, (void *)rowIndices); #endif } //############################################################################# // Methods to input a problem //############################################################################# //----------------------------------------------------------------------------- // Loads a problem. Should have its "own" implementation so we don't have to convert // to triplet, since this is convertet back in the load function called. But // for simplicity, this is not done. void OsiMskSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub ) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p)\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowlb, (void *)rowub); #endif const double inf = getInfinity(); int nrows = matrix.getNumRows(); char * rowSense; double * rowRhs; double * rowRange; if( nrows ) { rowSense = new char [nrows]; rowRhs = new double[nrows]; rowRange = new double[nrows]; } else { rowSense = NULL; rowRhs = NULL; rowRange = NULL; } int i; if( rowlb == NULL && rowub == NULL) for ( i = nrows - 1; i >= 0; --i ) convertBoundToSense( -inf, inf, rowSense[i], rowRhs[i], rowRange[i] ); else if( rowlb == NULL) for ( i = nrows - 1; i >= 0; --i ) convertBoundToSense( -inf, rowub[i], rowSense[i], rowRhs[i], rowRange[i] ); else if( rowub == NULL) for ( i = nrows - 1; i >= 0; --i ) convertBoundToSense( rowlb[i], inf, rowSense[i], rowRhs[i], rowRange[i] ); else for ( i = nrows - 1; i >= 0; --i ) convertBoundToSense( rowlb[i], rowub[i], rowSense[i], rowRhs[i], rowRange[i] ); loadProblem( matrix, collb, colub, obj, rowSense, rowRhs, rowRange ); if( nrows ) { delete [] rowSense; delete [] rowRhs; delete [] rowRange; } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p)\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowlb, (void *)rowub); #endif } //----------------------------------------------------------------------------- // Loads a problem void OsiMskSolverInterface::assignProblem( CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, double*& rowlb, double*& rowub ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::assignProblem()\n"); #endif loadProblem( *matrix, collb, colub, obj, rowlb, rowub ); delete matrix; matrix = 0; delete[] collb; collb = 0; delete[] colub; colub = 0; delete[] obj; obj = 0; delete[] rowlb; rowlb = 0; delete[] rowub; rowub = 0; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::assignProblem()\n"); #endif } //----------------------------------------------------------------------------- // Loads a problem void OsiMskSolverInterface::loadProblem( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng ) { int nc=matrix.getNumCols(); int nr=matrix.getNumRows(); #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p, %p) numcols : %d numrows : %d\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng,nc,nr); #endif if( nr == 0 && nc == 0 ) gutsOfDestructor(); else { /* Warning input pointers can be NULL */ int i,j; double * ob; int * rtag = NULL; double * rlb = NULL; double * rub = NULL; int * ctag = NULL; int * cends = NULL; const int *len; const int *start; double * clb = NULL; double * cub = NULL; if( obj != NULL ) ob=const_cast(obj); else { ob = new double[nc]; CoinFillN(ob, nc, 0.0); } if( nr ) { rtag = new int[nr]; rlb = new double[nr]; rub = new double[nr]; } if( rowsen && rowrng && rowrhs ) { for( i=0; i < nr; i++ ) MskConvertSenseToBound( rowsen[i], rowrng[i], rowrhs[i], rlb[i], rub[i], rtag[i]); } else { for( i=0; i < nr; i++ ) { rlb[i] = 0.0; rub[i] = MSK_INFINITY; rtag[i] = MSK_BK_LO; } } bool freeMatrixRequired = false; CoinPackedMatrix * m = NULL; if( !matrix.isColOrdered() ) { m = new CoinPackedMatrix(); m->reverseOrderedCopyOf(matrix); freeMatrixRequired = true; } else m = const_cast(&matrix); MSKassert(3,nc == m->getNumCols(),"nc == m->getNumCols()","loadProblem"); MSKassert(3,nr == m->getNumRows(),"nr == m->getNumRows()","loadProblem"); MSKassert(3,m->isColOrdered(),"m->isColOrdered()","loadProblem"); double inf =getInfinity(); if( nc ) { ctag = new int[nc]; cends = new int[nc]; clb = new double[nc]; cub = new double[nc]; } len = (m->getVectorLengths()); start = (m->getVectorStarts()); if( collb == NULL && colub == NULL ) { for(j=0; j < nc; j++) { cends[j] = start[j] + len[j]; MskConvertColBoundToTag(0, inf, clb[j], cub[j], ctag[j]); } } else if( collb == NULL ) { for(j=0; j < nc; j++) { cends[j] = start[j] + len[j]; MskConvertColBoundToTag( 0, colub[j], clb[j], cub[j], ctag[j]); } } else if( colub == NULL ) { for(j=0; j < nc; j++) { cends[j] = start[j] + len[j]; MskConvertColBoundToTag(collb[j], inf, clb[j], cub[j], ctag[j]); } } else { for(j=0; j < nc; j++) { cends[j] = start[j] + len[j]; MskConvertColBoundToTag( collb[j], colub[j], clb[j], cub[j], ctag[j]); } } int err=MSK_inputdata(getLpPtr( OsiMskSolverInterface::KEEPCACHED_NONE ), nr, nc, nr, nc, ob, 0.0, const_cast(m->getVectorStarts()), cends, const_cast(m->getIndices()), const_cast(m->getElements()), (MSKboundkeye*)rtag, rlb, rub, (MSKboundkeye*)ctag, clb, cub); checkMSKerror( err, "MSK_inputdata", "loadProblem" ); if( obj == NULL ) delete[] ob; if( nr ) { delete[] rtag; delete[] rlb; delete[] rub; } if( nc ) { delete[] ctag; delete[] clb; delete[] cub; delete[] cends; } if ( freeMatrixRequired ) delete m; resizeColType(nc); CoinFillN(coltype_, nc, 'C'); } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p, %p)\n", (void *)&matrix, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng); #endif } //----------------------------------------------------------------------------- // Assigns a problem void OsiMskSolverInterface::assignProblem( CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::assignProblem()\n"); #endif loadProblem( *matrix, collb, colub, obj, rowsen, rowrhs, rowrng ); delete matrix; matrix = 0; delete[] collb; collb = 0; delete[] colub; colub = 0; delete[] obj; obj = 0; delete[] rowsen; rowsen = 0; delete[] rowrhs; rowrhs = 0; delete[] rowrng; rowrng = 0; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::assignProblem()\n"); #endif } //----------------------------------------------------------------------------- // Loads a problem void OsiMskSolverInterface::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 ) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::loadProblem() numcols : %d numrows : %d\n",numcols,numrows); #endif const double inf = getInfinity(); char * rowSense = new char [numrows]; double * rowRhs = new double[numrows]; double * rowRange = new double[numrows]; for ( int i = numrows - 1; i >= 0; --i ) { const double lower = rowlb ? rowlb[i] : -inf; const double upper = rowub ? rowub[i] : inf; convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] ); } loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowSense, rowRhs, rowRange); delete [] rowSense; delete [] rowRhs; delete [] rowRange; #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::loadProblem()\n"); #endif } //----------------------------------------------------------------------------- // Loads a problem void OsiMskSolverInterface::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 ) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::loadProblem(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n", numcols, numrows, (void *)start, (void *)index, (void *)value, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen,(void *)rowrhs, (void *)rowrng); #endif const int nc = numcols; const int nr = numrows; if( nr == 0 && nc == 0 ) gutsOfDestructor(); else { MSKassert(3,rowsen != NULL,"rowsen != NULL","loadProblem"); MSKassert(3,rowrhs != NULL,"rowrhs != NULL","loadProblem"); int i,j; double * ob; int * rtag =NULL; double * rlb = NULL; double * rub = NULL; int * ctag =NULL; int * cends = NULL; double * clb = NULL; double * cub = NULL; if( obj != NULL ) ob=const_cast(obj); else { ob = new double[nc]; CoinFillN(ob, nc, 0.0); } if( nr ) { rtag = new int[nr]; rlb = new double[nr]; rub = new double[nr]; } for( i=0; i < nr; i++ ) MskConvertSenseToBound( rowsen[i], rowrng != NULL ? rowrng[i] : 0.0, rowrhs[i], rlb[i], rub[i], rtag[i]); double inf = getInfinity(); if( nc ) { ctag = new int[nc]; cends = new int[nc]; clb = new double[nc]; cub = new double[nc]; } if( collb == NULL && colub == NULL ) for(j=0; j < nc; j++) { cends[j] = start[j+1]; MskConvertColBoundToTag(0, inf, clb[j], cub[j], ctag[j]); } else if( collb == NULL ) for(j=0; j < nc; j++) { cends[j] = start[j+1]; MskConvertColBoundToTag( 0, colub[j], clb[j], cub[j], ctag[j]); } else if( colub == NULL ) for(j=0; j < nc; j++) { cends[j] = start[j+1]; MskConvertColBoundToTag(collb[j], inf, clb[j], cub[j], ctag[j]); } else for(j=0; j < nc; j++) { cends[j] = start[j+1]; MskConvertColBoundToTag( collb[j], colub[j], clb[j], cub[j], ctag[j]); } int err=MSK_inputdata(getLpPtr( OsiMskSolverInterface::KEEPCACHED_NONE ), nr, nc, nr, nc, ob, 0.0, const_cast(start), cends, const_cast(index), const_cast(value), (MSKboundkeye*)rtag, rlb, rub, (MSKboundkeye*)ctag, clb, cub); checkMSKerror( err, "MSK_inputdata", "loadProblem3" ); if( obj == NULL ) delete[] ob; if( nr ) { delete[] rtag; delete[] rlb; delete[] rub; } if( nc ) { delete[] ctag; delete[] cends; delete[] clb; delete[] cub; } resizeColType(nc); CoinFillN(coltype_, nc, 'C'); } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::loadProblem(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n", numcols, numrows, (void *)start, (void *)index, (void *)value, (void *)collb, (void *)colub, (void *)obj, (void *)rowsen, (void *)rowrhs, (void *)rowrng); #endif } //----------------------------------------------------------------------------- // Reads a MPS file with Coin native MPS reader. If marked code is switch on // then MOSEK file reader is used, and .gz files can be read aswell. int OsiMskSolverInterface::readMps(const char * filename, const char * extension ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::readMps(%s, %s) %p\n", filename, extension,(void*)this); debugMessage("End OsiMskSolverInterface::readMps(%s, %s)\n", filename, extension); #endif return OsiSolverInterface::readMps(filename,extension); } //----------------------------------------------------------------------------- // Writes the problem in MPS format, uses MOSEK writer. void OsiMskSolverInterface::writeMps( const char * filename, const char * extension, double objSense ) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense); #endif std::string f(filename); std::string e(extension); std::string fullname = f + "." + e; OsiSolverInterface::writeMpsNative(fullname.c_str(),NULL, NULL, 0, 2, objSense); #if 0 int err = MSK_writedata( getMutableLpPtr(), const_cast( fullname.c_str() )); checkMSKerror( err, "MSK_writedatafile", "writeMps" ); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense); #endif } void OsiMskSolverInterface::passInMessageHandler(CoinMessageHandler * handler) { OsiSolverInterface::passInMessageHandler(handler); MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog); MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncWarning); MSK_linkfunctotaskstream(getMutableLpPtr(), MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncError); } //############################################################################# // MSK specific public interfaces //############################################################################# //----------------------------------------------------------------------------- // Returns MOSEK task in the interface object MSKenv_t OsiMskSolverInterface::getEnvironmentPtr() { MSKassert(3,env_ != NULL,"probtypemip_","getEnvironmentPtr"); return env_; } //----------------------------------------------------------------------------- // Returns MOSEK task in the interface object MSKtask_t OsiMskSolverInterface::getLpPtr( int keepCached ) { freeCachedData( keepCached ); return getMutableLpPtr(); } //----------------------------------------------------------------------------- // Returns the coltype_ array const char * OsiMskSolverInterface::getCtype() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getCtype()\n"); debugMessage("End OsiMskSolverInterface::getCtype()\n"); #endif return coltype_; } //############################################################################# // Static instance counter methods //############################################################################# //----------------------------------------------------------------------------- // Increment the instance count, so we know when to close and open MOSEK. void OsiMskSolverInterface::incrementInstanceCounter() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::incrementInstanceCounter()\n"); #endif if ( numInstances_ == 0 ) { int err=0; #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("creating new Mosek environment\n"); #endif #if MSK_VERSION_MAJOR >= 7 err = MSK_makeenv(&env_,NULL); #else err = MSK_makeenv(&env_,NULL,NULL,NULL,NULL); #endif checkMSKerror( err, "MSK_makeenv", "incrementInstanceCounter" ); err = MSK_linkfunctoenvstream(env_, MSK_STREAM_LOG, NULL, printlog); checkMSKerror( err, "MSK_linkfunctoenvstream", "incrementInstanceCounter" ); #if MSK_VERSION_MAJOR < 8 err = MSK_initenv(env_); checkMSKerror( err, "MSK_initenv", "incrementInstanceCounter" ); #endif } numInstances_++; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::incrementInstanceCounter()\n"); #endif } //----------------------------------------------------------------------------- // Decrement the instance count, so we know when to close and open MOSEK. void OsiMskSolverInterface::decrementInstanceCounter() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::decrementInstanceCounter()\n"); #endif MSKassert(3,numInstances_ != 0,"numInstances_ != 0","decrementInstanceCounter"); numInstances_--; if ( numInstances_ == 0 ) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("deleting Mosek environment\n"); #endif int err = MSK_deleteenv(&env_); checkMSKerror( err, "MSK_deleteenv", "decrementInstanceCounter" ); env_ = NULL; } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::decrementInstanceCounter()\n"); #endif } //----------------------------------------------------------------------------- // Returns the number of OsiMskSolverInterface objects in play unsigned int OsiMskSolverInterface::getNumInstances() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getNumInstances()\n"); debugMessage("End OsiMskSolverInterface::getNumInstances()\n"); #endif return numInstances_; } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //----------------------------------------------------------------------------- // Constructor OsiMskSolverInterface::OsiMskSolverInterface(MSKenv_t mskenv) : OsiSolverInterface(), Mskerr(MSK_RES_OK), ObjOffset_(0.0), InitialSolver(INITIAL_SOLVE), task_(NULL), hotStartCStat_(NULL), hotStartCStatSize_(0), hotStartRStat_(NULL), hotStartRStatSize_(0), hotStartMaxIteration_(1000000), obj_(NULL), collower_(NULL), colupper_(NULL), rowsense_(NULL), rhs_(NULL), rowrange_(NULL), rowlower_(NULL), rowupper_(NULL), colsol_(NULL), rowsol_(NULL), redcost_(NULL), rowact_(NULL), matrixByRow_(NULL), matrixByCol_(NULL), coltype_(NULL), coltypesize_(0), probtypemip_(false) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::OsiMskSolverinterface()\n"); #endif if (mskenv) { if (env_) { throw CoinError("Already have a global Mosek environment. Cannot use second one.", "OsiMskSolverInterface", "OsiMskSolverInterface"); } env_ = mskenv; ++numInstances_; } else incrementInstanceCounter(); gutsOfConstructor(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::OsiMskSolverinterface()\n"); #endif } //----------------------------------------------------------------------------- // Clone from one to another object OsiSolverInterface * OsiMskSolverInterface::clone(bool copyData) const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::clone(%d)\n", copyData); debugMessage("End OsiMskSolverInterface::clone(%d)\n", copyData); #endif return( new OsiMskSolverInterface( *this ) ); } //----------------------------------------------------------------------------- // Copy constructor OsiMskSolverInterface::OsiMskSolverInterface( const OsiMskSolverInterface & source ) : OsiSolverInterface(source), Mskerr(MSK_RES_OK), MSKsolverused_(INITIAL_SOLVE), ObjOffset_(source.ObjOffset_), InitialSolver(INITIAL_SOLVE), task_(NULL), hotStartCStat_(NULL), hotStartCStatSize_(0), hotStartRStat_(NULL), hotStartRStatSize_(0), hotStartMaxIteration_(source.hotStartMaxIteration_), obj_(NULL), collower_(NULL), colupper_(NULL), rowsense_(NULL), rhs_(NULL), rowrange_(NULL), rowlower_(NULL), rowupper_(NULL), colsol_(NULL), rowsol_(NULL), redcost_(NULL), rowact_(NULL), matrixByRow_(NULL), matrixByCol_(NULL), coltype_(NULL), coltypesize_(0), probtypemip_(false) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::OsiMskSolverInterface from (%p) to %p\n", (void *)&source,(void*)this); #endif incrementInstanceCounter(); gutsOfConstructor(); gutsOfCopy( source ); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::OsiMskSolverInterface(%p)\n", (void *)&source); #endif } //----------------------------------------------------------------------------- // Destructor OsiMskSolverInterface::~OsiMskSolverInterface() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::~OsiMskSolverInterface()\n"); #endif gutsOfDestructor(); decrementInstanceCounter(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::~OsiMskSolverInterface()\n"); #endif } //----------------------------------------------------------------------------- // Assign operator OsiMskSolverInterface& OsiMskSolverInterface::operator=( const OsiMskSolverInterface& rhs ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::operator=(%p)\n", (void *)&rhs); #endif if (this != &rhs) { OsiSolverInterface::operator=( rhs ); gutsOfDestructor(); gutsOfConstructor(); if ( rhs.task_ !=NULL ) gutsOfCopy( rhs ); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::operator=(%p)\n", (void *)&rhs); #endif return *this; } //############################################################################# // Applying cuts //############################################################################# //----------------------------------------------------------------------------- // Apply col cut void OsiMskSolverInterface::applyColCut( const OsiColCut & cc ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::applyColCut(%p)\n", (void *)&cc); #endif double * MskColLB = new double[getNumCols()]; double * MskColUB = new double[getNumCols()]; const CoinPackedVector & lbs = cc.lbs(); const CoinPackedVector & ubs = cc.ubs(); int i; for( i = 0; i < getNumCols(); ++i ) { MskColLB[i] = getColLower()[i]; MskColUB[i] = getColUpper()[i]; } for( i = 0; i < lbs.getNumElements(); ++i ) if ( lbs.getElements()[i] > MskColLB[lbs.getIndices()[i]] ) setColLower( lbs.getIndices()[i], lbs.getElements()[i] ); for( i = 0; i < ubs.getNumElements(); ++i ) if ( ubs.getElements()[i] < MskColUB[ubs.getIndices()[i]] ) setColUpper( ubs.getIndices()[i], ubs.getElements()[i] ); delete[] MskColLB; delete[] MskColUB; #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::applyColCut(%p)\n", (void *)&cc); #endif } //----------------------------------------------------------------------------- // Apply row cut void OsiMskSolverInterface::applyRowCut( const OsiRowCut & rowCut ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::applyRowCut(%p)\n", (void *)&rowCut); #endif const CoinPackedVector & row=rowCut.row(); addRow(row , rowCut.lb(),rowCut.ub()); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::applyRowCut(%p)\n", (void *)&rowCut); #endif } //############################################################################# // Private methods (non-static and static) and static data //############################################################################# unsigned int OsiMskSolverInterface::numInstances_ = 0; MSKenv_t OsiMskSolverInterface::env_=NULL; //----------------------------------------------------------------------------- // Returns MOSEK task in object MSKtask_t OsiMskSolverInterface::getMutableLpPtr() const { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::getMutableLpPtr()\n"); #endif if ( task_ == NULL ) { MSKassert(3,env_ != NULL,"env_ == NULL","getMutableLpPtr"); int err = MSK_makeemptytask(env_,&task_); checkMSKerror(err, "MSK_makeemptytask","getMutableLpPtr"); err = MSK_linkfunctotaskstream(task_, MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog); checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" ); err = MSK_linkfunctotaskstream(task_, MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncWarning); checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" ); err = MSK_linkfunctotaskstream(task_, MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncError); checkMSKerror( err, "MSK_linkfunctotaskstream", "getMutableLpPtr" ); err = MSK_putintparam(task_, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); err = MSK_putintparam(task_, MSK_IPAR_PRESOLVE_USE, MSK_ON); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); #if MSK_VERSION_MAJOR < 9 err = MSK_putintparam(task_, MSK_IPAR_WRITE_DATA_FORMAT, MSK_DATA_FORMAT_MPS); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); #endif err = MSK_putintparam(task_, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); #if MSK_DO_MOSEK_LOG > 0 char file[] = "MOSEK.log"; err = MSK_linkfiletotaskstream(task_, MSK_STREAM_LOG, file, 0); checkMSKerror( err, "MSK_linkfiletotaskstream", "getMutableLpPtr" ); err = MSK_putintparam(task_, MSK_IPAR_LOG, 100); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); err = MSK_putintparam(task_, MSK_IPAR_LOG_SIM, 100); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); err = MSK_putintparam(task_, MSK_IPAR_LOG_INTPNT, 100); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); #else err = MSK_putintparam(task_, MSK_IPAR_LOG, 100); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); #endif err = MSK_putintparam(task_,MSK_IPAR_SIM_SOLVE_FORM,MSK_SOLVE_PRIMAL); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); err = MSK_putintparam(task_,MSK_IPAR_SIM_HOTSTART,MSK_SIM_HOTSTART_STATUS_KEYS); checkMSKerror(err,"MSK_putintparam","getMutableLpPtr()"); std::string pn; getStrParam(OsiProbName,pn); MSK_puttaskname( task_, const_cast(pn.c_str()) ); checkMSKerror(err,"MSK_puttaskname","getMutableLpPtr()"); } #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::getMutableLpPtr()\n"); #endif return task_; } //----------------------------------------------------------------------------- // Makes a copy void OsiMskSolverInterface::gutsOfCopy( const OsiMskSolverInterface & source ) { #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("Begin OsiMskSolverInterface::gutsOfCopy()\n"); #endif int err; InitialSolver = source.InitialSolver; MSKassert(3, task_ == NULL, "task_ == NULL", "gutsOfCopy"); err = MSK_clonetask(source.getMutableLpPtr(),&task_); checkMSKerror( err, "MSK_clonetask", "gutsOfCopy" ); // reinitialize output streams to use message handler of copy, also not sure that MSK_clonetask copied these over MSK_linkfunctotaskstream(task_, MSK_STREAM_LOG, messageHandler(), OsiMskStreamFuncLog); MSK_linkfunctotaskstream(task_, MSK_STREAM_ERR, messageHandler(), OsiMskStreamFuncWarning); MSK_linkfunctotaskstream(task_, MSK_STREAM_WRN, messageHandler(), OsiMskStreamFuncError); // Set MIP information resizeColType(source.coltypesize_); CoinDisjointCopyN( source.coltype_, source.coltypesize_, coltype_ ); // Updates task MIP information for( int k = 0; k < source.coltypesize_; ++k ) { switch(coltype_[k]) { case 'I': setInteger(k); break; case 'C': setContinuous(k); break; } } #if MSK_OSI_DEBUG_LEVEL > 1 debugMessage("End OsiMskSolverInterface::gutsOfCopy()\n"); #endif } //----------------------------------------------------------------------------- // Empty function void OsiMskSolverInterface::gutsOfConstructor() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::gutsOfConstructor()\n"); #endif #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::gutsOfConstructor()\n"); #endif } //----------------------------------------------------------------------------- // Function called from destructor void OsiMskSolverInterface::gutsOfDestructor() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::gutsOfDestructor()\n"); #endif freeCachedData(KEEPCACHED_NONE); if ( task_ != NULL ) { MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_LOG); MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_ERR); MSK_unlinkfuncfromtaskstream(getMutableLpPtr(), MSK_STREAM_WRN); int err = MSK_deletetask(&task_); checkMSKerror( err, "MSK_deletetask", "gutsOfDestructor" ); task_ = NULL; freeAllMemory(); } MSKassert(3,task_==NULL,"task_==NULL","gutsOfDestructor"); MSKassert(3,obj_==NULL,"obj_==NULL","gutsOfDestructor"); MSKassert(3,collower_==NULL,"collower_==NULL","gutsOfDestructor"); MSKassert(3,colupper_==NULL,"colupper_==NULL","gutsOfDestructor"); MSKassert(3,rowsense_==NULL,"rowsense_==NULL","gutsOfDestructor"); MSKassert(3,rhs_==NULL,"rhs_==NULL","gutsOfDestructor"); MSKassert(3,rowrange_==NULL,"rowrange_==NULL","gutsOfDestructor"); MSKassert(3,rowlower_==NULL,"rowlower_==NULL","gutsOfDestructor"); MSKassert(3,rowupper_==NULL,"rowupper_==NULL","gutsOfDestructor"); MSKassert(3,colsol_==NULL,"colsol_==NULL","gutsOfDestructor"); MSKassert(3,rowsol_==NULL,"rowsol_==NULL","gutsOfDestructor"); MSKassert(3,redcost_==NULL,"redcost_==NULL","gutsOfDestructor"); MSKassert(3,rowact_==NULL,"rowact_==NULL","gutsOfDestructor"); MSKassert(3,matrixByRow_==NULL,"probtypemip_","gutsOfDestructor"); MSKassert(3,matrixByCol_==NULL,"matrixByCol_==NULL","gutsOfDestructor"); MSKassert(3,coltype_==NULL,"coltype_==NULL","gutsOfDestructor"); MSKassert(3,coltypesize_==0,"coltypesize_==0","gutsOfDestructor"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::gutsOfDestructor()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeCachedColRim() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedColRim()\n"); #endif freeCacheDouble( obj_ ); freeCacheDouble( collower_ ); freeCacheDouble( colupper_ ); MSKassert(3,obj_==NULL,"obj_==NULL","freeCachedColRim"); MSKassert(3,collower_==NULL,"collower_==NULL","freeCachedColRim"); MSKassert(3,colupper_==NULL,"colupper_==NULL","freeCachedColRim"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedColRim()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeCachedRowRim() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedRowRim()\n"); #endif freeCacheChar( rowsense_ ); freeCacheDouble( rhs_ ); freeCacheDouble( rowrange_ ); freeCacheDouble( rowlower_ ); freeCacheDouble( rowupper_ ); MSKassert(3,rowsense_==NULL,"rowsense_==NULL","freeCachedRowRim"); MSKassert(3,rhs_==NULL,"rhs_==NULL","freeCachedRowRim"); MSKassert(3,rowrange_==NULL,"rowrange_==NULL","freeCachedRowRim"); MSKassert(3,rowlower_==NULL,"rowlower_==NULL","freeCachedRowRim"); MSKassert(3,rowupper_==NULL,"rowupper_==NULL","freeCachedRowRim"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedRowRim()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeCachedMatrix() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedMatrix()\n"); #endif freeCacheMatrix( matrixByRow_ ); freeCacheMatrix( matrixByCol_ ); MSKassert(3,matrixByRow_==NULL,"matrixByRow_==NULL","freeCachedMatrix"); MSKassert(3,matrixByCol_==NULL,"matrixByCol_==NULL","freeCachedMatrix"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedMatrix()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeCachedResults() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n"); #endif freeCacheDouble( colsol_ ); freeCacheDouble( rowsol_ ); freeCacheDouble( redcost_ ); freeCacheDouble( rowact_ ); MSKassert(3,colsol_==NULL,"colsol_==NULL","freeCachedResults"); MSKassert(3,rowsol_==NULL,"rowsol_==NULL","freeCachedResults"); MSKassert(3,redcost_==NULL,"redcost_==NULL","freeCachedResults"); MSKassert(3,rowact_==NULL,"rowact_==NULL","freeCachedResults"); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedResults()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeCachedData( int keepCached ) { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n"); #endif if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_COLUMN) ) freeCachedColRim(); if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_ROW) ) freeCachedRowRim(); if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_MATRIX) ) freeCachedMatrix(); if( !(keepCached & OsiMskSolverInterface::KEEPCACHED_RESULTS) ) freeCachedResults(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedResults()\n"); #endif } //----------------------------------------------------------------------------- // Free function void OsiMskSolverInterface::freeAllMemory() { #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("Begin OsiMskSolverInterface::freeCachedResults()\n"); #endif freeCachedData(); if( hotStartCStat_ != NULL ) delete[] hotStartCStat_; if( hotStartRStat_ != NULL ) delete[] hotStartRStat_; hotStartCStat_ = NULL; hotStartCStatSize_ = 0; hotStartRStat_ = NULL; hotStartRStatSize_ = 0; freeColType(); #if MSK_OSI_DEBUG_LEVEL > 3 debugMessage("End OsiMskSolverInterface::freeCachedResults()\n"); #endif }