/home/coin/SVN-release/OS-2.2.0/Bonmin/src/Algorithms/OaGenerators/BonOACutGenerator2.cpp

Go to the documentation of this file.
00001 // (C) Copyright Carnegie Mellon University 2005, 2006
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // P. Bonami, Carnegie Mellon University
00007 //
00008 // Date : 05/26/2005
00009 
00010 #include "BonOACutGenerator2.hpp"
00011 #include "BonminConfig.h"
00012 
00013 #include "OsiClpSolverInterface.hpp"
00014 
00015 #include "CbcModel.hpp"
00016 #include "BonCbcLpStrategy.hpp"
00017 #ifdef COIN_HAS_CPX
00018 #include "OsiCpxSolverInterface.hpp"
00019 #endif
00020 #include "OsiAuxInfo.hpp"
00021 #include "BonSolverHelp.hpp"
00022 
00023 #include <climits>
00024 
00025 namespace Bonmin
00026 {
00027    static const char * txt_id = "OA decomposition";
00028 
00029 
00031   OACutGenerator2::OACutGenerator2(BabSetupBase & b):
00032       OaDecompositionBase(b, true, false)
00033   {
00034     int ivalue;
00035     std::string bonmin="bonmin.";
00036     std::string prefix = (b.prefix() == bonmin) ? "" : b.prefix();
00037     prefix += "oa_decomposition.";
00038     b.options()->GetEnumValue("milp_solver",ivalue,prefix);
00039     if (ivalue <= 0) {//uses cbc
00040       CbcStrategyDefault strategy;
00041       setStrategy(strategy);
00042     }
00043     else if (ivalue == 1) {
00044       CbcStrategyChooseCuts strategy(b, prefix);
00045       setStrategy(strategy);
00046     }
00047     else if (ivalue == 2) {
00048 #ifdef COIN_HAS_CPX
00049       OsiCpxSolverInterface * cpxSolver = new OsiCpxSolverInterface;
00050       b.nonlinearSolver()->extractLinearRelaxation(*cpxSolver);
00051       assignLpInterface(cpxSolver);
00052 #else
00053       std::cerr << "You have set an option to use CPLEX as the milp\n"
00054       << "subsolver in oa decomposition. However, apparently\n"
00055       << "CPLEX is not configured to be used in bonmin.\n"
00056       << "See the manual for configuring CPLEX\n";
00057       throw -1;
00058 #endif
00059     }
00060 
00061     double oaTime;
00062     b.options()->GetNumericValue("time_limit",oaTime,prefix);
00063     parameter().maxLocalSearchTime_ =
00064     std::min(b.getDoubleParameter(BabSetupBase::MaxTime), oaTime);
00065     parameter().maxLocalSearch_ = INT_MAX;
00066     b.options()->GetIntegerValue("solution_limit", parameter().maxSols_,prefix);
00067   }
00068   OACutGenerator2::~OACutGenerator2()
00069   {}
00070 
00072   bool
00073   OACutGenerator2::doLocalSearch(BabInfo * babInfo) const
00074   {
00075     return (nLocalSearch_<parameters_.maxLocalSearch_ &&
00076             numSols_ < parameters_.maxSols_ &&
00077             CoinCpuTime() - timeBegin_ < parameters_.maxLocalSearchTime_);
00078   }
00080   double
00081   OACutGenerator2::performOa(OsiCuts &cs,
00082       solverManip &lpManip,
00083       SubMipSolver * &subMip,
00084       BabInfo * babInfo,
00085       double & cutoff, const CglTreeInfo & info) const
00086   {
00087 
00088     double lastPeriodicLog = CoinCpuTime();
00089 
00090     //const int numcols = nlp_->getNumCols();
00091 
00092 
00093     bool isInteger = false;
00094 
00095     OsiSolverInterface * lp = lpManip.si();
00096     OsiBranchingInformation branch_info(lp, false);
00097     bool milpOptimal = 1;
00098 
00099 
00100     double milpBound = -COIN_DBL_MAX;
00101     bool milpFeasible = 1;
00102     bool feasible = 1;
00103 
00104     if (subMip)//Perform a local search
00105     {
00106       subMip->find_good_sol(cutoff, parameters_.subMilpLogLevel_,
00107           (parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime()));
00108       milpBound = std::max(milpBound, subMip->lowBound());
00109       milpOptimal = subMip->optimal();
00110 
00111       feasible = milpBound < cutoff;
00112       milpFeasible = feasible;
00113       isInteger = (subMip->getLastSolution() != NULL);
00114       nLocalSearch_++;
00115 
00116       if (milpOptimal)
00117         handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip->nodeCount()<<subMip->iterationCount()<<CoinMessageEol;
00118       else
00119       {
00120         handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip->nodeCount()<<subMip->iterationCount()<<CoinMessageEol;
00121       }
00122     }
00123     int numberPasses = 0;
00124 
00125 #ifdef OA_DEBUG
00126     bool foundSolution = 0;
00127 #endif
00128     double * nlpSol = NULL;
00129     double ub = cutoff;
00130     while (isInteger && feasible ) {
00131       numberPasses++;
00132       //after a prescribed elapsed time give some information to user
00133       double time = CoinCpuTime();
00134       if (time - lastPeriodicLog > parameters_.logFrequency_) {
00135         handler_->message(PERIODIC_MSG,messages_)
00136         <<time - timeBegin_<<cutoff
00137         <<milpBound
00138         <<CoinMessageEol;
00139         lastPeriodicLog = CoinCpuTime();
00140       }
00141 
00142 
00143       //setup the nlp
00144       int numberCutsBefore = cs.sizeRowCuts();
00145 
00146       //Fix the variable which have to be fixed, after having saved the bounds
00147       const double * colsol = subMip == NULL ? lp->getColSolution():
00148           subMip->getLastSolution();
00149       branch_info.solution_ = colsol;
00150 
00151       fixIntegers(*nlp_,branch_info, parameters_.cbcIntegerTolerance_,objects_, nObjects_);
00152 
00153       nlp_->resolve(txt_id);
00154       if (post_nlp_solve(babInfo, cutoff)) {
00155         //nlp solved and feasible
00156         // Update the cutoff
00157         ub = std::min(nlp_->getObjValue(), ub);
00158         cutoff = ub *(1 - parameters_.cbcCutoffIncrement_);
00159         // Update the lp solver cutoff
00160         lp->setDblParam(OsiDualObjectiveLimit, cutoff);
00161         numSols_++;
00162       }
00163 
00164       nlpSol = const_cast<double *>(nlp_->getColSolution());
00165 
00166       // Get the cuts outer approximation at the current point
00167       const double * toCut = (parameter().addOnlyViolated_)?
00168           colsol:NULL;
00169       nlp_->getOuterApproximation(cs, nlpSol, 1, toCut,
00170                                   parameter().global_);
00171 
00172       int numberCuts = cs.sizeRowCuts() - numberCutsBefore;
00173       assert(numberCuts);
00174       installCuts(*lp, cs, numberCuts);
00175 
00176       lp->resolve();
00177 
00178       double objvalue = lp->getObjValue();
00179       //milpBound = max(milpBound, lp->getObjValue());
00180       feasible = (lp->isProvenOptimal() &&
00181           !lp->isDualObjectiveLimitReached() && (objvalue<cutoff)) ;
00182       //if value of integers are unchanged then we have to get out
00183       bool changed = !feasible;//if lp is infeasible we don't have to check anything
00184       branch_info.solution_ = lp->getColSolution();
00185       if (!changed)
00186         changed = isDifferentOnIntegers(*nlp_, objects_, nObjects_,
00187                                         0.1,
00188                                         nlp_->getColSolution(), lp->getColSolution());
00189       if (changed) {
00190 
00191         isInteger = integerFeasible(*lp, branch_info, parameters_.cbcIntegerTolerance_,
00192                                      objects_, nObjects_);
00193       }
00194       else {
00195         isInteger = 0;
00196         //        if(!fixed)//fathom on bounds
00197         milpBound = 1e200;
00198       }
00199 #ifdef OA_DEBUG
00200       printf("Obj value after cuts %g %d rows\n",lp->getObjValue(),
00201           numberCuts) ;
00202 #endif
00203       //check time
00204       if (CoinCpuTime() - timeBegin_ > parameters_.maxLocalSearchTime_)
00205         break;
00206       //do we perform a new local search ?
00207       if (feasible && !isInteger &&
00208           nLocalSearch_ < parameters_.maxLocalSearch_ &&
00209           numSols_ < parameters_.maxSols_) {
00210 
00212         if (subMip == NULL) subMip = new SubMipSolver(lp, parameters_.strategy());
00213 
00214         nLocalSearch_++;
00215 
00216         subMip->find_good_sol(cutoff, parameters_.subMilpLogLevel_,
00217             parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime()
00218             );
00219 
00220         milpBound = std::max(milpBound, subMip->lowBound());
00221 
00222         if (subMip->optimal())
00223           handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip->nodeCount()<<subMip->iterationCount()<<CoinMessageEol;
00224         else
00225           handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip->nodeCount()<<subMip->iterationCount()<<CoinMessageEol;
00226 
00227 
00228         colsol = const_cast<double *> (subMip->getLastSolution());
00229         isInteger = (colsol != 0);
00230 
00231         feasible =  (milpBound < cutoff);
00232 
00233         if (feasible && isInteger) {
00234           bool changed = false;
00235           changed = isDifferentOnIntegers(*nlp_, objects_, nObjects_,
00236                                           0.1,
00237                                           nlp_->getColSolution(), colsol);
00238           //solution problem is solved
00239           if (!changed) {
00240             feasible = 0;
00241             milpBound = 1e50;
00242           }
00243           milpFeasible = feasible;
00244         }
00245         if (subMip->optimal())
00246           milpOptimal = 1;
00247         else {
00248           milpOptimal = 0;
00249         }
00250 
00251         if (milpBound < cutoff)
00252           handler_->message(UPDATE_LB, messages_)<<milpBound<<CoinCpuTime() - timeBegin_<<CoinMessageEol;
00253         else {
00254           milpBound = 1e50;
00255           feasible = 0;
00256           handler_->message(OASUCCESS, messages_)<<"OA"<<CoinCpuTime() - timeBegin_ 
00257           <<ub<<CoinMessageEol;
00258         }
00259       }
00260       else if (subMip!=NULL) {
00261         delete subMip;
00262         subMip = NULL;
00263       }
00264     }
00265 
00266 #ifdef OA_DEBUG
00267     debug_.printEndOfProcedureDebugMessage(cs, foundSolution, cutoff, milpBound, isInteger, feasible, std::cout);
00268 #endif
00269     return milpBound;
00270   }
00271 
00273   void
00274   OACutGenerator2::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00275   {
00276     roptions->SetRegisteringCategory("Options for OA decomposition", RegisteredOptions::BonminCategory);
00277     roptions->AddStringOption2("oa_decomposition", "If yes do initial OA decomposition",
00278                                "no",
00279                                "no","",
00280                                "yes","",
00281                                "");
00282     roptions->setOptionExtraInfo("oa_decomposition",19);
00283 
00284     roptions->AddBoundedIntegerOption("oa_log_level",
00285         "specify OA iterations log level.",
00286         0,2,1,
00287         "Set the level of output of OA decomposition solver : "
00288         "0 - none, 1 - normal, 2 - verbose"
00289                                      );
00290     roptions->setOptionExtraInfo("oa_log_level", 25);
00291 
00292     roptions->AddLowerBoundedNumberOption("oa_log_frequency",
00293         "display an update on lower and upper bounds in OA every n seconds",
00294         0.,1.,100.,
00295         "");
00296     roptions->setOptionExtraInfo("oa_log_frequency", 25);
00297   }
00298 }/* End namespace Bonmin. */
00299 

Generated on Thu Aug 5 03:02:54 2010 by  doxygen 1.4.7