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

Go to the documentation of this file.
00001 // $Id: BonCouenneSetup.cpp 291 2010-02-10 15:23:15Z stefan $
00002 //
00003 // (C) Copyright International Business Machines Corporation 2007
00004 // All Rights Reserved.
00005 // This code is published under the Common Public License.
00006 //
00007 // Authors :
00008 // Pierre Bonami, International Business Machines Corporation
00009 //
00010 // Date : 04/18/2007
00011 
00012 #include "BonCouenneSetup.hpp"
00013 #include "BonInitHeuristic.hpp"
00014 #include "BonNlpHeuristic.hpp"
00015 #include "BonCouenneInterface.hpp"
00016 
00017 #include "BonGuessHeuristic.hpp"
00018 #include "CbcCompareActual.hpp"
00019 
00020 #include "CouenneObject.hpp"
00021 //#include "CouenneComplObject.hpp"
00022 #include "CouenneVarObject.hpp"
00023 #include "CouenneVTObject.hpp"
00024 #include "CouenneOrbitObj.hpp"
00025 #include "CouenneChooseVariable.hpp"
00026 #include "CouenneChooseStrong.hpp"
00027 #include "CouenneSolverInterface.hpp"
00028 #include "CouenneCutGenerator.hpp"
00029 #include "CouenneDisjCuts.hpp"
00030 
00031 #include "BonCouenneInfo.hpp"
00032 #include "BonCbcNode.hpp"
00033 
00034 #include "OsiClpSolverInterface.hpp"
00035 #ifdef COIN_HAS_CPX
00036 #include "OsiCpxSolverInterface.hpp"
00037 #endif
00038 
00039 // MILP cuts
00040 #include "CglGomory.hpp"
00041 #include "CglProbing.hpp"
00042 #include "CglKnapsackCover.hpp"
00043 #include "CglOddHole.hpp"
00044 #include "CglClique.hpp"
00045 #include "CglFlowCover.hpp"
00046 #include "CglMixedIntegerRounding2.hpp"
00047 #include "CglTwomir.hpp"
00048 #include "CglPreProcess.hpp"
00049 #include "CglLandP.hpp"
00050 #include "CglRedSplit.hpp"
00051 
00052 // Ampl includes
00053 #ifdef COIN_HAS_ASL
00054 #include "asl.h"
00055 #include "getstub.h"
00056 #endif
00057 
00058 
00059 namespace Bonmin{
00060   
00061   SmartAsl::~SmartAsl(){
00062 #ifdef COIN_HAS_ASL
00063     //Code from Ipopt::AmplTNLP to free asl
00064     if(asl != NULL){
00065         if (X0) {
00066           delete [] X0;
00067           X0 = NULL;
00068         }
00069         if (havex0) {
00070           delete [] havex0;
00071           havex0 = NULL;
00072         }
00073         if (pi0) {
00074           delete [] pi0;
00075           pi0 = NULL;
00076         }
00077         if (havepi0) {
00078           delete [] havepi0;
00079           havepi0 = NULL;
00080         }
00081         ASL* asl_to_free = (ASL*)asl;
00082         ASL_free(&asl_to_free);
00083         asl = NULL;
00084     }
00085     ASL_free(&asl);
00086 #endif
00087   }
00088   
00089   CouenneSetup::~CouenneSetup(){
00090     if (couenneProb_ && couenneProb_is_own_)
00091       delete couenneProb_;
00092   }
00093 
00094   bool CouenneSetup::InitializeCouenne (char ** argv, 
00095                                         CouenneProblem *couenneProb,
00096           Ipopt::SmartPtr<Bonmin::TMINLP> tminlp,
00097                                         Bonmin::CouenneInterface *ci) {
00098     std::string s;
00099 
00100     if (couenneProb) {
00101         //TODO create a copy of user problem, since we modify it? 
00102         couenneProb_ = couenneProb;
00103         couenneProb_is_own_ = false;
00104     }
00105 
00106     /* Get the basic options. */
00107     readOptionsFile();
00108  
00109     // in check mode, avoid pop-up error message (there are quite a few messages)
00110     options_ -> GetStringValue ("test_mode", s, "couenne.");
00111     if (s == "yes")
00112       WindowsErrorPopupBlocker();
00113 
00117     options_ -> SetStringValue ("nlp_failure_behavior", "fathom", "bonmin.");
00118 
00119     gatherParametersValues (options_);
00120 
00121     if (!ci) {
00122 
00123       ci = new CouenneInterface;
00124 
00125       if (!couenneProb_ && argv) {
00126 #ifdef COIN_HAS_ASL
00127         /* Read the model in various places. */
00128         ci -> readAmplNlFile (argv, roptions (), options (), journalist ());
00129         aslfg_ = new SmartAsl;
00130         aslfg_ -> asl = readASLfg (argv);
00131 #else
00132         std::cerr << 
00133           "Couenne was compiled without AMPL Solver Library. Cannot initialize from AMPL NL File." 
00134                   << std::endl;
00135         return false;
00136 #endif
00137       } else {
00138         assert(couenneProb_ != NULL);
00139         assert(IsValid(tminlp)); //TODO would be great to setup own TMINLP based on CouenneProblem formulation
00140         ci -> initialize(roptions_, options_, journalist_, tminlp);
00141       }
00142     }
00143 
00144     nonlinearSolver_ = ci;
00145 
00149     int i;
00150 
00151     options()->GetIntegerValue("boundtightening_print_level", i, "bonmin.");
00152     journalist()->GetJournal("console")-> SetPrintLevel(J_BOUNDTIGHTENING, (EJournalLevel) i);
00153 
00154     options()->GetIntegerValue("branching_print_level", i, "bonmin.");
00155     journalist()->GetJournal("console")-> SetPrintLevel(J_BRANCHING, (EJournalLevel) i);
00156 
00157     options()->GetIntegerValue("convexifying_print_level", i, "bonmin.");
00158     journalist()->GetJournal("console")-> SetPrintLevel(J_CONVEXIFYING, (EJournalLevel) i);
00159 
00160     options()->GetIntegerValue("problem_print_level", i, "bonmin.");
00161     journalist()->GetJournal("console")-> SetPrintLevel(J_PROBLEM, (EJournalLevel) i);
00162 
00163     options()->GetIntegerValue("nlpheur_print_level", i, "bonmin.");
00164     journalist()->GetJournal("console")-> SetPrintLevel(J_NLPHEURISTIC, (EJournalLevel) i);
00165 
00166     options()->GetIntegerValue("disjcuts_print_level", i, "bonmin.");
00167     journalist()->GetJournal("console")-> SetPrintLevel(J_DISJCUTS, (EJournalLevel) i);
00168 
00169     options()->GetIntegerValue("reformulate_print_level", i, "bonmin.");
00170     journalist()->GetJournal("console")-> SetPrintLevel(J_REFORMULATE, (EJournalLevel) i);
00171 
00172     /* Initialize Couenne cut generator.*/
00173     //int ivalue, num_points;
00174     //options()->GetEnumValue("convexification_type", ivalue,"bonmin.");
00175     //options()->GetIntegerValue("convexification_points",num_points,"bonmin.");
00176 
00177     if (!couenneProb_)
00178       couenneProb_ = new CouenneProblem (aslfg_ -> asl, this, journalist ());
00179 
00180     CouenneCutGenerator * couenneCg = 
00181       new CouenneCutGenerator (ci, this, couenneProb_, NULL);
00182 
00183     options_ -> GetStringValue ("lp_solver", s, "couenne.");
00184 
00185     if (s == "clp") {
00186 
00187       CouenneSolverInterface <OsiClpSolverInterface> *CSI 
00188         = new CouenneSolverInterface <OsiClpSolverInterface>;
00189 
00190       continuousSolver_ = CSI;
00191       CSI -> setCutGenPtr (couenneCg);
00192 
00193     } else if (s == "cplex") {
00194 
00195 #ifdef COIN_HAS_CPX
00196       CouenneSolverInterface <OsiCpxSolverInterface> *CSI 
00197         = new CouenneSolverInterface <OsiCpxSolverInterface>;
00198 
00199       continuousSolver_ = CSI;
00200       CSI -> setCutGenPtr (couenneCg);
00201 #else
00202       journalist()->Printf(J_ERROR, J_INITIALIZATION, "Couenne was compiled without CPLEX interface. Please reconfigure, recompile, and try again.\n");
00203       return false;
00204 #endif
00205     }
00206     continuousSolver_ -> passInMessageHandler(ci -> messageHandler());
00207 
00208     couenneProb_ -> setBase (this);
00209 
00210     assert (couenneProb_);
00211 
00212     couenneProb_ -> reformulate (couenneCg);
00213 
00214     Bonmin::BabInfo * extraStuff = new Bonmin::CouenneInfo(0);
00215 
00216     // as per instructions by John Forrest, to get changed bounds
00217     extraStuff -> setExtraCharacteristics (extraStuff -> extraCharacteristics () | 2);
00218 
00219     continuousSolver_ -> setAuxiliaryInfo (extraStuff);
00220     delete extraStuff;
00221     
00222     extraStuff = dynamic_cast <Bonmin::BabInfo *> (continuousSolver_ -> getAuxiliaryInfo ());
00223 
00224     /* Setup log level*/
00225     int lpLogLevel;
00226     options()->GetIntegerValue("lp_log_level",lpLogLevel,"bonmin.");
00227     continuousSolver_->messageHandler()->setLogLevel(lpLogLevel);
00228 
00230 
00231     couenneCg -> Problem () -> setMaxCpuTime (getDoubleParameter (BabSetupBase::MaxTime));
00232 
00233     ci -> extractLinearRelaxation (*continuousSolver_, *couenneCg);
00234 
00235     // In case there are no discrete variables, we have already a
00236     // heuristic solution for which create a initialization heuristic
00237     if (!(extraStuff -> infeasibleNode ()) &&
00238         ci -> isProvenOptimal () && 
00239         ci -> haveNlpSolution ()) {
00240 
00242       InitHeuristic* initHeuristic = new InitHeuristic 
00243         (ci -> getObjValue (), ci -> getColSolution (), *couenneProb_);
00244       HeuristicMethod h;
00245       h.id = "Init Rounding NLP";
00246       h.heuristic = initHeuristic;
00247       heuristics_.push_back(h);
00248     }
00249 
00250     if (extraStuff -> infeasibleNode ()){
00251       journalist() -> Printf(J_SUMMARY, J_PROBLEM, "Initial linear relaxation constructed by Couenne is infeasible, exiting...\n");
00252       return false;
00253     }
00254 
00255     //continuousSolver_ -> findIntegersAndSOS (false);
00256     //addSos (); // only adds embedded SOS objects
00257 
00258     // Add Couenne SOS ///////////////////////////////////////////////////////////////
00259 
00260     int 
00261       nSOS  = 0,
00262       nVars = couenneProb_ -> nVars ();
00263 
00264     OsiObject ** objects = NULL;
00265 
00266     options () -> GetStringValue ("enable_sos", s, "couenne.");
00267 
00268     if (s == "yes") {
00269 
00270       // allocate sufficient space for both nonlinear variables and SOS's
00271       objects = new OsiObject* [couenneProb_ -> nCons () + nVars];
00272 
00273       nSOS = couenneProb_ -> findSOS (nonlinearSolver (), objects);
00274 
00275       nonlinearSolver () -> addObjects (nSOS, objects);
00276 
00277       //printf ("==================== found %d SOS\n", nSOS);
00278       //nonlinearSolver () -> addObjects (nSOS, objects);
00279       //continuousSolver () -> addObjects (nSOS, objects);
00280 
00281       //printf ("found %d SOS!\n", nSOS);
00282 
00283       /*for (int i=0; i<nSOS; i++)
00284         delete objects [i];
00285         delete [] objects;*/
00286 
00287       if (!nSOS) {
00288         delete [] objects;
00289         objects = NULL;
00290       } 
00291     }
00292 
00293     //model -> assignSolver (continuousSolver_, true);
00294     //continuousSolver_ = model -> solver();
00295 
00296     // Add Couenne objects for branching /////////////////////////////////////////////
00297 
00298     options () -> GetStringValue ("display_stats", s, "couenne.");
00299     displayStats_ = (s == "yes");
00300 
00301     options () -> GetStringValue ("branching_object", s, "couenne.");
00302 
00303     enum CouenneObject::branch_obj objType = CouenneObject::VAR_OBJ;
00304 
00305     if      (s ==   "vt_obj") objType = CouenneObject::VT_OBJ;
00306     else if (s ==  "var_obj") objType = CouenneObject::VAR_OBJ;
00307     else if (s == "expr_obj") objType = CouenneObject::EXPR_OBJ;
00308     else {
00309       printf ("CouenneSetup: Unknown branching object type\n");
00310       exit (-1);
00311     }
00312 
00313     int 
00314       nobj = nSOS; // if no SOS then objects is empty
00315 
00316     if (!objects)
00317       objects = new OsiObject* [nVars];
00318 
00319     int contObjPriority = 2000; // default object priority -- it is 1000 for integers and 10 for SOS
00320 
00321     options () -> GetIntegerValue ("cont_var_priority", contObjPriority, "bonmin.");
00322 
00323     for (int i = 0; i < nVars; i++) { // for each variable
00324 
00325       exprVar *var = couenneProb_ -> Var (i);
00326 
00327       // we only want enabled variables
00328       if (var -> Multiplicity () <= 0) 
00329         continue;
00330 
00331       switch (objType) {
00332 
00333       case CouenneObject::EXPR_OBJ:
00334 
00335         // if this variable is associated with a nonlinear function
00336         if (var -> isInteger () || 
00337             (var -> Type  () == AUX) && 
00338             (var -> Image () -> Linearity () > LINEAR)) {
00339 
00340           /*if ((var -> Image () -> code () == COU_EXPRMUL) &&
00341               (var -> Image () -> ArgList () [0] -> Index () >= 0) &&
00342               (var -> Image () -> ArgList () [1] -> Index () >= 0) &&
00343               (fabs (var -> lb ()) < COUENNE_EPS) &&
00344               (fabs (var -> ub ()) < COUENNE_EPS))
00345 
00346             // it's a complementarity constraint object!
00347             objects    [nobj] = new CouenneComplObject (couenneProb_, var, this, journalist ());
00348             else*/
00349           objects [nobj] = new CouenneObject (couenneCg, couenneProb_, var, this, journalist ());
00350 
00351           objects [nobj++] -> setPriority (contObjPriority);
00352           //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00353         }
00354 
00355         break;
00356 
00357       case CouenneObject::VAR_OBJ:
00358 
00359         // branching objects on variables
00360         if // comment three lines below for linear variables too
00361           (var -> isInteger () || 
00362            (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {  // has indep
00363            //|| ((var -> Type () == AUX) &&                                  // or, aux 
00364            //    (var -> Image () -> Linearity () > LINEAR))) {              // of nonlinear
00365 
00366           objects [nobj] = new CouenneVarObject (couenneCg, couenneProb_, var, this, journalist ());
00367           objects [nobj++] -> setPriority (contObjPriority);
00368           //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00369         }
00370 
00371         break;
00372 
00373       default:
00374       case CouenneObject::VT_OBJ:
00375 
00376         // branching objects on variables
00377         if // comment three lines below for linear variables too
00378           (var -> isInteger () || 
00379            (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) { // has indep
00380           //|| ((var -> Type () == AUX) &&                      // or, aux 
00381           //(var -> Image () -> Linearity () > LINEAR))) { // of nonlinear
00382 
00383           objects [nobj] = new CouenneVTObject (couenneCg, couenneProb_, var, this, journalist ());
00384           objects [nobj++] -> setPriority (contObjPriority);
00385           //objects [nobj++] -> setPriority (contObjPriority + var -> rank ());
00386         }
00387 
00388         break;
00389       }
00390     }
00391 
00392     // Experimental: orbital branching //////////////////////////////////////////////
00393     options () -> GetStringValue ("orbital_branching", s, "couenne.");
00394 
00395     if (s == "yes") {
00396 
00397       objects [nobj] = new CouenneOrbitObj (couenneCg, couenneProb_, NULL, this, journalist ());
00398       objects [nobj++] -> setPriority (contObjPriority);
00399     }
00400 
00401     // Add objects /////////////////////////////////
00402 
00403     continuousSolver_ -> addObjects (nobj, objects);
00404 
00405     for (int i = 0 ; i < nobj ; i++)
00406       delete objects [i];
00407 
00408     delete [] objects;
00409 
00410     // Setup Convexifier generators ////////////////////////////////////////////////
00411 
00412     int freq;
00413 
00414     options()->GetIntegerValue("convexification_cuts",freq,"couenne.");
00415 
00416     if (freq != 0) {
00417 
00418       CuttingMethod cg;
00419       cg.frequency = freq;
00420       cg.cgl = couenneCg;
00421       cg.id = "Couenne convexifier cuts";
00422       cutGenerators().push_back(cg);
00423 
00424       // set cut gen pointer
00425       //dynamic_cast <CouenneSolverInterface <OsiClpSolverInterface> *> 
00426       //(continuousSolver_)
00427 
00428       // this is done on an explicitly declared CSI pointer, however
00429       // CSI == continuousSolver_
00430     }
00431 
00432     // disjunctive cuts generator added AFTER 
00433 
00434     // add other cut generators -- test for integer variables first
00435     if (couenneCg -> Problem () -> nIntVars () > 0)
00436       addMilpCutGenerators ();
00437 
00438     CouennePtr_ = couenneCg;
00439 
00440     // Setup heuristic to solve nlp problems. /////////////////////////////////
00441 
00442     int doNlpHeurisitic = 0;
00443     options()->GetEnumValue("local_optimization_heuristic", doNlpHeurisitic, "couenne.");
00444     if(doNlpHeurisitic)
00445     {
00446       int numSolve;
00447       options()->GetIntegerValue("log_num_local_optimization_per_level",numSolve,"couenne.");
00448       NlpSolveHeuristic * nlpHeuristic = new NlpSolveHeuristic;
00449       nlpHeuristic->setNlp(*ci,false);
00450       nlpHeuristic->setCouenneProblem(couenneProb_);
00451       //nlpHeuristic->setMaxNlpInf(1e-4);
00452       nlpHeuristic->setMaxNlpInf(maxNlpInf_0);
00453       nlpHeuristic->setNumberSolvePerLevel(numSolve);
00454       HeuristicMethod h;
00455       h.id = "Couenne Rounding NLP";
00456       h.heuristic = nlpHeuristic;
00457       heuristics_.push_back(h);
00458     }
00459 
00460     // Add Branching rules ///////////////////////////////////////////////////////
00461 
00462     int varSelection;
00463     if (!options_->GetEnumValue("variable_selection",varSelection,"bonmin.")) {
00464       // change the default for Couenne
00465       varSelection = OSI_SIMPLE;
00466     }
00467 
00468     switch (varSelection) {
00469 
00470     case OSI_STRONG: { // strong branching
00471       CouenneChooseStrong * chooseVariable = new CouenneChooseStrong
00472         (*this, couenneProb_, journalist ());
00473       chooseVariable->setTrustStrongForSolution(false);
00474       chooseVariable->setTrustStrongForBound(false);
00475       chooseVariable->setOnlyPseudoWhenTrusted(true);
00476       branchingMethod_ = chooseVariable;
00477       break;
00478     }
00479 
00480     case OSI_SIMPLE: // default choice
00481       branchingMethod_ = new CouenneChooseVariable 
00482         (continuousSolver_, couenneProb_, journalist ());
00483       break;
00484 
00485     default:
00486       std::cerr << "Unknown variable_selection for Couenne\n" << std::endl;
00487       throw;
00488       break;
00489     }
00490 
00491     // Add disjunctive cuts ///////////////////////////////////////////////////////
00492 
00493     options () -> GetIntegerValue ("minlp_disj_cuts", freq, "couenne.");
00494 
00495     if (freq != 0) {
00496 
00497       CouenneDisjCuts * couenneDisj = 
00498         new CouenneDisjCuts (ci, this, 
00499                              couenneCg, 
00500                              branchingMethod_, 
00501                              varSelection == OSI_STRONG, // if true, use strong branching candidates
00502                              journalist (),
00503                              options ());
00504 
00505       CuttingMethod cg;
00506       cg.frequency = freq;
00507       cg.cgl = couenneDisj;
00508       cg.id = "Couenne disjunctive cuts";
00509       cutGenerators (). push_back(cg);
00510     }
00511 
00512     int ival;
00513     if (!options_->GetEnumValue("node_comparison",ival,"bonmin.")) {
00514       // change default for Couenne
00515       nodeComparisonMethod_ = bestBound;
00516     }
00517     else {
00518       nodeComparisonMethod_ = NodeComparison(ival);
00519     }
00520 
00521     if(intParam_[NumCutPasses] < 2)
00522     intParam_[NumCutPasses] = 2;
00523 
00524     // Tell Cbc not to check again if a solution returned from
00525     // heuristic is indeed feasible
00526     intParam_[BabSetupBase::SpecialOption] = 16 | 4;
00527 
00528     return true;
00529   }
00530 
00531   bool CouenneSetup::InitializeCouenne (char ** argv,
00532           CouenneProblem *couenneProb,
00533           Bonmin::CouenneInterface *ci) {
00534     return InitializeCouenne(argv, couenneProb, ci ? ci->model() : NULL, ci);
00535   }
00536  
00537   void CouenneSetup::registerOptions(){
00538     registerAllOptions(roptions());
00539   }
00540 
00541 
00542   void
00543   CouenneSetup::registerAllOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions){
00544     BabSetupBase::registerAllOptions(roptions);
00545     BonCbcFullNodeInfo::registerOptions(roptions);
00546     CouenneCutGenerator::registerOptions (roptions);
00547     CouenneDisjCuts::registerOptions (roptions);
00548 
00549     roptions -> AddNumberOption
00550       ("couenne_check",
00551        "known value of a global optimum",
00552        COIN_DBL_MAX,
00553        "Default value is +infinity.");
00554 
00555     roptions -> AddStringOption2 (
00556       "display_stats",
00557       "display statistics at the end of the run",
00558       "no",
00559       "yes", "",
00560       "no", "");
00561 
00562     roptions -> AddStringOption2 (
00563       "test_mode",
00564       "set to true if this is Couenne unit test",
00565       "no",
00566       "yes", "",
00567       "no", "");
00568 
00569     roptions -> AddStringOption3 (
00570       "lp_solver",
00571       "Linear Programming solver for the linearization",
00572       "clp",
00573       "clp", "Use the Coin-OR Open Source solver CLP",
00574       "cplex", "Use the commercial solver Cplex (license is needed)",
00575       "soplex", "Use the freely available Soplex (not available yet)");
00576 
00577     roptions->AddBoundedIntegerOption(
00578       "branching_print_level", "Output level for braching code in Couenne",
00579       -2, J_LAST_LEVEL-1, J_NONE, "");
00580 
00581     roptions->AddBoundedIntegerOption(
00582       "boundtightening_print_level", "Output level for bound tightening code in Couenne",
00583       -2, J_LAST_LEVEL-1, J_NONE, "");
00584 
00585     roptions->AddBoundedIntegerOption(
00586       "convexifying_print_level", "Output level for convexifying code in Couenne",
00587       -2, J_LAST_LEVEL-1, J_NONE, "");
00588 
00589     roptions->AddBoundedIntegerOption(
00590       "problem_print_level", "Output level for problem manipulation code in Couenne",
00591       -2, J_LAST_LEVEL-1, J_ERROR, "");
00592 
00593     roptions->AddBoundedIntegerOption(
00594       "nlpheur_print_level", "Output level for NLP heuristic in Couenne",
00595       -2, J_LAST_LEVEL-1, J_NONE, "");
00596 
00597     roptions->AddBoundedIntegerOption(
00598     "disjcuts_print_level", "Output level for disjunctive cuts in Couenne",
00599     -2, J_LAST_LEVEL-1, J_NONE, "");
00600 
00601     roptions->AddBoundedIntegerOption(
00602     "reformulate_print_level", "Output level for reformulating problems in Couenne",
00603     -2, J_LAST_LEVEL-1, J_NONE, "");
00604 
00605 
00606     // copied from BonminSetup::registerMilpCutGenerators(), in
00607     // BonBonminSetup.cpp
00608 
00609     struct cutOption_ {
00610 
00611       const char *cgname;
00612       int         defaultFreq;
00613 
00614     } cutOption [] = {
00615       {(const char *) "Gomory_cuts",             0},
00616       {(const char *) "probing_cuts",            0},
00617       {(const char *) "cover_cuts",              0},
00618       {(const char *) "mir_cuts",                0},
00619       {(const char *) "2mir_cuts",               0},
00620       {(const char *) "flow_covers_cuts",        0},
00621       {(const char *) "lift_and_project_cuts",   0},
00622       {(const char *) "reduce_split_cuts",       0},
00623       {(const char *) "clique_cuts",             0},
00624       {NULL, 0}};
00625 
00626     for (int i=0; cutOption [i].cgname; i++) {
00627 
00628       char descr [150];
00629 
00630       sprintf (descr, "Frequency k (in terms of nodes) for generating %s cuts in branch-and-cut.",
00631                cutOption [i].cgname);
00632 
00633       roptions -> AddLowerBoundedIntegerOption 
00634         (cutOption [i].cgname,
00635          descr,
00636          -100, cutOption [i].defaultFreq,
00637          "If k > 0, cuts are generated every k nodes, "
00638          "if -99 < k < 0 cuts are generated every -k nodes but "
00639          "Cbc may decide to stop generating cuts, if not enough are generated at the root node, "
00640          "if k=-99 generate cuts only at the root node, if k=0 or 100 do not generate cuts.");
00641 
00642       roptions->setOptionExtraInfo (cutOption [i].cgname, 5);
00643     }
00644   }
00645 
00646 
00647 
00649   void CouenneSetup::addMilpCutGenerators () {
00650 
00651     enum extraInfo_ {CUTINFO_NONE, CUTINFO_MIG, CUTINFO_PROBING, CUTINFO_CLIQUE};
00652 
00653     struct cutInfo {
00654 
00655       const char      *optname;
00656       CglCutGenerator *cglptr;
00657       const char      *cglId;
00658       enum extraInfo_  extraInfo;
00659 
00660     } cutList [] = {
00661       {(const char*)"Gomory_cuts",new CglGomory,      (const char*)"Mixed Integer Gomory",CUTINFO_MIG},
00662       {(const char*)"probing_cuts",new CglProbing,        (const char*) "Probing", CUTINFO_PROBING},
00663       {(const char*)"mir_cuts",new CglMixedIntegerRounding2, (const char*) "Mixed Integer Rounding", 
00664                                                                                         CUTINFO_NONE},
00665       {(const char*)"2mir_cuts",    new CglTwomir,         (const char*) "2-MIR",    CUTINFO_NONE},
00666       {(const char*)"cover_cuts",   new CglKnapsackCover,  (const char*) "Cover",    CUTINFO_NONE},
00667       {(const char*)"clique_cuts",  new CglClique,         (const char*) "Clique",   CUTINFO_CLIQUE},
00668       {(const char*)"lift_and_project_cuts",new CglLandP,(const char*)"Lift and Project",CUTINFO_NONE},
00669       {(const char*)"reduce_split_cuts",new CglRedSplit,(const char*) "Reduce and Split",CUTINFO_NONE},
00670       {(const char*)"flow_covers_cuts",new CglFlowCover,(const char*) "Flow cover cuts", CUTINFO_NONE},
00671       {NULL, NULL, NULL, CUTINFO_NONE}};
00672 
00673     int freq;
00674 
00675     for (int i=0; cutList [i]. optname; i++) {
00676 
00677       options_ -> GetIntegerValue (std::string (cutList [i]. optname), freq, "bonmin.");
00678 
00679       if (!freq) {
00680         delete cutList [i].cglptr;
00681         continue;
00682       }
00683 
00684       CuttingMethod cg;
00685       cg.frequency = freq;
00686       cg.cgl       = cutList [i].cglptr;
00687       cg.id        = std::string (cutList [i]. cglId);
00688       cutGenerators_.push_back (cg);
00689 
00690       // options for particular cases
00691       switch (cutList [i].extraInfo) {
00692 
00693       case CUTINFO_MIG: {
00694         CglGomory *gc = dynamic_cast <CglGomory *> (cutList [i].cglptr);
00695 
00696         if (!gc) break;
00697 
00698         gc -> setLimitAtRoot(512);
00699         gc -> setLimit(50);
00700       }
00701         break;
00702 
00703       case CUTINFO_PROBING: {
00704         CglProbing *pc = dynamic_cast <CglProbing *> (cutList [i].cglptr);
00705 
00706         if (!pc) break;
00707 
00708         pc->setUsingObjective(1);
00709         pc->setMaxPass(3);
00710         pc->setMaxPassRoot(3);
00711         // Number of unsatisfied variables to look at
00712         pc->setMaxProbe(10);
00713         pc->setMaxProbeRoot(50);
00714         // How far to follow the consequences
00715         pc->setMaxLook(10);
00716         pc->setMaxLookRoot(50);
00717         pc->setMaxLookRoot(10);
00718         // Only look at rows with fewer than this number of elements
00719         pc->setMaxElements(200);
00720         pc->setRowCuts(3);
00721       }
00722         break;
00723 
00724       case CUTINFO_CLIQUE: {
00725         CglClique *clique = dynamic_cast <CglClique *> (cutList [i].cglptr);
00726 
00727         if (!clique) break;
00728 
00729         clique -> setStarCliqueReport(false);
00730         clique -> setRowCliqueReport(false);
00731         clique -> setMinViolation(0.1);
00732       }
00733         break;
00734 
00735         //case CUTINFO_NONE:
00736       default:
00737         break;
00738       }
00739     }
00740   }
00741 }

Generated on Tue Mar 30 03:04:37 2010 by  doxygen 1.4.7