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
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
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 if ((Bonmin::BabSetupBase::OSI_STRONG == varSelection) &&
00377 (CouenneObject::VT_OBJ == objType)){
00378
00379 printf ("Warning: Violation Transfer and strong branching are mutually exclusive.\nResetting to Violation Transfer only.\n");
00380 varSelection = Bonmin::BabSetupBase::OSI_SIMPLE;
00381 }
00382
00383 for (int i = 0; i < nVars; i++) {
00384
00385 exprVar *var = couenneProb_ -> Var (i);
00386
00387
00388 if (var -> Multiplicity () <= 0)
00389 continue;
00390
00391 switch (objType) {
00392
00393 case CouenneObject::EXPR_OBJ:
00394
00395
00396 if (var -> isInteger () ||
00397 ((var -> Type () == AUX) &&
00398 (var -> Image () -> Linearity () > LINEAR))) {
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 objects [nobj] = new CouenneObject (couenneCg, couenneProb_, var, this, journalist ());
00410
00411 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00412
00413 }
00414
00415 break;
00416
00417 case CouenneObject::VAR_OBJ:
00418
00419
00420 if
00421 (var -> isInteger () ||
00422 (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {
00423
00424
00425
00426 objects [nobj] = new CouenneVarObject (couenneCg, couenneProb_, var, this, journalist (), varSelection);
00427 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00428
00429 }
00430
00431 break;
00432
00433 default:
00434 case CouenneObject::VT_OBJ:
00435
00436
00437 if
00438 (var -> isInteger () ||
00439 (couenneProb_ -> Dependence () [var -> Index ()] . size () > 0)) {
00440
00441
00442
00443 objects [nobj] = new CouenneVTObject (couenneCg, couenneProb_, var, this, journalist ());
00444 objects [nobj++] -> setPriority (var -> isInteger () ? intObjPriority : contObjPriority);
00445
00446 }
00447
00448 break;
00449 }
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 continuousSolver_ -> addObjects (nobj, objects);
00465
00466 for (int i = 0 ; i < nobj ; i++)
00467 delete objects [i];
00468
00469 delete [] objects;
00470
00471 int freq;
00472
00473
00474
00475 options () -> GetIntegerValue ("fixpoint_bt", freq, "couenne.");
00476
00477 if (freq != 0) {
00478
00479 CuttingMethod cg;
00480 cg.frequency = freq;
00481 cg.cgl = new CouenneFixPoint (couenneProb_, options ());
00482 cg.id = "Couenne fixed point FBBT";
00483 cutGenerators (). push_back (cg);
00484 }
00485
00486
00487
00488 options () -> GetIntegerValue ("convexification_cuts", freq, "couenne.");
00489
00490 if (freq != 0) {
00491
00492 CuttingMethod cg;
00493 cg.frequency = freq;
00494 cg.cgl = couenneCg;
00495 cg.id = "Couenne convexifier cuts";
00496 cutGenerators().push_back (cg);
00497
00498
00499
00500
00501
00502
00503
00504 }
00505
00506
00507 if (couenneCg -> Problem () -> nIntVars () > 0)
00508 addMilpCutGenerators ();
00509
00510 CouennePtr_ = couenneCg;
00511
00512
00513
00514 options () -> GetIntegerValue ("two_implied_bt", freq, "couenne.");
00515
00516 if (freq != 0) {
00517
00518 CouenneTwoImplied * couenne2I =
00519 new CouenneTwoImplied (couenneProb_,
00520 journalist (),
00521 options ());
00522 CuttingMethod cg;
00523 cg.frequency = freq;
00524 cg.cgl = couenne2I;
00525 cg.id = "Couenne two-implied cuts";
00526 cutGenerators (). push_back(cg);
00527 }
00528
00529
00530
00531
00532
00533 std::string doHeuristic;
00534
00535 options () -> GetStringValue ("local_optimization_heuristic", doHeuristic, "couenne.");
00536
00537 if (doHeuristic == "yes") {
00538
00539 int numSolve;
00540 options()->GetIntegerValue("log_num_local_optimization_per_level",numSolve,"couenne.");
00541 NlpSolveHeuristic * nlpHeuristic = new NlpSolveHeuristic;
00542 nlpHeuristic->setNlp(*ci,false);
00543 nlpHeuristic->setCouenneProblem(couenneProb_);
00544 nlpHeuristic->setMaxNlpInf(maxNlpInf_0);
00545 nlpHeuristic->setNumberSolvePerLevel(numSolve);
00546 HeuristicMethod h;
00547 h.id = "Couenne Rounding NLP";
00548 h.heuristic = nlpHeuristic;
00549 heuristics_.push_back(h);
00550 }
00551
00552 options () -> GetStringValue ("iterative_rounding_heuristic", doHeuristic, "couenne.");
00553
00554 if (doHeuristic == "yes") {
00555 CouenneIterativeRounding * nlpHeuristic = new CouenneIterativeRounding(nonlinearSolver_, ci, couenneProb_, options());
00556 HeuristicMethod h;
00557 h.id = "Couenne Iterative Rounding";
00558 h.heuristic = nlpHeuristic;
00559 heuristics_.push_back(h);
00560 }
00561
00562 options () -> GetStringValue ("feas_pump_heuristic", doHeuristic, "couenne.");
00563
00564 if (doHeuristic == "yes") {
00565
00566 int numSolve;
00567 options () -> GetIntegerValue ("feas_pump_level", numSolve, "couenne.");
00568
00569 CouenneFeasPump *nlpHeuristic = new CouenneFeasPump (couenneProb_, couenneCg, options ());
00570
00571 nlpHeuristic -> setNumberSolvePerLevel (numSolve);
00572
00573 HeuristicMethod h;
00574
00575 h.id = "Couenne Feasibility Pump";
00576 h.heuristic = nlpHeuristic;
00577 heuristics_. push_back (h);
00578 }
00579
00580 #if 0
00581 {
00582
00583 Ipopt::Index doHeuristicDiveFractional = false;
00584 options()->GetEnumValue("heuristic_dive_fractional",doHeuristicDiveFractional,prefix_.c_str());
00585 if(doHeuristicDiveFractional){
00586 Bonmin::HeuristicDiveFractional* dive_fractional = new Bonmin::HeuristicDiveFractional(this);
00587 HeuristicMethod h;
00588 h.heuristic = dive_fractional;
00589 h.id = "DiveFractional";
00590 heuristics_.push_back(h);
00591 }
00592
00593 Ipopt::Index doHeuristicDiveVectorLength = false;
00594 options()->GetEnumValue("heuristic_dive_vectorLength",doHeuristicDiveVectorLength,prefix_.c_str());
00595 if(doHeuristicDiveVectorLength){
00596 Bonmin::HeuristicDiveVectorLength* dive_vectorLength = new Bonmin::HeuristicDiveVectorLength(this);
00597 HeuristicMethod h;
00598 h.heuristic = dive_vectorLength;
00599 h.id = "DiveVectorLength";
00600 heuristics_.push_back(h);
00601 }
00602
00603 Ipopt::Index doHeuristicDiveMIPFractional = false;
00604 if(!options()->GetEnumValue("heuristic_dive_MIP_fractional",doHeuristicDiveMIPFractional,prefix_.c_str())){
00605 doHeuristicDiveMIPFractional = true;
00606 std::string o_name = prefix_ + "heuristic_dive_MIP_fractional";
00607 options_->SetStringValue(o_name.c_str(), "yes",true,true);
00608 }
00609 if(doHeuristicDiveMIPFractional){
00610 Bonmin::HeuristicDiveMIPFractional* dive_MIP_fractional = new Bonmin::HeuristicDiveMIPFractional(this);
00611 HeuristicMethod h;
00612 h.heuristic = dive_MIP_fractional;
00613 h.id = "DiveMIPFractional";
00614 heuristics_.push_back(h);
00615 }
00616
00617 Ipopt::Index doHeuristicDiveMIPVectorLength = false;
00618 options()->GetEnumValue("heuristic_dive_MIP_vectorLength",doHeuristicDiveMIPVectorLength,prefix_.c_str());
00619 if(doHeuristicDiveMIPVectorLength){
00620 Bonmin::HeuristicDiveMIPVectorLength* dive_MIP_vectorLength = new Bonmin::HeuristicDiveMIPVectorLength(this);
00621 HeuristicMethod h;
00622 h.heuristic = dive_MIP_vectorLength;
00623 h.id = "DiveMIPVectorLength";
00624 heuristics_.push_back(h);
00625 }
00626 Ipopt::Index doHeuristicFPump = false;
00627 if(!nonlinearSolver_->model()->hasGeneralInteger() && !options()->GetEnumValue("heuristic_feasibility_pump",doHeuristicFPump,prefix_.c_str())){
00628 doHeuristicFPump = true;
00629 std::string o_name = prefix_ + "heuristic_feasibility_pump";
00630 options_->SetStringValue(o_name.c_str(), "yes",true,true);
00631 }
00632 if(doHeuristicFPump){
00633 Bonmin::HeuristicFPump* feasibility_pump = new Bonmin::HeuristicFPump(this);
00634 HeuristicMethod h;
00635 h.heuristic = feasibility_pump;
00636 h.id = "FPump";
00637 heuristics_.push_back(h);
00638 }
00639
00640 Ipopt::Index doFixAndSolve = false;
00641 options()->GetEnumValue("fix_and_solve_heuristic",doFixAndSolve,prefix_.c_str());
00642 if(doFixAndSolve){
00643 Bonmin::FixAndSolveHeuristic* fix_and_solve = new Bonmin::FixAndSolveHeuristic(this);
00644 HeuristicMethod h;
00645 h.heuristic = fix_and_solve;
00646 h.id = "Fix and Solve";
00647 heuristics_.push_back(h);
00648 }
00649
00650 Ipopt::Index doDummyPump = false;
00651 options()->GetEnumValue("dummy_pump_heuristic",doDummyPump,prefix_.c_str());
00652 if(doDummyPump){
00653 Bonmin::DummyPump* fix_and_solve = new Bonmin::DummyPump(this);
00654 HeuristicMethod h;
00655 h.heuristic = fix_and_solve;
00656 h.id = "Dummy pump";
00657 heuristics_.push_back(h);
00658 }
00659
00660 Ipopt::Index doHeuristicRINS = false;
00661 options()->GetEnumValue("heuristic_RINS",doHeuristicRINS,prefix_.c_str());
00662 if(doHeuristicRINS){
00663 Bonmin::HeuristicRINS* rins = new Bonmin::HeuristicRINS(this);
00664 HeuristicMethod h;
00665 h.heuristic = rins;
00666 h.id = "RINS";
00667 heuristics_.push_back(h);
00668 }
00669
00670 Ipopt::Index doHeuristicLocalBranching = false;
00671 options()->GetEnumValue("heuristic_local_branching",doHeuristicLocalBranching,prefix_.c_str());
00672 if(doHeuristicLocalBranching){
00673 Bonmin::HeuristicLocalBranching* local_branching = new Bonmin::HeuristicLocalBranching(this);
00674 HeuristicMethod h;
00675 h.heuristic = local_branching;
00676 h.id = "LocalBranching";
00677 heuristics_.push_back(h);
00678 }
00679
00680 Ipopt::Index doHeuristicPumpForMinlp = false;
00681 options()->GetEnumValue("pump_for_minlp",doHeuristicPumpForMinlp,prefix_.c_str());
00682 if(doHeuristicPumpForMinlp){
00683 Bonmin::PumpForMinlp * pump = new Bonmin::PumpForMinlp(this);
00684 HeuristicMethod h;
00685 h.heuristic = pump;
00686 h.id = "Pump for MINLP";
00687 heuristics_.push_back(h);
00688 }
00689
00690 Ipopt::Index doHeuristicMilpRounding = false;
00691 options()->GetEnumValue("MILP_rounding_heuristic",doHeuristicMilpRounding,prefix_.c_str());
00692 if(doHeuristicMilpRounding){
00693 Bonmin::MilpRounding * round = new Bonmin::MilpRounding(this);
00694 HeuristicMethod h;
00695 h.heuristic = round;
00696 h.id = "MILP Rounding";
00697 heuristics_.push_back(h);
00698 }
00699 #endif
00700
00701
00702
00703 switch (varSelection) {
00704
00705 case OSI_STRONG: {
00706 CouenneChooseStrong * chooseVariable = new CouenneChooseStrong
00707 (*this, couenneProb_, journalist ());
00708 chooseVariable->setTrustStrongForSolution(false);
00709 chooseVariable->setTrustStrongForBound(false);
00710 chooseVariable->setOnlyPseudoWhenTrusted(true);
00711 branchingMethod_ = chooseVariable;
00712 break;
00713 }
00714
00715 case OSI_SIMPLE:
00716 branchingMethod_ = new CouenneChooseVariable
00717 (continuousSolver_, couenneProb_, journalist ());
00718 break;
00719
00720 default:
00721 std::cerr << "Unknown variable_selection for Couenne\n" << std::endl;
00722 throw;
00723 break;
00724 }
00725
00726
00727
00728 int ival;
00729 if (!options_->GetEnumValue("node_comparison", ival, "bonmin.")) {
00730
00731 nodeComparisonMethod_ = bestBound;
00732 }
00733 else {
00734 nodeComparisonMethod_ = NodeComparison(ival);
00735 }
00736
00737 if (intParam_[NumCutPasses] < 2)
00738 intParam_[NumCutPasses] = 2;
00739
00740
00741
00742 intParam_ [BabSetupBase::SpecialOption] = 16 | 4;
00743
00744
00745
00746 options () -> GetIntegerValue ("minlp_disj_cuts", freq, "couenne.");
00747
00748 if (freq != 0) {
00749
00750 CouenneDisjCuts * couenneDisj =
00751 new CouenneDisjCuts (ci, this,
00752 couenneCg,
00753 branchingMethod_,
00754 varSelection == OSI_STRONG,
00755 journalist (),
00756 options ());
00757
00758 CuttingMethod cg;
00759 cg.frequency = freq;
00760 cg.cgl = couenneDisj;
00761 cg.id = "Couenne disjunctive cuts";
00762 cutGenerators (). push_back(cg);
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
00798
00799
00800
00801
00802
00803
00804 return true;
00805 }
00806
00807 void CouenneSetup::registerOptions ()
00808 {registerAllOptions (roptions ());}
00809
00810
00811 void CouenneSetup::registerAllOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00812
00813 roptions -> SetRegisteringCategory ("Couenne options", Bonmin::RegisteredOptions::CouenneCategory);
00814
00815 BabSetupBase ::registerAllOptions (roptions);
00816 Bonmin::BonCbcFullNodeInfo ::registerOptions (roptions);
00817
00818 #if 0
00820 Bonmin::LocalSolverBasedHeuristic ::registerOptions (roptions);
00821 Bonmin::FixAndSolveHeuristic ::registerOptions (roptions);
00822 Bonmin::DummyPump ::registerOptions (roptions);
00823 Bonmin::MilpRounding ::registerOptions (roptions);
00824 Bonmin::PumpForMinlp ::registerOptions (roptions);
00825 Bonmin::HeuristicRINS ::registerOptions (roptions);
00826 Bonmin::HeuristicLocalBranching ::registerOptions (roptions);
00827 Bonmin::HeuristicFPump ::registerOptions (roptions);
00828 Bonmin::HeuristicDiveFractional ::registerOptions (roptions);
00829 Bonmin::HeuristicDiveVectorLength ::registerOptions (roptions);
00830 Bonmin::HeuristicDiveMIPFractional ::registerOptions (roptions);
00831 Bonmin::HeuristicDiveMIPVectorLength ::registerOptions (roptions);
00832 #endif
00833
00834 roptions -> AddStringOption3 ("milp_solver",
00835 "Choose the subsolver to solve MILP sub-problems in OA decompositions.",
00836 "Cbc_D",
00837 "Cbc_D","Coin Branch and Cut with its default",
00838 "Cbc_Par", "Coin Branch and Cut with passed parameters",
00839 "Cplex","Ilog Cplex",
00840 " To use Cplex, a valid license is required and you should have compiled OsiCpx in COIN-OR (see Osi documentation).");
00841
00842 roptions -> setOptionExtraInfo ("milp_solver",64);
00843
00844 roptions -> AddStringOption2 ("milp_strategy",
00845 "Choose a strategy for MILPs.",
00846 "find_good_sol",
00847 "find_good_sol","Stop sub milps when a solution improving the incumbent is found",
00848 "solve_to_optimality", "Solve MILPs to optimality",
00849 "");
00850
00851 roptions -> AddStringOption6 ("algorithm",
00852 "Choice of the algorithm.",
00853 "B-BB",
00854 "B-BB","simple branch-and-bound algorithm,",
00855 "B-OA","OA Decomposition algorithm,",
00856 "B-QG","Quesada and Grossmann branch-and-cut algorithm,",
00857 "B-Hyb","hybrid outer approximation based branch-and-cut,",
00858 "B-Ecp","ecp cuts based branch-and-cut a la FilMINT.",
00859 "B-iFP","Iterated Feasibility Pump for MINLP.",
00860 "This will preset some of the options of bonmin depending on the algorithm choice."
00861 );
00862
00863 CouenneProblem ::registerOptions (roptions);
00864 CouenneCutGenerator ::registerOptions (roptions);
00865 CouenneChooseStrong ::registerOptions (roptions);
00866 CouenneChooseVariable ::registerOptions (roptions);
00867 CouenneFixPoint ::registerOptions (roptions);
00868 CouenneDisjCuts ::registerOptions (roptions);
00869
00870 CouenneTwoImplied ::registerOptions (roptions);
00871 NlpSolveHeuristic ::registerOptions (roptions);
00872 CouenneFeasPump ::registerOptions (roptions);
00873 CouenneIterativeRounding::registerOptions (roptions);
00874
00876 roptions -> AddStringOption2
00877 ("local_branching_heuristic",
00878 "Apply local branching heuristic",
00879 "no",
00880 "no","",
00881 "yes","",
00882 "A local-branching heuristic based is used to find feasible solutions.");
00883
00884
00885 roptions -> AddNumberOption ("couenne_check",
00886 "known value of a global optimum (for debug purposes only)",
00887 COIN_DBL_MAX,
00888 "Default value is +infinity.");
00889
00890 roptions -> AddStringOption2 ("display_stats",
00891 "display statistics at the end of the run",
00892 "no",
00893 "yes", "",
00894 "no", "");
00895
00896 roptions -> AddStringOption2 ("test_mode",
00897 "set to true if this is Couenne unit test",
00898 "no",
00899 "yes", "",
00900 "no", "");
00901
00902 roptions -> AddStringOption5 ("lp_solver",
00903 "Linear Programming solver for the linearization",
00904 "clp",
00905 "clp", "Use the COIN-OR Open Source solver CLP",
00906 "cplex", "Use the commercial solver Cplex (license is needed)",
00907 "gurobi", "Use the commercial solver Gurobi (license is needed)",
00908 "soplex", "Use the freely available Soplex",
00909 "xpress-mp", "Use the commercial solver Xpress MP (license is needed)"
00910 );
00911
00912 #define addLevOption(optname,comment) roptions -> AddBoundedIntegerOption (optname, comment, -2, J_LAST_LEVEL-1, J_NONE, "")
00913
00914 addLevOption ("output_level", "Output level");
00915 addLevOption ("branching_print_level", "Output level for braching code in Couenne");
00916 addLevOption ("boundtightening_print_level", "Output level for bound tightening code in Couenne");
00917 addLevOption ("convexifying_print_level", "Output level for convexifying code in Couenne");
00918 addLevOption ("problem_print_level", "Output level for problem manipulation code in Couenne");
00919 addLevOption ("nlpheur_print_level", "Output level for NLP heuristic in Couenne");
00920 addLevOption ("disjcuts_print_level", "Output level for disjunctive cuts in Couenne");
00921 addLevOption ("reformulate_print_level", "Output level for reformulating problems in Couenne");
00922
00923 roptions -> AddNumberOption
00924 ("feas_tolerance",
00925 "Tolerance for constraints/auxiliary variables",
00926 feas_tolerance_default,
00927 "Default value is 1e-5.");
00928
00929 roptions -> AddStringOption2
00930 ("feasibility_bt",
00931 "Feasibility-based (cheap) bound tightening (FBBT)",
00932 "yes",
00933 "no","",
00934 "yes","",
00935 "A pre-processing technique to reduce the bounding box, before the generation of linearization cuts. "
00936 "This is a quick and effective way to reduce the solution set, and it is highly recommended to keep it active."
00937 );
00938
00939
00940
00941
00942 struct cutOption_ {
00943
00944 const char *cgname;
00945 int defaultFreq;
00946
00947 } cutOption [] = {
00948 {(const char *) "Gomory_cuts", 0},
00949 {(const char *) "probing_cuts", 0},
00950 {(const char *) "cover_cuts", 0},
00951 {(const char *) "mir_cuts", 0},
00952 {(const char *) "2mir_cuts", 0},
00953 {(const char *) "flow_covers_cuts", 0},
00954 {(const char *) "lift_and_project_cuts", 0},
00955 {(const char *) "reduce_split_cuts", 0},
00956 {(const char *) "clique_cuts", 0},
00957 {NULL, 0}};
00958
00959 for (int i=0; cutOption [i].cgname; i++) {
00960
00961 char descr [150];
00962
00963 sprintf (descr, "Frequency k (in terms of nodes) for generating %s cuts in branch-and-cut.",
00964 cutOption [i].cgname);
00965
00966 roptions -> AddLowerBoundedIntegerOption
00967 (cutOption [i].cgname,
00968 descr,
00969 -100, cutOption [i].defaultFreq,
00970 "If k > 0, cuts are generated every k nodes, "
00971 "if -99 < k < 0 cuts are generated every -k nodes but "
00972 "Cbc may decide to stop generating cuts, if not enough are generated at the root node, "
00973 "if k=-99 generate cuts only at the root node, if k=0 or 100 do not generate cuts.");
00974
00975 roptions->setOptionExtraInfo (cutOption [i].cgname, 5);
00976 }
00977 }
00978
00979
00980
00982 void CouenneSetup::addMilpCutGenerators () {
00983
00984 enum extraInfo_ {CUTINFO_NONE, CUTINFO_MIG, CUTINFO_PROBING, CUTINFO_CLIQUE};
00985
00986
00987
00988 struct cutInfo {
00989
00990 const char *optname;
00991 CglCutGenerator *cglptr;
00992 const char *cglId;
00993 enum extraInfo_ extraInfo;
00994
00995 } cutList [] = {
00996 {(const char*)"Gomory_cuts",new CglGomory, (const char*)"Mixed Integer Gomory",CUTINFO_MIG},
00997 {(const char*)"probing_cuts",new CglProbing, (const char*) "Probing", CUTINFO_PROBING},
00998 {(const char*)"mir_cuts",new CglMixedIntegerRounding2, (const char*) "Mixed Integer Rounding",
00999 CUTINFO_NONE},
01000 {(const char*)"2mir_cuts", new CglTwomir, (const char*) "2-MIR", CUTINFO_NONE},
01001 {(const char*)"cover_cuts", new CglKnapsackCover, (const char*) "Cover", CUTINFO_NONE},
01002 {(const char*)"clique_cuts", new CglClique, (const char*) "Clique", CUTINFO_CLIQUE},
01003 {(const char*)"lift_and_project_cuts",new CglLandP,(const char*)"Lift and Project",CUTINFO_NONE},
01004 {(const char*)"reduce_split_cuts",new CglRedSplit,(const char*) "Reduce and Split",CUTINFO_NONE},
01005 {(const char*)"flow_covers_cuts",new CglFlowCover,(const char*) "Flow cover cuts", CUTINFO_NONE},
01006 {NULL, NULL, NULL, CUTINFO_NONE}};
01007
01008 int freq;
01009
01010 for (int i=0; cutList [i]. optname; i++) {
01011
01012 options_ -> GetIntegerValue (std::string (cutList [i]. optname), freq, "couenne.");
01013
01014 if (!freq) {
01015 delete cutList [i].cglptr;
01016 continue;
01017 }
01018
01019 CuttingMethod cg;
01020 cg.frequency = freq;
01021 cg.cgl = cutList [i].cglptr;
01022 cg.id = std::string (cutList [i]. cglId);
01023 cutGenerators_.push_back (cg);
01024
01025
01026 switch (cutList [i].extraInfo) {
01027
01028 case CUTINFO_MIG: {
01029 CglGomory *gc = dynamic_cast <CglGomory *> (cutList [i].cglptr);
01030
01031 if (!gc) break;
01032
01033 gc -> setLimitAtRoot(512);
01034 gc -> setLimit(50);
01035 }
01036 break;
01037
01038 case CUTINFO_PROBING: {
01039 CglProbing *pc = dynamic_cast <CglProbing *> (cutList [i].cglptr);
01040
01041 if (!pc) break;
01042
01043 pc->setUsingObjective(1);
01044 pc->setMaxPass(3);
01045 pc->setMaxPassRoot(3);
01046
01047 pc->setMaxProbe(10);
01048 pc->setMaxProbeRoot(50);
01049
01050 pc->setMaxLook(10);
01051 pc->setMaxLookRoot(50);
01052 pc->setMaxLookRoot(10);
01053
01054 pc->setMaxElements(200);
01055 pc->setRowCuts(3);
01056 }
01057 break;
01058
01059 case CUTINFO_CLIQUE: {
01060 CglClique *clique = dynamic_cast <CglClique *> (cutList [i].cglptr);
01061
01062 if (!clique) break;
01063
01064 clique -> setStarCliqueReport(false);
01065 clique -> setRowCliqueReport(false);
01066 clique -> setMinViolation(0.1);
01067 }
01068 break;
01069
01070
01071 default:
01072 break;
01073 }
01074 }
01075
01076 double givenAllowFGap2 = 0.0;
01077 options_->GetNumericValue(std::string("allowable_fraction_gap"),
01078 givenAllowFGap2, "bonmin.");
01079 double upval = 1e50;
01080
01081 #ifdef FM_UP_BND
01082 printf("CutOff value:\n");
01083 scanf("%lf", &upval);
01084 #else
01085 options_->GetNumericValue(std::string("art_cutoff"), upval, "bonmin.");
01086 #endif
01087
01088 if(upval < 1e50) {
01089 double newCO = (1-givenAllowFGap2) * upval;
01090 couenneProb_->setCutOff(newCO);
01091 printf("CutOff set to %f\n", newCO);
01092
01093 #ifdef FM_TRACE_OPTSOL
01094 if(couenneProb_->getRecordBestSol()->getHasSol()) {
01095 if(newCO < couenneProb_->getRecordBestSol()->getVal()) {
01096 couenneProb_->getRecordBestSol()->setVal(newCO);
01097 }
01098 }
01099 #endif
01100 }
01101 }