/home/coin/SVN-release/OS-2.4.2/Couenne/src/main/BonCouenneSetup.cpp

Go to the documentation of this file.
00001 // $Id: BonCouenneSetup.cpp 749 2011-07-31 11:54:55Z pbelotti $
00002 //
00003 // (C) Copyright International Business Machines Corporation 2007
00004 // All Rights Reserved.
00005 // This code is published under the Eclipse Public License (EPL).
00006 //
00007 // Authors :
00008 // Pierre Bonami, International Business Machines Corporation
00009 //
00010 // Date : 04/18/2007
00011 
00012 // Ampl includes
00013 
00014 #include "CouenneConfig.h"
00015 
00016 #include "OsiClpSolverInterface.hpp"
00017 
00018 #ifdef COIN_HAS_CPX
00019 #include "OsiCpxSolverInterface.hpp"
00020 #endif
00021 #ifdef COIN_HAS_GRB
00022 #include "OsiGrbSolverInterface.hpp"
00023 #endif
00024 #ifdef COIN_HAS_SPX
00025 #include "OsiSpxSolverInterface.hpp"
00026 #endif
00027 #ifdef COIN_HAS_XPR
00028 #include "OsiXprSolverInterface.hpp"
00029 #endif
00030 
00031 // MILP cuts
00032 #include "CglGomory.hpp"
00033 #include "CglProbing.hpp"
00034 #include "CglKnapsackCover.hpp"
00035 #include "CglOddHole.hpp"
00036 #include "CglClique.hpp"
00037 #include "CglFlowCover.hpp"
00038 #include "CglMixedIntegerRounding2.hpp"
00039 #include "CglTwomir.hpp"
00040 #include "CglPreProcess.hpp"
00041 #include "CglLandP.hpp"
00042 #include "CglRedSplit.hpp"
00043 
00044 #include "BonCouenneSetup.hpp"
00045 #include "CouenneFeasPump.hpp"
00046 #include "CouenneIterativeRounding.hpp"
00047 #include "BonCouenneInterface.hpp"
00048 #include "BonInitHeuristic.hpp"
00049 #include "BonNlpHeuristic.hpp"
00050 
00051 #include "Heuristics/BonFixAndSolveHeuristic.hpp"
00052 #include "Heuristics/BonDummyPump.hpp"
00053 #include "Heuristics/BonPumpForMinlp.hpp"
00054 #include "Heuristics/BonHeuristicRINS.hpp"
00055 #include "Heuristics/BonHeuristicLocalBranching.hpp"
00056 #include "Heuristics/BonHeuristicFPump.hpp"
00057 #include "Heuristics/BonHeuristicDiveFractional.hpp"
00058 #include "Heuristics/BonHeuristicDiveVectorLength.hpp"
00059 #include "Heuristics/BonHeuristicDiveMIPFractional.hpp"
00060 #include "Heuristics/BonHeuristicDiveMIPVectorLength.hpp"
00061 #include "Heuristics/BonMilpRounding.hpp"
00062 
00063 #include "BonGuessHeuristic.hpp"
00064 #include "CbcCompareActual.hpp"
00065 
00066 #include "CouenneObject.hpp"
00067 #include "CouenneVarObject.hpp"
00068 #include "CouenneVTObject.hpp"
00069 #include "CouenneOrbitObj.hpp"
00070 #include "CouenneChooseVariable.hpp"
00071 #include "CouenneChooseStrong.hpp"
00072 #include "CouenneSolverInterface.hpp"
00073 #include "CouenneFixPoint.hpp"
00074 #include "CouenneCutGenerator.hpp"
00075 #include "CouenneDisjCuts.hpp"
00076 //#include "CouenneCrossConv.hpp"
00077 #include "CouenneTwoImplied.hpp"
00078 
00079 #include "BonCouenneInfo.hpp"
00080 #include "BonCbcNode.hpp"
00081 #include "BonCbc.hpp"
00082 
00083 // ASL includes need to come behind OsiClp and Bonmin, because it defines "filename",
00084 // which is used as variablename in Clp
00085 // (similar bad as windows.h, which defines "small")
00086 #ifdef COIN_HAS_ASL
00087 #include "asl.h"
00088 #include "getstub.h"
00089 #endif
00090 
00091 using namespace Ipopt;
00092 using namespace Couenne;
00093   
00094 CouenneSetup::~CouenneSetup(){
00095   if (couenneProb_ && couenneProb_is_own_)
00096     delete couenneProb_;
00097 
00098 #ifdef COIN_HAS_ASL
00099   // free (aslfg_ -> asl); // triggers segfault
00100 #endif
00101 }
00102 
00103 bool CouenneSetup::InitializeCouenne (char ** argv,
00104                                       CouenneProblem *couenneProb,
00105                                       Ipopt::SmartPtr<Bonmin::TMINLP> tminlp,
00106                                       CouenneInterface *ci,
00107                                       Bonmin::Bab *bb) {
00108 
00109   std::string s;
00110 
00111   if (couenneProb) {
00112     //TODO create a copy of user problem, since we modify it? 
00113     couenneProb_ = couenneProb;
00114     couenneProb_is_own_ = false;
00115   }
00116 
00117   /* Get the basic options. */
00118   readOptionsFile();
00119  
00120   // Suppress iteration output from nonlinear solver
00121   options () -> SetStringValue ("sb", "yes", false, true);
00122 
00123   // in check mode, avoid pop-up error message (there are quite a few messages)
00124   options_ -> GetStringValue ("test_mode", s, "couenne.");
00125   if (s == "yes")
00126     WindowsErrorPopupBlocker();
00127 
00131   options_ -> SetStringValue ("nlp_failure_behavior", "fathom", "couenne.");
00132 
00133   gatherParametersValues (options_);
00134 
00135   if (!ci) {
00136 
00137     ci = new CouenneInterface;
00138 
00139     if (!couenneProb_ && argv) {
00140 #ifdef COIN_HAS_ASL
00141       /* Read the model in various places. */
00142       ci -> readAmplNlFile (argv, roptions (), options (), journalist ());
00143       aslfg_ = new SmartAsl;
00144       aslfg_ -> asl = readASLfg (argv);
00145 #else
00146       std::cerr << 
00147         "Couenne was compiled without AMPL Solver Library. Cannot initialize from AMPL NL File." 
00148                 << std::endl;
00149       return false;
00150 #endif
00151     } else {
00152       assert (couenneProb_ != NULL);
00153       assert (IsValid (tminlp)); //TODO would be great to setup own TMINLP based on CouenneProblem formulation
00154       ci -> initialize (roptions_, options_, journalist_, tminlp);
00155     }
00156   }
00157 
00158   nonlinearSolver_ = ci;
00159 
00164   int i;
00165 
00167 
00168   // FIXME: doesn't work if suppress_all_output is true (gives
00169   // segfault on options(), but checking options()!=NULL won't work as
00170   // options() is a SmartPtr
00171 
00172 #define addJournalist(optname,jlevel) {                         \
00173     options    () -> GetIntegerValue ((optname), i, "couenne."); \
00174     journalist () -> GetJournal      ("console") -> SetPrintLevel ((jlevel), (EJournalLevel) i); \
00175 }
00176 
00177   addJournalist ("output_level",                J_COUENNE);
00178   addJournalist ("boundtightening_print_level", J_BOUNDTIGHTENING);
00179   addJournalist ("branching_print_level",       J_BRANCHING);
00180   addJournalist ("convexifying_print_level",    J_CONVEXIFYING);
00181   addJournalist ("problem_print_level",         J_PROBLEM);
00182   addJournalist ("nlpheur_print_level",         J_NLPHEURISTIC);
00183   addJournalist ("disjcuts_print_level",        J_DISJCUTS);
00184   addJournalist ("reformulate_print_level",     J_REFORMULATE);
00185 
00186   /* Initialize Couenne cut generator.*/
00187   //int ivalue, num_points;
00188   //options()->GetEnumValue("convexification_type", ivalue,"couenne.");
00189   //options()->GetIntegerValue("convexification_points",num_points,"couenne.");
00190 
00191   if (!couenneProb_)
00192     couenneProb_ = new CouenneProblem (aslfg_ -> asl, this, journalist ());
00193 
00194   CouenneCutGenerator * couenneCg = 
00195     new CouenneCutGenerator (ci, this, couenneProb_, NULL);
00196 
00197   options_ -> GetStringValue ("lp_solver", s, "couenne.");
00198 
00199   if (s == "clp") {
00200 
00201     CouenneSolverInterface <OsiClpSolverInterface> *CSI = new CouenneSolverInterface <OsiClpSolverInterface>;
00202     continuousSolver_ = CSI;
00203     CSI -> setCutGenPtr (couenneCg);
00204 
00205   } else if (s == "cplex") {
00206 
00207 #ifdef COIN_HAS_CPX
00208     CouenneSolverInterface <OsiCpxSolverInterface> *CSI = new CouenneSolverInterface <OsiCpxSolverInterface>;
00209     continuousSolver_ = CSI;
00210     CSI -> setCutGenPtr (couenneCg);
00211 #else
00212     journalist()->Printf(J_ERROR, J_INITIALIZATION, "Couenne was compiled without CPLEX interface. Please reconfigure, recompile, and try again.\n");
00213     return false;
00214 #endif
00215   } else if (s == "xpress-mp") {
00216 
00217 #ifdef COIN_HAS_XPR
00218     CouenneSolverInterface <OsiXprSolverInterface> *CSI = new CouenneSolverInterface <OsiXprSolverInterface>;
00219     continuousSolver_ = CSI;
00220     CSI -> setCutGenPtr (couenneCg);
00221 #else
00222     journalist()->Printf(J_ERROR, J_INITIALIZATION, "Couenne was compiled without Xpress-MP interface. Please reconfigure, recompile, and try again.\n");
00223     return false;
00224 #endif
00225   } else if (s == "gurobi") {
00226 
00227 #ifdef COIN_HAS_GRB
00228     CouenneSolverInterface <OsiGrbSolverInterface> *CSI = new CouenneSolverInterface <OsiGrbSolverInterface>;
00229     continuousSolver_ = CSI;
00230     CSI -> setCutGenPtr (couenneCg);
00231 #else
00232     journalist()->Printf(J_ERROR, J_INITIALIZATION, "Couenne was compiled without GUROBI interface. Please reconfigure, recompile, and try again.\n");
00233     return false;
00234 #endif
00235   } else if (s == "soplex") {
00236 
00237 #ifdef COIN_HAS_SPX
00238     CouenneSolverInterface <OsiSpxSolverInterface> *CSI = new CouenneSolverInterface <OsiSpxSolverInterface>;
00239     continuousSolver_ = CSI;
00240     CSI -> setCutGenPtr (couenneCg);
00241 #else
00242     journalist()->Printf(J_ERROR, J_INITIALIZATION, "Couenne was compiled without Soplex. Please reconfigure, recompile, and try again.\n");
00243     return false;
00244 #endif
00245   } else {
00246     journalist ()-> Printf (J_ERROR, J_INITIALIZATION, "The LP solver you specified hasn't been added to Couenne yet.\n");
00247     return false;
00248   }
00249 
00250   continuousSolver_ -> passInMessageHandler(ci -> messageHandler());
00251 
00252   couenneProb_ -> setBase (this);
00253 
00254   assert (couenneProb_);
00255 
00256   couenneProb_ -> reformulate (couenneCg);
00257 
00258   Bonmin::BabInfo * extraStuff = new CouenneInfo (0);
00259 
00260   // as per instructions by John Forrest, to get changed bounds
00261   extraStuff -> setExtraCharacteristics (extraStuff -> extraCharacteristics () | 2);
00262 
00263   continuousSolver_ -> setAuxiliaryInfo (extraStuff);
00264   delete extraStuff;
00265     
00266   extraStuff = dynamic_cast <Bonmin::BabInfo *> (continuousSolver_ -> getAuxiliaryInfo ());
00267 
00268   // Setup log level of LP solver
00269   int lpLogLevel;
00270   options () -> GetIntegerValue ("lp_log_level", lpLogLevel, "couenne.");
00271   continuousSolver_ -> messageHandler () -> setLogLevel (lpLogLevel);
00272 
00274 
00275   couenneCg -> Problem () -> setMaxCpuTime (getDoubleParameter (BabSetupBase::MaxTime));
00276 
00277   ci -> extractLinearRelaxation (*continuousSolver_, *couenneCg);
00278 
00279   // In case there are no discrete variables, we have already a
00280   // heuristic solution for which create a initialization heuristic
00281   if (!(extraStuff -> infeasibleNode ()) &&
00282       ci -> isProvenOptimal () && 
00283       ci -> haveNlpSolution ()) {
00284 
00286     InitHeuristic* initHeuristic = new InitHeuristic 
00287       (ci -> getObjValue (), ci -> getColSolution (), *couenneProb_);
00288     HeuristicMethod h;
00289     h.id = "Couenne Rounding NLP"; // same name as the real rounding one
00290     h.heuristic = initHeuristic;
00291     heuristics_.push_back(h);
00292   }
00293 
00294   if (extraStuff -> infeasibleNode ()){
00295     journalist() -> Printf(J_SUMMARY, J_PROBLEM, "Initial linear relaxation constructed by Couenne is infeasible, exiting...\n");
00296     return false;
00297   }
00298 
00299   //continuousSolver_ -> findIntegersAndSOS (false);
00300   //addSos (); // only adds embedded SOS objects
00301 
00302   // Add Couenne SOS ///////////////////////////////////////////////////////////////
00303 
00304   int 
00305     nSOS  = 0,
00306     nVars = couenneProb_ -> nVars ();
00307 
00308   OsiObject ** objects = NULL;
00309 
00310   options () -> GetStringValue ("enable_sos", s, "couenne.");
00311 
00312   if (s == "yes") {
00313 
00314     // allocate sufficient space for both nonlinear variables and SOS's
00315     objects = new OsiObject* [couenneProb_ -> nCons () + nVars];
00316 
00317     nSOS = couenneProb_ -> findSOS (&(bb -> model()), dynamic_cast <OsiSolverInterface *> (nonlinearSolver ()), objects);
00318 
00319     nonlinearSolver () -> addObjects (nSOS, objects);
00320 
00321     //printf ("==================== found %d SOS\n", nSOS);
00322     //nonlinearSolver () -> addObjects (nSOS, objects);
00323     //continuousSolver () -> addObjects (nSOS, objects);
00324 
00325     //printf ("found %d SOS!\n", nSOS);
00326 
00327     /*for (int i=0; i<nSOS; i++)
00328       delete objects [i];
00329       delete [] objects;*/
00330 
00331     if (!nSOS) {
00332       delete [] objects;
00333       objects = NULL;
00334     } 
00335   }
00336 
00337   //model -> assignSolver (continuousSolver_, true);
00338   //continuousSolver_ = model -> solver();
00339 
00340   // Add Couenne objects for branching /////////////////////////////////////////////
00341 
00342   options () -> GetStringValue ("display_stats", s, "couenne.");
00343   displayStats_ = (s == "yes");
00344 
00345   options () -> GetStringValue ("branching_object", s, "couenne.");
00346 
00347   enum CouenneObject::branch_obj objType = CouenneObject::VAR_OBJ;
00348 
00349   if      (s ==   "vt_obj") objType = CouenneObject::VT_OBJ;
00350   else if (s ==  "var_obj") objType = CouenneObject::VAR_OBJ;
00351   else if (s == "expr_obj") objType = CouenneObject::EXPR_OBJ;
00352   else {
00353     printf ("CouenneSetup: Unknown branching object type\n");
00354     exit (-1);
00355   }
00356 
00357   int 
00358     nobj = nSOS; // if no SOS then objects is empty
00359 
00360   if (!objects)
00361     objects = new OsiObject* [nVars];
00362 
00363   int 
00364     contObjPriority, 
00365     intObjPriority;
00366 
00367   options () -> GetIntegerValue ("cont_var_priority", contObjPriority, "couenne.");
00368   options () -> GetIntegerValue ( "int_var_priority",  intObjPriority, "couenne.");
00369 
00370   int varSelection;
00371   if (!options_ -> GetEnumValue ("variable_selection", varSelection, "couenne.")) {
00372     // change the default for Couenne
00373     varSelection = Bonmin::BabSetupBase::OSI_SIMPLE;
00374   }
00375 
00376   for (int i = 0; i < nVars; i++) { // for each variable
00377 
00378     exprVar *var = couenneProb_ -> Var (i);
00379 
00380     // we only want enabled variables
00381     if (var -> Multiplicity () <= 0) 
00382       continue;
00383 
00384     switch (objType) {
00385 
00386     case CouenneObject::EXPR_OBJ:
00387 
00388       // if this variable is associated with a nonlinear function
00389       if (var -> isInteger () || 
00390           ((var -> Type  () == AUX) && 
00391            (var -> Image () -> Linearity () > LINEAR))) {
00392 
00393         /*if ((var -> Image () -> code () == COU_EXPRMUL) &&
00394           (var -> Image () -> ArgList () [0] -> Index () >= 0) &&
00395           (var -> Image () -> ArgList () [1] -> Index () >= 0) &&
00396           (fabs (var -> lb ()) < COUENNE_EPS) &&
00397           (fabs (var -> ub ()) < COUENNE_EPS))
00398 
00399           // it's a complementarity constraint object!
00400           objects    [nobj] = new CouenneComplObject (couenneProb_, var, this, journalist ());
00401           else*/
00402         objects [nobj] = new CouenneObject (couenneCg, couenneProb_, var, this, journalist ());
00403 
00404         objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00405         //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00406       }
00407 
00408       break;
00409 
00410     case CouenneObject::VAR_OBJ:
00411 
00412       // branching objects on variables
00413       if // comment three lines below for linear variables too
00414         (var -> isInteger () || 
00415          (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {  // has indep
00416         //|| ((var -> Type () == AUX) &&                                  // or, aux 
00417         //    (var -> Image () -> Linearity () > LINEAR))) {              // of nonlinear
00418 
00419         objects [nobj] = new CouenneVarObject (couenneCg, couenneProb_, var, this, journalist (), varSelection);
00420         objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00421         //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00422       }
00423 
00424       break;
00425 
00426     default:
00427     case CouenneObject::VT_OBJ:
00428 
00429       // branching objects on variables
00430       if // comment three lines below for linear variables too
00431         (var -> isInteger () || 
00432          (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) { // has indep
00433         //|| ((var -> Type () == AUX) &&                      // or, aux 
00434         //(var -> Image () -> Linearity () > LINEAR))) { // of nonlinear
00435 
00436         objects [nobj] = new CouenneVTObject (couenneCg, couenneProb_, var, this, journalist ());
00437         objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00438         //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00439       }
00440 
00441       break;
00442     }
00443   }
00444 
00445   // // Experimental: orbital branching //////////////////////////////////////////////
00446 
00447   // options () -> GetStringValue ("orbital_branching", s, "couenne.");
00448 
00449   // if (s == "yes") {
00450 
00451   //   objects [nobj] = new CouenneOrbitObj (couenneCg, couenneProb_, NULL, this, journalist ());
00452   //   objects [nobj++] -> setPriority (contObjPriority);
00453   // }
00454 
00455   // Add objects /////////////////////////////////
00456 
00457   continuousSolver_ -> addObjects (nobj, objects);
00458 
00459   for (int i = 0 ; i < nobj ; i++)
00460     delete objects [i];
00461 
00462   delete [] objects;
00463 
00464   int freq;
00465 
00466   // Setup Fix Point bound tightener /////////////////////////////////////////////
00467 
00468   options () -> GetIntegerValue ("fixpoint_bt", freq, "couenne.");
00469 
00470   if (freq != 0) {
00471 
00472     CuttingMethod cg;
00473     cg.frequency = freq;
00474     cg.cgl = new CouenneFixPoint (couenneProb_, options ());
00475     cg.id = "Couenne fixed point FBBT";
00476     cutGenerators (). push_back (cg);
00477   }
00478 
00479   // Setup Convexifier generators ////////////////////////////////////////////////
00480 
00481   options () -> GetIntegerValue ("convexification_cuts", freq, "couenne.");
00482 
00483   if (freq != 0) {
00484 
00485     CuttingMethod cg;
00486     cg.frequency = freq;
00487     cg.cgl = couenneCg;
00488     cg.id = "Couenne convexifier cuts";
00489     cutGenerators().push_back (cg);
00490 
00491     // set cut gen pointer
00492     //dynamic_cast <CouenneSolverInterface <OsiClpSolverInterface> *> 
00493     //(continuousSolver_)
00494 
00495     // this is done on an explicitly declared CSI pointer, however
00496     // CSI == continuousSolver_
00497   }
00498 
00499   // add other cut generators -- test for integer variables first
00500   if (couenneCg -> Problem () -> nIntVars () > 0)
00501     addMilpCutGenerators ();
00502 
00503   CouennePtr_ = couenneCg;
00504 
00505   // Add two-inequalities based bound tightening ///////////////////////////////////////////////////////
00506 
00507   options () -> GetIntegerValue ("two_implied_bt", freq, "couenne.");
00508 
00509   if (freq != 0) {
00510 
00511     CouenneTwoImplied * couenne2I = 
00512       new CouenneTwoImplied (couenneProb_,
00513                              journalist (),
00514                              options    ());
00515     CuttingMethod cg;
00516     cg.frequency = freq;
00517     cg.cgl = couenne2I;
00518     cg.id = "Couenne two-implied cuts";
00519     cutGenerators (). push_back(cg);
00520   }
00521 
00522   // check branch variable selection for disjunctive cuts
00523 
00524   // Setup heuristic to solve MINLP problems. /////////////////////////////////
00525 
00526   std::string doHeuristic;
00527 
00528   options () -> GetStringValue ("local_optimization_heuristic", doHeuristic, "couenne.");
00529 
00530   if (doHeuristic == "yes") {
00531 
00532     int numSolve;
00533     options()->GetIntegerValue("log_num_local_optimization_per_level",numSolve,"couenne.");
00534     NlpSolveHeuristic * nlpHeuristic = new NlpSolveHeuristic;
00535     nlpHeuristic->setNlp(*ci,false);
00536     nlpHeuristic->setCouenneProblem(couenneProb_);
00537     nlpHeuristic->setMaxNlpInf(maxNlpInf_0);
00538     nlpHeuristic->setNumberSolvePerLevel(numSolve);
00539     HeuristicMethod h;
00540     h.id = "Couenne Rounding NLP";
00541     h.heuristic = nlpHeuristic;
00542     heuristics_.push_back(h);
00543   }
00544 
00545   options () -> GetStringValue ("iterative_rounding_heuristic", doHeuristic, "couenne.");
00546   
00547   if (doHeuristic == "yes") {
00548     CouenneIterativeRounding * nlpHeuristic = new CouenneIterativeRounding(nonlinearSolver_, ci, couenneProb_, options());
00549     HeuristicMethod h;
00550     h.id = "Couenne Iterative Rounding";
00551     h.heuristic = nlpHeuristic;
00552     heuristics_.push_back(h);
00553   }
00554 
00555   options () -> GetStringValue ("feas_pump_heuristic", doHeuristic, "couenne.");
00556 
00557   if (doHeuristic == "yes") {
00558 
00559     int numSolve;
00560     options () -> GetIntegerValue ("feas_pump_level", numSolve, "couenne.");
00561 
00562     CouenneFeasPump *nlpHeuristic = new CouenneFeasPump (couenneProb_, couenneCg, options ());
00563 
00564     nlpHeuristic -> setNumberSolvePerLevel (numSolve);
00565 
00566     HeuristicMethod h;
00567 
00568     h.id = "Couenne Feasibility Pump";
00569     h.heuristic = nlpHeuristic;
00570     heuristics_. push_back (h);
00571   }
00572 
00573 
00574   if (0) { // inactive as of yet -- segfaults 
00575 
00576     Ipopt::Index doHeuristicDiveFractional = false;
00577     options()->GetEnumValue("heuristic_dive_fractional",doHeuristicDiveFractional,prefix_.c_str());
00578     if(doHeuristicDiveFractional){
00579       Bonmin::HeuristicDiveFractional* dive_fractional = new Bonmin::HeuristicDiveFractional(this);
00580       HeuristicMethod h;
00581       h.heuristic = dive_fractional;
00582       h.id = "DiveFractional";
00583       heuristics_.push_back(h);
00584     }
00585 
00586     Ipopt::Index doHeuristicDiveVectorLength = false;
00587     options()->GetEnumValue("heuristic_dive_vectorLength",doHeuristicDiveVectorLength,prefix_.c_str());
00588     if(doHeuristicDiveVectorLength){
00589       Bonmin::HeuristicDiveVectorLength* dive_vectorLength = new Bonmin::HeuristicDiveVectorLength(this);
00590       HeuristicMethod h;
00591       h.heuristic = dive_vectorLength;
00592       h.id = "DiveVectorLength";
00593       heuristics_.push_back(h);
00594     }
00595 
00596     Ipopt::Index doHeuristicDiveMIPFractional = false;
00597     if(!options()->GetEnumValue("heuristic_dive_MIP_fractional",doHeuristicDiveMIPFractional,prefix_.c_str())){
00598       doHeuristicDiveMIPFractional = true;
00599       std::string o_name = prefix_ + "heuristic_dive_MIP_fractional";
00600       options_->SetStringValue(o_name.c_str(), "yes",true,true);
00601     }
00602     if(doHeuristicDiveMIPFractional){
00603       Bonmin::HeuristicDiveMIPFractional* dive_MIP_fractional = new Bonmin::HeuristicDiveMIPFractional(this);
00604       HeuristicMethod h;
00605       h.heuristic = dive_MIP_fractional;
00606       h.id = "DiveMIPFractional";
00607       heuristics_.push_back(h);
00608     }
00609 
00610     Ipopt::Index doHeuristicDiveMIPVectorLength = false;
00611     options()->GetEnumValue("heuristic_dive_MIP_vectorLength",doHeuristicDiveMIPVectorLength,prefix_.c_str());
00612     if(doHeuristicDiveMIPVectorLength){
00613       Bonmin::HeuristicDiveMIPVectorLength* dive_MIP_vectorLength = new Bonmin::HeuristicDiveMIPVectorLength(this);
00614       HeuristicMethod h;
00615       h.heuristic = dive_MIP_vectorLength;
00616       h.id = "DiveMIPVectorLength";
00617       heuristics_.push_back(h);
00618     }
00619     Ipopt::Index doHeuristicFPump = false;
00620     if(!nonlinearSolver_->model()->hasGeneralInteger() && !options()->GetEnumValue("heuristic_feasibility_pump",doHeuristicFPump,prefix_.c_str())){
00621       doHeuristicFPump = true;
00622       std::string o_name = prefix_ + "heuristic_feasibility_pump";
00623       options_->SetStringValue(o_name.c_str(), "yes",true,true);
00624     }
00625     if(doHeuristicFPump){
00626       Bonmin::HeuristicFPump* feasibility_pump = new Bonmin::HeuristicFPump(this);
00627       HeuristicMethod h;
00628       h.heuristic = feasibility_pump;
00629       h.id = "FPump";
00630       heuristics_.push_back(h);
00631     }
00632 
00633     Ipopt::Index doFixAndSolve = false;
00634     options()->GetEnumValue("fix_and_solve_heuristic",doFixAndSolve,prefix_.c_str());
00635     if(doFixAndSolve){
00636       Bonmin::FixAndSolveHeuristic* fix_and_solve = new Bonmin::FixAndSolveHeuristic(this);
00637       HeuristicMethod h;
00638       h.heuristic = fix_and_solve;
00639       h.id = "Fix and Solve";
00640       heuristics_.push_back(h);
00641     }
00642 
00643     Ipopt::Index doDummyPump = false;
00644     options()->GetEnumValue("dummy_pump_heuristic",doDummyPump,prefix_.c_str());
00645     if(doDummyPump){
00646       Bonmin::DummyPump* fix_and_solve = new Bonmin::DummyPump(this);
00647       HeuristicMethod h;
00648       h.heuristic = fix_and_solve;
00649       h.id = "Dummy pump";
00650       heuristics_.push_back(h);
00651     }
00652 
00653     Ipopt::Index doHeuristicRINS = false;
00654     options()->GetEnumValue("heuristic_RINS",doHeuristicRINS,prefix_.c_str());
00655     if(doHeuristicRINS){
00656       Bonmin::HeuristicRINS* rins = new Bonmin::HeuristicRINS(this);
00657       HeuristicMethod h;
00658       h.heuristic = rins;
00659       h.id = "RINS";
00660       heuristics_.push_back(h);
00661     }
00662 
00663     Ipopt::Index doHeuristicLocalBranching = false;
00664     options()->GetEnumValue("heuristic_local_branching",doHeuristicLocalBranching,prefix_.c_str());
00665     if(doHeuristicLocalBranching){
00666       Bonmin::HeuristicLocalBranching* local_branching = new Bonmin::HeuristicLocalBranching(this);
00667       HeuristicMethod h;
00668       h.heuristic = local_branching;
00669       h.id = "LocalBranching";
00670       heuristics_.push_back(h);
00671     }
00672 
00673     Ipopt::Index doHeuristicPumpForMinlp = false;
00674     options()->GetEnumValue("pump_for_minlp",doHeuristicPumpForMinlp,prefix_.c_str());
00675     if(doHeuristicPumpForMinlp){
00676       Bonmin::PumpForMinlp * pump = new Bonmin::PumpForMinlp(this);
00677       HeuristicMethod h;
00678       h.heuristic = pump;
00679       h.id = "Pump for MINLP";
00680       heuristics_.push_back(h);
00681     }
00682 
00683     Ipopt::Index doHeuristicMilpRounding = false;
00684     options()->GetEnumValue("MILP_rounding_heuristic",doHeuristicMilpRounding,prefix_.c_str());
00685     if(doHeuristicMilpRounding){
00686       Bonmin::MilpRounding * round = new Bonmin::MilpRounding(this);
00687       HeuristicMethod h;
00688       h.heuristic = round;
00689       h.id = "MILP Rounding";
00690       heuristics_.push_back(h);
00691     }
00692   }
00693 
00694   // Add Branching rules ///////////////////////////////////////////////////////
00695 
00696   switch (varSelection) {
00697 
00698   case OSI_STRONG: { // strong branching
00699     CouenneChooseStrong * chooseVariable = new CouenneChooseStrong
00700       (*this, couenneProb_, journalist ());
00701     chooseVariable->setTrustStrongForSolution(false);
00702     chooseVariable->setTrustStrongForBound(false);
00703     chooseVariable->setOnlyPseudoWhenTrusted(true);
00704     branchingMethod_ = chooseVariable;
00705     break;
00706   }
00707 
00708   case OSI_SIMPLE: // default choice
00709     branchingMethod_ = new CouenneChooseVariable 
00710       (continuousSolver_, couenneProb_, journalist ());
00711     break;
00712 
00713   default:
00714     std::cerr << "Unknown variable_selection for Couenne\n" << std::endl;
00715     throw;
00716     break;
00717   }
00718 
00719   // Node comparison method ///////////////////////////////////////////////////////////////////////////
00720 
00721   int ival;
00722   if (!options_->GetEnumValue("node_comparison", ival, "bonmin.")) {
00723     // change default for Couenne
00724     nodeComparisonMethod_ = bestBound;
00725   }
00726   else {
00727     nodeComparisonMethod_ = NodeComparison(ival);
00728   }
00729 
00730   if (intParam_[NumCutPasses] < 2)
00731     intParam_[NumCutPasses] = 2;
00732 
00733   // Tell Cbc not to check again if a solution returned from
00734   // heuristic is indeed feasible
00735   intParam_ [BabSetupBase::SpecialOption] = 16 | 4;
00736 
00737   // Add disjunctive cuts ///////////////////////////////////////////////////////
00738 
00739   options () -> GetIntegerValue ("minlp_disj_cuts", freq, "couenne.");
00740 
00741   if (freq != 0) {
00742 
00743     CouenneDisjCuts * couenneDisj = 
00744       new CouenneDisjCuts (ci, this, 
00745                            couenneCg, 
00746                            branchingMethod_, 
00747                            varSelection == OSI_STRONG, // if true, use strong branching candidates
00748                            journalist (),
00749                            options ());
00750 
00751     CuttingMethod cg;
00752     cg.frequency = freq;
00753     cg.cgl = couenneDisj;
00754     cg.id = "Couenne disjunctive cuts";
00755     cutGenerators (). push_back(cg);
00756   }
00757 
00758   // Add cross-aux redundant cuts ///////////////////////////////////////////////////////
00759 
00760   // options () -> GetIntegerValue ("crossconv_cuts", freq, "couenne.");
00761 
00762   // if (freq != 0) {
00763 
00764   //   CouenneCrossConv * couenneCross = 
00765   //     new CouenneCrossConv (couenneProb,
00766   //                        journalist (),
00767   //                        options ());
00768 
00769   //   CuttingMethod cg;
00770   //   cg.frequency = freq;
00771   //   cg.cgl = couenneCross;
00772   //   cg.id = "Couenne cross-aux cuts";
00773   //   cutGenerators (). push_back(cg);
00774   // }
00775 
00776   // Add sdp cuts ///////////////////////////////////////////////////////
00777 
00778   // options () -> GetIntegerValue ("sdp_cuts", freq, "couenne.");
00779 
00780   // if (freq != 0) {
00781 
00782   //   CouenneDisjCuts * couenneDisj = 
00783   //     new CouenneDisjCuts (ci, this, 
00784   //                       couenneCg, 
00785   //                       branchingMethod_, 
00786   //                       varSelection == OSI_STRONG, // if true, use strong branching candidates
00787   //                       journalist (),
00788   //                       options ());
00789 
00790   //   CuttingMethod cg;
00791   //   cg.frequency = freq;
00792   //   cg.cgl = couenneDisj;
00793   //   cg.id = "Couenne disjunctive cuts";
00794   //   cutGenerators (). push_back(cg);
00795   // }
00796 
00797   return true;
00798 }
00799  
00800 void CouenneSetup::registerOptions ()
00801 {registerAllOptions (roptions ());}
00802 
00803 
00804 void CouenneSetup::registerAllOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00805 
00806   roptions -> SetRegisteringCategory ("Couenne options", Bonmin::RegisteredOptions::CouenneCategory);
00807 
00808   BabSetupBase        ::registerAllOptions (roptions);
00809   Bonmin::BonCbcFullNodeInfo  ::registerOptions (roptions);
00810 
00812   Bonmin::LocalSolverBasedHeuristic    ::registerOptions (roptions);
00813   Bonmin::FixAndSolveHeuristic         ::registerOptions (roptions);
00814   Bonmin::DummyPump                    ::registerOptions (roptions);
00815   Bonmin::MilpRounding                 ::registerOptions (roptions);
00816   Bonmin::PumpForMinlp                 ::registerOptions (roptions);
00817   Bonmin::HeuristicRINS                ::registerOptions (roptions);
00818   Bonmin::HeuristicLocalBranching      ::registerOptions (roptions);
00819   Bonmin::HeuristicFPump               ::registerOptions (roptions);
00820   Bonmin::HeuristicDiveFractional      ::registerOptions (roptions);
00821   Bonmin::HeuristicDiveVectorLength    ::registerOptions (roptions);
00822   Bonmin::HeuristicDiveMIPFractional   ::registerOptions (roptions);
00823   Bonmin::HeuristicDiveMIPVectorLength ::registerOptions (roptions);  
00824 
00825   roptions -> AddStringOption3 ("milp_solver",
00826                                 "Choose the subsolver to solve MILP sub-problems in OA decompositions.",
00827                                 "Cbc_D",
00828                                 "Cbc_D","Coin Branch and Cut with its default",
00829                                 "Cbc_Par", "Coin Branch and Cut with passed parameters",
00830                                 "Cplex","Ilog Cplex",
00831                                 " To use Cplex, a valid license is required and you should have compiled OsiCpx in COIN-OR  (see Osi documentation).");
00832 
00833   roptions -> setOptionExtraInfo ("milp_solver",64);
00834 
00835   roptions -> AddStringOption2 ("milp_strategy",
00836                                 "Choose a strategy for MILPs.",
00837                                 "find_good_sol",
00838                                 "find_good_sol","Stop sub milps when a solution improving the incumbent is found",
00839                                 "solve_to_optimality", "Solve MILPs to optimality",
00840                                 "");
00841 
00842   roptions -> AddStringOption6 ("algorithm",
00843                                 "Choice of the algorithm.",
00844                                 "B-BB",
00845                                 "B-BB","simple branch-and-bound algorithm,",
00846                                 "B-OA","OA Decomposition algorithm,",
00847                                 "B-QG","Quesada and Grossmann branch-and-cut algorithm,",
00848                                 "B-Hyb","hybrid outer approximation based branch-and-cut,",
00849                                 "B-Ecp","ecp cuts based branch-and-cut a la FilMINT.",
00850                                 "B-iFP","Iterated Feasibility Pump for MINLP.",
00851                                 "This will preset some of the options of bonmin depending on the algorithm choice."
00852                                 );
00853 
00854   CouenneProblem          ::registerOptions (roptions);
00855   CouenneCutGenerator     ::registerOptions (roptions);
00856   CouenneChooseStrong     ::registerOptions (roptions);
00857   CouenneChooseVariable   ::registerOptions (roptions);
00858   CouenneFixPoint         ::registerOptions (roptions);
00859   CouenneDisjCuts         ::registerOptions (roptions);
00860   //  CouenneCrossConv        ::registerOptions (roptions);
00861   CouenneTwoImplied       ::registerOptions (roptions);
00862   NlpSolveHeuristic       ::registerOptions (roptions);
00863   CouenneFeasPump         ::registerOptions (roptions);
00864   CouenneIterativeRounding::registerOptions (roptions);
00865 
00867   roptions -> AddStringOption2
00868     ("local_branching_heuristic",
00869      "Apply local branching heuristic",
00870      "no",
00871      "no","",
00872      "yes","",
00873      "A local-branching heuristic based is used to find feasible solutions.");
00874 
00875 
00876   roptions -> AddNumberOption  ("couenne_check",
00877                                 "known value of a global optimum (for debug purposes only)",
00878                                 COIN_DBL_MAX,
00879                                 "Default value is +infinity.");
00880 
00881   roptions -> AddStringOption2 ("display_stats",
00882                                 "display statistics at the end of the run",
00883                                 "no",
00884                                 "yes", "",
00885                                 "no", "");
00886 
00887   roptions -> AddStringOption2 ("test_mode",
00888                                 "set to true if this is Couenne unit test",
00889                                 "no",
00890                                 "yes", "",
00891                                 "no", "");
00892 
00893   roptions -> AddStringOption4 ("lp_solver",
00894                                 "Linear Programming solver for the linearization",
00895                                 "clp",
00896                                 "clp",    "Use the Coin-OR Open Source solver CLP",
00897                                 "cplex",  "Use the commercial solver Cplex (license is needed)",
00898                                 "gurobi", "Use the commercial solver Gurobi (license is needed)",
00899                                 "soplex", "Use the freely available Soplex");
00900 
00901 #define addLevOption(optname,comment) roptions -> AddBoundedIntegerOption (optname, comment, -2, J_LAST_LEVEL-1, J_NONE, "")
00902 
00903   addLevOption ("output_level",                "Output level");
00904   addLevOption ("branching_print_level",       "Output level for braching code in Couenne");
00905   addLevOption ("boundtightening_print_level", "Output level for bound tightening code in Couenne");
00906   addLevOption ("convexifying_print_level",    "Output level for convexifying code in Couenne");
00907   addLevOption ("problem_print_level",         "Output level for problem manipulation code in Couenne");
00908   addLevOption ("nlpheur_print_level",         "Output level for NLP heuristic in Couenne");
00909   addLevOption ("disjcuts_print_level",        "Output level for disjunctive cuts in Couenne");
00910   addLevOption ("reformulate_print_level",     "Output level for reformulating problems in Couenne");
00911 
00912   roptions -> AddNumberOption
00913     ("feas_tolerance",
00914      "Tolerance for constraints/auxiliary variables",
00915      feas_tolerance_default,
00916      "Default value is 1e-5.");
00917 
00918   roptions -> AddStringOption2 
00919     ("feasibility_bt",
00920      "Feasibility-based (cheap) bound tightening (FBBT)",
00921      "yes",
00922      "no","",
00923      "yes","",
00924      "A pre-processing technique to reduce the bounding box, before the generation of linearization cuts. "
00925      "This is a quick and effective way to reduce the solution set, and it is highly recommended to keep it active."
00926     );
00927 
00928   // copied from BonminSetup::registerMilpCutGenerators(), in
00929   // BonBonminSetup.cpp
00930 
00931   struct cutOption_ {
00932 
00933     const char *cgname;
00934     int         defaultFreq;
00935 
00936   } cutOption [] = {
00937     {(const char *) "Gomory_cuts",             0},
00938     {(const char *) "probing_cuts",            0},
00939     {(const char *) "cover_cuts",              0},
00940     {(const char *) "mir_cuts",                0},
00941     {(const char *) "2mir_cuts",               0},
00942     {(const char *) "flow_covers_cuts",        0},
00943     {(const char *) "lift_and_project_cuts",   0},
00944     {(const char *) "reduce_split_cuts",       0},
00945     {(const char *) "clique_cuts",             0},
00946     {NULL, 0}};
00947 
00948   for (int i=0; cutOption [i].cgname; i++) {
00949 
00950     char descr [150];
00951 
00952     sprintf (descr, "Frequency k (in terms of nodes) for generating %s cuts in branch-and-cut.",
00953              cutOption [i].cgname);
00954 
00955     roptions -> AddLowerBoundedIntegerOption 
00956       (cutOption [i].cgname,
00957        descr,
00958        -100, cutOption [i].defaultFreq,
00959        "If k > 0, cuts are generated every k nodes, "
00960        "if -99 < k < 0 cuts are generated every -k nodes but "
00961        "Cbc may decide to stop generating cuts, if not enough are generated at the root node, "
00962        "if k=-99 generate cuts only at the root node, if k=0 or 100 do not generate cuts.");
00963 
00964     roptions->setOptionExtraInfo (cutOption [i].cgname, 5);
00965   }
00966 }
00967 
00968 
00969 
00971 void CouenneSetup::addMilpCutGenerators () {
00972 
00973   enum extraInfo_ {CUTINFO_NONE, CUTINFO_MIG, CUTINFO_PROBING, CUTINFO_CLIQUE};
00974 
00975   // extra data structure to avoid repeated code below
00976 
00977   struct cutInfo {
00978 
00979     const char      *optname;
00980     CglCutGenerator *cglptr;
00981     const char      *cglId;
00982     enum extraInfo_  extraInfo;
00983 
00984   } cutList [] = {
00985     {(const char*)"Gomory_cuts",new CglGomory,      (const char*)"Mixed Integer Gomory",CUTINFO_MIG},
00986     {(const char*)"probing_cuts",new CglProbing,        (const char*) "Probing", CUTINFO_PROBING},
00987     {(const char*)"mir_cuts",new CglMixedIntegerRounding2, (const char*) "Mixed Integer Rounding", 
00988      CUTINFO_NONE},
00989     {(const char*)"2mir_cuts",    new CglTwomir,         (const char*) "2-MIR",    CUTINFO_NONE},
00990     {(const char*)"cover_cuts",   new CglKnapsackCover,  (const char*) "Cover",    CUTINFO_NONE},
00991     {(const char*)"clique_cuts",  new CglClique,         (const char*) "Clique",   CUTINFO_CLIQUE},
00992     {(const char*)"lift_and_project_cuts",new CglLandP,(const char*)"Lift and Project",CUTINFO_NONE},
00993     {(const char*)"reduce_split_cuts",new CglRedSplit,(const char*) "Reduce and Split",CUTINFO_NONE},
00994     {(const char*)"flow_covers_cuts",new CglFlowCover,(const char*) "Flow cover cuts", CUTINFO_NONE},
00995     {NULL, NULL, NULL, CUTINFO_NONE}};
00996 
00997   int freq;
00998 
00999   for (int i=0; cutList [i]. optname; i++) {
01000 
01001     options_ -> GetIntegerValue (std::string (cutList [i]. optname), freq, "couenne.");
01002 
01003     if (!freq) {
01004       delete cutList [i].cglptr;
01005       continue;
01006     }
01007 
01008     CuttingMethod cg;
01009     cg.frequency = freq;
01010     cg.cgl       = cutList [i].cglptr;
01011     cg.id        = std::string (cutList [i]. cglId);
01012     cutGenerators_.push_back (cg);
01013 
01014     // options for particular cases
01015     switch (cutList [i].extraInfo) {
01016 
01017     case CUTINFO_MIG: {
01018       CglGomory *gc = dynamic_cast <CglGomory *> (cutList [i].cglptr);
01019 
01020       if (!gc) break;
01021 
01022       gc -> setLimitAtRoot(512);
01023       gc -> setLimit(50);
01024     }
01025       break;
01026 
01027     case CUTINFO_PROBING: {
01028       CglProbing *pc = dynamic_cast <CglProbing *> (cutList [i].cglptr);
01029 
01030       if (!pc) break;
01031 
01032       pc->setUsingObjective(1);
01033       pc->setMaxPass(3);
01034       pc->setMaxPassRoot(3);
01035       // Number of unsatisfied variables to look at
01036       pc->setMaxProbe(10);
01037       pc->setMaxProbeRoot(50);
01038       // How far to follow the consequences
01039       pc->setMaxLook(10);
01040       pc->setMaxLookRoot(50);
01041       pc->setMaxLookRoot(10);
01042       // Only look at rows with fewer than this number of elements
01043       pc->setMaxElements(200);
01044       pc->setRowCuts(3);
01045     }
01046       break;
01047 
01048     case CUTINFO_CLIQUE: {
01049       CglClique *clique = dynamic_cast <CglClique *> (cutList [i].cglptr);
01050 
01051       if (!clique) break;
01052 
01053       clique -> setStarCliqueReport(false);
01054       clique -> setRowCliqueReport(false);
01055       clique -> setMinViolation(0.1);
01056     }
01057       break;
01058 
01059       //case CUTINFO_NONE:
01060     default:
01061       break;
01062     }
01063   }
01064 
01065   double givenAllowFGap2 = 0.0;
01066   options_->GetNumericValue(std::string("allowable_fraction_gap"), 
01067                             givenAllowFGap2, "bonmin.");
01068   double upval = 1e50;
01069 
01070 #ifdef FM_UP_BND
01071   printf("CutOff value:\n");
01072   scanf("%lf", &upval);
01073 #else /* not FM_UP_BND */
01074   options_->GetNumericValue(std::string("art_cutoff"), upval, "bonmin.");
01075 #endif /* FM_UP_BND */
01076 
01077   if(upval < 1e50) {
01078     double newCO = (1-givenAllowFGap2) * upval;
01079     couenneProb_->setCutOff(newCO);
01080     printf("CutOff set to %f\n", newCO);
01081 
01082 #ifdef FM_TRACE_OPTSOL
01083     if(couenneProb_->getRecordBestSol()->getHasSol()) {
01084       if(newCO < couenneProb_->getRecordBestSol()->getVal()) {
01085         couenneProb_->getRecordBestSol()->setVal(newCO);
01086       }
01087     }
01088 #endif
01089   }
01090 }

Generated on Wed Nov 30 03:04:06 2011 by  doxygen 1.4.7