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