/home/coin/SVN-release/OS-2.4.2/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     std::string bonmin="bonmin.";
00035     std::string prefix = (b.prefix() == bonmin) ? "" : b.prefix();
00036     prefix += "oa_decomposition.";
00037     subMip_ = new SubMipSolver(b, prefix);
00038     double oaTime;
00039     b.options()->GetNumericValue("time_limit",oaTime,prefix);
00040     parameter().maxLocalSearch_ = INT_MAX;
00041     b.options()->GetIntegerValue("solution_limit", parameter().maxSols_,prefix);
00042     parameter().maxLocalSearchTime_ =
00043     std::min(b.getDoubleParameter(BabSetupBase::MaxTime), oaTime);
00044     if(parameter().maxSols_ > b.getIntParameter(BabSetupBase::MaxSolutions))
00045       parameter().maxSols_ = b.getIntParameter(BabSetupBase::MaxSolutions);
00046   }
00047   OACutGenerator2::~OACutGenerator2()
00048   {
00049      delete subMip_;
00050   }
00051 
00053   bool
00054   OACutGenerator2::doLocalSearch(BabInfo * babInfo) const
00055   {
00056     return (nLocalSearch_<parameters_.maxLocalSearch_ &&
00057             numSols_ < parameters_.maxSols_ &&
00058             CoinCpuTime() - timeBegin_ < parameters_.maxLocalSearchTime_);
00059   }
00061   double
00062   OACutGenerator2::performOa(OsiCuts &cs,
00063       solverManip &lpManip,
00064       BabInfo * babInfo,
00065       double & cutoff, const CglTreeInfo & info) const
00066   {
00067 
00068     double lastPeriodicLog = CoinCpuTime();
00069 
00070     //const int numcols = nlp_->getNumCols();
00071     double gap_tol = this->parameter().gap_tol_;
00072 
00073     bool isInteger = false;
00074 
00075     subMip_->setLpSolver(lpManip.si());
00076     OsiSolverInterface * lp = subMip_->solver();
00077     lp->resolve();
00078     OsiBranchingInformation branch_info(lp, false);
00079     bool milpOptimal = 1;
00080 
00081 
00082     double milpBound = -COIN_DBL_MAX;
00083     bool milpFeasible = 1;
00084     bool feasible = 1;
00085 
00086     subMip_->solve(cutoff, parameters_.subMilpLogLevel_,
00087         (parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime()));
00088     milpBound = std::max(milpBound, subMip_->lowBound());
00089     milpOptimal = subMip_->optimal();
00090 
00091     feasible = milpBound < cutoff;
00092     milpFeasible = feasible;
00093     isInteger = (subMip_->getLastSolution() != NULL);
00094     nLocalSearch_++;
00095 
00096     if (milpOptimal)
00097       handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00098     else
00099     {
00100       handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00101     }
00102 
00103     int nodeCount = subMip_->nodeCount();
00104 
00105     int numberPasses = 0;
00106 
00107 #ifdef OA_DEBUG
00108     bool foundSolution = 0;
00109 #endif
00110     double * nlpSol = NULL;
00111     double ub = cutoff;
00112     double gap = 1;
00113     while (isInteger && feasible) {
00114       numberPasses++;
00115       //after a prescribed elapsed time give some information to user
00116       double time = CoinCpuTime();
00117       if (time - lastPeriodicLog > parameters_.logFrequency_) {
00118         handler_->message(PERIODIC_MSG,messages_)
00119         <<time - timeBegin_<<cutoff
00120         <<milpBound
00121         <<CoinMessageEol;
00122         lastPeriodicLog = CoinCpuTime();
00123       }
00124 
00125 
00126       //setup the nlp
00127       int numberCutsBefore = cs.sizeRowCuts();
00128 
00129       //Fix the variable which have to be fixed, after having saved the bounds
00130       const double * colsol = 
00131           subMip_->getLastSolution();
00132       branch_info.solution_ = colsol;
00133 
00134       fixIntegers(*nlp_,branch_info, parameters_.cbcIntegerTolerance_,objects_, nObjects_);
00135 
00136       nlp_->resolve(txt_id);
00137       if (post_nlp_solve(babInfo, cutoff)) {
00138         //nlp solved and feasible
00139         // Update the cutoff
00140         ub = std::min(nlp_->getObjValue(), ub);
00141         cutoff = ub > 0 ? ub *(1 - parameters_.cbcCutoffIncrement_) : ub*(1 + parameters_.cbcCutoffIncrement_);
00142         assert(cutoff < ub);
00143         // Update the lp solver cutoff
00144         lp->setDblParam(OsiDualObjectiveLimit, cutoff);
00145         numSols_++;
00146       }
00147 
00148       nlpSol = const_cast<double *>(nlp_->getColSolution());
00149 
00150       // Get the cuts outer approximation at the current point
00151       const double * toCut = (parameter().addOnlyViolated_)?
00152           colsol:NULL;
00153       nlp_->getOuterApproximation(cs, nlpSol, 1, toCut,
00154                                   parameter().global_);
00155 
00156       int numberCuts = cs.sizeRowCuts() - numberCutsBefore;
00157       assert(numberCuts);
00158       installCuts(*lp, cs, numberCuts);
00159 
00160       lp->resolve();
00161 
00162       double objvalue = lp->getObjValue();
00163       //milpBound = max(milpBound, lp->getObjValue());
00164       feasible = (lp->isProvenOptimal() &&
00165           !lp->isDualObjectiveLimitReached() && (objvalue<cutoff)) ;
00166       //if value of integers are unchanged then we have to get out
00167       bool changed = !feasible;//if lp is infeasible we don't have to check anything
00168       branch_info.solution_ = lp->getColSolution();
00169       if (!changed)
00170         changed = isDifferentOnIntegers(*nlp_, objects_, nObjects_,
00171                                         0.1,
00172                                         nlp_->getColSolution(), lp->getColSolution());
00173       if (changed) {
00174 
00175         isInteger = integerFeasible(*lp, branch_info, parameters_.cbcIntegerTolerance_,
00176                                      objects_, nObjects_);
00177       }
00178       else {
00179         isInteger = 0;
00180         //        if(!fixed)//fathom on bounds
00181         milpBound = 1e200;
00182       }
00183 #ifdef OA_DEBUG
00184       printf("Obj value after cuts %g %d rows\n",lp->getObjValue(),
00185           numberCuts) ;
00186 #endif
00187       //check time
00188       if (CoinCpuTime() - timeBegin_ > parameters_.maxLocalSearchTime_)
00189         break;
00190       
00191       if(ub!=0)
00192           gap = (ub - milpBound)/fabs(ub);
00193       else
00194                   gap = -milpBound/(1e-10);
00195       if (gap < gap_tol){
00196                  milpBound = 1e50;
00197                  feasible = 0;
00198                  handler_->message(OASUCCESS, messages_)<<"OA finished due to gap tolerance"<<CoinCpuTime() - timeBegin_ 
00199                  <<ub<<CoinMessageEol;
00200            }
00201       //do we perform a new local search ?
00202       if (feasible && 
00203           nLocalSearch_ < parameters_.maxLocalSearch_ &&
00204           numSols_ < parameters_.maxSols_) {
00205 
00206           if(ub!=0)
00207                   gap = (ub - milpBound)/fabs(ub);
00208           else
00209                   gap = -milpBound/(1e-10);
00210           if (gap < gap_tol){
00211                  milpBound = 1e50;
00212                  feasible = 0;
00213                  handler_->message(OASUCCESS, messages_)<<"OA finished due to gap tolerance"<<CoinCpuTime() - timeBegin_ 
00214                  <<ub<<CoinMessageEol;
00215            }
00216         nLocalSearch_++;
00217 
00218         assert(cutoff < ub);
00219         subMip_->solve(cutoff, parameters_.subMilpLogLevel_,
00220             parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime()
00221             );
00222 
00223         milpBound = std::max(milpBound, subMip_->lowBound());
00224 
00225         if (subMip_->optimal())
00226           handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00227         else
00228           handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00229 
00230         nodeCount += subMip_->nodeCount();
00231 
00232         colsol = const_cast<double *> (subMip_->getLastSolution());
00233         isInteger = (colsol != 0);
00234 
00235         feasible =  (milpBound < cutoff);
00236 
00237         if (feasible && isInteger) {
00238           bool changed = false;
00239           changed = isDifferentOnIntegers(*nlp_, objects_, nObjects_,
00240                                           0.1,
00241                                           nlp_->getColSolution(), colsol);
00242           //solution problem is solved
00243           if (!changed) {
00244             feasible = 0;
00245             milpBound = 1e50;
00246           }
00247           milpFeasible = feasible;
00248         }
00249         if (subMip_->optimal())
00250           milpOptimal = 1;
00251         else {
00252           milpOptimal = 0;
00253         }
00254         if (milpBound < cutoff)
00255                   handler_->message(UPDATE_LB, messages_)<<milpBound<<CoinCpuTime() - timeBegin_<<CoinMessageEol;
00256                 else {
00257                   milpBound = 1e50;
00258                   feasible = 0;
00259                   handler_->message(OASUCCESS, messages_)<<"OA"<<CoinCpuTime() - timeBegin_ 
00260                   <<ub<<CoinMessageEol;
00261                 }
00262       }
00263       
00264     }
00265 
00266 
00267    handler_->message(OA_STATS, messages_)<<numberPasses<<nodeCount
00268                                          <<CoinMessageEol;
00269 #ifdef OA_DEBUG
00270     debug_.printEndOfProcedureDebugMessage(cs, foundSolution, cutoff, milpBound, isInteger, feasible, std::cout);
00271 #endif
00272     return milpBound;
00273   }
00274 
00276   void
00277   OACutGenerator2::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00278   {
00279     roptions->SetRegisteringCategory("Options for OA decomposition", RegisteredOptions::BonminCategory);
00280     roptions->AddStringOption2("oa_decomposition", "If yes do initial OA decomposition",
00281                                "no",
00282                                "no","",
00283                                "yes","",
00284                                "");
00285     roptions->setOptionExtraInfo("oa_decomposition",19);
00286 
00287     roptions->AddBoundedIntegerOption("oa_log_level",
00288         "specify OA iterations log level.",
00289         0,2,1,
00290         "Set the level of output of OA decomposition solver : "
00291         "0 - none, 1 - normal, 2 - verbose"
00292                                      );
00293     roptions->setOptionExtraInfo("oa_log_level", 25);
00294 
00295     roptions->AddLowerBoundedNumberOption("oa_log_frequency",
00296         "display an update on lower and upper bounds in OA every n seconds",
00297         0.,1.,100.,
00298         "");
00299     roptions->setOptionExtraInfo("oa_log_frequency", 25);
00300   }
00301 }/* End namespace Bonmin. */
00302 

Generated on Wed Nov 30 03:03:53 2011 by  doxygen 1.4.7