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