/home/coin/SVN-release/OS-2.4.0/Bonmin/src/Algorithms/OaGenerators/BonFpForMinlp.cpp

Go to the documentation of this file.
00001 // (C) Copyright CNRS 2008
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // P. Bonami, CNRS
00007 //
00008 // Date : 02/13/2009
00009 
00010 #include "BonFpForMinlp.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 = "FP for MINLP";
00029   MinlpFeasPump::MinlpFeasPump(BabSetupBase & b):
00030       OaDecompositionBase(b, true, false),
00031       subMip_(NULL)
00032   {
00033     std::string bonmin="bonmin.";
00034     std::string prefix = (b.prefix() == bonmin) ? "" : b.prefix();
00035     prefix += "pump_for_minlp.";
00036     subMip_ = new SubMipSolver(b, prefix);
00037     double oaTime;
00038     b.options()->GetNumericValue("time_limit",oaTime,prefix);
00039     parameter().maxLocalSearch_ = INT_MAX;
00040     b.options()->GetIntegerValue("solution_limit", parameter().maxSols_,prefix);
00041     parameter().maxLocalSearchTime_ =
00042     std::min(b.getDoubleParameter(BabSetupBase::MaxTime), oaTime);
00043     if(parameter().maxSols_ > b.getIntParameter(BabSetupBase::MaxSolutions))
00044       parameter().maxSols_ = b.getIntParameter(BabSetupBase::MaxSolutions);
00045     b.options()->GetEnumValue("fp_pass_infeasible", passBound_, prefix);
00046  }
00047 
00048   MinlpFeasPump::~MinlpFeasPump()
00049   {
00050     delete subMip_;
00051   }
00052 
00054   bool
00055   MinlpFeasPump::doLocalSearch(BabInfo * babInfo) const
00056   {
00057     return (nLocalSearch_<parameters_.maxLocalSearch_ &&
00058         CoinCpuTime() - timeBegin_ < parameters_.maxLocalSearchTime_ &&
00059         numSols_ < parameters_.maxSols_);
00060   }
00062   double
00063   MinlpFeasPump::performOa(OsiCuts &cs,
00064       solverManip &lpManip,
00065       BabInfo * babInfo,
00066       double & cutoff,const CglTreeInfo &info) const
00067   {
00068 
00069     //bool interuptOnLimit = false;
00070     //double lastPeriodicLog = CoinCpuTime();
00071 
00072     const int numcols = nlp_->getNumCols();
00073     vector<double> savedColLower(nlp_->getNumCols());
00074     CoinCopyN(nlp_->getColLower(), nlp_->getNumCols(), savedColLower());
00075     vector<double> savedColUpper(nlp_->getNumCols());
00076     CoinCopyN(nlp_->getColUpper(), nlp_->getNumCols(), savedColUpper());
00077 
00078 
00079     subMip_->setLpSolver(lpManip.si());
00080     OsiSolverInterface * lp = subMip_->solver();
00081 
00082     assert(lp);
00083     vector<int> indices;
00084     for(int i = 0; i < numcols ; i++) {
00085       lp->setObjCoeff(i,0);
00086       if(!lp->isInteger(i)) {
00087       }
00088       else { indices.push_back(i);}
00089     }
00090 
00091     // If objective is linear need to add to lp constraint for objective
00092     const double * colsol = NULL;
00093     lp->resolve();
00094     OsiBranchingInformation branch_info(lp, false);
00095     branch_info.lower_ = savedColLower();
00096     branch_info.upper_ = savedColUpper();
00097     if(lp->getNumCols() == nlp_->getNumCols())
00098       nlp_->addObjectiveFunction(*lp, nlp_->getColSolution());
00099     lp->setObjCoeff(numcols,0);
00100 
00101     bool milpOptimal = false;
00102     nlp_->resolve(txt_id);
00103     set_fp_objective(*lp, nlp_->getColSolution());
00104     lp->initialSolve();
00105     lp->setColUpper(numcols, cutoff);
00106     subMip_->solve(DBL_MAX, parameters_.subMilpLogLevel_,
00107     //subMip_->optimize(DBL_MAX, parameters_.subMilpLogLevel_,
00108         (parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime()) /* time limit */);
00109 
00110     milpOptimal = subMip_ -> optimal(); 
00111     colsol = subMip_->getLastSolution();
00112     nLocalSearch_++;
00113     if(milpOptimal)
00114       handler_->message(SOLVED_LOCAL_SEARCH, messages_)
00115       <<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00116     else
00117       handler_->message(LOCAL_SEARCH_ABORT, messages_)
00118       <<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00119     int numberPasses = 0;
00120 
00121 #ifdef OA_DEBUG
00122     bool foundSolution = 0;
00123 #endif
00124     double * nlpSol = NULL;
00125     int major_iteration = 0;
00126     double ub = cutoff;
00127     while (colsol) {
00128       numberPasses++;
00129 
00130       //setup the nlp
00131       int numberCutsBefore = cs.sizeRowCuts();
00132 
00133       //Fix the variable which have to be fixed, after having saved the bounds
00134       branch_info.solution_ = colsol;
00135 
00136       vector<double> x_bar(indices.size());
00137       for(unsigned int i = 0 ; i < indices.size() ; i++){
00138          assert(fabs(colsol[indices[i]] - floor(colsol[indices[i]] + 0.5)) < 1e-5);
00139          x_bar[i] = colsol[indices[i]];
00140       }
00141 
00142       double dist = nlp_->solveFeasibilityProblem(indices.size(), x_bar(), indices(), 1, 0, 2);
00143 
00144       handler_->message(FP_DISTANCE, messages_) 
00145       <<dist<<CoinMessageEol;
00146 
00147       if(dist < 1e-05){
00148          fixIntegers(*nlp_,branch_info, parameters_.cbcIntegerTolerance_, objects_, nObjects_);
00149 
00150          nlp_->resolve(txt_id);
00151          if(!nlp_->isProvenOptimal()){
00152            relaxIntegers(*nlp_,branch_info, parameters_.cbcIntegerTolerance_, objects_, nObjects_);
00153            nlp_->resolve(txt_id);
00154          }
00155          bool restart = false;
00156          if (post_nlp_solve(babInfo, cutoff)) {
00157            restart = true;
00158            //nlp is solved and feasible
00159            // Update the cutoff
00160            ub = std::min(ub, nlp_->getObjValue());
00161            cutoff = ub * (1 - parameters_.cbcCutoffIncrement_);
00162            
00163            numSols_++;
00164          }
00165          else{
00166            //nlp_->setColLower(savedColLower());
00167            //nlp_->setColUpper(savedColUpper());
00168            //dist = nlp_->solveFeasibilityProblem(indices.size(), x_bar(), indices(), 1, 0, 2);
00169          }
00170          nlpSol = const_cast<double *>(nlp_->getColSolution());
00171          nlp_->getOuterApproximation(cs, nlpSol, 1, NULL,
00172                                   parameter().global_);
00173          //if(restart){
00174            nlp_->setColLower(savedColLower());
00175            nlp_->setColUpper(savedColUpper());
00176         if(restart){
00177           major_iteration++;
00178           handler_->message(FP_MAJOR_ITERATION, messages_) 
00179           <<major_iteration<<cutoff<<CoinMessageEol;
00180           nlp_->resolve(txt_id);
00181         }
00182 
00183          //}
00184       }
00185       else {
00186          nlpSol = const_cast<double *>(nlp_->getColSolution());
00187          nlp_->getOuterApproximation(cs, nlpSol, 1, NULL,
00188                                   parameter().global_);
00189       }
00190 
00191 
00192 #if 0
00193       handler_->message(FP_MINOR_ITERATION, messages_) 
00194       <<nLocalSearch_<<cutoff<<CoinMessageEol;
00195 #endif
00196       
00197       int numberCuts = cs.sizeRowCuts() - numberCutsBefore;
00198       assert(numberCuts);
00199       installCuts(*lp, cs, numberCuts);
00200       numberCutsBefore = cs.sizeRowCuts();
00201      
00202       //check time
00203       if (CoinCpuTime() - timeBegin_ > parameters_.maxLocalSearchTime_){
00204         colsol = NULL;
00205         break;
00206       }
00207       //do we perform a new local search ?
00208       if (nLocalSearch_ < parameters_.maxLocalSearch_ &&
00209           numSols_ < parameters_.maxSols_) {
00210 
00211         nLocalSearch_++;
00212         set_fp_objective(*lp, nlp_->getColSolution());
00213 
00214         lp->setColUpper(numcols, cutoff); 
00215      
00216         subMip_->solve(DBL_MAX, parameters_.subMilpLogLevel_,
00217         // subMip_->optimize(DBL_MAX, parameters_.subMilpLogLevel_,
00218                          parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime());
00219         milpOptimal = subMip_ -> optimal(); 
00220         colsol = subMip_->getLastSolution();
00221       if(milpOptimal)
00222         handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00223       else
00224         handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
00225       if(colsol)
00226         handler_->message(FP_MILP_VAL, messages_) 
00227         <<colsol[nlp_->getNumCols()]<<CoinMessageEol;
00228          
00229       }
00230       else {
00231         colsol = NULL;
00232       }
00233     }
00234      //return -DBL_MAX;
00235     if(!passBound_ || colsol || ! milpOptimal)
00236       return -DBL_MAX;
00237     else{
00238       handler_->message(OASUCCESS, messages_)<<"FP"<<CoinCpuTime() - timeBegin_ 
00239       <<ub<<CoinMessageEol;
00240       return DBL_MAX;
00241     }
00242   }
00243 
00245   void
00246   MinlpFeasPump::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00247   {
00248     roptions->SetRegisteringCategory("Options for feasibility pump", RegisteredOptions::BonminCategory);
00249 
00250     roptions->AddStringOption2("fp_pass_infeasible", "Say whether feasibility pump should claim to converge or not",
00251                                "no",
00252                                "no", "When master MILP is infeasible just bail out (don't stop all algorithm). This is the option for using in B-Hyb.",
00253                                "yes", "Claim convergence, numerically dangerous.","");
00254     roptions->AddBoundedIntegerOption("fp_log_level",
00255         "specify FP iterations log level.",
00256         0,2,1,
00257         "Set the level of output of OA decomposition solver : "
00258         "0 - none, 1 - normal, 2 - verbose"
00259                                      );
00260     roptions->setOptionExtraInfo("fp_log_level",3);
00261 
00262     roptions->AddLowerBoundedNumberOption("fp_log_frequency",
00263         "display an update on lower and upper bounds in FP every n seconds",
00264         0.,1.,100.,
00265         "");
00266     roptions->setOptionExtraInfo("fp_log_frequency",3);
00267   }
00268 
00270 void
00271 MinlpFeasPump::set_fp_objective(OsiSolverInterface &si, const double * colsol) const{
00272   if (objects_) {
00273     for (int i = 0 ; i < nObjects_ ; i++) {
00274       OsiObject * obj = objects_[i];
00275       int colnum = obj->columnNumber();
00276       if (colnum >= 0) {//Variable branching object
00277         double round = floor(colsol[colnum] + 0.5);
00278         double coeff = (colsol[colnum] - round ) < 0;
00279         si.setObjCoeff(colnum, 1 - 2 * coeff);
00280       }
00281       else {
00282         throw CoinError("OaDecompositionBase::solverManip",
00283                         "setFpObjective",
00284                         "Can not use FP on problem with SOS constraints");
00285       }
00286     }
00287   }
00288   else {
00289     int numcols = nlp_->getNumCols();
00290     for (int i = 0; i < numcols ; i++) {
00291       if (nlp_->isInteger(i)){
00292          double round = floor(colsol[i] + 0.5);
00293          double coeff = (colsol[i] - round ) < 0;
00294          si.setObjCoeff(i, 1 - 2*coeff);
00295       }
00296     }
00297   }
00298   si.initialSolve();
00299 }
00300 
00301 }/* End namespace Bonmin. */

Generated on Thu Sep 22 03:05:53 2011 by  doxygen 1.4.7