00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00077 #include "CouenneTwoImplied.hpp"
00078
00079 #include "BonCouenneInfo.hpp"
00080 #include "BonCbcNode.hpp"
00081 #include "BonCbc.hpp"
00082
00083
00084
00085
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
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
00113 couenneProb_ = couenneProb;
00114 couenneProb_is_own_ = false;
00115 }
00116
00117
00118 readOptionsFile();
00119
00120
00121 options () -> SetStringValue ("sb", "yes", false, true);
00122
00123
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
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));
00154 ci -> initialize (roptions_, options_, journalist_, tminlp);
00155 }
00156 }
00157
00158 nonlinearSolver_ = ci;
00159
00164 int i;
00165
00167
00168
00169
00170
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
00187
00188
00189
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
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
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
00280
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";
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
00300
00301
00302
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
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
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 if (!nSOS) {
00332 delete [] objects;
00333 objects = NULL;
00334 }
00335 }
00336
00337
00338
00339
00340
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;
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
00373 varSelection = Bonmin::BabSetupBase::OSI_SIMPLE;
00374 }
00375
00376 for (int i = 0; i < nVars; i++) {
00377
00378 exprVar *var = couenneProb_ -> Var (i);
00379
00380
00381 if (var -> Multiplicity () <= 0)
00382 continue;
00383
00384 switch (objType) {
00385
00386 case CouenneObject::EXPR_OBJ:
00387
00388
00389 if (var -> isInteger () ||
00390 ((var -> Type () == AUX) &&
00391 (var -> Image () -> Linearity () > LINEAR))) {
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 objects [nobj] = new CouenneObject (couenneCg, couenneProb_, var, this, journalist ());
00403
00404 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00405
00406 }
00407
00408 break;
00409
00410 case CouenneObject::VAR_OBJ:
00411
00412
00413 if
00414 (var -> isInteger () ||
00415 (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {
00416
00417
00418
00419 objects [nobj] = new CouenneVarObject (couenneCg, couenneProb_, var, this, journalist (), varSelection);
00420 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00421
00422 }
00423
00424 break;
00425
00426 default:
00427 case CouenneObject::VT_OBJ:
00428
00429
00430 if
00431 (var -> isInteger () ||
00432 (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {
00433
00434
00435
00436 objects [nobj] = new CouenneVTObject (couenneCg, couenneProb_, var, this, journalist ());
00437 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00438
00439 }
00440
00441 break;
00442 }
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
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
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
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
00492
00493
00494
00495
00496
00497 }
00498
00499
00500 if (couenneCg -> Problem () -> nIntVars () > 0)
00501 addMilpCutGenerators ();
00502
00503 CouennePtr_ = couenneCg;
00504
00505
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
00523
00524
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) {
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
00695
00696 switch (varSelection) {
00697
00698 case OSI_STRONG: {
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:
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
00720
00721 int ival;
00722 if (!options_->GetEnumValue("node_comparison", ival, "bonmin.")) {
00723
00724 nodeComparisonMethod_ = bestBound;
00725 }
00726 else {
00727 nodeComparisonMethod_ = NodeComparison(ival);
00728 }
00729
00730 if (intParam_[NumCutPasses] < 2)
00731 intParam_[NumCutPasses] = 2;
00732
00733
00734
00735 intParam_ [BabSetupBase::SpecialOption] = 16 | 4;
00736
00737
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,
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
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
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
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
00929
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
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
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
01036 pc->setMaxProbe(10);
01037 pc->setMaxProbeRoot(50);
01038
01039 pc->setMaxLook(10);
01040 pc->setMaxLookRoot(50);
01041 pc->setMaxLookRoot(10);
01042
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
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
01074 options_->GetNumericValue(std::string("art_cutoff"), upval, "bonmin.");
01075 #endif
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 }