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 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 #if 0
00574 {
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 #endif
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
00811 #if 0
00813 Bonmin::LocalSolverBasedHeuristic ::registerOptions (roptions);
00814 Bonmin::FixAndSolveHeuristic ::registerOptions (roptions);
00815 Bonmin::DummyPump ::registerOptions (roptions);
00816 Bonmin::MilpRounding ::registerOptions (roptions);
00817 Bonmin::PumpForMinlp ::registerOptions (roptions);
00818 Bonmin::HeuristicRINS ::registerOptions (roptions);
00819 Bonmin::HeuristicLocalBranching ::registerOptions (roptions);
00820 Bonmin::HeuristicFPump ::registerOptions (roptions);
00821 Bonmin::HeuristicDiveFractional ::registerOptions (roptions);
00822 Bonmin::HeuristicDiveVectorLength ::registerOptions (roptions);
00823 Bonmin::HeuristicDiveMIPFractional ::registerOptions (roptions);
00824 Bonmin::HeuristicDiveMIPVectorLength ::registerOptions (roptions);
00825 #endif
00826
00827 roptions -> AddStringOption3 ("milp_solver",
00828 "Choose the subsolver to solve MILP sub-problems in OA decompositions.",
00829 "Cbc_D",
00830 "Cbc_D","Coin Branch and Cut with its default",
00831 "Cbc_Par", "Coin Branch and Cut with passed parameters",
00832 "Cplex","Ilog Cplex",
00833 " To use Cplex, a valid license is required and you should have compiled OsiCpx in COIN-OR (see Osi documentation).");
00834
00835 roptions -> setOptionExtraInfo ("milp_solver",64);
00836
00837 roptions -> AddStringOption2 ("milp_strategy",
00838 "Choose a strategy for MILPs.",
00839 "find_good_sol",
00840 "find_good_sol","Stop sub milps when a solution improving the incumbent is found",
00841 "solve_to_optimality", "Solve MILPs to optimality",
00842 "");
00843
00844 roptions -> AddStringOption6 ("algorithm",
00845 "Choice of the algorithm.",
00846 "B-BB",
00847 "B-BB","simple branch-and-bound algorithm,",
00848 "B-OA","OA Decomposition algorithm,",
00849 "B-QG","Quesada and Grossmann branch-and-cut algorithm,",
00850 "B-Hyb","hybrid outer approximation based branch-and-cut,",
00851 "B-Ecp","ecp cuts based branch-and-cut a la FilMINT.",
00852 "B-iFP","Iterated Feasibility Pump for MINLP.",
00853 "This will preset some of the options of bonmin depending on the algorithm choice."
00854 );
00855
00856 CouenneProblem ::registerOptions (roptions);
00857 CouenneCutGenerator ::registerOptions (roptions);
00858 CouenneChooseStrong ::registerOptions (roptions);
00859 CouenneChooseVariable ::registerOptions (roptions);
00860 CouenneFixPoint ::registerOptions (roptions);
00861 CouenneDisjCuts ::registerOptions (roptions);
00862
00863 CouenneTwoImplied ::registerOptions (roptions);
00864 NlpSolveHeuristic ::registerOptions (roptions);
00865 CouenneFeasPump ::registerOptions (roptions);
00866 CouenneIterativeRounding::registerOptions (roptions);
00867
00869 roptions -> AddStringOption2
00870 ("local_branching_heuristic",
00871 "Apply local branching heuristic",
00872 "no",
00873 "no","",
00874 "yes","",
00875 "A local-branching heuristic based is used to find feasible solutions.");
00876
00877
00878 roptions -> AddNumberOption ("couenne_check",
00879 "known value of a global optimum (for debug purposes only)",
00880 COIN_DBL_MAX,
00881 "Default value is +infinity.");
00882
00883 roptions -> AddStringOption2 ("display_stats",
00884 "display statistics at the end of the run",
00885 "no",
00886 "yes", "",
00887 "no", "");
00888
00889 roptions -> AddStringOption2 ("test_mode",
00890 "set to true if this is Couenne unit test",
00891 "no",
00892 "yes", "",
00893 "no", "");
00894
00895 roptions -> AddStringOption4 ("lp_solver",
00896 "Linear Programming solver for the linearization",
00897 "clp",
00898 "clp", "Use the Coin-OR Open Source solver CLP",
00899 "cplex", "Use the commercial solver Cplex (license is needed)",
00900 "gurobi", "Use the commercial solver Gurobi (license is needed)",
00901 "soplex", "Use the freely available Soplex");
00902
00903 #define addLevOption(optname,comment) roptions -> AddBoundedIntegerOption (optname, comment, -2, J_LAST_LEVEL-1, J_NONE, "")
00904
00905 addLevOption ("output_level", "Output level");
00906 addLevOption ("branching_print_level", "Output level for braching code in Couenne");
00907 addLevOption ("boundtightening_print_level", "Output level for bound tightening code in Couenne");
00908 addLevOption ("convexifying_print_level", "Output level for convexifying code in Couenne");
00909 addLevOption ("problem_print_level", "Output level for problem manipulation code in Couenne");
00910 addLevOption ("nlpheur_print_level", "Output level for NLP heuristic in Couenne");
00911 addLevOption ("disjcuts_print_level", "Output level for disjunctive cuts in Couenne");
00912 addLevOption ("reformulate_print_level", "Output level for reformulating problems in Couenne");
00913
00914 roptions -> AddNumberOption
00915 ("feas_tolerance",
00916 "Tolerance for constraints/auxiliary variables",
00917 feas_tolerance_default,
00918 "Default value is 1e-5.");
00919
00920 roptions -> AddStringOption2
00921 ("feasibility_bt",
00922 "Feasibility-based (cheap) bound tightening (FBBT)",
00923 "yes",
00924 "no","",
00925 "yes","",
00926 "A pre-processing technique to reduce the bounding box, before the generation of linearization cuts. "
00927 "This is a quick and effective way to reduce the solution set, and it is highly recommended to keep it active."
00928 );
00929
00930
00931
00932
00933 struct cutOption_ {
00934
00935 const char *cgname;
00936 int defaultFreq;
00937
00938 } cutOption [] = {
00939 {(const char *) "Gomory_cuts", 0},
00940 {(const char *) "probing_cuts", 0},
00941 {(const char *) "cover_cuts", 0},
00942 {(const char *) "mir_cuts", 0},
00943 {(const char *) "2mir_cuts", 0},
00944 {(const char *) "flow_covers_cuts", 0},
00945 {(const char *) "lift_and_project_cuts", 0},
00946 {(const char *) "reduce_split_cuts", 0},
00947 {(const char *) "clique_cuts", 0},
00948 {NULL, 0}};
00949
00950 for (int i=0; cutOption [i].cgname; i++) {
00951
00952 char descr [150];
00953
00954 sprintf (descr, "Frequency k (in terms of nodes) for generating %s cuts in branch-and-cut.",
00955 cutOption [i].cgname);
00956
00957 roptions -> AddLowerBoundedIntegerOption
00958 (cutOption [i].cgname,
00959 descr,
00960 -100, cutOption [i].defaultFreq,
00961 "If k > 0, cuts are generated every k nodes, "
00962 "if -99 < k < 0 cuts are generated every -k nodes but "
00963 "Cbc may decide to stop generating cuts, if not enough are generated at the root node, "
00964 "if k=-99 generate cuts only at the root node, if k=0 or 100 do not generate cuts.");
00965
00966 roptions->setOptionExtraInfo (cutOption [i].cgname, 5);
00967 }
00968 }
00969
00970
00971
00973 void CouenneSetup::addMilpCutGenerators () {
00974
00975 enum extraInfo_ {CUTINFO_NONE, CUTINFO_MIG, CUTINFO_PROBING, CUTINFO_CLIQUE};
00976
00977
00978
00979 struct cutInfo {
00980
00981 const char *optname;
00982 CglCutGenerator *cglptr;
00983 const char *cglId;
00984 enum extraInfo_ extraInfo;
00985
00986 } cutList [] = {
00987 {(const char*)"Gomory_cuts",new CglGomory, (const char*)"Mixed Integer Gomory",CUTINFO_MIG},
00988 {(const char*)"probing_cuts",new CglProbing, (const char*) "Probing", CUTINFO_PROBING},
00989 {(const char*)"mir_cuts",new CglMixedIntegerRounding2, (const char*) "Mixed Integer Rounding",
00990 CUTINFO_NONE},
00991 {(const char*)"2mir_cuts", new CglTwomir, (const char*) "2-MIR", CUTINFO_NONE},
00992 {(const char*)"cover_cuts", new CglKnapsackCover, (const char*) "Cover", CUTINFO_NONE},
00993 {(const char*)"clique_cuts", new CglClique, (const char*) "Clique", CUTINFO_CLIQUE},
00994 {(const char*)"lift_and_project_cuts",new CglLandP,(const char*)"Lift and Project",CUTINFO_NONE},
00995 {(const char*)"reduce_split_cuts",new CglRedSplit,(const char*) "Reduce and Split",CUTINFO_NONE},
00996 {(const char*)"flow_covers_cuts",new CglFlowCover,(const char*) "Flow cover cuts", CUTINFO_NONE},
00997 {NULL, NULL, NULL, CUTINFO_NONE}};
00998
00999 int freq;
01000
01001 for (int i=0; cutList [i]. optname; i++) {
01002
01003 options_ -> GetIntegerValue (std::string (cutList [i]. optname), freq, "couenne.");
01004
01005 if (!freq) {
01006 delete cutList [i].cglptr;
01007 continue;
01008 }
01009
01010 CuttingMethod cg;
01011 cg.frequency = freq;
01012 cg.cgl = cutList [i].cglptr;
01013 cg.id = std::string (cutList [i]. cglId);
01014 cutGenerators_.push_back (cg);
01015
01016
01017 switch (cutList [i].extraInfo) {
01018
01019 case CUTINFO_MIG: {
01020 CglGomory *gc = dynamic_cast <CglGomory *> (cutList [i].cglptr);
01021
01022 if (!gc) break;
01023
01024 gc -> setLimitAtRoot(512);
01025 gc -> setLimit(50);
01026 }
01027 break;
01028
01029 case CUTINFO_PROBING: {
01030 CglProbing *pc = dynamic_cast <CglProbing *> (cutList [i].cglptr);
01031
01032 if (!pc) break;
01033
01034 pc->setUsingObjective(1);
01035 pc->setMaxPass(3);
01036 pc->setMaxPassRoot(3);
01037
01038 pc->setMaxProbe(10);
01039 pc->setMaxProbeRoot(50);
01040
01041 pc->setMaxLook(10);
01042 pc->setMaxLookRoot(50);
01043 pc->setMaxLookRoot(10);
01044
01045 pc->setMaxElements(200);
01046 pc->setRowCuts(3);
01047 }
01048 break;
01049
01050 case CUTINFO_CLIQUE: {
01051 CglClique *clique = dynamic_cast <CglClique *> (cutList [i].cglptr);
01052
01053 if (!clique) break;
01054
01055 clique -> setStarCliqueReport(false);
01056 clique -> setRowCliqueReport(false);
01057 clique -> setMinViolation(0.1);
01058 }
01059 break;
01060
01061
01062 default:
01063 break;
01064 }
01065 }
01066
01067 double givenAllowFGap2 = 0.0;
01068 options_->GetNumericValue(std::string("allowable_fraction_gap"),
01069 givenAllowFGap2, "bonmin.");
01070 double upval = 1e50;
01071
01072 #ifdef FM_UP_BND
01073 printf("CutOff value:\n");
01074 scanf("%lf", &upval);
01075 #else
01076 options_->GetNumericValue(std::string("art_cutoff"), upval, "bonmin.");
01077 #endif
01078
01079 if(upval < 1e50) {
01080 double newCO = (1-givenAllowFGap2) * upval;
01081 couenneProb_->setCutOff(newCO);
01082 printf("CutOff set to %f\n", newCO);
01083
01084 #ifdef FM_TRACE_OPTSOL
01085 if(couenneProb_->getRecordBestSol()->getHasSol()) {
01086 if(newCO < couenneProb_->getRecordBestSol()->getVal()) {
01087 couenneProb_->getRecordBestSol()->setVal(newCO);
01088 }
01089 }
01090 #endif
01091 }
01092 }