/home/coin/SVN-release/OS-2.1.1/Bonmin/src/Algorithms/BonSubMipSolver.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines (IBM) 2006
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // P. Bonami, International Business Machines
00007 //
00008 // Date :  12/07/2006
00009 
00010 
00011 // Code separated from BonOaDecBase to try to clarify OAs
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       //Change Cbc messages prefixes
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           //iterationCount_ += CPXgetitcnt(env, cpxlp);
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       //Change Cbc messages prefixes
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       //cbc_->solver()->writeMpsNative("FP.mps", NULL, NULL, 1);
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         //CpxModel = cpx_;
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       //CpxModel = NULL;
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 }/* Ends Bonmin namespace.*/

Generated on Mon May 3 03:05:14 2010 by  doxygen 1.4.7