00001
00019 #include "OSCoinSolver.h"
00020 #include "OSInstance.h"
00021 #include "OSFileUtil.h"
00022 #include "OSOutput.h"
00023 #include "CoinTime.hpp"
00024 #include "CglPreProcess.hpp"
00025 #include "CglGomory.hpp"
00026 #include "CglSimpleRounding.hpp"
00027 #include "CglMixedIntegerRounding2.hpp"
00028 #include "CglKnapsackCover.hpp"
00029 #include "CglFlowCover.hpp"
00030 #include "CbcBranchActual.hpp"
00031 #include "CoinMessageHandler.hpp"
00032 #include "CoinMessage.hpp"
00033
00034 #include "OsiClpSolverInterface.hpp"
00035 #include "CoinWarmStartBasis.hpp"
00036
00037 #ifdef COIN_HAS_SYMPHONY
00038 #include "OsiSymSolverInterface.hpp"
00039 #endif
00040
00041 #ifdef COIN_HAS_VOL
00042 #include "OsiVolSolverInterface.hpp"
00043 #endif
00044
00045 #ifdef COIN_HAS_DYLP
00046 #include "OsiDylpSolverInterface.hpp"
00047 #endif
00048
00049 #ifdef COIN_HAS_GLPK
00050 #include "OsiGlpkSolverInterface.hpp"
00051 #endif
00052
00053 #ifdef COIN_HAS_CPX
00054 #include "OsiCpxSolverInterface.hpp"
00055 #endif
00056
00057 #ifdef COIN_HAS_GRB
00058 #include "OsiGrbSolverInterface.hpp"
00059 #endif
00060
00061 #ifdef COIN_HAS_MSK
00062 #include "OsiMskSolverInterface.hpp"
00063 #endif
00064
00065 #ifdef COIN_HAS_SOPLEX
00066 #include "OsiSpxSolverInterface.hpp"
00067 #endif
00068
00069 #ifdef COIN_HAS_XPR
00070 #include "OsiXprSolverInterface.hpp"
00071 #endif
00072
00073 #include "OSGeneral.h"
00074 #include "OSParameters.h"
00075 #include "OSMathUtil.h"
00076
00077 #include <map>
00078
00079 #include <iostream>
00080 #ifdef HAVE_CTIME
00081 # include <ctime>
00082 #else
00083 # ifdef HAVE_TIME_H
00084 # include <time.h>
00085 # else
00086 # error "don't have header file for time"
00087 # endif
00088 #endif
00089
00090 using std::cout;
00091 using std::endl;
00092 using std::ostringstream;
00093
00094
00095
00096 CoinSolver::CoinSolver() :
00097 osiSolver(NULL),
00098 m_osilreader(NULL),
00099 m_osolreader(NULL),
00100 m_CoinPackedMatrix(NULL),
00101 cbc_argv( NULL),
00102 num_cbc_argv( 0),
00103 cpuTime( 0)
00104 {
00105 osrlwriter = new OSrLWriter();
00106 }
00107
00108 CoinSolver::~CoinSolver()
00109 {
00110 #ifndef NDEBUG
00111 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00112 ENUM_OUTPUT_LEVEL_debug, "inside CoinSolver destructor\n");
00113 #endif
00114 if(m_osilreader != NULL) delete m_osilreader;
00115 m_osilreader = NULL;
00116 if(m_osolreader != NULL) delete m_osolreader;
00117 m_osolreader = NULL;
00118 delete m_CoinPackedMatrix;
00119 m_CoinPackedMatrix = NULL;
00120 delete osiSolver;
00121 if(osiSolver != NULL) osiSolver = NULL;
00122 delete osrlwriter;
00123 osrlwriter = NULL;
00124 delete osresult;
00125 osresult = NULL;
00126 if(num_cbc_argv > 0)
00127 {
00128
00129
00130
00131
00132
00133
00134
00135
00136 cbc_argv = NULL;
00137 }
00138 #ifndef NDEBUG
00139 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00140 ENUM_OUTPUT_LEVEL_trace, "Leaving CoinSolver destructor\n");
00141 #endif
00142 }
00143
00144
00145 void CoinSolver::buildSolverInstance() throw (ErrorClass)
00146 {
00147 std::ostringstream outStr;
00148 try
00149 {
00150 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00151 clock_t start, finish;
00152 double duration;
00153 start = clock();
00154 if(osinstance == NULL)
00155 {
00156 m_osilreader = new OSiLReader();
00157 osinstance = m_osilreader->readOSiL( osil);
00158 }
00159 finish = clock();
00160 duration = (double) (finish - start) / CLOCKS_PER_SEC;
00161
00162
00163 if (osinstance->getObjectiveNumber() > 1)
00164 throw ErrorClass("Solver cannot handle multiple objectives --- please delete all but one");
00165
00166
00167 if (sSolverName == "clp")
00168 osiSolver = new OsiClpSolverInterface();
00169
00170 else if (sSolverName == "cbc")
00171 osiSolver = new OsiClpSolverInterface();
00172
00173 else if (sSolverName == "vol")
00174 #ifdef COIN_HAS_VOL
00175 osiSolver = new OsiVolSolverInterface();
00176 #else
00177 throw ErrorClass("This OSSolverService was built without solver vol");
00178 #endif
00179
00180 else if (sSolverName == "cplex")
00181 #ifdef COIN_HAS_CPX
00182 osiSolver = new OsiCpxSolverInterface();
00183 #else
00184 throw ErrorClass("This OSSolverService was built without solver cplex");
00185 #endif
00186
00187 else if (sSolverName == "gurobi")
00188 #ifdef COIN_HAS_GRB
00189 osiSolver = new OsiGrbSolverInterface();
00190 #else
00191 throw ErrorClass("This OSSolverService was built without solver gurobi");
00192 #endif
00193
00194 else if (sSolverName == "mosek")
00195 #ifdef COIN_HAS_MSK
00196 osiSolver = new OsiMskSolverInterface();
00197 #else
00198 throw ErrorClass("This OSSolverService was built without solver mosek");
00199 #endif
00200
00201 else if (sSolverName == "soplex")
00202 #ifdef COIN_HAS_SOPLEX
00203 osiSolver = new OsiSpxSolverInterface();
00204 #else
00205 throw ErrorClass("This OSSolverService was built without solver soplex");
00206 #endif
00207
00208 else if (sSolverName == "xpress")
00209 #ifdef COIN_HAS_XPR
00210 osiSolver = new OsiXprSolverInterface();
00211 #else
00212 throw ErrorClass("This OSSolverService was built without solver xpress");
00213 #endif
00214
00215 else if (sSolverName == "glpk")
00216 #ifdef COIN_HAS_GLPK
00217 osiSolver = new OsiGlpkSolverInterface();
00218 #else
00219 throw ErrorClass("This OSSolverService was built without solver glpk");
00220 #endif
00221
00222 else if (sSolverName == "dylp")
00223 #ifdef COIN_HAS_DYLP
00224 osiSolver = new OsiDylpSolverInterface();
00225 #else
00226 throw ErrorClass("This OSSolverService was built without solver dylp");
00227 #endif
00228
00229 else if (sSolverName == "symphony")
00230 #ifdef COIN_HAS_SYMPHONY
00231 osiSolver = new OsiSymSolverInterface();
00232 #else
00233 throw ErrorClass("This OSSolverService was built without solver symphony");
00234 #endif
00235
00236 else if (sSolverName == "")
00237 {
00238
00239 if( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0 ||
00240 sSolverName.find( "cbc") != std::string::npos ) sSolverName = "cbc";
00241 else sSolverName = "clp";
00242 osiSolver = new OsiClpSolverInterface();
00243 }
00244 else
00245 throw ErrorClass("Solver selected is not supported by this version of OSSolverService");
00246
00247
00248 if ( (osinstance->getNumberOfNonlinearExpressions() > 0) )
00249 {
00250 throw ErrorClass( "This COIN-OR Solver is not configured for nonlinear programming");
00251 }
00252 if ((osinstance->getNumberOfQuadraticTerms() > 0) &&
00253 (sSolverName.find( "cbc") == std::string::npos) &&
00254 (sSolverName.find( "clp") == std::string::npos))
00255 {
00256 throw ErrorClass( "This COIN-OR Solver is not configured for quadratic programming");
00257 }
00258
00259 if( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
00260 {
00261 if( sSolverName.find("clp") != std::string::npos)
00262 throw ErrorClass( "Clp cannot do integer programming");
00263 if( sSolverName.find("vol") != std::string::npos)
00264 throw ErrorClass( "Vol cannot do integer programming");
00265 if( sSolverName.find("dylp") != std::string::npos)
00266 throw ErrorClass( "DyLP cannot do integer programming");
00267 if( sSolverName.find("soplex") != std::string::npos)
00268 throw ErrorClass( "SoPlex cannot do integer programming");
00269 }
00270
00271 if( osinstance->getNumberOfSemiIntegerVariables() + osinstance->getNumberOfSemiContinuousVariables() > 0)
00272 {
00273 throw ErrorClass( "Semi-integer and semi-continuous variables not supported");
00274
00275
00276
00277
00278 }
00279
00280
00281
00282 if(osinstance->getObjectiveNumber() <= 0)
00283 throw ErrorClass("Coin solver: " + sSolverName + " needs an objective function");
00284 if(osinstance->getNumberOfStringVariables() > 0)
00285 throw ErrorClass("Coin solver: " + sSolverName + " can only handle numeric variables");
00286 if(osinstance->getLinearConstraintCoefficientNumber() <= 0 && sSolverName == "symphony")
00287 throw ErrorClass("Coin solver: " + sSolverName + " needs a positive number of constraints");
00288
00289 if(!setCoinPackedMatrix() ) throw ErrorClass("Problem generating coin packed matrix");
00290 osiSolver->loadProblem(*m_CoinPackedMatrix, osinstance->getVariableLowerBounds(),
00291 osinstance->getVariableUpperBounds(),
00292 osinstance->getDenseObjectiveCoefficients()[0],
00293 osinstance->getConstraintLowerBounds(),
00294 osinstance->getConstraintUpperBounds()
00295 );
00296 #ifndef NDEBUG
00297
00298 #endif
00299 if( osinstance->getObjectiveMaxOrMins()[0] == "min") osiSolver->setObjSense(1.0);
00300 else osiSolver->setObjSense(-1.0);
00301
00302 int numOfIntVars
00303 = osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables();
00304 if (numOfIntVars > 0)
00305 {
00306 int *intIndex = NULL;
00307 int i = 0;
00308 int k = 0;
00309 char *varType;
00310 intIndex = new int[ numOfIntVars];
00311 varType = osinstance->getVariableTypes();
00312 for(i = 0; i < osinstance->getVariableNumber(); i++)
00313 {
00314 if( (varType[i] == 'B') || (varType[i]) == 'I' )
00315 {
00316 intIndex[k++] = i;
00317 }
00318 }
00319 osiSolver->setInteger( intIndex, numOfIntVars);
00320
00321 delete[] intIndex;
00322 intIndex = NULL;
00323 }
00324
00325
00326 int nq = osinstance->getNumberOfQuadraticTerms();
00327 if (nq > 0)
00328 {
00329 if ( (sSolverName.find("clp") != std::string::npos) )
00330 {
00331
00332 QuadraticTerms* qterms = osinstance->getQuadraticTerms();
00333
00334 #ifndef NDEBUG
00335 outStr.str("");
00336 outStr.clear();
00337 outStr << "original arrays:" << std::endl;
00338 outStr << " var One indexes:";
00339 for (int i=0; i<nq; i++)
00340 outStr << " " << qterms->varOneIndexes[i];
00341 outStr << std::endl;
00342 outStr << " var Two indexes:";
00343 for (int i=0; i<nq; i++)
00344 outStr << " " << qterms->varTwoIndexes[i];
00345 outStr << std::endl;
00346 outStr << " coefficients: ";
00347 for (int i=0; i<nq; i++)
00348 outStr << " " << qterms->coefficients[i];
00349 outStr << std::endl;
00350 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00351 ENUM_OUTPUT_LEVEL_trace, outStr.str());
00352 #endif
00353
00354 int ncols = osinstance->getVariableNumber();
00355 int* colStarts = new int[ncols+1];
00356 for (int i=0; i<=ncols; i++)
00357 colStarts[i] = 0;
00358
00359
00360 for (int i=0; i<nq; i++)
00361 {
00362 if (qterms->rowIndexes[i] != -1)
00363 throw ErrorClass("Clp solver cannot handle quadratic terms in the constraints");
00364 else
00365 colStarts[qterms->varOneIndexes[i]+1] += 1;
00366 }
00367
00368
00369 for (int i=0; i<ncols; i++)
00370 colStarts[i+1] += colStarts[i];
00371
00372
00373
00374
00375 int swapLoc;
00376 int iswap;
00377 double dswap;
00378 for (int i=0; i< ncols-1; i++)
00379 {
00380 swapLoc = colStarts[i+1];
00381 for (int j=colStarts[i]; j<colStarts[i+1]; j++)
00382 {
00383 if (qterms->varOneIndexes[j] != i)
00384 {
00385 while ( (qterms->varOneIndexes[swapLoc] != i) && (swapLoc < nq))
00386 swapLoc++;
00387 if (swapLoc < nq)
00388 {
00389 iswap = qterms->varOneIndexes[j];
00390 qterms->varOneIndexes[j] = qterms->varOneIndexes[swapLoc];
00391 qterms->varOneIndexes[swapLoc] = iswap;
00392 iswap = qterms->varTwoIndexes[j];
00393 qterms->varTwoIndexes[j] = qterms->varTwoIndexes[swapLoc];
00394 qterms->varTwoIndexes[swapLoc] = iswap;
00395 dswap = qterms->coefficients[j];
00396 qterms->coefficients[j] = qterms->coefficients[swapLoc];
00397 qterms->coefficients[swapLoc] = dswap;
00398 #ifndef NDEBUG
00399 outStr.str("");
00400 outStr.clear();
00401 outStr << "swapping locations " << j << " and " << swapLoc << std::endl;
00402
00403 outStr << "after swap:" << std::endl;
00404 outStr << " var One indexes:";
00405 for (int i=0; i<nq; i++)
00406 outStr << " " << qterms->varOneIndexes[i];
00407 outStr << std::endl;
00408 outStr << " var Two indexes:";
00409 for (int i=0; i<nq; i++)
00410 outStr << " " << qterms->varTwoIndexes[i];
00411 outStr << std::endl;
00412 outStr << " coefficients: ";
00413 for (int i=0; i<nq; i++)
00414 outStr << " " << qterms->coefficients[i];
00415 outStr << std::endl;
00416 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00417 ENUM_OUTPUT_LEVEL_detailed_trace, outStr.str());
00418 #endif
00419 }
00420 else
00421 throw ErrorClass("Sorting of quadratic terms failed in OSCoinSolver");
00422 }
00423 }
00424 }
00425 #ifndef NDEBUG
00426 outStr.str("");
00427 outStr.clear();
00428 outStr << "terminal arrays:" << std::endl;
00429 outStr << " var One indexes:";
00430 for (int i=0; i<nq; i++)
00431 outStr << " " << qterms->varOneIndexes[i];
00432 outStr << std::endl;
00433 outStr << " var Two indexes:";
00434 for (int i=0; i<nq; i++)
00435 outStr << " " << qterms->varTwoIndexes[i];
00436 outStr << std::endl;
00437 outStr << " coefficients: ";
00438 for (int i=0; i<nq; i++)
00439 outStr << " " << qterms->coefficients[i];
00440 outStr << std::endl;
00441 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00442 ENUM_OUTPUT_LEVEL_trace, outStr.str());
00443 #endif
00444
00445
00446 throw ErrorClass("Quadratic terms not implemented yet");
00447 }
00448 }
00449
00450 bCallbuildSolverInstance = true;
00451 }
00452 catch(const ErrorClass& eclass)
00453 {
00454 osresult = new OSResult();
00455 osresult->setGeneralMessage( eclass.errormsg);
00456 osresult->setGeneralStatusType( "error");
00457 osrl = osrlwriter->writeOSrL( osresult);
00458 throw ErrorClass( osrl) ;
00459 }
00460 }
00461
00462
00463
00464 void CoinSolver::setSolverOptions() throw (ErrorClass)
00465 {
00466 std::ostringstream outStr;
00467
00468 #ifndef NDEBUG
00469 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "build solver options\n");
00470 #endif
00471 this->bSetSolverOptions = true;
00472
00473
00474 std::map<std::string, OsiHintParam> hintParamMap;
00475 hintParamMap["OsiDoPresolveInInitial"] = OsiDoPresolveInInitial;
00476 hintParamMap["OsiDoDualInInitial"] = OsiDoDualInInitial;
00477 hintParamMap["OsiDoPresolveInResolve"] = OsiDoPresolveInResolve;
00478 hintParamMap["OsiDoDualInResolve"] = OsiDoDualInResolve;
00479 hintParamMap["OsiDoScale"] = OsiDoScale;
00480 hintParamMap["OsiDoCrash"] = OsiDoCrash;
00481 hintParamMap["OsiDoReducePrint"] = OsiDoReducePrint;
00482 hintParamMap["OsiDoInBranchAndCut"] = OsiDoInBranchAndCut;
00483 hintParamMap["OsiLastHintParam"] = OsiLastHintParam;
00484
00485
00486 std::map<std::string, OsiHintStrength> hintStrengthMap;
00487 hintStrengthMap["OsiHintIgnore"] = OsiHintIgnore;
00488 hintStrengthMap["OsiHintTry"] = OsiHintTry;
00489 hintStrengthMap["OsiHintDo"] = OsiHintDo;
00490 hintStrengthMap["OsiForceDo"] = OsiForceDo;
00491
00492
00493 std::map<std::string, OsiStrParam> strParamMap;
00494 strParamMap["OsiProbName"] = OsiProbName;
00495 strParamMap["OsiSolverName"] = OsiSolverName;
00496 strParamMap["OsiLastStrParam"] = OsiLastStrParam;
00497
00498
00499 std::map<std::string, OsiDblParam> dblParamMap;
00500 dblParamMap["OsiDualObjectiveLimit"] = OsiDualObjectiveLimit;
00501 dblParamMap["OsiPrimalObjectiveLimit"] = OsiPrimalObjectiveLimit;
00502 dblParamMap["OsiDualTolerance"] = OsiDualTolerance;
00503 dblParamMap["OsiPrimalTolerance"] = OsiPrimalTolerance;
00504 dblParamMap["OsiObjOffset"] = OsiObjOffset;
00505 dblParamMap["OsiLastDblParam"] = OsiLastDblParam;
00506
00507
00508 std::map<std::string, OsiIntParam> intParamMap;
00509 intParamMap["OsiMaxNumIteration"] = OsiMaxNumIteration;
00510 intParamMap["OsiMaxNumIterationHotStart"] = OsiMaxNumIterationHotStart;
00511 intParamMap["OsiNameDiscipline"] = OsiNameDiscipline;
00512 intParamMap["OsiLastIntParam"] = OsiLastIntParam;
00513
00514
00515
00516
00517
00518
00519 OsiHintStrength hintStrength = OsiHintTry;
00520 osiSolver->setHintParam(OsiDoReducePrint, true, hintStrength);
00521
00522
00523 osiSolver->setDblParam(OsiObjOffset, -osinstance->getObjectiveConstants()[0]);
00524
00525
00526 #ifdef COIN_HAS_SYMPHONY
00527 if( sSolverName.find( "symphony") != std::string::npos)
00528 {
00529 OsiSymSolverInterface * si =
00530 dynamic_cast<OsiSymSolverInterface *>(osiSolver) ;
00531 si->setSymParam("verbosity", -2);
00532 }
00533 #endif //symphony end
00534
00535
00536
00537
00538
00539
00540 try
00541 {
00542 if(osoption == NULL && osol.length() > 0)
00543 {
00544 m_osolreader = new OSoLReader();
00545 osoption = m_osolreader->readOSoL( osol);
00546 }
00547
00548
00549 if(osoption != NULL)
00550 {
00551 int i;
00552
00553 #ifndef NDEBUG
00554 outStr.str("");
00555 outStr.clear();
00556 outStr << "number of solver options " << osoption->getNumberOfSolverOptions() << std::endl;
00557 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00558 #endif
00559 if( osoption->getNumberOfSolverOptions() > 0)
00560 {
00561
00562 std::vector<SolverOption*> optionsVector;
00563
00564
00565 optionsVector = osoption->getSolverOptions( "osi",true);
00566 int num_osi_options = optionsVector.size();
00567 char *pEnd;
00568 bool yesNo;
00569
00574 for(i = 0; i < num_osi_options; i++)
00575 {
00576 #ifndef NDEBUG
00577 outStr.str("");
00578 outStr.clear();
00579 outStr << "osi solver option " << optionsVector[ i]->name << std::endl;
00580 outStr << "osi solver value " << optionsVector[ i]->value << std::endl;
00581 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00582 ENUM_OUTPUT_LEVEL_trace, outStr.str());
00583 #endif
00584 if (optionsVector[ i]->type == "OsiHintStrength" )
00585 {
00586 if( hintStrengthMap.find( optionsVector[ i]->name ) != hintStrengthMap.end() )
00587 {
00588 hintStrength = hintStrengthMap[ optionsVector[ i]->name] ;
00589 }
00590 }
00591 }
00592
00596 for(i = 0; i < num_osi_options; i++)
00597 {
00598 #ifndef NDEBUG
00599 outStr.str("");
00600 outStr.clear();
00601 outStr << "osi solver option " << optionsVector[ i]->name << std::endl;
00602 outStr << "osi solver value " << optionsVector[ i]->value << std::endl;
00603 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00604 ENUM_OUTPUT_LEVEL_trace, outStr.str());
00605 #endif
00606 if (optionsVector[ i]->type == "OsiHintParam" )
00607 {
00608 if( optionsVector[ i]->value == "true" )
00609 {
00610 yesNo = true;
00611 }
00612 else
00613 {
00614 yesNo = false;
00615 }
00616 if( hintParamMap.find( optionsVector[ i]->name ) != hintParamMap.end() )
00617 {
00618 osiSolver->setHintParam( hintParamMap[ optionsVector[ i]->name] , yesNo, hintStrength);
00619 }
00620 }
00621 else if(optionsVector[ i]->type == "OsiStrParam" )
00622 {
00623 if( strParamMap.find( optionsVector[ i]->name ) != strParamMap.end() )
00624 {
00625 osiSolver->setStrParam( strParamMap[ optionsVector[ i]->name] , optionsVector[ i]->value);
00626 }
00627 }
00628 else if(optionsVector[ i]->type == "OsiDblParam" )
00629 {
00630 if( dblParamMap.find( optionsVector[ i]->name ) != dblParamMap.end() )
00631 {
00632 osiSolver->setDblParam( dblParamMap[ optionsVector[ i]->name] , os_strtod( optionsVector[ i]->value.c_str(), &pEnd ));
00633 }
00634
00635 }
00636 else if(optionsVector[ i]->type == "OsiIntParam" )
00637 {
00638 if( intParamMap.find( optionsVector[ i]->name ) != intParamMap.end() )
00639 {
00640 osiSolver->setIntParam( intParamMap[ optionsVector[ i]->name] , atoi( optionsVector[ i]->value.c_str() ) );
00641 }
00642 }
00643 else if (optionsVector[ i]->type == "bool" )
00644 {
00645 if( optionsVector[ i]->name == "primalSimplex" )
00646 {
00647 if (optionsVector[ i]->value != "false")
00648 osiSolver->enableSimplexInterface((optionsVector[ i]->value != "false"));
00649 }
00650 }
00651 }
00652
00653
00654
00655 if( sSolverName.find( "cbc") != std::string::npos)
00656 {
00657
00658 if(optionsVector.size() > 0) optionsVector.clear();
00659 optionsVector = osoption->getSolverOptions( "cbc",true);
00660
00661 int num_cbc_options = optionsVector.size();
00662 char *cstr;
00663 std::string cbc_option;
00664 num_cbc_argv = optionsVector.size() + 3;
00665 cbc_argv = new const char*[ num_cbc_argv];
00666
00667
00668 cbc_option = "OS";
00669 cstr = new char [cbc_option.size() + 1];
00670 strcpy (cstr, cbc_option.c_str());
00671 cbc_argv[ 0] = cstr;
00672
00673 for(i = 0; i < num_cbc_options; i++)
00674 {
00675 #ifndef NDEBUG
00676 outStr.str("");
00677 outStr.clear();
00678 outStr << "cbc solver option " << optionsVector[ i]->name << std::endl;
00679 outStr << "cbc solver value " << optionsVector[ i]->name << std::endl;
00680 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00681 ENUM_OUTPUT_LEVEL_debug, outStr.str());
00682 #endif
00683
00684 if(optionsVector[ i]->value.length() > 0 )
00685 {
00686 cbc_option = "-" + optionsVector[ i]->name +"="+optionsVector[ i]->value;
00687 }
00688 else
00689 {
00690 cbc_option = "-" + optionsVector[ i]->name ;
00691 }
00692 cstr = new char [cbc_option.size() + 1];
00693 strcpy (cstr, cbc_option.c_str());
00694 cbc_argv[i + 1] = cstr;
00695 }
00696
00697
00698 cbc_option = "-solve";
00699 cstr = new char [cbc_option.size() + 1];
00700 strcpy (cstr, cbc_option.c_str());
00701 cbc_argv[ num_cbc_argv - 2] = cstr;
00702
00703
00704 cbc_option = "-quit";
00705 cstr = new char [cbc_option.size() + 1];
00706 strcpy (cstr, cbc_option.c_str());
00707 cbc_argv[ num_cbc_argv - 1] = cstr;
00708
00709 }
00710
00711
00712
00713 else if( sSolverName.find( "clp") != std::string::npos)
00714 {
00715
00716 if(optionsVector.size() > 0) optionsVector.clear();
00717 optionsVector = osoption->getSolverOptions( "clp",true);
00718
00719 int num_cbc_options = optionsVector.size();
00720 if (num_cbc_options > 0)
00721 {
00722 char *cstr;
00723 std::string cbc_option;
00724 num_cbc_argv = optionsVector.size() + 3;
00725 cbc_argv = new const char*[ num_cbc_argv];
00726
00727
00728 cbc_option = "OS";
00729 cstr = new char [cbc_option.size() + 1];
00730 strcpy (cstr, cbc_option.c_str());
00731 cbc_argv[ 0] = cstr;
00732
00733 for(i = 0; i < num_cbc_options; i++)
00734 {
00735 #ifndef NDEBUG
00736 outStr.str("");
00737 outStr.clear();
00738 outStr << "clp solver option " << optionsVector[ i]->name << std::endl;
00739 outStr << "clp solver value " << optionsVector[ i]->name << std::endl;
00740 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
00741 ENUM_OUTPUT_LEVEL_debug, outStr.str());
00742 #endif
00743
00744 if(optionsVector[ i]->value.length() > 0 )
00745 {
00746 cbc_option = "-" + optionsVector[ i]->name +"="+optionsVector[ i]->value;
00747 }
00748 else
00749 {
00750 cbc_option = "-" + optionsVector[ i]->name ;
00751 }
00752 cstr = new char [cbc_option.size() + 1];
00753 strcpy (cstr, cbc_option.c_str());
00754 cbc_argv[i + 1] = cstr;
00755 }
00756
00757
00758 cbc_option = "-solve";
00759 cstr = new char [cbc_option.size() + 1];
00760 strcpy (cstr, cbc_option.c_str());
00761 cbc_argv[ num_cbc_argv - 2] = cstr;
00762
00763
00764 cbc_option = "-quit";
00765 cstr = new char [cbc_option.size() + 1];
00766 strcpy (cstr, cbc_option.c_str());
00767 cbc_argv[ num_cbc_argv - 1] = cstr;
00768 }
00769 }
00770
00771
00772
00773 else if( sSolverName.find( "symphony") != std::string::npos)
00774 {
00775 #ifdef COIN_HAS_SYMPHONY
00776 if(optionsVector.size() > 0) optionsVector.clear();
00777
00778 OsiSymSolverInterface * si =
00779 dynamic_cast<OsiSymSolverInterface *>(osiSolver) ;
00780
00781 optionsVector = osoption->getSolverOptions( "symphony",true);
00782 int num_sym_options = optionsVector.size();
00783 for(i = 0; i < num_sym_options; i++)
00784 {
00785 #ifndef NDEBUG
00786 outStr.str("");
00787 outStr.clear();
00788 outStr << "symphony solver option " << optionsVector[ i]->name << std::endl;
00789 outStr << "symphony solver value " << optionsVector[ i]->name << std::endl;
00790 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00791 #endif
00792 if (optionsVector[ i]->type == "OsiStrParam" || optionsVector[ i]->type == "string")
00793 {
00794 if (!si->setSymParam(optionsVector[ i]->name, optionsVector[ i]->value))
00795 throw ErrorClass ("Failed to set Symphony solver option "+optionsVector[ i]->name);
00796 }
00797 else if (optionsVector[ i]->type == "OsiDblParam" || optionsVector[ i]->type == "double")
00798 {
00799 if (!si->setSymParam(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd )))
00800 throw ErrorClass ("Failed to set Symphony solver option "+optionsVector[ i]->name);
00801 }
00802 else if (optionsVector[ i]->type == "OsiIntParam" || optionsVector[ i]->type == "integer")
00803 {
00804 if (!si->setSymParam(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) ))
00805 throw ErrorClass ("Failed to set Symphony solver option "+optionsVector[ i]->name);
00806 }
00807 }
00808 #endif //symphony end
00809 }
00810 }
00811
00812
00813 int n,m,k;
00814 if (osoption != NULL)
00815 m = osoption->getNumberOfInitVarValues();
00816 else
00817 m = 0;
00818 #ifndef NDEBUG
00819 outStr.str("");
00820 outStr.clear();
00821 outStr << "number of variables initialed: " << m << std::endl;
00822 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00823 #endif
00824
00825 if (m > 0)
00826 {
00827 #ifndef NDEBUG
00828 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "get initial values\n");
00829 #endif
00830 n = osinstance->getVariableNumber();
00831 double* denseInitVarVector;
00832 denseInitVarVector = new double[n];
00833 bool* initialed;
00834 initialed = new bool[n];
00835
00836 for(k = 0; k < n; k++)
00837 initialed[k] = false;
00838
00839 InitVarValue** initVarVector = osoption->getInitVarValuesSparse();
00840 #ifndef NDEBUG
00841 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "done\n");
00842 #endif
00843
00844 double initval;
00845 for(k = 0; k < m; k++)
00846 {
00847 i = initVarVector[k]->idx;
00848 if (initVarVector[k]->idx >= n)
00849 throw ErrorClass ("Illegal index value in variable initialization");
00850
00851 initval = initVarVector[k]->value;
00852 if (osinstance->instanceData->variables->var[k]->ub == OSDBL_MAX)
00853 {
00854 if (osinstance->instanceData->variables->var[k]->lb > initval)
00855 throw ErrorClass ("Initial value outside of bounds");
00856 }
00857 else if (osinstance->instanceData->variables->var[k]->lb == -OSDBL_MAX)
00858 {
00859 if (osinstance->instanceData->variables->var[k]->ub < initval)
00860 throw ErrorClass ("Initial value outside of bounds");
00861 }
00862 else
00863 {
00864 if ((osinstance->instanceData->variables->var[k]->lb > initval) ||
00865 (osinstance->instanceData->variables->var[k]->ub < initval))
00866 throw ErrorClass ("Initial value outside of bounds");
00867 }
00868
00869 denseInitVarVector[initVarVector[k]->idx] = initval;
00870 initialed[initVarVector[k]->idx] = true;
00871 }
00872
00873 double default_initval;
00874 default_initval = 0.0;
00875
00876 for(k = 0; k < n; k++)
00877 {
00878 if (!initialed[k])
00879 {
00880 if (osinstance->instanceData->variables->var[k]->ub == OSDBL_MAX)
00881 if (osinstance->instanceData->variables->var[k]->lb <= default_initval)
00882 denseInitVarVector[k] = default_initval;
00883 else
00884 denseInitVarVector[k] = osinstance->instanceData->variables->var[k]->lb;
00885 else if (osinstance->instanceData->variables->var[k]->lb == -OSDBL_MAX)
00886 if (osinstance->instanceData->variables->var[k]->ub >= default_initval)
00887 denseInitVarVector[k] = default_initval;
00888 else
00889 denseInitVarVector[k] = osinstance->instanceData->variables->var[k]->ub;
00890 else if ((osinstance->instanceData->variables->var[k]->lb <= default_initval) &&
00891 (osinstance->instanceData->variables->var[k]->ub >= default_initval))
00892 denseInitVarVector[k] = default_initval;
00893 else if (osinstance->instanceData->variables->var[k]->lb > default_initval)
00894 denseInitVarVector[k] = osinstance->instanceData->variables->var[k]->lb;
00895 else
00896 denseInitVarVector[k] = osinstance->instanceData->variables->var[k]->ub;
00897 }
00898
00899
00900 }
00901 #ifndef NDEBUG
00902 outStr.str("");
00903 outStr.clear();
00904 outStr << "set initial values: " << std::endl;
00905 for (k=0; k < n; k++)
00906 outStr << " " << k << ": " << denseInitVarVector[k] << std::endl;
00907 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00908 #endif
00909 osiSolver->setColSolution( denseInitVarVector);
00910 delete[] denseInitVarVector;
00911 delete[] initialed;
00912 #ifndef NDEBUG
00913 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "done\n");
00914 #endif
00915
00916 }
00917
00918
00919
00920
00921
00922 {
00923 if ( osoption != NULL &&
00924 osoption->optimization != NULL &&
00925 ((osoption->optimization->variables != NULL &&
00926 osoption->optimization->variables->initialBasisStatus != NULL) ||
00927 (osoption->optimization->constraints != NULL &&
00928 osoption->optimization->constraints->initialBasisStatus != NULL)) )
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 {
00942 int nsBas,naBas,nsUpp,naUpp,nsLow,naLow,nvar,ncon;
00943 int* tmpBas = NULL;
00944 CoinWarmStartBasis* warmstart = new CoinWarmStartBasis();
00945 nvar = osinstance->getVariableNumber();
00946 ncon = osinstance->getConstraintNumber();
00947 warmstart->setSize(nvar, ncon);
00948
00949
00950 if ( osoption->optimization->variables != NULL &&
00951 osoption->optimization->variables->initialBasisStatus != NULL )
00952 {
00953 nsBas = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_basic);
00954 nsUpp = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atUpper);
00955 nsLow = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atLower);
00956 }
00957 else
00958 {
00959 nsBas = 0;
00960 nsUpp = 0;
00961 nsLow = 0;
00962 }
00963 if ( osoption->optimization->constraints != NULL &&
00964 osoption->optimization->constraints->initialBasisStatus != NULL )
00965 {
00966 naBas = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_basic);
00967 naUpp = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atUpper);
00968 naLow = osoption->getNumberOfInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atLower);
00969 }
00970 else
00971 {
00972 naBas = 0;
00973 naUpp = 0;
00974 naLow = 0;
00975 }
00976
00977
00978 if (nsBas > 0)
00979 {
00980 tmpBas = new int[nsBas];
00981 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_basic,tmpBas);
00982 for (int i=0; i<nsBas; i++)
00983 warmstart->setStructStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x01);
00984 delete [] tmpBas;
00985 }
00986 if (naBas > 0)
00987 {
00988 tmpBas = new int[naBas];
00989 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_basic,tmpBas);
00990 for (int i=0; i<naBas; i++)
00991 warmstart->setArtifStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x01);
00992 delete [] tmpBas;
00993 }
00994
00995 if (nsUpp > 0)
00996 {
00997 tmpBas = new int[nsUpp];
00998 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atUpper,tmpBas);
00999 for (int i=0; i<nsUpp; i++)
01000 warmstart->setStructStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x02);
01001 delete [] tmpBas;
01002 }
01003 if (naUpp > 0)
01004 {
01005 tmpBas = new int[naUpp];
01006 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atUpper,tmpBas);
01007 for (int i=0; i<naUpp; i++)
01008 warmstart->setArtifStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x02);
01009 delete [] tmpBas;
01010 }
01011
01012 if (nsLow > 0)
01013 {
01014 tmpBas = new int[nsLow];
01015 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atLower,tmpBas);
01016 for (int i=0; i<nsLow; i++)
01017 warmstart->setStructStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x03);
01018 delete [] tmpBas;
01019 }
01020 if (naLow > 0)
01021 {
01022 tmpBas = new int[naLow];
01023 osoption->getInitialBasisElements(ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atLower,tmpBas);
01024 for (int i=0; i<naLow; i++)
01025 warmstart->setArtifStatus(tmpBas[i], (CoinWarmStartBasis::Status)0x03);
01026 delete [] tmpBas;
01027 }
01028
01029 osiSolver->setWarmStart(warmstart);
01030
01031 }
01032 }
01033
01034 }
01035
01036 #ifndef NDEBUG
01037 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "solver options set\n");
01038 #endif
01039 }
01040
01041 catch(const ErrorClass& eclass)
01042 {
01043 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_error, "THERE IS AN ERROR\n");
01044 osresult = new OSResult();
01045 osresult->setGeneralMessage( eclass.errormsg);
01046 osresult->setGeneralStatusType( "error");
01047 osrl = osrlwriter->writeOSrL( osresult);
01048 throw ErrorClass( osrl) ;
01049 }
01050 }
01051
01052
01053 bool CoinSolver::setCoinPackedMatrix()
01054 {
01055 bool columnMajor = osinstance->getLinearConstraintCoefficientMajor();
01056 try
01057 {
01058 double maxGap = 0;
01059 if(osinstance->getLinearConstraintCoefficientNumber() > 0)
01060 {
01061 m_CoinPackedMatrix = new CoinPackedMatrix(
01062 columnMajor,
01063 columnMajor? osinstance->getConstraintNumber() : osinstance->getVariableNumber(),
01064 columnMajor? osinstance->getVariableNumber() : osinstance->getConstraintNumber(),
01065 osinstance->getLinearConstraintCoefficientNumber(),
01066 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->values : osinstance->getLinearConstraintCoefficientsInRowMajor()->values,
01067 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes : osinstance->getLinearConstraintCoefficientsInRowMajor()->indexes,
01068 columnMajor? osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts : osinstance->getLinearConstraintCoefficientsInRowMajor()->starts,
01069 0, 0, maxGap );
01070 }
01071 else
01072 {
01073 int* start = new int[osinstance->getVariableNumber()+1];
01074 for (int i=0; i <= osinstance->getVariableNumber(); i++)
01075 start[i] = 0;
01076 m_CoinPackedMatrix = new CoinPackedMatrix(
01077 columnMajor,
01078 columnMajor? osinstance->getConstraintNumber() : osinstance->getVariableNumber(),
01079 columnMajor? osinstance->getVariableNumber() : osinstance->getConstraintNumber(),
01080 osinstance->getLinearConstraintCoefficientNumber(),
01081 NULL,
01082 NULL,
01083 start,
01084 NULL, 0.0, maxGap );
01085 }
01086
01087
01088 return true;
01089 }
01090 catch(const ErrorClass& eclass)
01091 {
01092 osresult = new OSResult();
01093 osresult->setGeneralMessage( eclass.errormsg);
01094 osresult->setGeneralStatusType( "error");
01095 osrl = osrlwriter->writeOSrL( osresult);
01096 throw ErrorClass( osrl) ;
01097 }
01098 }
01099
01100 void CoinSolver::solve() throw (ErrorClass)
01101 {
01102 std::ostringstream outStr;
01103 if(osresult != NULL) delete osresult;
01104 osresult = new OSResult();
01105 try
01106 {
01107
01108 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
01109
01110 if( this->bSetSolverOptions == false) setSolverOptions();
01111 }
01112 catch(const ErrorClass& eclass)
01113 {
01114 throw ErrorClass( osrl) ;
01115 }
01116
01117
01118 if(osresult->setSolverInvoked("COIN-OR " + sSolverName) != true)
01119 throw ErrorClass("OSResult error: SetSolverInvoked");
01120 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
01121 throw ErrorClass("OSResult error: setInstanceName");
01122
01123
01124
01125
01126
01127
01128 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
01129 throw ErrorClass("OSResult error: setVariableNumer");
01130 if(osresult->setObjectiveNumber( 1) != true)
01131 throw ErrorClass("OSResult error: setObjectiveNumber");
01132 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
01133 throw ErrorClass("OSResult error: setConstraintNumber");
01134 if(osresult->setSolutionNumber( 1) != true)
01135 throw ErrorClass("OSResult error: setSolutionNumer");
01136
01137
01138 try
01139 {
01140 double start = CoinCpuTime();
01141 try
01142 {
01143 if( (sSolverName.find( "cbc") != std::string::npos) ||
01144 ((sSolverName.find( "clp") != std::string::npos) && num_cbc_argv > 0) )
01145 {
01146
01147 CbcModel model( *osiSolver);
01148
01149 CbcMain0( model);
01150
01151
01152 if(num_cbc_argv <= 0)
01153 {
01154 char *cstr;
01155 std::string cbc_option;
01156 num_cbc_argv = 4;
01157 cbc_argv = new const char*[ num_cbc_argv];
01158
01159
01160 cbc_option = "OS";
01161 cstr = new char [cbc_option.size() + 1];
01162 strcpy (cstr, cbc_option.c_str());
01163 cbc_argv[ 0] = cstr;
01164
01165
01166 cbc_option = "-log=0";
01167 cstr = new char [cbc_option.size() + 1];
01168 strcpy (cstr, cbc_option.c_str());
01169 cbc_argv[ 1] = cstr;
01170
01171
01172 cbc_option = "-solve";
01173 cstr = new char [cbc_option.size() + 1];
01174 strcpy (cstr, cbc_option.c_str());
01175 cbc_argv[ 2] = cstr;
01176
01177
01178 cbc_option = "-quit";
01179 cstr = new char [cbc_option.size() + 1];
01180 strcpy (cstr, cbc_option.c_str());
01181 cbc_argv[ 3] = cstr;
01182 }
01183 int i;
01184
01185 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces,
01186 ENUM_OUTPUT_LEVEL_info, "CALLING THE CBC SOLVER CBCMAIN1()\n");
01187 #ifndef NDEBUG
01188 outStr.str("");
01189 outStr.clear();
01190 for(i = 0; i < num_cbc_argv; i++)
01191 {
01192 outStr << sSolverName << " option: " << cbc_argv[ i] << std::endl;
01193 }
01194 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
01195 #endif
01196 CbcMain1( num_cbc_argv, cbc_argv, model);
01197
01198
01199 for(i = 0; i < num_cbc_argv; i++)
01200 {
01201 delete[] cbc_argv[ i];
01202 cbc_argv[i] = NULL;
01203 }
01204 if( num_cbc_argv > 0)
01205 {
01206 delete[] cbc_argv;
01207 cbc_argv = NULL;
01208 num_cbc_argv = 0;
01209 }
01210
01211 cpuTime = CoinCpuTime() - start;
01212
01213
01214 OsiSolverInterface *solver = model.solver();
01215 if(osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
01216 {
01217 writeResult( &model);
01218 }
01219 else
01220 {
01221 writeResult( solver);
01222 }
01223 }
01224 else
01225 {
01226
01227 if( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
01228 {
01229 osiSolver->branchAndBound();
01230 }
01231 else
01232 {
01233 osiSolver->initialSolve();
01234 }
01235 cpuTime = CoinCpuTime() - start;
01236
01237 writeResult( osiSolver);
01238 }
01239 }
01240
01241 catch(CoinError e)
01242 {
01243 std::string errmsg;
01244 errmsg = "Coin Solver Error: " + e.message() + "\n" + " see method "
01245 + e.methodName() + " in class " + e.className();
01246 throw ErrorClass( errmsg );
01247 }
01248 }
01249
01250 catch(const ErrorClass& eclass)
01251 {
01252 std::string::size_type pos1 = eclass.errormsg.find( "<osrl");
01253 if(pos1 == std::string::npos)
01254 {
01255 osresult->setGeneralMessage(eclass.errormsg);
01256 osresult->setGeneralStatusType("error");
01257 osrl = osrlwriter->writeOSrL(osresult);
01258 }
01259 else
01260 {
01261 osrl = eclass.errormsg;
01262 }
01263 throw ErrorClass( osrl);
01264 }
01265 }
01266
01267 std::string CoinSolver::getCoinSolverType(std::string lcl_osol)
01268 {
01269
01270 try
01271 {
01272 if( lcl_osol.find( "clp") != std::string::npos)
01273 {
01274 return "coin_solver_glpk";
01275 }
01276 else
01277 {
01278 if( lcl_osol.find( "cbc") != std::string::npos)
01279 {
01280 return "coin_solver_cpx";
01281 }
01282 else
01283 {
01284 if( lcl_osol.find( "cpx") != std::string::npos)
01285 {
01286 return "coin_solver_clp";
01287 }
01288 else
01289 {
01290 if(lcl_osol.find( "glpk") != std::string::npos)
01291 {
01292 return "";
01293 }
01294 else throw ErrorClass("a supported solver was not defined");
01295 }
01296 }
01297 }
01298 }
01299 catch(const ErrorClass& eclass)
01300 {
01301 osresult->setGeneralMessage( eclass.errormsg);
01302 osresult->setGeneralStatusType( "error");
01303 osrl = osrlwriter->writeOSrL( osresult);
01304 throw ErrorClass( osrl) ;
01305 }
01306 }
01307
01308 #ifndef NDEBUG
01309 void CoinSolver::dataEchoCheck()
01310 {
01311 int i;
01312
01313 cout << "This is problem: " << osinstance->getInstanceName() << endl;
01314 cout << "The problem source is: " << osinstance->getInstanceSource() << endl;
01315 cout << "The problem description is: " << osinstance->getInstanceDescription() << endl;
01316 cout << "number of variables = " << osinstance->getVariableNumber() << endl;
01317 cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
01318
01319
01320 if(osinstance->getVariableNumber() > 0)
01321 {
01322 for(i = 0; i < osinstance->getVariableNumber(); i++)
01323 {
01324 if(osinstance->getVariableNames() != NULL) cout << "variable Names " << osinstance->getVariableNames()[ i] << endl;
01325 if(osinstance->getVariableTypes() != NULL) cout << "variable Types " << osinstance->getVariableTypes()[ i] << endl;
01326 if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds " << osinstance->getVariableLowerBounds()[ i] << endl;
01327 if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds " << osinstance->getVariableUpperBounds()[i] << endl;
01328 }
01329 }
01330
01331
01332 if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0)
01333 {
01334 if( osinstance->getObjectiveMaxOrMins()[0] == "min") cout << "problem is a minimization" << endl;
01335 else cout << "problem is a maximization" << endl;
01336 for(i = 0; i < osinstance->getVariableNumber(); i++)
01337 {
01338 cout << "OBJ COEFFICIENT = " << osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
01339 }
01340 }
01341
01342 if(osinstance->getConstraintNumber() > 0)
01343 {
01344 for(i = 0; i < osinstance->getConstraintNumber(); i++)
01345 {
01346 if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] << endl;
01347 if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] << endl;
01348 if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] << endl;
01349 }
01350 }
01351
01352
01353 if(m_CoinPackedMatrix != NULL) m_CoinPackedMatrix->dumpMatrix();
01354 }
01355 #endif
01356
01357
01358 void CoinSolver::writeResult(OsiSolverInterface *solver)
01359 {
01360 double *x = NULL;
01361 double *y = NULL;
01362 double *z = NULL;
01363 int *cbasis = NULL;
01364 int *rbasis = NULL;
01365 int *idx = NULL;
01366 int kount;
01367
01368
01369 std::vector<int> freeVars;
01370 std::vector<int> basicVars;
01371 std::vector<int> nonBasicLower;
01372 std::vector<int> nonBasicUpper;
01373 std::vector<int>::iterator vit;
01374 int **basisIdx;
01375 basisIdx = new int*[ 4];
01376
01377
01378 int numberOfVar = solver->getNumCols();
01379 int numberOfCon = solver->getNumRows();
01380 int numOfIntVars = osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables();
01381 std::string *rcost = NULL;
01382 if ( numberOfVar > 0 ) x = new double[numberOfVar];
01383 if ( numberOfCon > 0 ) y = new double[numberOfCon ];
01384 if ( numberOfVar > 0 ) idx = new int[ numberOfVar];
01385 if ( numberOfVar > 0 ) rcost = new std::string[numberOfVar];
01386 z = new double[1];
01387
01388
01389 bool supportsBasis = false;
01390 if ( (sSolverName.find( "clp") != std::string::npos)
01391 || (sSolverName.find( "cbc") != std::string::npos)
01392 || (sSolverName.find( "cplex") != std::string::npos)
01393 || (sSolverName.find( "gurobi") != std::string::npos) )
01394 {
01395 if (numOfIntVars == 0)
01396 {
01397 if (numberOfVar > 0) cbasis = new int[numberOfVar];
01398 if (numberOfCon > 0) rbasis = new int[numberOfCon];
01399 supportsBasis = true;
01400 }
01401 }
01402
01403 int solIdx = 0;
01404 int i = 0;
01405 int numberOfOtherVariableResults = 1;
01406 int otherIdx = 0;
01407 std::string description = "";
01408
01409 try
01410 {
01411 osresult->setGeneralStatusType("normal");
01412 osresult->setTime(cpuTime);
01413 osresult->setServiceName( OSgetVersionInfo() );
01414 osresult->setSolverInvoked( "COIN-OR " + sSolverName );
01415 if (solver->isProvenOptimal() == true)
01416 {
01417 osresult->setSolutionStatus(solIdx, "optimal", description);
01418 if ( supportsBasis )
01419 {
01420 solver->getBasisStatus( cbasis, rbasis);
01421 }
01422
01423 }
01424 else
01425 {
01426 if(solver->isProvenPrimalInfeasible() == true)
01427 osresult->setSolutionStatus(solIdx, "infeasible", "the problem is primal infeasible");
01428 else
01429 {
01430 if(solver->isProvenDualInfeasible() == true)
01431 osresult->setSolutionStatus(solIdx, "unbounded", "the problem is unbounded");
01432 else
01433 {
01434 if(solver->isPrimalObjectiveLimitReached() == true)
01435 {
01436 osresult->setSolutionStatus(solIdx, "other", "primal objective limit reached");
01437 if ( supportsBasis )
01438 {
01439 solver->getBasisStatus( cbasis, rbasis);
01440 }
01441 }
01442 else
01443 {
01444 if(solver->isDualObjectiveLimitReached() == true)
01445 {
01446 osresult->setSolutionStatus(solIdx, "other", "dual objective limit reached");
01447 if ( supportsBasis )
01448 {
01449 solver->getBasisStatus( cbasis, rbasis);
01450 }
01451 }
01452 else
01453 {
01454 if(solver->isIterationLimitReached() == true)
01455 {
01456 osresult->setSolutionStatus(solIdx, "other", "iteration limit reached");
01457 if ( supportsBasis )
01458 {
01459 solver->getBasisStatus( cbasis, rbasis);
01460 }
01461 }
01462 else
01463 {
01464 if(solver->isAbandoned() == true)
01465 osresult->setSolutionStatus(solIdx, "other", "there are numerical difficulties");
01466 else
01467 if( solver->getNumCols() == 0) osresult->setSolutionMessage(solIdx, "Warning: this problem has zero decision variables!");
01468 else
01469 osresult->setSolutionStatus(solIdx, "other", description);
01470 }
01471 }
01472 }
01473 }
01474 }
01475 }
01476
01477
01478
01479 *(z + 0) = solver->getObjValue();
01480
01481 osresult->setObjectiveValuesDense(solIdx, z);
01482
01483 for(i=0; i < numberOfVar; i++)
01484 {
01485 *(x + i) = solver->getColSolution()[i];
01486 *(idx + i) = i;
01487
01488
01489 if( (cbasis != NULL) && (solver->isProvenOptimal() == true) )
01490 {
01491 switch (cbasis[ i] )
01492 {
01493 case 0:
01494 {
01495
01496 freeVars.push_back( i);
01497 break;
01498 }
01499
01500 case 1:
01501 {
01502
01503 basicVars.push_back( i);
01504 break;
01505 }
01506
01507 case 2:
01508 {
01509
01510 nonBasicUpper.push_back( i );
01511 break;
01512 }
01513
01514 case 3:
01515 {
01516
01517 nonBasicLower.push_back( i) ;
01518 break;
01519 }
01520 default:
01521 throw ErrorClass("unknown result from Osi getBasisStatus when getting variable basis status");
01522
01523 }
01524
01525 }
01526
01527 }
01528
01529
01530 if(freeVars.size() > 0)
01531 {
01532 kount = 0;
01533
01534
01535 basisIdx[ 0] = new int[ freeVars.size()];
01536
01537 for(vit = freeVars.begin(); vit < freeVars.end(); vit++)
01538 {
01539 basisIdx[0][ kount++] = *vit;
01540 }
01541
01542 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_isFree, basisIdx[ 0], kount);
01543 delete[] basisIdx[ 0];
01544 freeVars.clear();
01545 }
01546
01547 if(basicVars.size() > 0)
01548 {
01549 kount = 0;
01550
01551 basisIdx[ 1] = new int[ basicVars.size()];
01552
01553 for(vit = basicVars.begin(); vit < basicVars.end(); vit++)
01554 {
01555 basisIdx[1][ kount++] = *vit;
01556 }
01557
01558 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_basic, basisIdx[ 1], kount);
01559 delete[] basisIdx[ 1];
01560 basicVars.clear();
01561 }
01562
01563 if(nonBasicUpper.size() > 0)
01564 {
01565 kount = 0;
01566
01567 basisIdx[ 2] = new int[ nonBasicUpper.size()];
01568
01569 for(vit = nonBasicUpper.begin(); vit < nonBasicUpper.end(); vit++)
01570 {
01571 basisIdx[2][ kount++] = *vit;
01572 }
01573
01574 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atUpper, basisIdx[ 2], kount);
01575 delete[] basisIdx[ 2];
01576 nonBasicUpper.clear();
01577 }
01578
01579
01580 if(nonBasicLower.size() > 0)
01581 {
01582 kount = 0;
01583
01584 basisIdx[ 3] = new int[ nonBasicLower.size()];
01585
01586 for(vit = nonBasicLower.begin(); vit < nonBasicLower.end(); vit++)
01587 {
01588 basisIdx[3][ kount++] = *vit;
01589 }
01590
01591 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_variables, ENUM_BASIS_STATUS_atLower, basisIdx[ 3], kount);
01592 delete[] basisIdx[ 3];
01593 nonBasicLower.clear();
01594 }
01595
01596
01597 osresult->setPrimalVariableValuesDense(solIdx, x);
01598
01599 if( sSolverName.find( "symphony") == std::string::npos && osinstance->getNumberOfIntegerVariables() == 0 && osinstance->getNumberOfBinaryVariables() == 0)
01600 {
01601 for(i = 0; i < numberOfCon; i++)
01602 {
01603 *(y + i) = solver->getRowPrice()[ i];
01604
01605
01606 if((rbasis != NULL) && (solver->isProvenOptimal() == true) )
01607 {
01608 switch (rbasis[ i] )
01609 {
01610 case 0:
01611 {
01612
01613 freeVars.push_back( i);
01614 break;
01615 }
01616
01617 case 1:
01618 {
01619
01620 basicVars.push_back( i);
01621 break;
01622 }
01623
01624 case 2:
01625 {
01626
01627 nonBasicUpper.push_back( i );
01628 break;
01629 }
01630
01631 case 3:
01632 {
01633
01634 nonBasicLower.push_back( i) ;
01635 break;
01636 }
01637 default:
01638 throw ErrorClass("unknown result from Osi getBasisStatus when getting row basis status");
01639
01640 }
01641
01642 }
01643
01644
01645 }
01646
01647 osresult->setDualVariableValuesDense(solIdx, y);
01648
01649
01650
01651 if(freeVars.size() > 0)
01652 {
01653 kount = 0;
01654
01655 basisIdx[ 0] = new int[ freeVars.size()];
01656
01657 for(vit = freeVars.begin(); vit < freeVars.end(); vit++)
01658 {
01659 basisIdx[0][ kount++] = *vit;
01660 }
01661
01662 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_isFree, basisIdx[ 0], kount);
01663 delete[] basisIdx[ 0];
01664 freeVars.clear();
01665 }
01666
01667 if(basicVars.size() > 0)
01668 {
01669 kount = 0;
01670
01671 basisIdx[ 1] = new int[ basicVars.size()];
01672
01673 for(vit = basicVars.begin(); vit < basicVars.end(); vit++)
01674 {
01675 basisIdx[1][ kount++] = *vit;
01676 }
01677
01678 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_basic, basisIdx[ 1], kount);
01679 delete[] basisIdx[ 1];
01680 basicVars.clear();
01681 }
01682
01683 if(nonBasicUpper.size() > 0)
01684 {
01685
01686 kount = 0;
01687
01688 basisIdx[ 2] = new int[ nonBasicUpper.size()];
01689
01690 for(vit = nonBasicUpper.begin(); vit < nonBasicUpper.end(); vit++)
01691 {
01692 basisIdx[2][ kount++] = *vit;
01693 }
01694
01695 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atUpper, basisIdx[ 2], kount);
01696 delete[] basisIdx[ 2];
01697 nonBasicUpper.clear();
01698 }
01699
01700 if(nonBasicLower.size() > 0)
01701 {
01702 kount = 0;
01703
01704 basisIdx[ 3] = new int[ nonBasicLower.size()];
01705
01706 for(vit = nonBasicLower.begin(); vit < nonBasicLower.end(); vit++)
01707 {
01708 basisIdx[3][ kount++] = *vit;
01709 }
01710
01711 osresult->setBasisStatus(0, ENUM_PROBLEM_COMPONENT_constraints, ENUM_BASIS_STATUS_atLower, basisIdx[ 3], kount);
01712 delete[] basisIdx[ 3];
01713 nonBasicLower.clear();
01714
01715 }
01716
01717
01718
01719 }
01720
01721
01722
01723
01724 if( sSolverName.find( "symphony") == std::string::npos && osinstance->getNumberOfIntegerVariables() == 0 && osinstance->getNumberOfBinaryVariables() == 0)
01725 {
01726
01727 if(numOfIntVars <= 0)
01728 {
01729 osresult->setNumberOfOtherVariableResults(solIdx, numberOfOtherVariableResults);
01730 for(i=0; i < numberOfVar; i++)
01731 {
01732 rcost[ i] = os_dtoa_format( solver->getReducedCost()[ i]);
01733 }
01734 osresult->setAnOtherVariableResultSparse(solIdx, otherIdx, "reduced_costs", "", "the variable reduced costs", idx, rcost, solver->getNumCols(), "", "double", "");
01735
01736 }
01737 }
01738
01739 ostringstream temp;
01740 temp << solver->getIterationCount();
01741 if (!osresult->setAnOtherSolutionResult(0,"iterations",temp.str(),"","",0,NULL))
01742 throw ErrorClass("error setting iteration count");
01743
01744 osrl = osrlwriter->writeOSrL( osresult);
01745
01746 if (y != NULL)
01747 {
01748 delete[] y;
01749 y = NULL;
01750 }
01751
01752 if (rbasis != NULL)
01753 {
01754 delete[] rbasis;
01755 rbasis = NULL;
01756 }
01757
01758 delete[] z;
01759 z = NULL;
01760
01761 delete[] basisIdx;
01762 basisIdx = NULL;
01763
01764 if (x != NULL)
01765 {
01766 delete[] x;
01767 x = NULL;
01768 }
01769
01770 if (cbasis != NULL)
01771 {
01772 delete[] cbasis;
01773 cbasis = NULL;
01774 }
01775
01776 if (rcost != NULL)
01777 {
01778 delete[] rcost;
01779 rcost = NULL;
01780 }
01781
01782 if (idx != NULL)
01783 {
01784 delete[] idx;
01785 idx = NULL;
01786 }
01787 }
01788
01789 catch(const ErrorClass& eclass)
01790 {
01791 if (y != NULL)
01792 {
01793 delete[] y;
01794 y = NULL;
01795 }
01796
01797 if (rbasis != NULL)
01798 {
01799 delete[] rbasis;
01800 rbasis = NULL;
01801 }
01802
01803 delete[] z;
01804 z = NULL;
01805
01806 delete[] basisIdx;
01807 basisIdx = NULL;
01808
01809 if (x != NULL)
01810 {
01811 delete[] x;
01812 x = NULL;
01813 }
01814
01815 if (cbasis != NULL)
01816 {
01817 delete[] cbasis;
01818 cbasis = NULL;
01819 }
01820
01821 if (rcost != NULL)
01822 {
01823 delete[] rcost;
01824 rcost = NULL;
01825 }
01826
01827 if (idx != NULL)
01828 {
01829 delete[] idx;
01830 idx = NULL;
01831 }
01832
01833 osresult->setGeneralMessage( eclass.errormsg);
01834 osresult->setGeneralStatusType( "error");
01835 osrl = osrlwriter->writeOSrL( osresult);
01836 throw ErrorClass( osrl) ;
01837 }
01838 }
01839
01840
01841 void CoinSolver::writeResult(CbcModel *model)
01842 {
01843 double *x = NULL;
01844 double *y = NULL;
01845
01846 double *z = NULL;
01847 int *idx = NULL;
01848 std::string *rcost = NULL;
01849
01850 if( model->getNumCols() > 0 ) x = new double[model->getNumCols() ];
01851 if( model->getNumRows() > 0 ) y = new double[model->getNumRows() ];
01852 if( model->getNumCols() > 0 ) idx = new int[ model->getNumCols() ];
01853 z = new double[1];
01854 if( model->getNumCols() > 0 ) rcost = new std::string[ model->getNumCols()];
01855
01856 int numberOfOtherVariableResults = 1;
01857 int otherIdx = 0;
01858 int numberOfVar = model->getNumCols();
01859 int numOfIntVars = osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables();
01860 int i = 0;
01861 int solIdx = 0;
01862 std::string description = "";
01863 osresult->setGeneralStatusType("normal");
01864 osresult->setTime(cpuTime);
01865
01866 osresult->setServiceName( OSgetVersionInfo() );
01867
01868
01869 int numberIntegerInfeasibilities = 0;
01870 int numberObjectInfeasibilities = 0;
01871 bool isFeasible = false;
01872 isFeasible = model->feasibleSolution( numberIntegerInfeasibilities,
01873 numberObjectInfeasibilities);
01874 std::string statusMsg;
01875 if(isFeasible == true)
01876 {
01877 statusMsg = "feasible";
01878 }
01879 else
01880 {
01881 statusMsg = "infeasible";
01882 }
01883
01884
01885 if (model->isProvenOptimal() == true )
01886 {
01887 osresult->setSolutionStatus(solIdx, "optimal", description);
01888 }
01889 else
01890 {
01891 if(model->isProvenInfeasible() == true)
01892 osresult->setSolutionStatus(solIdx, "infeasible", "the integer program is infeasible");
01893 else
01894 {
01895 if(model->isProvenDualInfeasible() == true)
01896 osresult->setSolutionStatus(solIdx, "infeasible", "the continuous relaxation is dual infeasible");
01897 else
01898 {
01899 if(model->isContinuousUnbounded() == true)
01900 osresult->setSolutionStatus(solIdx, statusMsg, "the continuous relaxation is unbounded");
01901 else
01902 {
01903 if(model->isNodeLimitReached() == true)
01904 osresult->setSolutionStatus(solIdx, statusMsg, "node limit reached");
01905 else
01906 {
01907 if(model->isSecondsLimitReached() == true)
01908 osresult->setSolutionStatus(solIdx, statusMsg, "time limit reached");
01909 else
01910 {
01911 if(model->isSolutionLimitReached() == true)
01912 osresult->setSolutionStatus(solIdx, statusMsg, "solution limit reached");
01913 else
01914 {
01915 if(model->isAbandoned() == true)
01916 osresult->setSolutionStatus(solIdx, statusMsg, "there are numerical difficulties");
01917 else
01918 osresult->setSolutionStatus(solIdx, statusMsg,"unknown");
01919 }
01920 }
01921 }
01922 }
01923 }
01924 }
01925 }
01926
01927
01928 if(numOfIntVars > 0) *(z + 0) = model->getObjValue();
01929 osresult->setObjectiveValuesDense(solIdx, z);
01930 for(i=0; i < model->getNumCols(); i++)
01931 {
01932 *(x + i) = model->getColSolution()[i];
01933 *(idx + i) = i;
01934 }
01935 osresult->setPrimalVariableValuesDense(solIdx, x);
01936 for(i=0; i < model->getNumRows(); i++)
01937 {
01938 *(y + i) = model->getRowPrice()[ i];
01939 }
01940 if(numOfIntVars <= 0) osresult->setDualVariableValuesDense(solIdx, y);
01941
01942
01943 if(numOfIntVars <= 0)
01944 {
01945 osresult->setNumberOfOtherVariableResults(solIdx, numberOfOtherVariableResults);
01946 for(i=0; i < numberOfVar; i++)
01947 {
01948 rcost[ i] = os_dtoa_format( model->getReducedCost()[ i]);
01949 }
01950 osresult->setAnOtherVariableResultSparse(solIdx, otherIdx, "reduced_costs", "", "the variable reduced costs", idx, rcost, model->getNumCols());
01951 }
01952
01953 osrl = osrlwriter->writeOSrL( osresult);
01954
01955 if(model->getNumCols() > 0) delete[] x;
01956 x = NULL;
01957 if(model->getNumRows() > 0) delete[] y;
01958 y = NULL;
01959 delete[] z;
01960 z = NULL;
01961 if(model->getNumCols() > 0)
01962 {
01963 delete[] rcost;
01964 rcost = NULL;
01965 delete[] idx;
01966 idx = NULL;
01967 }
01968 }
01969
01970