00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "BonSubMipSolver.hpp"
00013 #include "CbcModel.hpp"
00014 #include "CbcStrategy.hpp"
00015 #include "OsiAuxInfo.hpp"
00016 #include "OsiClpSolverInterface.hpp"
00017
00018 #ifdef COIN_HAS_CPX
00019 #include "OsiCpxSolverInterface.hpp"
00020 #include "cplex.h"
00021 #define CHECK_CPX_STAT(a,b) if(b) throw CoinError("Error in CPLEX call",__FILE__,a);
00022
00023 #endif
00024
00025 #include "BonRegisteredOptions.hpp"
00026
00027 namespace Bonmin {
00029 SubMipSolver::SubMipSolver(OsiSolverInterface * lp,
00030 const CbcStrategy * strategy):
00031 lp_(lp),
00032 clp_(NULL),
00033 cpx_(NULL),
00034 cbc_(NULL),
00035 lowBound_(-COIN_DBL_MAX),
00036 optimal_(false),
00037 integerSolution_(NULL),
00038 strategy_(NULL)
00039 {
00040 clp_ = (lp_ == NULL)? NULL :
00041 dynamic_cast<OsiClpSolverInterface *>(lp_);
00042 #ifdef COIN_HAS_CPX
00043 cpx_ = (lp_ == NULL)? NULL :
00044 dynamic_cast<OsiCpxSolverInterface *>(lp_);
00045 #endif
00046 if (strategy) {
00047 strategy_ = dynamic_cast<CbcStrategyDefault *>(strategy->clone());
00048 assert(strategy_);
00049 }
00050 }
00051 SubMipSolver::~SubMipSolver()
00052 {
00053 if (strategy_) delete strategy_;
00054 if (integerSolution_) delete [] integerSolution_;
00055 if (cbc_) delete cbc_;
00056 }
00057
00059 void
00060 SubMipSolver::setLpSolver(OsiSolverInterface * lp)
00061 {
00062 lp_ = lp;
00063 clp_ = (lp_ == NULL) ? NULL :
00064 dynamic_cast<OsiClpSolverInterface *>(lp_);
00065 #ifdef COIN_HAS_CPX
00066 cpx_ = (lp_ == NULL) ? NULL :
00067 dynamic_cast<OsiCpxSolverInterface *>(lp_);
00068 #endif
00069 lowBound_ = -COIN_DBL_MAX;
00070 optimal_ = false;
00071 if (integerSolution_) {
00072 delete [] integerSolution_;
00073 integerSolution_ = NULL;
00074 }
00075 }
00076
00077
00078 void
00079 SubMipSolver::find_good_sol(double cutoff, int loglevel, double max_time){
00080
00081 if(clp_){
00082 CbcStrategyDefault * strat_default = NULL;
00083 if (!strategy_){
00084 strat_default = new CbcStrategyDefault(1,5,5, loglevel);
00085 strat_default->setupPreProcessing();
00086 strategy_ = strat_default;
00087 }
00088 OsiBabSolver empty;
00089 if (cbc_) delete cbc_;
00090 cbc_ = new CbcModel(*clp_);
00091 cbc_->solver()->setAuxiliaryInfo(&empty);
00092
00093
00094 strcpy(cbc_->messagesPointer()->source_,"OaCbc");
00095
00096 cbc_->setLogLevel(loglevel);
00097 cbc_->solver()->messageHandler()->setLogLevel(0);
00098 clp_->resolve();
00099 cbc_->setStrategy(*strategy_);
00100 cbc_->setLogLevel(loglevel);
00101 cbc_->solver()->messageHandler()->setLogLevel(0);
00102 cbc_->setMaximumSeconds(max_time);
00103 cbc_->setMaximumSolutions(1);
00104 cbc_->setCutoff(cutoff);
00105
00106
00107 cbc_->branchAndBound();
00108 lowBound_ = cbc_->getBestPossibleObjValue();
00109
00110 if (cbc_->isProvenOptimal() || cbc_->isProvenInfeasible())
00111 optimal_ = true;
00112 else optimal_ = false;
00113
00114 if (cbc_->getSolutionCount()) {
00115 if (!integerSolution_)
00116 integerSolution_ = new double[lp_->getNumCols()];
00117 CoinCopyN(cbc_->bestSolution(), lp_->getNumCols(), integerSolution_);
00118 }
00119 else if (integerSolution_) {
00120 delete [] integerSolution_;
00121 integerSolution_ = NULL;
00122 }
00123 nodeCount_ = cbc_->getNodeCount();
00124 iterationCount_ = cbc_->getIterationCount();
00125
00126 if(strat_default != NULL){
00127 delete strat_default;
00128 strategy_ = NULL;
00129 }
00130 }
00131 else if (cpx_){
00132 #ifndef COIN_HAS_CPX
00133 throw CoinError("Unsuported solver, for local searches you should use clp or cplex",
00134 "performLocalSearch",
00135 "OaDecompositionBase::SubMipSolver");
00136 #else
00137 cpx_->switchToMIP();
00138 CPXENVptr env = cpx_->getEnvironmentPtr();
00139 CPXLPptr cpxlp = cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
00140 CPXsetdblparam(env, CPX_PARAM_TILIM, max_time);
00141 CPXsetdblparam(env, CPX_PARAM_EPINT, 1e-08);
00142 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
00143
00144
00145 CPXsetintparam(env,CPX_PARAM_INTSOLLIM, 10000);
00146 CPXsetintparam(env,CPX_PARAM_NODELIM, 100000);
00147 CPXsetdblparam(env,CPX_PARAM_TILIM, max_time);
00148
00149 nodeCount_ = 0;
00150 iterationCount_ = 0;
00151 int status = CPXmipopt(env,cpxlp);
00152 CHECK_CPX_STAT("mipopt",status)
00153
00154 status = CPXgetbestobjval(env, cpxlp, &lowBound_);
00155 CHECK_CPX_STAT("bestobjvalue",status)
00156
00157 int stat = CPXgetstat( env, cpxlp);
00158 CHECK_CPX_STAT("getstat",status)
00159 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL);
00160 nodeCount_ = CPXgetnodecnt(env , cpxlp);
00161 iterationCount_ = CPXgetmipitcnt(env , cpxlp);
00162
00163 CPXsetintparam(env, CPX_PARAM_INTSOLLIM, 1);
00164 CPXsetintparam(env,CPX_PARAM_NODELIM, 1000);
00165 while(stat == CPXMIP_NODE_LIM_INFEAS){
00166 status = CPXmipopt(env,cpxlp);
00167 CHECK_CPX_STAT("mipopt",status)
00168
00169 status = CPXgetstat( env, cpxlp);
00170 CHECK_CPX_STAT("getstat",status)
00171 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL);
00172 nodeCount_ = CPXgetnodecnt(env , cpxlp);
00173 iterationCount_ = CPXgetmipitcnt(env , cpxlp);
00174 }
00175 bool infeasible = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_ABORT_INFEAS) || (stat == CPXMIP_TIME_LIM_INFEAS)
00176 || (stat == CPXMIP_NODE_LIM_INFEAS) || (stat == CPXMIP_FAIL_INFEAS)
00177 || (stat == CPXMIP_MEM_LIM_INFEAS) || (stat == CPXMIP_INForUNBD);
00178
00179
00180 if(!infeasible){
00181 nodeCount_ += CPXgetnodecnt(env, cpxlp);
00182
00183 if(!integerSolution_){
00184 integerSolution_ = new double[lp_->getNumCols()];
00185 }
00186 CPXgetmipx(env, cpxlp, integerSolution_, 0, lp_->getNumCols() -1);
00187 CHECK_CPX_STAT("getmipx",status)
00188 }
00189 else {
00190 if (integerSolution_) {
00191 delete [] integerSolution_;
00192 integerSolution_ = NULL;
00193 }
00194 }
00195 cpx_->switchToLP();
00196 #endif
00197 }
00198 else {
00199
00200 lp_->branchAndBound();
00201
00202 optimal_ = lp_->isProvenOptimal();
00203 if (lp_->getFractionalIndices().size() == 0) {
00204 if (!integerSolution_)
00205 integerSolution_ = new double[lp_->getNumCols()];
00206 CoinCopyN(lp_->getColSolution(), lp_->getNumCols() , integerSolution_);
00207 }
00208 else if (integerSolution_) {
00209 delete [] integerSolution_;
00210 integerSolution_ = NULL;
00211 }
00212 }
00213 }
00214
00215 void
00216 SubMipSolver::optimize(double cutoff, int loglevel, double maxTime)
00217 {
00218 if (clp_) {
00219 assert(strategy_);
00220 CbcStrategyDefault * strat_default = dynamic_cast<CbcStrategyDefault *>(strategy_->clone());
00221 assert(strat_default);
00222 strat_default->setupPreProcessing();
00223
00224 OsiBabSolver empty;
00225 if (cbc_) delete cbc_;
00226 cbc_ = new CbcModel(*clp_);
00227 cbc_->solver()->setAuxiliaryInfo(&empty);
00228
00229
00230 strcpy(cbc_->messagesPointer()->source_,"OaCbc");
00231
00232 cbc_->setLogLevel(loglevel);
00233 cbc_->solver()->messageHandler()->setLogLevel(0);
00234 clp_->resolve();
00235 cbc_->setStrategy(*strategy_);
00236 cbc_->setLogLevel(loglevel);
00237 cbc_->solver()->messageHandler()->setLogLevel(0);
00238 cbc_->setMaximumSeconds(maxTime);
00239 cbc_->setCutoff(cutoff);
00240
00241
00242 cbc_->branchAndBound();
00243 lowBound_ = cbc_->getBestPossibleObjValue();
00244
00245 if (cbc_->isProvenOptimal() || cbc_->isProvenInfeasible())
00246 optimal_ = true;
00247 else optimal_ = false;
00248
00249 if (cbc_->getSolutionCount()) {
00250 if (!integerSolution_)
00251 integerSolution_ = new double[lp_->getNumCols()];
00252 CoinCopyN(cbc_->bestSolution(), lp_->getNumCols(), integerSolution_);
00253 }
00254 else if (integerSolution_) {
00255 delete [] integerSolution_;
00256 integerSolution_ = NULL;
00257 }
00258 nodeCount_ = cbc_->getNodeCount();
00259 iterationCount_ = cbc_->getIterationCount();
00260 delete strat_default;
00261 }
00262 else {
00263 lp_->messageHandler()->setLogLevel(loglevel);
00264 #ifdef COIN_HAS_CPX
00265 if (cpx_) {
00266 CPXENVptr env = cpx_->getEnvironmentPtr();
00267 CPXsetdblparam(env, CPX_PARAM_TILIM, maxTime);
00268 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
00269
00270 }
00271 else
00272 #endif
00273 {
00274 throw CoinError("Unsuported solver, for local searches you should use clp or cplex",
00275 "performLocalSearch",
00276 "OaDecompositionBase::SubMipSolver");
00277 }
00278
00279 #ifdef COIN_HAS_CPX
00280 if (cpx_) {
00281 cpx_->switchToMIP();
00282
00283 CPXENVptr env = cpx_->getEnvironmentPtr();
00284 CPXLPptr cpxlp = cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
00285
00286 int status = CPXmipopt(env,cpxlp);
00287 CHECK_CPX_STAT("mipopt",status)
00288
00289 int stat = CPXgetstat( env, cpxlp);
00290 bool infeasible = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_ABORT_INFEAS) || (stat == CPXMIP_TIME_LIM_INFEAS) || (stat == CPXMIP_NODE_LIM_INFEAS) || (stat == CPXMIP_FAIL_INFEAS)
00291 || (stat == CPXMIP_MEM_LIM_INFEAS) || (stat == CPXMIP_INForUNBD);
00292 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL);
00293 nodeCount_ = CPXgetnodecnt(env , cpxlp);
00294 iterationCount_ = CPXgetmipitcnt(env , cpxlp);
00295 status = CPXgetbestobjval(env, cpxlp, &lowBound_);
00296 CHECK_CPX_STAT("getbestobjval",status)
00297
00298 if(!infeasible){
00299 if(!integerSolution_){
00300 integerSolution_ = new double[lp_->getNumCols()];
00301 }
00302 CPXgetmipx(env, cpxlp, integerSolution_, 0, lp_->getNumCols() -1);
00303 CHECK_CPX_STAT("getmipx",status)
00304 }
00305 else {
00306 if (integerSolution_) {
00307 delete [] integerSolution_;
00308 integerSolution_ = NULL;
00309 }
00310 }
00311 cpx_->switchToLP();
00312 }
00313 else {
00314 #endif
00315 lp_->branchAndBound();
00316
00317 optimal_ = lp_->isProvenOptimal();
00318
00319
00320 if (lp_->getFractionalIndices().size() == 0) {
00321 if (!integerSolution_)
00322 integerSolution_ = new double[lp_->getNumCols()];
00323 CoinCopyN(lp_->getColSolution(), lp_->getNumCols() , integerSolution_);
00324 }
00325 else if (integerSolution_) {
00326 delete [] integerSolution_;
00327 integerSolution_ = NULL;
00328 }
00329 #ifdef COIN_HAS_CPX
00330 }
00331 #endif
00332 }
00333 }
00334
00336 void
00337 SubMipSolver::setStrategy(CbcStrategyDefault * strategy)
00338 {
00339 if (strategy_) delete strategy_;
00340 strategy_ = dynamic_cast<CbcStrategyDefault *>(strategy->clone());
00341 assert(strategy_);
00342 }
00343
00345 void
00346 SubMipSolver::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00347 {
00348 roptions->SetRegisteringCategory("Options for MILP solver", RegisteredOptions::BonminCategory);
00349 roptions->AddStringOption3("milp_solver",
00350 "Choose the subsolver to solve MILP sub-problems in OA decompositions.",
00351 "Cbc_D",
00352 "Cbc_D","Coin Branch and Cut with its default",
00353 "Cbc_Par", "Coin Branch and Cut with passed parameters",
00354 "Cplex","Ilog Cplex",
00355 " To use Cplex, a valid license is required and you should have compiled OsiCpx in COIN-OR (see Osi documentation).");
00356 roptions->setOptionExtraInfo("milp_solver",64);
00357
00358 roptions->AddBoundedIntegerOption("milp_log_level",
00359 "specify MILP solver log level.",
00360 0,3,0,
00361 "Set the level of output of the MILP subsolver in OA : "
00362 "0 - none, 1 - minimal, 2 - normal low, 3 - normal high"
00363 );
00364 roptions->setOptionExtraInfo("milp_log_level",64);
00365
00366 roptions->AddLowerBoundedIntegerOption("cplex_number_threads",
00367 "Set number of threads to use with cplex.",
00368 0, 0,
00369 "number of threads used with cplex (refer to CPLEX documentation)"
00370 );
00371 roptions->setOptionExtraInfo("cplex_number_threads",64);
00372
00373
00374 }
00375 }