00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BonminConfig.h"
00011 #ifdef COIN_HAS_FILTERSQP
00012 # include "BonFilterSolver.hpp"
00013 #endif
00014 #include "BonBabSetupBase.hpp"
00015 #include <climits>
00016 #include <fstream>
00017 #include <sstream>
00018
00019 #include "BonDiver.hpp"
00020 #include "BonQpBranchingSolver.hpp"
00021 #include "BonLpBranchingSolver.hpp"
00022 #include "BonChooseVariable.hpp"
00023 #include "BonTMINLP2Quad.hpp"
00024 #include "BonTMINLPLinObj.hpp"
00025 namespace Bonmin
00026 {
00027 int BabSetupBase::defaultIntParam_[BabSetupBase::NumberIntParam] = {
00028 1 ,
00029 100 ,
00030 2 ,
00031 0 ,
00032 0 ,
00033 5 ,
00034 2 ,
00035 COIN_INT_MAX ,
00036 COIN_INT_MAX ,
00037 COIN_INT_MAX ,
00038 0 ,
00039 0 ,
00040 1 ,
00041 20 ,
00042 0
00043 };
00044
00045
00046 double BabSetupBase::defaultDoubleParam_[BabSetupBase::NumberDoubleParam] = {
00047 0 ,
00048 COIN_DBL_MAX ,
00049 0 ,
00050 0 ,
00051 1e-09 ,
00052 COIN_DBL_MAX ,
00053 };
00054
00055 BabSetupBase::BabSetupBase(const CoinMessageHandler * handler):
00056 nonlinearSolver_(NULL),
00057 continuousSolver_(NULL),
00058 linearizer_(NULL),
00059 cutGenerators_(),
00060 heuristics_(),
00061 branchingMethod_(NULL),
00062 nodeComparisonMethod_(),
00063 treeTraversalMethod_(),
00064 objects_(0),
00065 journalist_(NULL),
00066 options_(NULL),
00067 roptions_(NULL),
00068 readOptions_(false),
00069 messageHandler_(NULL),
00070 prefix_("bonmin.")
00071 {
00072 CoinCopyN(defaultIntParam_, NumberIntParam, intParam_);
00073 CoinCopyN(defaultDoubleParam_, NumberDoubleParam, doubleParam_);
00074 if(handler) messageHandler_ = handler->clone();
00075 }
00076
00078 BabSetupBase::BabSetupBase(const BabSetupBase & other):
00079 nonlinearSolver_(NULL),
00080 continuousSolver_(NULL),
00081 linearizer_(other.linearizer_),
00082 cutGenerators_(),
00083 heuristics_(),
00084 branchingMethod_(NULL),
00085 nodeComparisonMethod_(other.nodeComparisonMethod_),
00086 treeTraversalMethod_(other.treeTraversalMethod_),
00087 objects_(other.objects_),
00088 journalist_(other.journalist_),
00089 options_(NULL),
00090 roptions_(other.roptions_),
00091 readOptions_(other.readOptions_),
00092 messageHandler_(NULL),
00093 prefix_(other.prefix_)
00094 {
00095 if (other.nonlinearSolver_) {
00096 nonlinearSolver_ = static_cast<OsiTMINLPInterface *>(other.nonlinearSolver_->clone());
00097 }
00098 if (other.continuousSolver_) {
00099 continuousSolver_ = other.continuousSolver_->clone();
00100 }
00101 if (other.messageHandler_) {
00102 messageHandler_ = other.messageHandler_->clone();
00103 continuousSolver_->passInMessageHandler(messageHandler_);
00104 }
00105 for (CuttingMethods::const_iterator i = other.cutGenerators_.begin() ; i != other.cutGenerators_.end() ; i++) {
00106 cutGenerators_.push_back(*i);
00107 cutGenerators_.back().cgl = cutGenerators_.back().cgl->clone();
00108 }
00109
00110 for (HeuristicMethods::iterator i = heuristics_.begin() ; i != heuristics_.end() ; i++) {
00111 heuristics_.push_back(*i);
00112 heuristics_.back().heuristic = i->heuristic->clone();
00113 }
00114
00115 if(other.branchingMethod_ != NULL)
00116 branchingMethod_ = other.branchingMethod_->clone();
00117 if (IsValid(other.options_)) {
00118 options_ = new Ipopt::OptionsList;
00119 *options_ = *other.options_;
00120 }
00121 CoinCopyN(other.intParam_, NumberIntParam, intParam_);
00122 CoinCopyN(other.doubleParam_, NumberDoubleParam, doubleParam_);
00123 for (unsigned int i = 0 ; i < objects_.size() ; i++) {
00124 objects_[i]->clone();
00125 }
00126 }
00127
00129 BabSetupBase::BabSetupBase(const BabSetupBase & other,
00130 OsiTMINLPInterface &nlp):
00131 nonlinearSolver_(NULL),
00132 continuousSolver_(NULL),
00133 linearizer_(other.linearizer_),
00134 cutGenerators_(),
00135 heuristics_(),
00136 branchingMethod_(NULL),
00137 nodeComparisonMethod_(other.nodeComparisonMethod_),
00138 treeTraversalMethod_(other.treeTraversalMethod_),
00139 objects_(other.objects_),
00140 journalist_(other.journalist_),
00141 options_(NULL),
00142 roptions_(other.roptions_),
00143 readOptions_(other.readOptions_),
00144 messageHandler_(NULL),
00145 prefix_(other.prefix_)
00146 {
00147 nonlinearSolver_ = &nlp;
00148 if (other.continuousSolver_ != other.nonlinearSolver_) {
00149 continuousSolver_ = NULL;
00150 }
00151 else
00152 continuousSolver_ = nonlinearSolver_;
00153 if (other.messageHandler_) {
00154 messageHandler_ = other.messageHandler_->clone();
00155 continuousSolver_->passInMessageHandler(messageHandler_);
00156 }
00157 for (CuttingMethods::const_iterator i = other.cutGenerators_.begin() ; i != other.cutGenerators_.end() ; i++) {
00158 cutGenerators_.push_back(*i);
00159 cutGenerators_.back().cgl = cutGenerators_.back().cgl->clone();
00160 }
00161
00162 for (HeuristicMethods::iterator i = heuristics_.begin() ; i != heuristics_.end() ; i++) {
00163 heuristics_.push_back(*i);
00164 heuristics_.back().heuristic = i->heuristic->clone();
00165 }
00166
00167 if(other.branchingMethod_ != NULL)
00168 branchingMethod_ = other.branchingMethod_->clone();
00169 if (IsValid(other.options_)) {
00170 options_ = new Ipopt::OptionsList;
00171 *options_ = *other.options_;
00172 }
00173 CoinCopyN(other.intParam_, NumberIntParam, intParam_);
00174 CoinCopyN(other.doubleParam_, NumberDoubleParam, doubleParam_);
00175 for (unsigned int i = 0 ; i < objects_.size() ; i++) {
00176 objects_[i]->clone();
00177 }
00178 }
00180 BabSetupBase::BabSetupBase(const BabSetupBase & other,
00181 OsiTMINLPInterface &nlp,
00182 const std::string & prefix):
00183 nonlinearSolver_(other.nonlinearSolver_),
00184 continuousSolver_(NULL),
00185 linearizer_(other.linearizer_),
00186 cutGenerators_(),
00187 heuristics_(),
00188 branchingMethod_(NULL),
00189 nodeComparisonMethod_(),
00190 treeTraversalMethod_(),
00191 objects_(other.objects_),
00192 journalist_(other.journalist_),
00193 options_(NULL),
00194 roptions_(other.roptions_),
00195 readOptions_(other.readOptions_),
00196 messageHandler_(NULL),
00197 prefix_(prefix)
00198 {
00199 nonlinearSolver_ = &nlp;
00200 if (IsValid(other.options_)) {
00201 options_ = new Ipopt::OptionsList;
00202 *options_ = *other.options_;
00203 }
00204 if (other.messageHandler_) {
00205 messageHandler_ = other.messageHandler_->clone();
00206 nonlinearSolver_->passInMessageHandler(messageHandler_);
00207 }
00208 CoinCopyN(defaultIntParam_, NumberIntParam, intParam_);
00209 CoinCopyN(defaultDoubleParam_, NumberDoubleParam, doubleParam_);
00210 gatherParametersValues(options_);
00211 for (unsigned int i = 0 ; i < objects_.size() ; i++) {
00212 objects_[i]->clone();
00213 }
00214 }
00215
00216 BabSetupBase::BabSetupBase(Ipopt::SmartPtr<TMINLP> tminlp, const CoinMessageHandler * handler):
00217 nonlinearSolver_(NULL),
00218 continuousSolver_(NULL),
00219 linearizer_(NULL),
00220 cutGenerators_(),
00221 heuristics_(),
00222 branchingMethod_(NULL),
00223 nodeComparisonMethod_(),
00224 treeTraversalMethod_(),
00225 objects_(0),
00226 readOptions_(false),
00227 messageHandler_(NULL),
00228 prefix_("bonmin.")
00229 {
00230 CoinCopyN(defaultIntParam_, NumberIntParam, intParam_);
00231 CoinCopyN(defaultDoubleParam_, NumberDoubleParam, doubleParam_);
00232 if(handler) messageHandler_ = handler->clone();
00233 use(tminlp);
00234 }
00235
00236
00238 BabSetupBase *
00239 BabSetupBase::clone(OsiTMINLPInterface&nlp)const {
00240 throw(CoinError("BabSetupBase", "CloneWithOtherNlp","Not implemented"));
00241 }
00242
00243
00244 void
00245 BabSetupBase::use(Ipopt::SmartPtr<TMINLP> tminlp)
00246 {
00247 readOptionsFile();
00248 assert(IsValid(tminlp));
00249 nonlinearSolver_ = new OsiTMINLPInterface;
00250 int ival;
00251 options_->GetEnumValue("enable_dynamic_nlp", ival, "bonmin.");
00252 if(ival && ! tminlp->hasLinearObjective()){
00253 Ipopt::SmartPtr<Bonmin::TMINLPLinObj> linObj =
00254 new Bonmin::TMINLPLinObj;
00255 linObj->setTminlp(GetRawPtr(tminlp));
00256 tminlp = GetRawPtr(linObj);
00257 }
00258 nonlinearSolver_->initialize(roptions_, options_, journalist_, prefix(), tminlp);
00259 if(messageHandler_ != NULL)
00260 nonlinearSolver_->passInMessageHandler(messageHandler_);
00261 else
00262 messageHandler_ = nonlinearSolver_->messageHandler()->clone();
00263 if (ival){
00264 nonlinearSolver_->use(new Bonmin::TMINLP2TNLPQuadCuts(tminlp));
00265 }
00266 }
00267
00268 BabSetupBase::BabSetupBase(const OsiTMINLPInterface& nlp):
00269 nonlinearSolver_(NULL),
00270 continuousSolver_(NULL),
00271 linearizer_(NULL),
00272 cutGenerators_(),
00273 heuristics_(),
00274 branchingMethod_(NULL),
00275 nodeComparisonMethod_(),
00276 treeTraversalMethod_(),
00277 objects_(0),
00278 journalist_(NULL),
00279 options_(NULL),
00280 roptions_(NULL),
00281 readOptions_(false),
00282 messageHandler_(NULL),
00283 prefix_("bonmin.")
00284 {
00285 CoinCopyN(defaultIntParam_, NumberIntParam, intParam_);
00286 CoinCopyN(defaultDoubleParam_, NumberDoubleParam, doubleParam_);
00287 use(nlp);
00288 }
00289
00290 void
00291 BabSetupBase::use(const OsiTMINLPInterface& nlp)
00292 {
00293 nonlinearSolver_ = dynamic_cast<OsiTMINLPInterface *>(nlp.clone());
00294 options_ = nonlinearSolver_->solver()->options();
00295 roptions_ = nonlinearSolver_->solver()->roptions();
00296 journalist_ = nonlinearSolver_->solver()->journalist();
00297 if(messageHandler_ != NULL ) delete messageHandler_;
00298 messageHandler_ = nlp.messageHandler()->clone();
00299 readOptions_ = true;
00300 }
00301
00302 BabSetupBase::BabSetupBase( Ipopt::SmartPtr<TNLPSolver> app):
00303 nonlinearSolver_(NULL),
00304 continuousSolver_(NULL),
00305 linearizer_(NULL),
00306 cutGenerators_(),
00307 heuristics_(),
00308 branchingMethod_(NULL),
00309 nodeComparisonMethod_(),
00310 treeTraversalMethod_(),
00311 objects_(0),
00312 journalist_(app->journalist()),
00313 options_(app->options()),
00314 roptions_(app->roptions()),
00315 readOptions_(true),
00316 messageHandler_(NULL),
00317 prefix_("bonmin.")
00318 {
00319 CoinCopyN(defaultIntParam_, NumberIntParam, intParam_);
00320 CoinCopyN(defaultDoubleParam_, NumberDoubleParam, doubleParam_);
00321 }
00322
00323
00324 BabSetupBase::~BabSetupBase()
00325 {
00326 if (nonlinearSolver_ != continuousSolver_) {
00327 delete nonlinearSolver_;
00328 }
00329 delete continuousSolver_;
00330 delete branchingMethod_;
00331 for (CuttingMethods::iterator i = cutGenerators_.begin() ; i != cutGenerators_.end() ; i++) {
00332 delete i->cgl;
00333 i->cgl = NULL;
00334 }
00335
00336 for (HeuristicMethods::iterator i = heuristics_.begin() ; i != heuristics_.end() ; i++) {
00337 delete i->heuristic;
00338 }
00339
00340 for (unsigned int i = 0 ; i < objects_.size() ; i++) {
00341 delete objects_[i];
00342 }
00343
00344 if(messageHandler_)
00345 delete messageHandler_;
00346 }
00347
00348
00349 void
00350 BabSetupBase::gatherParametersValues(Ipopt::SmartPtr<Ipopt::OptionsList> options)
00351 {
00352
00353 options->GetIntegerValue("bb_log_level",intParam_[BabLogLevel],prefix_.c_str());
00354 options->GetIntegerValue("bb_log_interval",intParam_[BabLogInterval],prefix_.c_str());
00355 options->GetIntegerValue("max_consecutive_failures",intParam_[MaxFailures],prefix_.c_str());
00356 options->GetEnumValue("nlp_failure_behavior",intParam_[FailureBehavior],prefix_.c_str());
00357 options->GetIntegerValue("max_consecutive_infeasible",intParam_[MaxInfeasible],prefix_.c_str());
00358 options->GetIntegerValue("number_strong_branch",intParam_[NumberStrong],prefix_.c_str());
00359 options->GetIntegerValue("number_before_trust",intParam_[MinReliability],prefix_.c_str());
00360 options->GetIntegerValue("node_limit",intParam_[MaxNodes],prefix_.c_str());
00361 options->GetIntegerValue("solution_limit",intParam_[MaxSolutions],prefix_.c_str());
00362 options->GetIntegerValue("iteration_limit",intParam_[MaxIterations],prefix_.c_str());
00363 options->GetEnumValue("sos_constraints",intParam_[DisableSos],prefix_.c_str());
00364 options->GetIntegerValue("num_cut_passes",intParam_[NumCutPasses],prefix_.c_str());
00365 options->GetIntegerValue("num_cut_passes_at_root",intParam_[NumCutPassesAtRoot],prefix_.c_str());
00366 options->GetIntegerValue("nlp_log_at_root",intParam_[RootLogLevel],prefix_.c_str());
00367
00368 options->GetNumericValue("cutoff_decr",doubleParam_[CutoffDecr],prefix_.c_str());
00369 options->GetNumericValue("cutoff",doubleParam_[Cutoff],prefix_.c_str());
00370 options->GetNumericValue("allowable_gap",doubleParam_[AllowableGap],prefix_.c_str());
00371 options->GetNumericValue("allowable_fraction_gap",doubleParam_[AllowableFractionGap],prefix_.c_str());
00372 options->GetNumericValue("integer_tolerance",doubleParam_[IntTol],prefix_.c_str());
00373 options->GetNumericValue("time_limit", doubleParam_[MaxTime],prefix_.c_str());
00374
00375 int ival;
00376 int seed = 0;
00377 ival = options->GetIntegerValue("random_generator_seed",seed,prefix_.c_str());
00378 if(seed == -1)
00379 CoinSeedRandom((int)CoinGetTimeOfDay());
00380 else if (ival != 0) CoinSeedRandom(seed);
00381
00382 options->GetEnumValue("node_comparison",ival,prefix_.c_str());
00383 nodeComparisonMethod_ = NodeComparison(ival);
00384
00385 options->GetEnumValue("tree_search_strategy", ival, prefix_.c_str());
00386 treeTraversalMethod_ = TreeTraversal(ival);
00387
00388 int varSelection;
00389 options->GetEnumValue("variable_selection",varSelection,prefix_.c_str());
00390
00391 if (varSelection == MOST_FRACTIONAL) {
00392 intParam_[NumberStrong] = 0;
00393 intParam_[MinReliability] = 0;
00394 options_->SetIntegerValue("bonmin.number_strong_branch",intParam_[BabSetupBase::NumberStrong],true,true);
00395 options_->SetIntegerValue("bonmin.number_before_trust",intParam_[BabSetupBase::MinReliability],true,true);
00396 }
00397 else if (varSelection == RELIABILITY_BRANCHING) {
00398 intParam_[MinReliability] = 10;
00399 options_->SetIntegerValue("bonmin.number_before_trust",intParam_[BabSetupBase::MinReliability],true,true);
00400 }
00401 }
00402
00403 void
00404 BabSetupBase::registerOptions()
00405 {
00406 registerAllOptions(roptions_);
00407 }
00408
00409 void
00410 BabSetupBase::registerAllOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00411 {
00412 OsiTMINLPInterface::registerOptions(roptions);
00413
00414 roptions->SetRegisteringCategory("Output and Loglevel", RegisteredOptions::BonminCategory);
00415
00416 roptions->AddBoundedIntegerOption("bb_log_level",
00417 "specify main branch-and-bound log level.",
00418 0,5,1,
00419 "Set the level of output of the branch-and-bound : "
00420 "0 - none, 1 - minimal, 2 - normal low, 3 - normal high"
00421 );
00422 roptions->setOptionExtraInfo("bb_log_level", 127);
00423
00424 roptions->AddLowerBoundedIntegerOption("bb_log_interval",
00425 "Interval at which node level output is printed.",
00426 0,100,
00427 "Set the interval (in terms of number of nodes) at which "
00428 "a log on node resolutions (consisting of lower and upper bounds) is given.");
00429 roptions->setOptionExtraInfo("bb_log_interval", 127);
00430
00431 roptions->AddBoundedIntegerOption("lp_log_level",
00432 "specify LP log level.",
00433 0,4,0,
00434 "Set the level of output of the linear programming sub-solver in B-Hyb or B-QG : "
00435 "0 - none, 1 - minimal, 2 - normal low, 3 - normal high, 4 - verbose"
00436 );
00437 roptions->setOptionExtraInfo("lp_log_level", 119);
00438
00439 roptions->AddBoundedIntegerOption("nlp_log_at_root","specify a different log level "
00440 "for root relaxation.",
00441 0,12,0,
00442 "");
00443 roptions->setOptionExtraInfo("nlp_log_at_root",63);
00444
00445 roptions->SetRegisteringCategory("Branch-and-bound options", RegisteredOptions::BonminCategory);
00446
00447 roptions->AddLowerBoundedIntegerOption
00448 ("random_generator_seed",
00449 "Set seed for random number generator (a value of -1 sets seeds to time since Epoch).",
00450 -1,0,
00451 "");
00452 roptions->setOptionExtraInfo("random_generator_seed",127);
00453
00454 roptions->AddLowerBoundedNumberOption("time_limit",
00455 "Set the global maximum computation time (in secs) for the algorithm.",
00456 0.,0,1e10,
00457 "");
00458 roptions->setOptionExtraInfo("time_limit", 127);
00459
00460 roptions->AddLowerBoundedIntegerOption("node_limit",
00461 "Set the maximum number of nodes explored in the branch-and-bound search.",
00462 0,COIN_INT_MAX,
00463 "");
00464 roptions->setOptionExtraInfo("node_limit", 127);
00465
00466 roptions->AddLowerBoundedIntegerOption("iteration_limit",
00467 "Set the cumulative maximum number of iteration in the algorithm used to process nodes continuous relaxations in the branch-and-bound.",
00468 0,COIN_INT_MAX,
00469 "value 0 deactivates option.");
00470 roptions->setOptionExtraInfo("iteration_limit", 127);
00471
00472 roptions->AddLowerBoundedIntegerOption("solution_limit",
00473 "Abort after that much integer feasible solution have been found by algorithm",
00474 0,COIN_INT_MAX,
00475 "value 0 deactivates option");
00476 roptions->setOptionExtraInfo("solution_limit", 127);
00477
00478 roptions->AddLowerBoundedNumberOption("integer_tolerance",
00479 "Set integer tolerance.",
00480 0.,1,1e-06,
00481 "Any number within that value of an integer is considered integer.");
00482 roptions->setOptionExtraInfo("integer_tolerance", 127);
00483
00484 roptions->AddBoundedNumberOption("allowable_gap",
00485 "Specify the value of absolute gap under which the algorithm stops.",
00486 -1.e20,0,1.e20,0,0.,
00487 "Stop the tree search when the gap between the objective value of the best known solution"
00488 " and the best bound on the objective of any solution is less than this.");
00489 roptions->setOptionExtraInfo("allowable_gap", 127);
00490
00491 roptions->AddBoundedNumberOption("allowable_fraction_gap",
00492 "Specify the value of relative gap under which the algorithm stops.",
00493 -1.e20,0,1.e20,0,0.0,
00494 "Stop the tree search when the gap between the objective value of the best known solution "
00495 "and the best bound on the objective of any solution is less than this "
00496 "fraction of the absolute value of the best known solution value.");
00497 roptions->setOptionExtraInfo("allowable_fraction_gap", 127);
00498
00499 roptions->AddBoundedNumberOption("cutoff",
00500 "Specify cutoff value.",
00501 -1e100,0,1e100,0,1e100,
00502 "cutoff should be the value of a feasible solution known by the user "
00503 "(if any). The algorithm will only look for solutions better than cutoff.");
00504 roptions->setOptionExtraInfo("cutoff", 127);
00505
00506
00507 roptions->AddBoundedNumberOption("cutoff_decr",
00508 "Specify cutoff decrement.",
00509 -1e10,0,1e10,0,1e-05,
00510 "Specify the amount by which cutoff is decremented below "
00511 "a new best upper-bound"
00512 " (usually a small positive value but in non-convex problems it may be a negative value).");
00513 roptions->setOptionExtraInfo("cutoff_decr", 127);
00514
00515
00516 roptions->AddStringOption5("node_comparison",
00517 "Choose the node selection strategy.",
00518 "best-bound",
00519 "best-bound", "choose node with the smallest bound,",
00520 "depth-first", "Perform depth first search,",
00521 "breadth-first", "Perform breadth first search,",
00522 "dynamic", "Cbc dynamic strategy (starts with a depth first search and turn to best bound after 3 "
00523 "integer feasible solutions have been found).",
00524 "best-guess", "choose node with smallest guessed integer solution",
00525 "Choose the strategy for selecting the next node to be processed.");
00526 roptions->setOptionExtraInfo("node_comparison", 63);
00527
00528 roptions->AddStringOption5("tree_search_strategy",
00529 "Pick a strategy for traversing the tree",
00530 "probed-dive",
00531 "top-node"," Always pick the top node as sorted by the node comparison function",
00532 "dive","Dive in the tree if possible, otherwise pick top node as sorted by the tree comparison function.",
00533 "probed-dive","Dive in the tree exploring two children before continuing the dive at each level.",
00534 "dfs-dive","Dive in the tree if possible doing a depth first search. "
00535 "Backtrack on leaves or when a prescribed depth is attained or "
00536 "when estimate of best possible integer feasible solution in subtree "
00537 "is worst than cutoff. "
00538 "Once a prescribed limit of backtracks is attained pick top node "
00539 "as sorted by the tree comparison function",
00540 "dfs-dive-dynamic","Same as dfs-dive but once enough solution are found switch to best-bound and if too many nodes switch to depth-first.",
00541 "All strategies can be used in conjunction with any of the node comparison functions. "
00542 "Options which affect dfs-dive are max-backtracks-in-dive and max-dive-depth. "
00543 "The dfs-dive won't work in a non-convex problem where objective does not decrease down branches."
00544 );
00545 roptions->setOptionExtraInfo("tree_search_strategy", 63);
00546
00547 roptions->AddLowerBoundedIntegerOption("number_strong_branch",
00548 "Choose the maximum number of variables considered for strong branching.",
00549 0,20,
00550 "Set the number of variables on which to do strong branching.");
00551 roptions->setOptionExtraInfo("number_strong_branch", 127);
00552
00553
00554 roptions->AddLowerBoundedIntegerOption
00555 ("number_before_trust",
00556 "Set the number of branches on a variable before its pseudo costs are to be believed "
00557 "in dynamic strong branching.",
00558 0,8,
00559 "A value of 0 disables pseudo costs.");
00560 roptions->setOptionExtraInfo("number_before_trust", 127);
00561
00562 roptions->AddStringOption2("nlp_failure_behavior",
00563 "Set the behavior when an NLP or a series of NLP are unsolved by Ipopt (we call unsolved an NLP for which Ipopt is not "
00564 "able to guarantee optimality within the specified tolerances).",
00565 "stop",
00566 "stop", "Stop when failure happens.",
00567 "fathom", "Continue when failure happens.",
00568 "If set to \"fathom\", the algorithm will fathom the node when Ipopt fails to find a solution to the nlp "
00569 "at that node within the specified tolerances. "
00570 "The algorithm then becomes a heuristic, and the user will be warned that the solution might not be optimal.");
00571 roptions->setOptionExtraInfo("nlp_failure_behavior", 8);
00572
00573 roptions->AddStringOption2("sos_constraints",
00574 "Whether or not to activate SOS constraints.",
00575 "enable",
00576 "enable","",
00577 "disable","",
00578 "(only type 1 SOS are supported at the moment)");
00579 roptions->setOptionExtraInfo("sos_constraints", 63);
00580
00581 #ifdef BONMIN_CURVATURE_BRANCHING
00582 roptions->AddStringOption10("variable_selection",
00583 #else
00584 roptions->AddStringOption9("variable_selection",
00585 #endif
00586 "Chooses variable selection strategy",
00587 "strong-branching",
00588 "most-fractional", "Choose most fractional variable",
00589 "strong-branching", "Perform strong branching",
00590 "reliability-branching", "Use reliability branching",
00591 #ifdef BONMIN_CURVATURE_BRANCHING
00592 "curvature-estimator", "Use curvature estimation to select branching variable",
00593 #endif
00594 "qp-strong-branching", "Perform strong branching with QP approximation",
00595 "lp-strong-branching", "Perform strong branching with LP approximation",
00596 "nlp-strong-branching", "Perform strong branching with NLP approximation",
00597 "osi-simple", "Osi method to do simple branching",
00598 "osi-strong", "Osi method to do strong branching",
00599 "random", "Method to choose branching variable randomly");
00600
00601 roptions->setOptionExtraInfo("variable_selection", 27);
00602
00603 roptions->AddLowerBoundedIntegerOption("num_cut_passes",
00604 "Set the maximum number of cut passes at regular nodes of the branch-and-cut.",
00605 0,1,
00606 "");
00607 roptions->setOptionExtraInfo("num_cut_passes", 19);
00608
00609 roptions->AddLowerBoundedIntegerOption("num_cut_passes_at_root",
00610 "Set the maximum number of cut passes at regular nodes of the branch-and-cut.",
00611 0,20,
00612 "");
00613 roptions->setOptionExtraInfo("num_cut_passes_at_root", 19);
00614
00615 roptions->AddStringOption2("enable_dynamic_nlp",
00616 "Enable dynamic linear and quadratic rows addition in nlp",
00617 "no",
00618 "no", "",
00619 "yes", "",
00620 "");
00621 roptions->setOptionExtraInfo("enable_dynamic_nlp", 19);
00622
00623
00624
00625 roptions->AddStringOption2("read_solution_file",
00626 "Read a file with the optimal solution to test if algorithms cuts it.",
00627 "no",
00628 "no","",
00629 "yes","",
00630 "For Debugging purposes only.");
00631 roptions->setOptionExtraInfo("enable_dynamic_nlp", 8);
00632
00633
00634 LpBranchingSolver::registerOptions(roptions);
00635
00636 #ifdef COIN_HAS_FILTERSQP
00637 FilterSolver::registerOptions(roptions);
00638 BqpdSolver::registerOptions(roptions);
00639 #endif
00640 CbcDiver::registerOptions(roptions);
00641 CbcDfsDiver::registerOptions(roptions);
00642 BonChooseVariable::registerOptions(roptions);
00643 }
00644
00645
00647 void
00648 BabSetupBase::initializeOptionsAndJournalist()
00649 {
00650 options_ = new Ipopt::OptionsList();
00651
00652 journalist_= new Ipopt::Journalist();
00653 roptions_ = new Bonmin::RegisteredOptions();
00654
00655 try {
00656 Ipopt::SmartPtr<Ipopt::Journal> stdout_journal =
00657 journalist_->AddFileJournal("console", "stdout", Ipopt::J_ITERSUMMARY);
00658
00659 options_->SetJournalist(journalist_);
00660 options_->SetRegisteredOptions(GetRawPtr(roptions_));
00661 }
00662 catch (Ipopt::IpoptException &E) {
00663 E.ReportException(*journalist_);
00664 throw E;
00665 }
00666 catch (std::bad_alloc) {
00667 journalist_->Printf(Ipopt::J_ERROR, Ipopt::J_MAIN, "\n Not enough memory .... EXIT\n");
00668 throw -1;
00669 }
00670 catch (...) {
00671 Ipopt::IpoptException E("Uncaught exception in FilterSolver::FilterSolver()",
00672 "BonFilterSolver.cpp",-1);
00673 throw E;
00674 }
00675
00676 registerOptions();
00677 }
00678
00680 void
00681 BabSetupBase::readOptionsFile(std::string fileName)
00682 {
00683 if (GetRawPtr(options_) == NULL || GetRawPtr(roptions_) == NULL || GetRawPtr(journalist_) == NULL)
00684 initializeOptionsAndJournalist();
00685 std::ifstream is;
00686 if (fileName != "") {
00687 try {
00688 is.open(fileName.c_str());
00689 }
00690 catch (std::bad_alloc) {
00691 journalist_->Printf(Ipopt::J_SUMMARY, Ipopt::J_MAIN, "\nEXIT: Not enough memory.\n");
00692 throw -1;
00693 }
00694 catch (...) {
00695 Ipopt::IpoptException E("Unknown Exception caught in ipopt", "Unknown File", -1);
00696 E.ReportException(*journalist_);
00697 throw -1;
00698 }
00699 }
00700 readOptionsStream(is);
00701 if (is) {
00702 is.close();
00703 }
00704 }
00705
00707 void
00708 BabSetupBase::readOptionsString(std::string opt_string)
00709 {
00710 if (GetRawPtr(options_) == NULL || GetRawPtr(roptions_) == NULL || GetRawPtr(journalist_) == NULL)
00711 initializeOptionsAndJournalist();
00712 std::stringstream is(opt_string.c_str());
00713 readOptionsStream(is);
00714 }
00715
00716
00717 void
00718 BabSetupBase::readOptionsStream(std::istream& is)
00719 {
00720 if (GetRawPtr(options_) == NULL || GetRawPtr(roptions_) == NULL || GetRawPtr(journalist_) == NULL)
00721 initializeOptionsAndJournalist();
00722 if (is.good()) {
00723 try {
00724 options_->ReadFromStream(*journalist_, is);
00725 }
00726 catch (Ipopt::IpoptException &E) {
00727 E.ReportException(*journalist_);
00728 throw E;
00729 }
00730 }
00731 mayPrintDoc();
00732 readOptions_=true;
00733 }
00734
00736 void
00737 BabSetupBase::mayPrintDoc()
00738 {
00739 bool print_options_documentation;
00740 options_->GetBoolValue("print_options_documentation",
00741 print_options_documentation, "");
00742 if (print_options_documentation) {
00743 std::list<std::string> categories;
00744 categories.push_back("Algorithm choice");
00745 categories.push_back("Branch-and-bound options");
00746 categories.push_back("ECP cuts generation");
00747 categories.push_back("Feasibility checker using OA cuts");
00748 categories.push_back("MILP Solver");
00749 categories.push_back("MILP cutting planes in hybrid algorithm");
00750 categories.push_back("Primal Heuristics");
00751 categories.push_back("NLP interface");
00752 categories.push_back("NLP solution robustness");
00753 categories.push_back("NLP solves in hybrid algorithm");
00754 categories.push_back("Nonconvex problems");
00755 categories.push_back("Outer Approximation Decomposition (B-OA)");
00756 categories.push_back("Outer Approximation cuts generation");
00757 categories.push_back("Output and Loglevel");
00758 categories.push_back("Strong branching setup");
00759
00760 categories.push_back("Diving options");
00761 categories.push_back("ECP based strong branching");
00762 categories.push_back("Primal Heuristics (undocumented)");
00763 categories.push_back("Outer Approximation strengthening");
00764 #ifdef COIN_HAS_FILTERSQP
00765 categories.push_back("FilterSQP options");
00766 #endif
00767
00768 roptions_->OutputOptionDocumentation(*(journalist_),categories);
00769 }
00770 }
00771
00772 void
00773 BabSetupBase::setPriorities()
00774 {
00775 const int * priorities = nonlinearSolver()->getPriorities();
00776 const double * upPsCosts = nonlinearSolver()->getUpPsCosts();
00777 const int * directions = nonlinearSolver()->getBranchingDirections();
00778 bool hasPseudo = (upPsCosts!=NULL);
00779 if (priorities == NULL && directions && NULL && hasPseudo)
00780 return;
00781 int n = nonlinearSolver()->numberObjects();
00782 OsiObject ** objects = nonlinearSolver()->objects();
00783 for (int i = 0 ; i < n; i++) {
00784 OsiObject2 * object = dynamic_cast<OsiObject2 *>(objects[i]);
00785 int iCol = objects[i]->columnNumber();
00786 if (iCol < 0) {
00787 throw CoinError("BabSetupBase","setPriorities",
00788 "Don't know how to set priority for non-column object.");
00789 }
00790 if (priorities) {
00791 objects[i]->setPriority(priorities[iCol]);
00792 }
00793 if (directions) {
00794 if (object == NULL) {
00795 throw CoinError("BabSetupBase","setPriorities",
00796 "Don't know how to set preferred way for object.");
00797 }
00798 object->setPreferredWay(directions[iCol]);
00799 }
00800 if (upPsCosts) {
00801 throw CoinError("BabSetupBase","setPriorities",
00802 "Can not handle user set pseudo-costs with OsiObjects\n"
00803 "You should use one of the Cbc branching rules:\n"
00804 "most-fractional or strong-branching.");
00805 }
00806 }
00807 }
00808
00809 void
00810 BabSetupBase::addSos()
00811 {
00812
00813
00814 const TMINLP::SosInfo * sos = nonlinearSolver()->model()->sosConstraints();
00815 if (!getIntParameter(BabSetupBase::DisableSos) && sos && sos->num > 0)
00816 {
00817 const int & numSos = sos->num;
00818 OsiObject ** objects = new OsiObject*[numSos];
00819 const int * starts = sos->starts;
00820 const int * indices = sos->indices;
00821 const char * types = sos->types;
00822 const double * weights = sos->weights;
00823 bool hasPriorities = false;
00824 const int * varPriorities = nonlinearSolver()->getPriorities();
00825 int numberObjects = nonlinearSolver()->numberObjects();
00826 if (varPriorities)
00827 {
00828 for (int i = 0 ; i < numberObjects ; i++) {
00829 if (varPriorities[i]) {
00830 hasPriorities = true;
00831 break;
00832 }
00833 }
00834 }
00835 const int * sosPriorities = sos->priorities;
00836 if (sosPriorities)
00837 {
00838 for (int i = 0 ; i < numSos ; i++) {
00839 if (sosPriorities[i]) {
00840 hasPriorities = true;
00841 break;
00842 }
00843 }
00844 }
00845 for (int i = 0 ; i < numSos ; i++)
00846 {
00847 int start = starts[i];
00848 int length = starts[i + 1] - start;
00849 objects[i] = new OsiSOS(nonlinearSolver(), length, &indices[start],
00850 &weights[start], (int) types[i]);
00851
00852 objects[i]->setPriority(10);
00853 if (hasPriorities && sosPriorities && sosPriorities[i]) {
00854 objects[i]->setPriority(sosPriorities[i]);
00855 }
00856 }
00857 nonlinearSolver()->addObjects(numSos, objects);
00858 for (int i = 0 ; i < numSos ; i++)
00859 delete objects[i];
00860 delete [] objects;
00861 }
00862 }
00863
00864
00865 }
00866