00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "BonminConfig.h"
00015
00016 #include "BonOsiTMINLPInterface.hpp"
00017 #include "BonTMINLP.hpp"
00018 #include "BonTMINLP2TNLP.hpp"
00019 #include "BonTNLP2FPNLP.hpp"
00020 #include "BonTMINLP2OsiLP.hpp"
00021 #include "BonTNLPSolver.hpp"
00022 #include "CoinTime.hpp"
00023 #include <climits>
00024 #include <string>
00025 #include <sstream>
00026 #include "BonAuxInfos.hpp"
00027
00028 #include "Ipopt/BonIpoptSolver.hpp"
00029 #include "Ipopt/BonIpoptWarmStart.hpp"
00030 #ifdef COIN_HAS_FILTERSQP
00031 #include "Filter/BonFilterSolver.hpp"
00032 #include "Filter/BonFilterWarmStart.hpp"
00033
00034 #endif
00035
00036 #include "OsiBranchingObject.hpp"
00037 #include "OsiRowCutDebugger.hpp"
00038 #include "BonStrongBranchingSolver.hpp"
00039
00040
00041 #include "BonMsgUtils.hpp"
00042
00043 using namespace Ipopt;
00044
00045
00046 namespace Bonmin {
00048 static void
00049 register_general_options
00050 (SmartPtr<RegisteredOptions> roptions)
00051 {
00052 roptions->SetRegisteringCategory("nlp interface option", RegisteredOptions::BonminCategory);
00053 roptions->AddStringOption3("nlp_solver",
00054 "Choice of the solver for local optima of continuous nlp's",
00055 "Ipopt",
00056 "Ipopt", "Interior Point OPTimizer (https://projects.coin-or.org/Ipopt)",
00057 "filterSQP", "Sequential quadratic programming trust region "
00058 "algorithm (http://www-unix.mcs.anl.gov/~leyffer/solvers.html)",
00059 "all", "run all available solvers at each node",
00060 "Note that option will work only if the specified solver has been installed. Ipopt will usualy be installed with Bonmin by default. For FilterSQP please see http://www-unix.mcs.anl.gov/~leyffer/solvers.html on how to obtain it and https://projects.coin-or.org/Bonmin/wiki/HintTricks on how to configure Bonmin to use it.");
00061 roptions->setOptionExtraInfo("nlp_solver",127);
00062 roptions->AddBoundedIntegerOption("nlp_log_level",
00063 "specify NLP solver interface log level (independent from ipopt print_level).",
00064 0,2,1,
00065 "Set the level of output of the OsiTMINLPInterface : "
00066 "0 - none, 1 - normal, 2 - verbose"
00067 );
00068 roptions->setOptionExtraInfo("nlp_log_level",127);
00069
00070 roptions->AddStringOption2("file_solution",
00071 "Write a file bonmin.sol with the solution",
00072 "no",
00073 "yes","",
00074 "no","","");
00075 roptions->setOptionExtraInfo("file_solution",127);
00076
00077 roptions->AddStringOption4("warm_start",
00078 "Select the warm start method",
00079 "none",
00080 "none","No warm start, just start NLPs from optimal solution of the root relaxation",
00081 "fake_basis", "builds fake basis, useful for cut management in Cbc (warm start is the same as in none)",
00082 "optimum","Warm start with direct parent optimum",
00083 "interior_point","Warm start with an interior point of direct parent",
00084 "This will affect the function getWarmStart(), and as a consequence the warm starting in the various algorithms.");
00085 roptions->setOptionExtraInfo("warm_start",8);
00086
00087 roptions->SetRegisteringCategory("Nlp solution robustness", RegisteredOptions::BonminCategory);
00088
00089 roptions->AddLowerBoundedNumberOption("max_random_point_radius",
00090 "Set max value r for coordinate of a random point.",
00091 0.,1,1e5,
00092 "When picking a random point, coordinate i will be in the interval [min(max(l,-r),u-r), max(min(u,r),l+r)] "
00093 "(where l is the lower bound for the variable and u is its upper bound)");
00094 roptions->setOptionExtraInfo("max_random_point_radius",8);
00095
00096 roptions->AddStringOption3("random_point_type","method to choose a random starting point",
00097 "Jon",
00098 "Jon", "Choose random point uniformly between the bounds",
00099 "Andreas", "perturb the starting point of the problem within a prescribed interval",
00100 "Claudia", "perturb the starting point using the perturbation radius suffix information",
00101 "");
00102 roptions->setOptionExtraInfo("random_point_type",8);
00103
00104 roptions->AddLowerBoundedNumberOption("random_point_perturbation_interval",
00105 "Amount by which starting point is perturbed when choosing to pick random point by perturbating starting point",
00106 0.,true, 1.,
00107 "");
00108 roptions->setOptionExtraInfo("random_point_perturbation_interval",8);
00109
00110
00111 roptions->AddLowerBoundedIntegerOption
00112 ("num_iterations_suspect",
00113 "Number of iterations over which a node is considered \"suspect\" (for debugging purposes only, see detailed documentation).",
00114 -1,-1,
00115 "When the number of iterations to solve a node is above this number, the subproblem at this"
00116 " node is considered to be suspect and it will be outputed in a file (set to -1 to deactivate this).");
00117 roptions->setOptionExtraInfo("num_iterations_suspect",127);
00118
00119
00120
00121 roptions->AddLowerBoundedIntegerOption("num_retry_unsolved_random_point",
00122 "Number $k$ of times that the algorithm will try to resolve an unsolved NLP with a random starting point "
00123 "(we call unsolved an NLP for which Ipopt is not "
00124 "able to guarantee optimality within the specified tolerances).",
00125 0,0,
00126 "When Ipopt fails to solve a continuous NLP sub-problem, if $k > 0$, the algorithm will "
00127 "try again to solve the failed NLP with $k$ new randomly chosen starting points "
00128 " or until the problem is solved with success.");
00129 roptions->setOptionExtraInfo("num_retry_unsolved_random_point",127);
00130
00131 roptions->AddLowerBoundedNumberOption("resolve_on_small_infeasibility",
00132 "If a locally infeasible problem is infeasible by less than this, resolve it "
00133 "with initial starting point.",
00134 0.,false, 0.,
00135 "It is set to 0 by default with Ipopt. "
00136 "For filter Bonmin sets it to a small value.");
00137 roptions->setOptionExtraInfo("random_point_perturbation_interval",8);
00138
00139
00140 roptions->SetRegisteringCategory("Options for non-convex problems", RegisteredOptions::BonminCategory);
00141
00142
00143 roptions->AddLowerBoundedIntegerOption("num_resolve_at_root",
00144 "Number $k$ of tries to resolve the root node with different starting points.",
00145 0,0,
00146 "The algorithm will solve the root node with $k$ random starting points"
00147 " and will keep the best local optimum found.");
00148 roptions->setOptionExtraInfo("num_resolve_at_root",8);
00149
00150 roptions->AddLowerBoundedIntegerOption("num_resolve_at_node",
00151 "Number $k$ of tries to resolve a node (other than the root) of the tree with different starting point.",
00152 0,0,
00153 "The algorithm will solve all the nodes with $k$ different random starting points "
00154 "and will keep the best local optimum found.");
00155 roptions->setOptionExtraInfo("num_resolve_at_node",8);
00156
00157 roptions->AddLowerBoundedIntegerOption("num_resolve_at_infeasibles",
00158 "Number $k$ of tries to resolve an infeasible node (other than the root) of the tree with different starting point.",
00159 0,0,
00160 "The algorithm will solve all the infeasible nodes with $k$ different random starting points "
00161 "and will keep the best local optimum found.");
00162 roptions->setOptionExtraInfo("num_resolve_at_infeasibles",8);
00163
00164
00165 roptions->AddStringOption2("dynamic_def_cutoff_decr",
00166 "Do you want to define the parameter cutoff_decr dynamically?",
00167 "no",
00168 "no", "No, define it statically",
00169 "yes","Yes, define it dynamically");
00170 roptions->setOptionExtraInfo("dynamic_def_cutoff_decr",8);
00171
00172 roptions->AddLowerBoundedNumberOption("coeff_var_threshold",
00173 "Coefficient of variation threshold (for dynamic definition of cutoff_decr).",
00174 0.0,
00175 false,
00176 0.1);
00177 roptions->setOptionExtraInfo("coeff_var_threshold",8);
00178
00179 roptions->AddNumberOption("first_perc_for_cutoff_decr",
00180 "The percentage used when, the coeff of variance is smaller than the threshold, to compute the cutoff_decr dynamically.",
00181 -0.02);
00182 roptions->setOptionExtraInfo("first_perc_for_cutoff_decr",8);
00183
00184 roptions->AddNumberOption("second_perc_for_cutoff_decr",
00185 "The percentage used when, the coeff of variance is greater than the threshold, to compute the cutoff_decr dynamically.",
00186 -0.05);
00187 roptions->setOptionExtraInfo("second_perc_for_cutoff_decr",8);
00188
00189 }
00190
00191 static void register_OA_options
00192 (SmartPtr<RegisteredOptions> roptions)
00193 {
00194
00195
00196 roptions->SetRegisteringCategory("Outer Approximations strengthening", RegisteredOptions::UndocumentedCategory);
00197 roptions->AddStringOption2("disjunctive_cut_type",
00198 "Determine if and what kind of disjunctive cuts should be computed.",
00199 "none",
00200 "none", "No disjunctive cuts.",
00201 "most-fractional", "If discrete variables present, compute disjunction for most-fractional variable");
00202 roptions->setOptionExtraInfo("disjunctive_cut_type",119);
00203
00204
00205
00206
00207 roptions->AddStringOption4("cut_strengthening_type",
00208 "Determines if and what kind of cut strengthening should be performed.",
00209 "none",
00210 "none", "No strengthening of cuts.",
00211 "sglobal", "Strengthen global cuts.",
00212 "uglobal-slocal", "Unstrengthened global and strengthened local cuts",
00213 "sglobal-slocal", "Strengthened global and strengthened local cuts",
00214 "");
00215 roptions->setOptionExtraInfo("cut_strengthening_type",119);
00216
00217 roptions->SetRegisteringCategory("Outer Approximation cuts generation", RegisteredOptions::BonminCategory);
00218
00219 roptions->AddStringOption2("oa_cuts_scope","Specify if OA cuts added are to be set globally or locally valid",
00220 "global",
00221 "local","Cuts are treated as locally valid",
00222 "global", "Cuts are treated as globally valid",
00223 "");
00224 roptions->setOptionExtraInfo("oa_cuts_scope",119);
00225
00226 roptions->AddStringOption2("add_only_violated_oa","Do we add all OA cuts or only the ones violated by current point?",
00227 "no",
00228 "no","Add all cuts",
00229 "yes","Add only violated Cuts","");
00230 roptions->setOptionExtraInfo("add_only_violated_oa",119);
00231
00232
00233 roptions->AddLowerBoundedNumberOption("tiny_element","Value for tiny element in OA cut",
00234 -0.,0,1e-08,
00235 "We will remove \"cleanly\" (by relaxing cut) an element lower"
00236 " than this.");
00237 roptions->setOptionExtraInfo("tiny_element",119);
00238
00239 roptions->AddLowerBoundedNumberOption("very_tiny_element","Value for very tiny element in OA cut",
00240 -0.,0,1e-17,
00241 "Algorithm will take the risk of neglecting an element lower"
00242 " than this.");
00243 roptions->setOptionExtraInfo("very_tiny_element",119);
00244
00245 roptions->AddLowerBoundedNumberOption("oa_rhs_relax","Value by which to relax OA cut",
00246 -0.,0,1e-8,
00247 "RHS of OA constraints will be relaxed by this amount times the absolute value of the initial rhs if it is >= 1 (otherwise by this amount)."
00248 );
00249 roptions->setOptionExtraInfo("oa_rhs_relax",119);
00250
00251 roptions->AddLowerBoundedIntegerOption("oa_cuts_log_level",
00252 "level of log when generating OA cuts.",
00253 0, 0,
00254 "0: outputs nothing,\n"
00255 "1: when a cut is generated, its violation and index of row from which it originates,\n"
00256 "2: always output violation of the cut.\n"
00257 "3: output generated cuts incidence vectors.");
00258 roptions->setOptionExtraInfo("oa_cuts_log_level",119);
00259
00260 }
00261
00262
00264 void
00265 OsiTMINLPInterface::registerOptions
00266 (SmartPtr<RegisteredOptions> roptions)
00267 {
00268
00269
00270 try {
00271 register_general_options(roptions);
00272 register_OA_options(roptions);
00273 #ifdef COIN_HAS_FILTERSQP
00274 FilterSolver::RegisterOptions(roptions);
00275 #endif
00276 IpoptSolver::RegisterOptions(roptions);
00277 }
00278 catch(RegisteredOptions::OPTION_ALREADY_REGISTERED) {
00279
00280 }
00281
00282
00283 }
00284
00286 void
00287 OsiTMINLPInterface::setAppDefaultOptions(SmartPtr<OptionsList> Options)
00288 {}
00289
00290 OsiTMINLPInterface::Messages::Messages
00291 ():CoinMessages((int)OSITMINLPINTERFACE_DUMMY_END)
00292 {
00293 strcpy(source_ ,"NLP");
00294 ADD_MSG(SOLUTION_FOUND, std_m, 2,
00295 "After %d tries found a solution of %g (previous best %g).");
00296
00297 ADD_MSG(INFEASIBLE_SOLUTION_FOUND, std_m, 2,
00298 "After %d tries found an solution of %g infeasible problem.");
00299
00300 ADD_MSG(UNSOLVED_PROBLEM_FOUND, std_m, 2,
00301 "After %d tries found an solution of %g unsolved problem.");
00302 ADD_MSG(WARN_SUCCESS_WS, warn_m, 2,
00303 "Problem not solved with warm start but solved without");
00304
00305 ADD_MSG(WARNING_RESOLVING, warn_m,2,
00306 "Trying to resolve NLP with different starting point (%d attempts).");
00307 ADD_MSG(WARN_SUCCESS_RANDOM, warn_m, 1,
00308 "Problem initially not solved but solved with a random starting point (success on %d attempt)");
00309 ADD_MSG(WARN_CONTINUING_ON_FAILURE, warn_m, 1,
00310 "Warning : continuing branching, while there are unrecovered failures at nodes");
00311
00312 ADD_MSG(SUSPECT_PROBLEM, std_m, 2, "NLP number %d is suspect (see bounds and start file)");
00313 ADD_MSG(IPOPT_SUMMARY, std_m, 2, "Ipopt return (for %s): status %2d, iter count %4d, time %g");
00314 ADD_MSG(BETTER_SOL, std_m, 2, "Solution of value %g found on %d'th attempt");
00315
00316 ADD_MSG(LOG_HEAD, std_m, 1,
00317 "\n "
00318 " Num Status Obj It time Location");
00319 ADD_MSG(LOG_LINE, std_m, 1,
00320 "%c %8d %11s %g %8d %g %20s");
00321
00322 ADD_MSG(ALTERNATE_OBJECTIVE, std_m, 1, "Objective value recomputed with alternate objective: %g.");
00323
00324 ADD_MSG(WARN_RESOLVE_BEFORE_INITIAL_SOLVE, warn_m, 1,
00325 "resolve called before any call to initialSol can not use warm starts.");
00326 ADD_MSG(ERROR_NO_TNLPSOLVER, warn_m, 1,"Can not parse options when no IpApplication has been created");
00327 ADD_MSG(WARNING_NON_CONVEX_OA, warn_m, 1,
00328 "OA on non-convex constraint is very experimental.");
00329 ADD_MSG(SOLVER_DISAGREE_STATUS, warn_m, 1, "%s says problem %s, %s says %s.");
00330 ADD_MSG(SOLVER_DISAGREE_VALUE, warn_m, 1, "%s gives objective %.16g, %s gives %.16g.");
00331
00332 }
00333
00334
00335 void
00336 OsiTMINLPInterface::OaMessageHandler::print(OsiRowCut &row){
00337 FILE * fp = filePointer();
00338 const int &n = row.row().getNumElements();
00339 fprintf(fp,"Row cut has %d elements. Lower bound: %g, upper bound %g.\n", n, row.lb(), row.ub());
00340 const int * idx = row.row().getIndices();
00341 const double * val = row.row().getElements();
00342 for(int i = 0 ; i < n ; i++){
00343 fprintf(fp,"%g, x%d",val[i], idx[i]);
00344 if(i && i % 7 == 0)
00345 fprintf(fp,"\n");
00346 }
00347 }
00348
00349 OsiTMINLPInterface::OaMessages::OaMessages(): CoinMessages((int) OA_MESSAGES_DUMMY_END){
00350 strcpy(source_,"OaCg");
00351 ADD_MSG(VIOLATED_OA_CUT_GENERATED, std_m, 1,"Row %d, cut violation is %g: Outer approximation cut generated.");
00352
00353 ADD_MSG(CUT_NOT_VIOLATED_ENOUGH, std_m, 2,"Row %d, cut violation is %g: Outer approximation cut not generated.");
00354
00355 ADD_MSG(OA_CUT_GENERATED, std_m, 1,"Row %d: Outer approximation cut not generated.");
00356 }
00357 bool OsiTMINLPInterface::hasPrintedOptions=0;
00358
00360
00363 OsiTMINLPInterface::OsiTMINLPInterface():
00364 OsiSolverInterface(),
00365 tminlp_(NULL),
00366 problem_(NULL),
00367 problem_to_optimize_(NULL),
00368 feasibility_mode_(false),
00369 app_(NULL),
00370 debug_apps_(),
00371 testOthers_(false),
00372 warmstart_(NULL),
00373 rowsense_(NULL),
00374 rhs_(NULL),
00375 rowrange_(NULL),
00376 reducedCosts_(NULL),
00377 OsiDualObjectiveLimit_(1e200),
00378 hasVarNamesFile_(true),
00379 nCallOptimizeTNLP_(0),
00380 totalNlpSolveTime_(0),
00381 totalIterations_(0),
00382 maxRandomRadius_(1e08),
00383 randomGenerationType_(0),
00384 max_perturbation_(COIN_DBL_MAX),
00385 pushValue_(1e-02),
00386 numRetryInitial_(-1),
00387 numRetryResolve_(-1),
00388 numRetryInfeasibles_(-1),
00389 numRetryUnsolved_(1),
00390 infeasibility_epsilon_(0),
00391 dynamicCutOff_(0),
00392 coeff_var_threshold_(0.1),
00393 first_perc_for_cutoff_decr_(-0.02),
00394 second_perc_for_cutoff_decr_(-0.05),
00395 messages_(),
00396 pretendFailIsInfeasible_(0),
00397 pretendSucceededNext_(0),
00398 hasContinuedAfterNlpFailure_(false),
00399 numIterationSuspect_(-1),
00400 hasBeenOptimized_(false),
00401 obj_(NULL),
00402 feasibilityProblem_(NULL),
00403 jRow_(NULL),
00404 jCol_(NULL),
00405 jValues_(NULL),
00406 nnz_jac(0),
00407 constTypes_(NULL),
00408 nNonLinear_(0),
00409 tiny_(1e-8),
00410 veryTiny_(1e-20),
00411 rhsRelax_(tiny_),
00412 infty_(1e100),
00413 warmStartMode_(None),
00414 firstSolve_(true),
00415 cutStrengthener_(NULL),
00416 oaMessages_(),
00417 oaHandler_(NULL),
00418 newCutoffDecr(COIN_DBL_MAX)
00419
00420 {
00421 oaHandler_ = new OaMessageHandler;
00422 oaHandler_->setLogLevel(0);
00423 }
00424
00425 void
00426 OsiTMINLPInterface::initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00427 Ipopt::SmartPtr<Ipopt::OptionsList> options,
00428 Ipopt::SmartPtr<Ipopt::Journalist> journalist,
00429 const std::string & prefix,
00430 Ipopt::SmartPtr<TMINLP> tminlp){
00431 if(!IsValid(app_))
00432 createApplication(roptions, options, journalist, prefix);
00433 setModel(tminlp);
00434 }
00435
00436 void OsiTMINLPInterface::setSolver(Ipopt::SmartPtr<TNLPSolver> app){
00437 app_ = app;
00438 }
00439
00440
00441 void
00442 OsiTMINLPInterface::createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00443 Ipopt::SmartPtr<Ipopt::OptionsList> options,
00444 Ipopt::SmartPtr<Ipopt::Journalist> journalist,
00445 const std::string & prefix
00446 )
00447 {
00448 assert(!IsValid(app_));
00449 int ival;
00450 options->GetEnumValue("nlp_solver", ival, prefix.c_str());
00451 Solver s = (Solver) ival;
00452 if(s == EFilterSQP){
00453 testOthers_ = false;;
00454 #ifdef COIN_HAS_FILTERSQP
00455 app_ = new Bonmin::FilterSolver(roptions, options, journalist, prefix);
00456 #else
00457 throw SimpleError("createApplication",
00458 "Bonmin not configured to run with FilterSQP.");
00459 #endif
00460
00461 debug_apps_.push_back(new IpoptSolver(roptions, options, journalist, prefix));
00462 }
00463 else if(s == EIpopt){
00464 testOthers_ = false;
00465 app_ = new IpoptSolver(roptions, options, journalist, prefix);
00466
00467 #ifdef COIN_HAS_FILTERSQP
00468 debug_apps_.push_back(new Bonmin::FilterSolver(roptions, options, journalist, prefix));
00469 #endif
00470 }
00471 else if(s == EAll){
00472 #ifdef COIN_HAS_FILTERSQP
00473 app_ = new Bonmin::FilterSolver(roptions, options, journalist, prefix);
00474 #else
00475 throw SimpleError("createApplication",
00476 "Bonmin not configured to run with Ipopt.");
00477 #endif
00478 debug_apps_.push_back(new IpoptSolver(roptions, options, journalist, prefix));
00479 testOthers_ = true;
00480 }
00481 if (!app_->Initialize("")) {
00482 throw CoinError("Error during initialization of app_","createApplication", "OsiTMINLPInterface");
00483 }
00484 for(std::list<Ipopt::SmartPtr<TNLPSolver> >::iterator i = debug_apps_.begin() ;
00485 i != debug_apps_.end() ; i++){
00486 (*i)->Initialize("");
00487 }
00488 extractInterfaceParams();
00489
00490 }
00491
00493 void
00494 OsiTMINLPInterface::setModel(SmartPtr<TMINLP> tminlp)
00495 {
00496 assert(IsValid(tminlp));
00497 tminlp_ = tminlp;
00498 problem_ = new TMINLP2TNLP(tminlp_);
00499 feasibilityProblem_ = new TNLP2FPNLP
00500 (SmartPtr<TNLP>(GetRawPtr(problem_)));
00501 if(feasibility_mode_){
00502 problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
00503 }
00504 else {
00505 problem_to_optimize_ = GetRawPtr(problem_);
00506 }
00507 }
00508
00509
00510
00511 void
00512 OsiTMINLPInterface::readOptionFile(const std::string & fileName)
00513 {
00514 if(IsValid(app_)){
00515 std::ifstream is;
00516 if (fileName != "") {
00517 try {
00518 is.open(fileName.c_str());
00519 }
00520 catch(std::bad_alloc) {
00521 throw CoinError("Not enough memory to open option file.\n", "readOptionFile", "OsiTMINLPInterface");
00522 }
00523 }
00524 options()->ReadFromStream(*app_->journalist(), is);
00525 extractInterfaceParams();
00526 }
00527 }
00528
00530 OsiTMINLPInterface::OsiTMINLPInterface (const OsiTMINLPInterface &source):
00531 OsiSolverInterface(source),
00532 tminlp_(source.tminlp_),
00533 problem_(NULL),
00534 problem_to_optimize_(NULL),
00535 feasibility_mode_(source.feasibility_mode_),
00536 rowsense_(NULL),
00537 rhs_(NULL),
00538 rowrange_(NULL),
00539 reducedCosts_(NULL),
00540 OsiDualObjectiveLimit_(source.OsiDualObjectiveLimit_),
00541 hasVarNamesFile_(source.hasVarNamesFile_),
00542 nCallOptimizeTNLP_(0),
00543 totalNlpSolveTime_(0),
00544 totalIterations_(0),
00545 maxRandomRadius_(source.maxRandomRadius_),
00546 randomGenerationType_(source.randomGenerationType_),
00547 max_perturbation_(source.max_perturbation_),
00548 pushValue_(source.pushValue_),
00549 numRetryInitial_(source.numRetryInitial_),
00550 numRetryResolve_(source.numRetryResolve_),
00551 numRetryInfeasibles_(source.numRetryInfeasibles_),
00552 numRetryUnsolved_(source.numRetryUnsolved_),
00553 infeasibility_epsilon_(source.infeasibility_epsilon_),
00554 dynamicCutOff_(source.dynamicCutOff_),
00555 coeff_var_threshold_(source.coeff_var_threshold_),
00556 first_perc_for_cutoff_decr_(source.first_perc_for_cutoff_decr_),
00557 second_perc_for_cutoff_decr_(source.second_perc_for_cutoff_decr_),
00558 messages_(),
00559 pretendFailIsInfeasible_(source.pretendFailIsInfeasible_),
00560 pretendSucceededNext_(source.pretendSucceededNext_),
00561 hasContinuedAfterNlpFailure_(source.hasContinuedAfterNlpFailure_),
00562 numIterationSuspect_(source.numIterationSuspect_),
00563 hasBeenOptimized_(source.hasBeenOptimized_),
00564 obj_(NULL),
00565 feasibilityProblem_(NULL),
00566 jRow_(NULL),
00567 jCol_(NULL),
00568 jValues_(NULL),
00569 nnz_jac(source.nnz_jac),
00570 constTypes_(NULL),
00571
00572 nNonLinear_(0),
00573 tiny_(source.tiny_),
00574 veryTiny_(source.veryTiny_),
00575 rhsRelax_(source.rhsRelax_),
00576 infty_(source.infty_),
00577 warmStartMode_(source.warmStartMode_),
00578 firstSolve_(true),
00579 cutStrengthener_(source.cutStrengthener_),
00580 oaMessages_(),
00581 oaHandler_(NULL),
00582 newCutoffDecr(source.newCutoffDecr),
00583 strong_branching_solver_(source.strong_branching_solver_)
00584 {
00585 if(IsValid(source.tminlp_)) {
00586 problem_ = source.problem_->clone();
00587 feasibilityProblem_ = new TNLP2FPNLP
00588 (SmartPtr<TNLP>(GetRawPtr(problem_)), source.feasibilityProblem_);
00589 if(feasibility_mode_)
00590 problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
00591 else
00592 problem_to_optimize_ = GetRawPtr(problem_);
00593 pretendFailIsInfeasible_ = source.pretendFailIsInfeasible_;
00594 pretendSucceededNext_ = source.pretendSucceededNext_;
00595
00596 setAuxiliaryInfo(source.getAuxiliaryInfo());
00597
00598 app_ = source.app_->clone();
00599 for(std::list<Ipopt::SmartPtr<TNLPSolver> >::const_iterator i = source.debug_apps_.begin();
00600 i != source.debug_apps_.end() ; i++){
00601 debug_apps_.push_back((*i)->clone());
00602 }
00603 testOthers_ = source.testOthers_;
00604 }
00605 else {
00606 throw SimpleError("Don't know how to copy an empty IpoptInterface.",
00607 "copy constructor");
00608 }
00609
00610 warmstart_ = source.warmstart_ ? source.warmstart_->clone() : NULL;
00611
00612 if(source.obj_) {
00613 obj_ = new double[source.getNumCols()];
00614 CoinCopyN(source.obj_, source.getNumCols(), obj_);
00615 }
00616
00617
00618 oaHandler_ = new OaMessageHandler(*source.oaHandler_);;
00619
00620 }
00621
00622 OsiSolverInterface *
00623 OsiTMINLPInterface::clone(bool copyData ) const
00624 {
00625 if(copyData)
00626 return new OsiTMINLPInterface(*this);
00627 else return new OsiTMINLPInterface;
00628 }
00629
00631 OsiTMINLPInterface & OsiTMINLPInterface::operator=(const OsiTMINLPInterface& rhs)
00632 {
00633 if(this!= &rhs) {
00634 OsiSolverInterface::operator=(rhs);
00635 OsiDualObjectiveLimit_ = rhs.OsiDualObjectiveLimit_;
00636 nCallOptimizeTNLP_ = rhs.nCallOptimizeTNLP_;
00637 totalNlpSolveTime_ = rhs.nCallOptimizeTNLP_;
00638 totalIterations_ = rhs.totalIterations_;
00639 maxRandomRadius_ = rhs.maxRandomRadius_;
00640 hasVarNamesFile_ = rhs.hasVarNamesFile_;
00641 pushValue_ = rhs.pushValue_;
00642
00643 delete warmstart_;
00644 warmstart_ = NULL;
00645
00646 if(IsValid(rhs.tminlp_)) {
00647
00648 tminlp_ = rhs.tminlp_;
00649 problem_ = new TMINLP2TNLP(tminlp_);
00650 problem_to_optimize_ = GetRawPtr(problem_);
00651 app_ = rhs.app_->clone();
00652
00653 warmstart_ = rhs.warmstart_ ? rhs.warmstart_->clone() : NULL;
00654
00655 feasibilityProblem_ = new TNLP2FPNLP
00656 (SmartPtr<TNLP>(GetRawPtr(problem_)));
00657 nnz_jac = rhs.nnz_jac;
00658
00659 if(constTypes_ != NULL) {
00660 delete [] constTypes_;
00661 constTypes_ = NULL;
00662 }
00663 if(rhs.constTypes_ != NULL) {
00664 constTypes_ = new TNLP::LinearityType[getNumRows()];
00665 CoinCopyN(rhs.constTypes_, getNumRows(), constTypes_);
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 if(rhs.jValues_!=NULL && rhs.jRow_ != NULL && rhs.jCol_ != NULL && nnz_jac>0) {
00678 jValues_ = new double [nnz_jac];
00679 jCol_ = new Index [nnz_jac];
00680 jRow_ = new Index [nnz_jac];
00681 CoinCopyN(rhs.jValues_ , nnz_jac,jValues_ );
00682 CoinCopyN(rhs.jCol_ , nnz_jac,jCol_ );
00683 CoinCopyN(rhs.jRow_ , nnz_jac,jRow_ );
00684 }
00685 else if(nnz_jac > 0) {
00686 throw CoinError("Arrays for storing jacobian are inconsistant.",
00687 "copy constructor",
00688 "IpoptOAInterface");
00689 }
00690 tiny_ = rhs.tiny_;
00691 veryTiny_ = rhs.veryTiny_;
00692 rhsRelax_ = rhs.rhsRelax_;
00693 infty_ = rhs.infty_;
00694 warmStartMode_ = rhs.warmStartMode_;
00695 newCutoffDecr = rhs.newCutoffDecr;
00696
00697 }
00698 else {
00699 tminlp_ =NULL;
00700 problem_ = NULL;
00701 app_ = NULL;
00702 feasibilityProblem_ = NULL;
00703 }
00704
00705
00706 if(obj_) {
00707 delete [] obj_;
00708 obj_ = NULL;
00709 }
00710 if(rhs.obj_) {
00711 obj_ = new double[rhs.getNumCols()];
00712 CoinCopyN(rhs.obj_, rhs.getNumCols(), obj_);
00713 }
00714
00715 hasVarNamesFile_ = rhs.hasVarNamesFile_;
00716
00717 nCallOptimizeTNLP_ = rhs.nCallOptimizeTNLP_;
00718 totalNlpSolveTime_ = rhs.totalNlpSolveTime_;
00719 totalIterations_ = rhs.totalIterations_;
00720 maxRandomRadius_ = rhs.maxRandomRadius_;
00721 pushValue_ = rhs.pushValue_;
00722 numRetryInitial_ = rhs.numRetryInitial_;
00723 numRetryResolve_ = rhs.numRetryResolve_;
00724 numRetryInfeasibles_ = rhs.numRetryInfeasibles_;
00725 numRetryUnsolved_ = rhs.numRetryUnsolved_;
00726 infeasibility_epsilon_ = rhs.infeasibility_epsilon_;
00727 pretendFailIsInfeasible_ = rhs.pretendFailIsInfeasible_;
00728 pretendSucceededNext_ = rhs.pretendSucceededNext_;
00729 numIterationSuspect_ = rhs.numIterationSuspect_;
00730
00731 hasBeenOptimized_ = rhs.hasBeenOptimized_;
00732 cutStrengthener_ = rhs.cutStrengthener_;
00733
00734 delete oaHandler_;
00735 oaHandler_ = new OaMessageHandler(*rhs.oaHandler_);
00736 strong_branching_solver_ = rhs.strong_branching_solver_;
00737
00738 dynamicCutOff_ = rhs.dynamicCutOff_;
00739 coeff_var_threshold_ = rhs.coeff_var_threshold_;
00740 first_perc_for_cutoff_decr_ = rhs.first_perc_for_cutoff_decr_;
00741 second_perc_for_cutoff_decr_ = rhs.second_perc_for_cutoff_decr_;
00742
00743 freeCachedData();
00744 }
00745 return *this;
00746 }
00747
00748 const SmartPtr<OptionsList> OsiTMINLPInterface::options() const
00749 {
00750 if(!IsValid(app_)) {
00751 messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
00752 return NULL;
00753 }
00754 else
00755 return app_->options();
00756 }
00757
00758 SmartPtr<OptionsList> OsiTMINLPInterface::options()
00759 {
00760 if(!IsValid(app_)) {
00761 messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
00762 return NULL;
00763 }
00764 else
00765 return app_->options();
00766 }
00767
00769 OsiTMINLPInterface::~OsiTMINLPInterface ()
00770 {
00771 freeCachedData();
00772 delete [] jRow_;
00773 delete [] jCol_;
00774 delete [] jValues_;
00775 delete [] constTypes_;
00776 delete [] obj_;
00777 delete oaHandler_;
00778 delete warmstart_;
00779 }
00780
00781 void
00782 OsiTMINLPInterface::freeCachedColRim()
00783 {
00784 if(reducedCosts_!=NULL) {
00785 delete [] reducedCosts_;
00786 reducedCosts_ = NULL;
00787 }
00788
00789 }
00790
00791 void
00792 OsiTMINLPInterface::freeCachedRowRim()
00793 {
00794 if(rowsense_!=NULL) {
00795 delete [] rowsense_;
00796 rowsense_ = NULL;
00797 }
00798 if(rhs_!=NULL) {
00799 delete [] rhs_;
00800 rhs_ = NULL;
00801 }
00802 if(rowrange_!=NULL) {
00803 delete [] rowrange_;
00804 rowrange_ = NULL;
00805 }
00806
00807
00808
00809
00810 }
00811
00812 void
00813 OsiTMINLPInterface::freeCachedData()
00814 {
00815 freeCachedColRim();
00816 freeCachedRowRim();
00817 }
00818
00819 const char * OsiTMINLPInterface::OPT_SYMB="OPT";
00820 const char * OsiTMINLPInterface::FAILED_SYMB="FAILED";
00821 const char * OsiTMINLPInterface::UNBOUND_SYMB="UNBOUNDED";
00822 const char * OsiTMINLPInterface::INFEAS_SYMB="INFEAS";
00823 const char * OsiTMINLPInterface::TIME_SYMB="TIME";
00825
00827
00828
00829 void
00830 OsiTMINLPInterface::resolveForCost(int numsolve, bool keepWarmStart)
00831 {
00832
00833
00834
00835 delete warmstart_;
00836 warmstart_ = NULL;
00837
00838 double * of_current = (numsolve > 0) ? new double[numsolve]: NULL;
00839 int num_failed, num_infeas;
00840 double mean, std_dev, var_coeff;
00841 double min = DBL_MAX;
00842 double max = -DBL_MAX;
00843
00844 Coin::SmartPtr<SimpleReferencedPtr<CoinWarmStart> > ws_backup = NULL;
00845 if(warmStartMode_ <= Optimum && keepWarmStart){
00846
00847
00848 ws_backup = make_referenced(app_->getUsedWarmStart(problem_));
00849 }
00851 vector<double> point(getNumCols()*3+ getNumRows());
00852 double bestBound = (isProvenOptimal()) ? getObjValue() : DBL_MAX;
00853 CoinCopyN(getColSolution(),
00854 getNumCols(), point());
00855 CoinCopyN(getRowPrice(),
00856 2*getNumCols()+ getNumRows(),
00857 point() + getNumCols());
00858 TNLPSolver::ReturnStatus savedStatus = optimizationStatus_;
00859 if(isProvenOptimal())
00860 messageHandler()->message(SOLUTION_FOUND,
00861 messages_)
00862 <<1<<getObjValue()<<bestBound
00863 <<CoinMessageEol;
00864 else
00865 messageHandler()->message(INFEASIBLE_SOLUTION_FOUND,
00866 messages_)
00867 <<1
00868 <<CoinMessageEol;
00869
00870 num_failed = 0;
00871 num_infeas = 0;
00872 mean = 0;
00873
00874 for(int f = 0; f < numsolve ; f++) {
00875 messageHandler()->message(WARNING_RESOLVING,
00876 messages_)
00877 <<f+1<< CoinMessageEol ;
00878 randomStartingPoint();
00879 solveAndCheckErrors(0,0,"resolve cost");
00880
00881
00882 char c=' ';
00883
00884 if(isProvenOptimal() &&
00885 getObjValue()<bestBound) {
00886 c='*';
00887 messageHandler()->message(BETTER_SOL, messages_)<<getObjValue()<<f+1<< CoinMessageEol;
00888 CoinCopyN(getColSolution(),
00889 getNumCols(), point());
00890 CoinCopyN(getRowPrice(),
00891 2*getNumCols()+ getNumRows(),
00892 point() + getNumCols());
00893 bestBound = getObjValue();
00894 savedStatus = optimizationStatus_;
00895 }
00896
00897 messageHandler()->message(LOG_LINE, messages_)
00898 <<c<<f+1<<statusAsString()<<getObjValue()<<app_->IterationCount()<<app_->CPUTime()<<"resolve cost"<<CoinMessageEol;
00899
00900 if(isAbandoned()) {
00901 num_failed++;
00902 }
00903 else if(isProvenPrimalInfeasible()) {
00904 num_infeas++;
00905 }
00906
00907 else if(isProvenOptimal())
00908 messageHandler()->message(SOLUTION_FOUND,
00909 messages_)
00910 <<f+2<<getObjValue()<<bestBound
00911 <<CoinMessageEol;
00912 else if(!isAbandoned())
00913 messageHandler()->message(UNSOLVED_PROBLEM_FOUND,
00914 messages_)
00915 <<f+2
00916 <<CoinMessageEol;
00917 else
00918 messageHandler()->message(INFEASIBLE_SOLUTION_FOUND,
00919 messages_)
00920 <<f+2
00921 <<CoinMessageEol;
00922
00923 if(of_current != NULL){
00924 if(isProvenOptimal())
00925 {
00926 of_current[f] = getObjValue();
00927 mean=mean+of_current[f];
00928 if (of_current[f] < min)
00929 min = of_current[f];
00930 else if (of_current[f] > max)
00931 max = of_current[f];
00932 }
00933 else
00934 {
00935 of_current[f] = 0;
00936 }
00937 }
00938 }
00939
00940
00941 if(of_current != NULL){
00942
00943 mean=mean/(numsolve-num_failed-num_infeas);
00944
00945 std_dev = 0;
00946
00947
00948 for(int i=0; i<numsolve; i++)
00949 {
00950 if(of_current[i]!=0)
00951 std_dev=std_dev+pow(of_current[i]-mean,2);
00952 }
00953 std_dev=pow((std_dev/(numsolve-num_failed-num_infeas)),0.5);
00954
00955
00956 var_coeff=std_dev/mean;
00957 }
00958
00959
00960
00961
00962 if(dynamicCutOff_)
00963 {
00964 if(var_coeff<0.1)
00965 {
00966 setNewCutoffDecr(mean*first_perc_for_cutoff_decr_);
00967 }
00968 else
00969 {
00970 setNewCutoffDecr(mean*second_perc_for_cutoff_decr_);
00971 }
00972 }
00973
00974
00975 problem_->Set_x_sol(getNumCols(),point());
00976 problem_->Set_dual_sol((int) point.size()-getNumCols(), point() + getNumCols());
00977 problem_->set_obj_value(bestBound);
00978 optimizationStatus_ = savedStatus;
00979 hasBeenOptimized_ = true;
00980
00981 if(warmStartMode_ < Optimum && keepWarmStart) {
00982 app_->setWarmStart(ws_backup->ptr(), problem_);
00983 }
00984 }
00985
00986 void
00987 OsiTMINLPInterface::resolveForRobustness(int numsolve)
00988 {
00989
00990
00991
00992 delete warmstart_;
00993 warmstart_ = NULL;
00994
00995
00996 CoinWarmStart * ws_backup = NULL;
00997 if(warmStartMode_ < Optimum){
00998
00999
01000 ws_backup = app_->getUsedWarmStart(problem_);
01001 }
01002
01003
01004 app_->disableWarmStart();
01005 problem()->resetStartingPoint();
01006 messageHandler()->message(WARNING_RESOLVING,
01007 messages_)
01008 <<1<< CoinMessageEol ;
01009 solveAndCheckErrors(0,0,"resolve robustness");
01010
01011
01012 char c='*';
01013 if(isAbandoned()) {
01014 c=' ';
01015 }
01016 messageHandler()->message(LOG_LINE, messages_)
01017 <<c<<1<<statusAsString()<<getObjValue()<<app_->IterationCount()<<
01018 app_->CPUTime()<<"resolve robustness"<<CoinMessageEol;
01019
01020
01021 if(!isAbandoned()) {
01022 messageHandler()->message(WARN_SUCCESS_WS, messages_) << CoinMessageEol ;
01023
01024 app_->enableWarmStart();
01025 if (warmStartMode_ < Optimum) {
01026 app_->setWarmStart(ws_backup, problem_);
01027 delete ws_backup;
01028 }
01029 return;
01030 }
01031
01032
01033 for(int f = 0; f < numsolve ; f++) {
01034 messageHandler()->message(WARNING_RESOLVING,
01035 messages_)
01036 <<f+2<< CoinMessageEol ;
01037
01038 randomStartingPoint();
01039 solveAndCheckErrors(0,0,"resolve robustness");
01040
01041
01042 messageHandler()->message(IPOPT_SUMMARY, messages_)
01043 <<"resolveForRobustness"<<optimizationStatus_<<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
01044
01045
01046 char c='*';
01047 if(isAbandoned()) {
01048 c=' ';
01049 }
01050 messageHandler()->message(LOG_LINE, messages_)
01051 <<c<<f+2<<statusAsString()<<getObjValue()
01052 <<app_->IterationCount()<<app_->CPUTime()<<"resolve robustness"<<CoinMessageEol;
01053
01054
01055 if(!isAbandoned()) {
01056 messageHandler()->message(WARN_SUCCESS_RANDOM, messages_)
01057 << f+2 << CoinMessageEol ;
01058
01059 app_->enableWarmStart();
01060 if (warmStartMode_ < Optimum) {
01061 app_->setWarmStart(ws_backup, problem_);
01062 delete ws_backup;
01063 }
01064
01065 return;
01066 }
01067 }
01068
01069
01070 if(warmStartMode_ < Optimum){
01071 app_->setWarmStart(ws_backup, problem_);
01072 delete ws_backup;
01073 }
01074 if(pretendFailIsInfeasible_) {
01075 pretendSucceededNext_ = true;
01076 if(pretendFailIsInfeasible_ == 1) {
01077 messageHandler()->message(WARN_CONTINUING_ON_FAILURE,
01078 messages_)
01079 <<CoinMessageEol;
01080 hasContinuedAfterNlpFailure_ = 1;
01081 }
01082 return;
01083 }
01084 else {
01085 std::string probName;
01086 getStrParam(OsiProbName,probName);
01087 throw newUnsolvedError(app_->errorCode(), problem_,
01088 probName);
01089 }
01090
01091 }
01092
01094
01097 int OsiTMINLPInterface::getNumCols() const
01098 {
01099
01100 return problem_->num_variables();
01101 }
01102
01103
01105 int
01106 OsiTMINLPInterface::getNumRows() const
01107 {
01108 return problem_->num_constraints();
01109 }
01110
01111 const double *
01112 OsiTMINLPInterface::getColLower() const
01113 {
01114 return problem_->x_l();
01115 }
01116
01117 const double *
01118 OsiTMINLPInterface::getColUpper() const
01119 {
01120 return problem_->x_u();
01121 }
01122
01123 #if 1
01124
01125
01127 const OsiSolverInterface::OsiNameVec&
01128 OsiTMINLPInterface::getVarNames() {
01129 return getColNames();
01130 }
01131 #endif
01132
01133
01134 void OsiTMINLPInterface::extractSenseRhsAndRange() const
01135 {
01136 assert(rowsense_==NULL&&rhs_==NULL&&rowrange_==NULL);
01137 int numrows = problem_->num_constraints();
01138 if(numrows == 0) return;
01139 const double * rowLower = getRowLower();
01140 const double * rowUpper = getRowUpper();
01141 rowsense_ = new char [numrows];
01142 rhs_ = new double [numrows];
01143 rowrange_ = new double [numrows];
01144 for(int i = 0 ; i < numrows ; i++) {
01145 rowrange_[i]=0.;
01146 convertBoundToSense(rowLower[i], rowUpper[i], rowsense_[i], rhs_[i], rowrange_[i]);
01147 }
01148 }
01149
01159 const char *
01160 OsiTMINLPInterface::getRowSense() const
01161 {
01162 if(rowsense_==NULL) {
01163 extractSenseRhsAndRange();
01164 }
01165 return rowsense_;
01166 }
01167
01176 const double *
01177 OsiTMINLPInterface::getRightHandSide() const
01178 {
01179 if(rhs_==NULL) {
01180 extractSenseRhsAndRange();
01181 }
01182 return rhs_;
01183 }
01184
01193 const double *
01194 OsiTMINLPInterface::getRowRange() const
01195 {
01196 if(rowrange_==NULL) {
01197 extractSenseRhsAndRange();
01198 }
01199 return rowrange_;
01200 }
01201
01202 const double *
01203 OsiTMINLPInterface::getRowLower() const
01204 {
01205 return problem_->g_l();
01206 }
01207
01208 const double *
01209 OsiTMINLPInterface::getRowUpper() const
01210 {
01211 return problem_->g_u();
01212 }
01213
01215 bool
01216 OsiTMINLPInterface::isContinuous(int colNumber) const
01217 {
01218 return (problem_->var_types()[colNumber]==TMINLP::CONTINUOUS);
01219 }
01220
01222 bool
01223 OsiTMINLPInterface::isBinary(int colNumber) const
01224 {
01225 return (problem_->var_types()[colNumber]==TMINLP::BINARY);
01226 }
01227
01232 bool
01233 OsiTMINLPInterface::isInteger(int colNumber) const
01234 {
01235 return ((problem_->var_types()[colNumber]==TMINLP::BINARY)||
01236 (problem_->var_types()[colNumber]==TMINLP::INTEGER));
01237 }
01238
01240 bool
01241 OsiTMINLPInterface::isIntegerNonBinary(int colNumber) const
01242 {
01243 return (problem_->var_types()[colNumber]==TMINLP::INTEGER);
01244 }
01246 bool
01247 OsiTMINLPInterface::isFreeBinary(int colNumber) const
01248 {
01249 return ((problem_->var_types()[colNumber]==TMINLP::BINARY)
01250 &&((getColUpper()[colNumber]-getColLower()[colNumber]) > 1 - 1e-09));
01251 }
01252
01254 double
01255 OsiTMINLPInterface::getInfinity() const
01256 {
01257 return COIN_DBL_MAX;
01258 }
01259
01261 const double *
01262 OsiTMINLPInterface::getColSolution() const
01263 {
01264 if(hasBeenOptimized_)
01265 return problem_->x_sol();
01266 else
01267 return problem_->x_init();
01268 }
01269
01271 const double *
01272 OsiTMINLPInterface::getRowPrice() const
01273 {
01274 if(hasBeenOptimized_)
01275 return problem_->duals_sol();
01276 else
01277 return problem_->duals_init();
01278 }
01279
01281 const double *
01282 OsiTMINLPInterface::getReducedCost() const
01283 {
01284 (*handler_)<<"WARNING : trying to access reduced cost in Ipopt always retrun 0"<<CoinMessageEol;
01285 if(reducedCosts_==NULL) {
01286 reducedCosts_ = new double [getNumCols()];
01287 CoinFillN(reducedCosts_,getNumCols(),0.);
01288 }
01289 return reducedCosts_;
01290 }
01291
01294 const double *
01295 OsiTMINLPInterface::getRowActivity() const
01296 {
01297 return problem_->g_sol();
01298 }
01299
01303 int
01304 OsiTMINLPInterface::getIterationCount() const
01305 {
01306 return app_->IterationCount();
01307 }
01308
01309
01312 void
01313 OsiTMINLPInterface::setColLower( int elementIndex, double elementValue )
01314 {
01315
01316 problem_->SetVariableLowerBound(elementIndex,elementValue);
01317 hasBeenOptimized_ = false;
01318 }
01319
01322 void
01323 OsiTMINLPInterface::setColUpper( int elementIndex, double elementValue )
01324 {
01325
01326 problem_->SetVariableUpperBound(elementIndex,elementValue);
01327 hasBeenOptimized_ = false;
01328 }
01329
01332 void
01333 OsiTMINLPInterface::setColLower( const double* array )
01334 {
01335 problem_->SetVariablesLowerBounds(problem_->num_variables(),
01336 array);
01337 hasBeenOptimized_ = false;
01338 }
01339
01342 void
01343 OsiTMINLPInterface::setColUpper( const double* array )
01344 {
01345 problem_->SetVariablesUpperBounds(problem_->num_variables(),
01346 array);
01347 hasBeenOptimized_ = false;
01348 }
01349
01352 void
01353 OsiTMINLPInterface::setRowLower( int elementIndex, double elementValue )
01354 {
01355 throw SimpleError("Not implemented yet but should be if necessary.",
01356 "setRowLower");
01357 hasBeenOptimized_ = false;
01358 }
01359
01362 void
01363 OsiTMINLPInterface::setRowUpper( int elementIndex, double elementValue )
01364 {
01365 throw SimpleError("Not implemented yet but should be if necessary.",
01366 "setRowUpper");
01367 hasBeenOptimized_ = false;
01368 }
01369
01371 void
01372 OsiTMINLPInterface::setRowType(int index, char sense, double rightHandSide,
01373 double range)
01374 {
01375 throw SimpleError("Not implemented yet but should be if necessary.",
01376 "setRowType");
01377 hasBeenOptimized_ = false;
01378 }
01379
01380
01383 void
01384 OsiTMINLPInterface::setObjSense(double s)
01385 {
01386 throw SimpleError("Can not change objective sense of an Ipopt problem.",
01387 "setObjSense");
01388 hasBeenOptimized_ = false;
01389 }
01390
01400 void
01401 OsiTMINLPInterface::setColSolution(const double *colsol)
01402 {
01403 if(colsol != NULL)
01404 problem_->setxInit(getNumCols(), colsol);
01405 else
01406 problem_->resetStartingPoint();
01407 hasBeenOptimized_ = false;
01408 }
01409
01420 void
01421 OsiTMINLPInterface::setRowPrice(const double * rowprice)
01422 {
01423 problem_->setDualsInit(getNumCols()*2 + getNumRows(), rowprice);
01424 hasBeenOptimized_ = false;
01425 }
01426
01433 CoinWarmStart *
01434 OsiTMINLPInterface::getEmptyWarmStart () const
01435 {return app_->getEmptyWarmStart();}
01436
01438 CoinWarmStart*
01439 OsiTMINLPInterface::getWarmStart() const
01440 {
01441 if (warmStartMode_ >= Optimum) {
01442 return internal_getWarmStart();;
01443 }
01444 else if(warmStartMode_ == FakeBasis){
01445 return build_fake_basis();
01446 }
01447 else {
01448 return getEmptyWarmStart();
01449 }
01450 }
01453 bool
01454 OsiTMINLPInterface::setWarmStart(const CoinWarmStart* ws)
01455 {
01456 if (warmStartMode_ >= Optimum) {
01457 return internal_setWarmStart(ws);
01458 }
01459 else {
01460 return true;
01461 }
01462 }
01463
01464
01465 #define EPSILON 1e-4
01466
01467 CoinWarmStart*
01468 OsiTMINLPInterface::build_fake_basis() const{
01469 CoinWarmStartBasis * r_val = new CoinWarmStartBasis();
01470 int n_con = problem_->num_constraints();
01471 r_val->setSize(problem_->num_variables(), n_con);
01472 const double * act = problem_->g_sol();
01473 const double * lb = problem_->g_l();
01474 const double * ub = problem_->g_u();
01475 for(int i = 0 ; i < n_con ; i++){
01476 if(lb[i] > ub[i] - EPSILON){
01477 r_val->setArtifStatus(i, CoinWarmStartBasis::isFree);
01478 }
01479 if(act[i] > ub[i] - EPSILON){
01480 r_val->setArtifStatus(i, CoinWarmStartBasis::atLowerBound);
01481 }
01482 else if(act[i] < lb[i] + EPSILON){
01483 r_val->setArtifStatus(i, CoinWarmStartBasis::atLowerBound);
01484 }
01485 else {
01486 r_val->setArtifStatus(i, CoinWarmStartBasis::basic);
01487 }
01488 }
01489 return r_val;
01490 }
01491
01493 CoinWarmStart*
01494 OsiTMINLPInterface::internal_getWarmStart() const
01495 {
01496 if (warmStartMode_ >= Optimum && warmstart_) {
01497 return warmstart_->clone();
01498 }
01499 else {
01500 return getEmptyWarmStart();
01501 }
01502 }
01505 bool
01506 OsiTMINLPInterface::internal_setWarmStart(const CoinWarmStart* ws)
01507 {
01508 delete warmstart_;
01509 warmstart_ = NULL;
01510 hasBeenOptimized_ = false;
01511 if (warmStartMode_ >= Optimum) {
01512 if (ws == NULL) {
01513 return true;
01514 }
01515 if(app_->warmStartIsValid(ws)) {
01516 warmstart_ = ws->clone();
01517 return true;
01518 }
01519
01520
01521 const CoinWarmStartPrimalDual* pdws =
01522 dynamic_cast<const CoinWarmStartPrimalDual*>(ws);
01523 if (pdws) {
01524
01525
01526 warmstart_ = new IpoptWarmStart(*pdws);
01527 return true;
01528 }
01529 return false;
01530 }
01531 else {
01532 return true;
01533 }
01534 }
01535
01537 void
01538 OsiTMINLPInterface::setContinuous(int index)
01539 {
01540 problem_->SetVariableType(index, TMINLP::CONTINUOUS);
01541 hasBeenOptimized_ = false;
01542 }
01544 void
01545 OsiTMINLPInterface::setInteger(int index)
01546 {
01547 problem_->SetVariableType(index, TMINLP::INTEGER);
01548 hasBeenOptimized_ = false;
01549 }
01550
01552 double
01553 OsiTMINLPInterface::getObjValue() const
01554 {
01555 return problem_->obj_value();
01556 }
01557
01558
01559
01560
01561
01562 bool
01563 OsiTMINLPInterface::setIntParam(OsiIntParam key, int value)
01564 {
01565
01566
01567 bool retval = false;
01568 switch (key) {
01569 case OsiMaxNumIteration:
01570 retval = false;
01571 break;
01572 case OsiMaxNumIterationHotStart:
01573 if( value >= 0 ) {
01574 retval = false;
01575 }
01576 else
01577 retval = false;
01578 break;
01579 case OsiLastIntParam:
01580 retval = false;
01581 break;
01582 default:
01583 retval = false;
01584 (*handler_)<< "Unhandled case in setIntParam\n"<<CoinMessageEol;
01585 break;
01586 }
01587 return retval;
01588 }
01589
01590
01591
01592 bool
01593 OsiTMINLPInterface::setDblParam(OsiDblParam key, double value)
01594 {
01595
01596
01597 bool retval = false;
01598 switch (key) {
01599 case OsiDualObjectiveLimit:
01600 OsiDualObjectiveLimit_ = value;
01601 retval = true;
01602 break;
01603 case OsiPrimalObjectiveLimit:
01604 (*handler_)<<"Can not set primal objective limit parameter"<<CoinMessageEol;
01605 retval = false;
01606 break;
01607 case OsiDualTolerance:
01608 (*handler_)<<"Can not set dual tolerance parameter"<<CoinMessageEol;
01609 retval = false;
01610 break;
01611 case OsiPrimalTolerance:
01612 (*handler_)<<"Can not set primal tolerance parameter"<<CoinMessageEol;
01613 retval = false;
01614 case OsiObjOffset:
01615 retval = OsiSolverInterface::setDblParam(key,value);
01616 break;
01617 case OsiLastDblParam:
01618 retval = false;
01619 break;
01620 default:
01621 retval = false;
01622 (*handler_) << "Unhandled case in setDblParam"<<CoinMessageEol;
01623 break;
01624 }
01625 return retval;
01626 }
01627
01628
01629
01630
01631 bool
01632 OsiTMINLPInterface::setStrParam(OsiStrParam key, const std::string & value)
01633 {
01634
01635
01636 bool retval=false;
01637 switch (key) {
01638 case OsiProbName:
01639 OsiSolverInterface::setStrParam(key,value);
01640 return retval = true;
01641 case OsiSolverName:
01642 return false;
01643 case OsiLastStrParam:
01644 return false;
01645 }
01646 return false;
01647 }
01648
01649
01650
01651 bool
01652 OsiTMINLPInterface::getIntParam(OsiIntParam key, int& value) const
01653 {
01654
01655
01656 value = -COIN_INT_MAX;
01657 bool retval = false;
01658 switch (key) {
01659 case OsiMaxNumIteration:
01660 retval = false;
01661 break;
01662 case OsiMaxNumIterationHotStart:
01663 retval = false;
01664 break;
01665 case OsiLastIntParam:
01666 retval = false;
01667 break;
01668 default:
01669 retval = false;
01670 (*handler_) << "Unhandled case in setIntParam"<<CoinMessageEol;
01671 }
01672 return retval;
01673 }
01674
01675
01676
01677 bool
01678 OsiTMINLPInterface::getDblParam(OsiDblParam key, double& value) const
01679 {
01680
01681
01682 bool retval = false;
01683 switch (key) {
01684 case OsiDualObjectiveLimit:
01685 value = OsiDualObjectiveLimit_;
01686 retval = true;
01687 break;
01688 case OsiPrimalObjectiveLimit:
01689 value = getInfinity();
01690 retval = true;
01691 break;
01692 case OsiDualTolerance:
01693 retval = false;
01694 break;
01695 case OsiPrimalTolerance:
01696 options()->GetNumericValue("tol", value,"");
01697 value = 1e-07;
01698 retval = true;
01699 break;
01700 case OsiObjOffset:
01701 retval = OsiSolverInterface::getDblParam(key, value);
01702 break;
01703 case OsiLastDblParam:
01704 retval = false;
01705 break;
01706 }
01707 return retval;
01708 }
01709
01710
01711
01712
01713 bool
01714 OsiTMINLPInterface::getStrParam(OsiStrParam key, std::string & value) const
01715 {
01716
01717
01718 switch (key) {
01719 case OsiProbName:
01720 OsiSolverInterface::getStrParam(key, value);
01721 break;
01722 case OsiSolverName:
01723 value = "Ipopt";
01724 break;
01725 case OsiLastStrParam:
01726 return false;
01727 }
01728
01729 return true;
01730 }
01731
01732 void
01733 OsiTMINLPInterface::set_linearizer(Ipopt::SmartPtr<TMINLP2OsiLP> linearizer)
01734 {
01735 linearizer_ = linearizer->clone();
01736 linearizer_->set_tols(tiny_, veryTiny_, rhsRelax_, infty_);
01737 linearizer_->set_model(GetRawPtr(problem_));
01738 }
01739
01740 Ipopt::SmartPtr<TMINLP2OsiLP>
01741 OsiTMINLPInterface::linearizer(){
01742 return linearizer_;
01743 }
01744
01745
01746 void
01747 OsiTMINLPInterface::randomStartingPoint()
01748 {
01749 int numcols = getNumCols();
01750 const double * colLower = getColLower();
01751 const double * colUpper = getColUpper();
01752 double * sol = new double[numcols];
01753 const Number * x_init = problem_->x_init_user();
01754 const double* perturb_radius = NULL;
01755 if (randomGenerationType_ == perturb_suffix) {
01756 const TMINLP::PerturbInfo* pertubinfo = tminlp_->perturbInfo();
01757 if (pertubinfo) {
01758 perturb_radius = pertubinfo->GetPerturbationArray();
01759 }
01760 if (!perturb_radius) {
01761 throw SimpleError("Can't use perturb_radius if no radii are given.",
01762 "randomStartingPoint");
01763 }
01764 }
01765 for(int i = 0 ; i < numcols ; i++) {
01766 int randomGenerationType = randomGenerationType_;
01767 if(x_init[i] < colLower[i] || x_init[i] > colUpper[i])
01768 randomGenerationType = uniform;
01769 if(randomGenerationType_ == uniform){
01770 double lower = std::min(-maxRandomRadius_,colUpper[i] - maxRandomRadius_);
01771 lower = std::max(colLower[i], lower);
01772 double upper = std::max(maxRandomRadius_,colLower[i] + maxRandomRadius_);
01773 upper = std::min(colUpper[i],upper);
01774 lower = std::min(upper,lower);
01775 upper = std::max(upper, lower);
01776 double interval = upper - lower;
01777 sol[i] = CoinDrand48()*(interval) + lower;}
01778 else if (randomGenerationType_ == perturb){
01779 const double lower = std::max(x_init[i] - max_perturbation_, colLower[i]);
01780 const double upper = std::min(x_init[i] + max_perturbation_, colUpper[i]);
01781 const double interval = upper - lower;
01782 sol[i] = lower + CoinDrand48()*(interval);
01783 }
01784 else if (randomGenerationType_ == perturb_suffix){
01785 const double radius = perturb_radius[i];
01786 const double lower = std::max(x_init[i] - radius*max_perturbation_, colLower[i]);
01787 const double upper = std::min(x_init[i] + radius*max_perturbation_, colUpper[i]);
01788 const double interval = upper - lower;
01789 sol[i] = lower + CoinDrand48()*(interval);
01790 }
01791 }
01792 app_->disableWarmStart();
01793 setColSolution(sol);
01794 delete [] sol;
01795 }
01796
01797
01798
01800 int OsiTMINLPInterface::initializeJacobianArrays()
01801 {
01802 Index n, m, nnz_h_lag;
01803 TNLP::IndexStyleEnum index_style;
01804 problem_to_optimize_->get_nlp_info( n, m, nnz_jac, nnz_h_lag, index_style);
01805
01806 if(jRow_ != NULL) delete [] jRow_;
01807 if(jCol_ != NULL) delete [] jCol_;
01808 if(jValues_ != NULL) delete [] jValues_;
01809
01810 jRow_ = new Index[nnz_jac];
01811 jCol_ = new Index[nnz_jac];
01812 jValues_ = new Number[nnz_jac];
01813 problem_to_optimize_->eval_jac_g(n, NULL, 0, m, nnz_jac, jRow_, jCol_, NULL);
01814 if(index_style == Ipopt::TNLP::FORTRAN_STYLE)
01815 {
01816 for(int i = 0 ; i < nnz_jac ; i++){
01817 jRow_[i]--;
01818 jCol_[i]--;
01819 }
01820 }
01821
01822 if(constTypes_ != NULL) delete [] constTypes_;
01823
01824
01825 constTypes_ = new TNLP::LinearityType[getNumRows()];
01826 problem_to_optimize_->get_constraints_linearity(getNumRows(), constTypes_);
01827
01828 for(int i = 0; i < getNumRows() ; i++) {
01829 if(constTypes_[i]==TNLP::NON_LINEAR) {
01830
01831 nNonLinear_++;
01832 }
01833 }
01834 return nnz_jac;
01835 }
01836
01837
01838 double
01839 OsiTMINLPInterface::getConstraintsViolation(const double *x, double &obj)
01840 {
01841 int numcols = getNumCols();
01842 int numrows = getNumRows();
01843 double * g = new double[numrows];
01844 tminlp_->eval_g(numcols, x, 1, numrows, g);
01845 const double * rowLower = getRowLower();
01846 const double * rowUpper = getRowUpper();
01847
01848
01849 double norm = 0;
01850 for(int i = 0; i< numrows ; i++) {
01851 if(!constTypes_ || constTypes_[i] == TNLP::NON_LINEAR) {
01852 double rowViolation = 0;
01853 if(rowLower[i] > -1e10)
01854 rowViolation = std::max(0.,rowLower[i] - g[i]);
01855
01856 if(rowUpper[i] < 1e10);
01857 rowViolation = std::max(rowViolation, g[i] - rowUpper[i]);
01858
01859 norm = rowViolation > norm ? rowViolation : norm;
01860 }
01861 }
01862 tminlp_->eval_f(numcols, x, 1, obj);
01863 delete [] g;
01864 return norm;
01865 }
01866
01868 double
01869 OsiTMINLPInterface::getNonLinearitiesViolation(const double *x, const double obj)
01870 {
01871 double f;
01872 double norm = getConstraintsViolation(x, f);
01873 assert((f - obj) > -1e-08);
01874 norm = (f - obj) > norm ? f - obj : norm;
01875 return norm;
01876 }
01877
01878
01879
01880
01881 static inline
01882 bool cleanNnz(double &value, double colLower, double colUpper,
01883 double rowLower, double rowUpper, double colsol,
01884 double & lb, double &ub, double tiny, double veryTiny,
01885 double infty)
01886 {
01887
01888 if(fabs(value)>= tiny) return 1;
01889
01890 if(fabs(value)<veryTiny) return 0;
01891
01892
01893 bool colUpBounded = colUpper < infty;
01894 bool colLoBounded = colLower > -infty;
01895 bool rowNotLoBounded = rowLower <= - infty;
01896 bool rowNotUpBounded = rowUpper >= infty;
01897 bool pos = value > 0;
01898 if(colUpBounded && pos && rowNotUpBounded) {
01899 lb += value * (colsol - colUpper);
01900 return 0;
01901 }
01902 else
01903 if(colUpBounded && !pos && rowNotLoBounded) {
01904 ub += value * (colsol - colUpper);
01905 return 0;
01906 }
01907 else
01908 if(colLoBounded && !pos && rowNotUpBounded) {
01909 lb += value * (colsol - colLower);
01910 return 0;
01911 }
01912 else
01913 if(colLoBounded && pos && rowNotLoBounded) {
01914 ub += value * (colsol - colLower);
01915 return 0;
01916 }
01917
01918 return 1;
01919 }
01920
01923 void
01924 OsiTMINLPInterface::getOuterApproximation(OsiCuts &cs, const double * x,
01925 int getObj, const double * x2,
01926 double theta, bool global)
01927 {
01928 if(IsValid(linearizer_) && x2 == NULL){
01929 linearizer_->get_oas(cs, x, getObj, global);
01930 return;
01931 }
01932 int n,m, nnz_jac_g, nnz_h_lag;
01933 TNLP::IndexStyleEnum index_style;
01934 problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
01935 if(jRow_ == NULL || jCol_ == NULL || jValues_ == NULL)
01936 initializeJacobianArrays();
01937 assert(jRow_ != NULL);
01938 assert(jCol_ != NULL);
01939 vector<double> g(m);
01940 problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
01941 problem_to_optimize_->eval_g(n,x,1,m,g());
01942
01943 vector<CoinPackedVector> cuts(nNonLinear_ + 1);
01944 vector<double> lb(nNonLinear_ + 1);
01945 vector<double> ub(nNonLinear_ + 1);
01946
01947 vector<int> row2cutIdx(m,-1);
01948 int numCuts = 0;
01949
01950 const double * rowLower = getRowLower();
01951 const double * rowUpper = getRowUpper();
01952 const double * colLower = getColLower();
01953 const double * colUpper = getColUpper();
01954 const double * duals = getRowPrice() + 2 * n;
01955 double infty = getInfinity();
01956
01957 for(int rowIdx = 0; rowIdx < m ; rowIdx++) {
01958 if(constTypes_[rowIdx] == TNLP::NON_LINEAR) {
01959 row2cutIdx[rowIdx] = numCuts;
01960 if(rowLower[rowIdx] > - infty_)
01961 lb[numCuts] = rowLower[rowIdx] - g[rowIdx];
01962 else
01963 lb[numCuts] = - infty;
01964 if(rowUpper[rowIdx] < infty_)
01965 ub[numCuts] = rowUpper[rowIdx] - g[rowIdx];
01966 else
01967 ub[numCuts] = infty;
01968 if(rowLower[rowIdx] > -infty && rowUpper[rowIdx] < infty)
01969 {
01970 if(duals[rowIdx] >= 0)
01971 lb[numCuts] = - infty;
01972 if(duals[rowIdx] <= 0)
01973 ub[numCuts] = infty;
01974 }
01975
01976 numCuts++;
01977 }
01978 }
01979
01980
01981 for(int i = 0 ; i < nnz_jac_g ; i++) {
01982 const int &rowIdx = jRow_[i];
01983 const int & cutIdx = row2cutIdx[ rowIdx ];
01984 if(cutIdx != -1) {
01985 const int &colIdx = jCol_[i];
01986
01987 if(cleanNnz(jValues_[i],colLower[colIdx], colUpper[colIdx],
01988 rowLower[rowIdx], rowUpper[rowIdx],
01989 x[colIdx],
01990 lb[cutIdx],
01991 ub[cutIdx], tiny_, veryTiny_, infty_)) {
01992 cuts[cutIdx].insert(colIdx,jValues_[i]);
01993 if(lb[cutIdx] > - infty)
01994 lb[cutIdx] += jValues_[i] * x[colIdx];
01995 if(ub[cutIdx] < infty)
01996 ub[cutIdx] += jValues_[i] * x[colIdx];
01997 }
01998 }
01999 }
02000
02001 vector<int> cut2rowIdx(0);
02002 if (IsValid(cutStrengthener_) || oaHandler_->logLevel() > 0) {
02003 cut2rowIdx.resize(numCuts);
02004 for(int rowIdx = 0 ; rowIdx < m ; rowIdx++){
02005 if(row2cutIdx[rowIdx] >= 0){
02006 cut2rowIdx[row2cutIdx[rowIdx]] = rowIdx;
02007 }
02008 }
02009 }
02010
02011 for(int cutIdx = 0; cutIdx < numCuts; cutIdx++) {
02012
02013 if(x2 != NULL) {
02014 double rhs = cuts[cutIdx].dotProduct(x2);
02015 double violation = 0.;
02016 violation = std::max(violation, rhs - ub[cutIdx]);
02017 violation = std::max(violation, lb[cutIdx] - rhs);
02018 if(violation < theta && oaHandler_) {
02019 oaHandler_->message(CUT_NOT_VIOLATED_ENOUGH, oaMessages_)<<cut2rowIdx[cutIdx]<<violation<<CoinMessageEol;
02020 continue;}
02021 if(oaHandler_)
02022 oaHandler_->message(VIOLATED_OA_CUT_GENERATED, oaMessages_)<<cut2rowIdx[cutIdx]<<violation<<CoinMessageEol;
02023 }
02024 OsiRowCut newCut;
02025
02026
02027 if (IsValid(cutStrengthener_)) {
02028 const int& rowIdx = cut2rowIdx[cutIdx];
02029 bool retval =
02030 cutStrengthener_->ComputeCuts(cs, GetRawPtr(tminlp_),
02031 GetRawPtr(problem_), rowIdx,
02032 cuts[cutIdx], lb[cutIdx], ub[cutIdx], g[rowIdx],
02033 rowLower[rowIdx], rowUpper[rowIdx],
02034 n, x, infty);
02035 if (!retval) {
02036 (*messageHandler()) << "error in cutStrengthener_->ComputeCuts\n";
02037
02038 }
02039 }
02040 if(global) {
02041 newCut.setGloballyValidAsInteger(1);
02042 }
02043 if(lb[cutIdx] > infty) lb[cutIdx] -= rhsRelax_*std::max(fabs(lb[cutIdx]), 1.);
02044 if(ub[cutIdx] < infty) ub[cutIdx] += rhsRelax_*std::max(fabs(ub[cutIdx]), 1.);
02045 newCut.setLb(lb[cutIdx]);
02046 newCut.setUb(ub[cutIdx]);
02047 newCut.setRow(cuts[cutIdx]);
02048 if(oaHandler_->logLevel()>2){
02049 oaHandler_->print(newCut);}
02050 cs.insert(newCut);
02051 }
02052
02053 if(getObj == 2 || (getObj && !problem_->hasLinearObjective())) {
02054 vector<double> obj(n);
02055 problem_to_optimize_->eval_grad_f(n, x, 1,obj());
02056 double f;
02057 problem_to_optimize_->eval_f(n, x, 1, f);
02058
02059 CoinPackedVector v;
02060 v.reserve(n);
02061 lb[nNonLinear_] = -f;
02062 ub[nNonLinear_] = -f;
02063
02064 for(int i = 0; i<n ; i++) {
02065 if(cleanNnz(obj[i],colLower[i], colUpper[i],
02066 -getInfinity(), 0,
02067 x[i],
02068 lb[nNonLinear_],
02069 ub[nNonLinear_],tiny_, 1e-15, infty_)) {
02070 v.insert(i,obj[i]);
02071 lb[nNonLinear_] += obj[i] * x[i];
02072 ub[nNonLinear_] += obj[i] * x[i];
02073 }
02074 }
02075 v.insert(n,-1);
02076
02077 bool genCut = true;
02078 if(x2 != NULL) {
02079 double rhs = v.dotProduct(x2);
02080 double violation = std::max(0., rhs - ub[nNonLinear_]);
02081 if(violation < theta) genCut = false;
02082 }
02083 if(genCut) {
02084 if (IsValid(cutStrengthener_)) {
02085 lb[nNonLinear_] = -infty;
02086 bool retval =
02087 cutStrengthener_->ComputeCuts(cs, GetRawPtr(tminlp_),
02088 GetRawPtr(problem_), -1,
02089 v, lb[nNonLinear_], ub[nNonLinear_],
02090 ub[nNonLinear_], -infty, 0.,
02091 n, x, infty);
02092 if (!retval) {
02093 (*handler_)<< "error in cutStrengthener_->ComputeCuts"<<CoinMessageEol;
02094
02095 }
02096 }
02097 OsiRowCut newCut;
02098 if(global)
02099 newCut.setGloballyValidAsInteger(1);
02100
02101 newCut.setRow(v);
02102 newCut.setLb(-COIN_DBL_MAX);
02103 newCut.setUb(ub[nNonLinear_]);
02104 cs.insert(newCut);
02105 }
02106 }
02107 }
02108
02110 void
02111 OsiTMINLPInterface::getBendersCut(OsiCuts &cs,
02112 bool global){
02113 int n,m, nnz_jac_g, nnz_h_lag;
02114 TNLP::IndexStyleEnum index_style;
02115 problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
02116 if(jRow_ == NULL || jCol_ == NULL || jValues_ == NULL)
02117 initializeJacobianArrays();
02118 assert(jRow_ != NULL);
02119 assert(jCol_ != NULL);
02120 vector<double> g(m);
02121 const double * x = getColSolution();
02122 problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
02123 problem_to_optimize_->eval_g(n,x,1,m,g());
02124
02125 vector<double> cut(n+1,0.);
02126 vector<bool> keep(m+1,false);
02127 double lb = 0;
02128 double ub = 0;
02129
02130 const double * rowLower = getRowLower();
02131 const double * rowUpper = getRowUpper();
02132 const double * colLower = getColLower();
02133 const double * colUpper = getColUpper();
02134 const double * duals = getRowPrice() + 2 * n;
02135
02136
02137 for(int rowIdx = 0; rowIdx < m ; rowIdx++) {
02138 if(constTypes_[rowIdx] == TNLP::NON_LINEAR && fabs(duals[rowIdx]) > 1e-06)
02139 {
02140 const double & lam = duals[rowIdx];
02141 keep[rowIdx] = true;
02142 assert(lam < 0 || rowUpper[rowIdx] < 1e10);
02143 assert(lam > 0 || rowLower[rowIdx] > -1e10);
02144 if(lam < 0){
02145 assert(rowLower[rowIdx] > -1e10);
02146 ub += lam*(rowLower[rowIdx] -g[rowIdx]);
02147 }
02148 else {
02149 assert(rowUpper[rowIdx] < 1e10);
02150 ub += lam*(rowUpper[rowIdx] -g[rowIdx]);
02151 }
02152 }
02153 }
02154
02155
02156 for(int i = 0 ; i < nnz_jac_g ; i++) {
02157 const int &rowIdx = jRow_[i];
02158 if (!keep[rowIdx]) continue;
02159 const int &colIdx = jCol_[i];
02160
02161 const double & lam = duals[rowIdx];
02162 double coeff = lam*jValues_[i];
02163 if(cleanNnz(coeff,colLower[colIdx], colUpper[colIdx],
02164 rowLower[rowIdx], rowUpper[rowIdx], x[colIdx], lb,
02165 ub, tiny_, veryTiny_, infty_)) {
02166 cut[colIdx] += coeff;
02167 ub += coeff * x[colIdx];
02168 }
02169 }
02170
02171 CoinPackedVector v;
02172 if(!problem_->hasLinearObjective() &&
02173 isProvenOptimal()) {
02174 vector<double> obj(n);
02175 problem_to_optimize_->eval_grad_f(n, x, 1,obj());
02176 double f;
02177 problem_to_optimize_->eval_f(n, x, 1, f);
02178
02179 ub = -f;
02180
02181 for(int i = 0; i<n ; i++) {
02182 if(cleanNnz(obj[i],colLower[i], colUpper[i], -getInfinity(), 0,
02183 x[i], lb, ub,tiny_, 1e-15, infty_)) {
02184 cut[i] += obj[i];
02185 ub += obj[i] * x[i];
02186 }
02187 }
02188 v.insert(n,-1);
02189 }
02190 for(int i = 0 ; i < n ; i++){
02191 if(fabs(cut[i])>1e-020){
02192 v.insert(i, cut[i]);
02193 }
02194 }
02195 OsiRowCut newCut;
02196 if(global)
02197 newCut.setGloballyValidAsInteger(1);
02198 newCut.setLb(-COIN_DBL_MAX);
02199 newCut.setUb(ub);
02200 newCut.setRow(v);
02201 cs.insert(newCut);
02202 }
02203
02206 void
02207 OsiTMINLPInterface::getConstraintOuterApproximation(OsiCuts &cs, int rowIdx,
02208 const double * x,
02209 const double * x2, bool global)
02210 {
02211 double g;
02212 int * indices = new int[getNumCols()];
02213 double * values = new double[getNumCols()];
02214 int nnz;
02215 problem_->eval_grad_gi(getNumCols(), x, 1, rowIdx, nnz, indices, values);
02216 problem_->eval_gi(getNumCols(),x,1, rowIdx, g);
02217
02218 CoinPackedVector cut;
02219 double lb;
02220 double ub;
02221
02222
02223 const double rowLower = getRowLower()[rowIdx];
02224 const double rowUpper = getRowUpper()[rowIdx];
02225 const double * colLower = getColLower();
02226 const double * colUpper = getColUpper();
02227 const double dual = (getRowPrice() + 2 * getNumCols())[rowIdx];
02228 double infty = getInfinity();
02229
02230 if(rowLower > - infty_)
02231 lb = rowLower - g;
02232 else
02233 lb = - infty;
02234 if(rowUpper < infty_)
02235 ub = rowUpper - g;
02236 else
02237 ub = infty;
02238 if(rowLower > -infty && rowUpper < infty)
02239 {
02240 if(dual >= 0)
02241 lb = - infty;
02242 if(dual <= 0)
02243 ub = infty;
02244 }
02245
02246 for(int i = 0 ; i < nnz; i++) {
02247 const int &colIdx = indices[i];
02248
02249 if(cleanNnz(values[i],colLower[colIdx], colUpper[colIdx],
02250 rowLower, rowUpper,
02251 x[colIdx],
02252 lb,
02253 ub, tiny_, veryTiny_, infty_)) {
02254 cut.insert(colIdx,values[i]);
02255 if(lb > - infty)
02256 lb += values[i] * x[colIdx];
02257 if(ub < infty)
02258 ub += values[i] * x[colIdx];
02259 }
02260 }
02261
02262 OsiRowCut newCut;
02263
02264 if(global) {
02265 newCut.setGloballyValidAsInteger(1);
02266 }
02267
02268 newCut.setLb(lb);
02269 newCut.setUb(ub);
02270 newCut.setRow(cut);
02271 cs.insert(newCut);
02272
02273 delete [] indices;
02274 delete [] values;
02275 }
02276
02277 void
02278 OsiTMINLPInterface::switchToFeasibilityProblem(size_t n,const double * x_bar,const int *inds,
02279 double a, double s, int L){
02280 if(! IsValid(feasibilityProblem_)) {
02281 throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
02282 }
02283 feasibilityProblem_->set_use_feasibility_pump_objective(true);
02284 feasibilityProblem_->set_dist_to_point_obj(n,(const Number *) x_bar,(const Index *) inds);
02285 feasibilityProblem_->setLambda(a);
02286 feasibilityProblem_->setSigma(s);
02287 feasibilityProblem_->setNorm(L);
02288 feasibilityProblem_->set_use_cutoff_constraint(false);
02289 feasibilityProblem_->set_use_local_branching_constraint(false);
02290 problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
02291 feasibility_mode_ = true;
02292 }
02293
02294 void
02295 OsiTMINLPInterface::switchToFeasibilityProblem(size_t n,const double * x_bar,const int *inds,
02296 double rhs_local_branching_constraint){
02297 if(! IsValid(feasibilityProblem_)) {
02298 throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
02299 }
02300 feasibilityProblem_->set_use_feasibility_pump_objective(false);
02301 feasibilityProblem_->set_dist_to_point_obj(n,(const Number *) x_bar,(const Index *) inds);
02302 feasibilityProblem_->set_use_cutoff_constraint(false);
02303 feasibilityProblem_->set_use_local_branching_constraint(true);
02304 feasibilityProblem_->set_rhs_local_branching_constraint(rhs_local_branching_constraint);
02305 problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
02306 feasibility_mode_ = true;
02307 }
02308
02309 void
02310 OsiTMINLPInterface::switchToOriginalProblem(){
02311 problem_to_optimize_ = GetRawPtr(problem_);
02312 feasibility_mode_ = false;
02313 }
02314
02315 double
02316 OsiTMINLPInterface::solveFeasibilityProblem(size_t n,const double * x_bar,const int *inds,
02317 double a, double s, int L)
02318 {
02319 if(! IsValid(feasibilityProblem_)) {
02320 throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
02321 }
02322 feasibilityProblem_->set_use_feasibility_pump_objective(true);
02323 feasibilityProblem_->set_dist_to_point_obj(n,(const Number *) x_bar,(const Index *) inds);
02324 feasibilityProblem_->setLambda(a);
02325 feasibilityProblem_->setSigma(s);
02326 feasibilityProblem_->setNorm(L);
02327 feasibilityProblem_->set_use_cutoff_constraint(false);
02328 feasibilityProblem_->set_use_local_branching_constraint(false);
02329 nCallOptimizeTNLP_++;
02330 totalNlpSolveTime_-=CoinCpuTime();
02331 SmartPtr<TNLPSolver> app2 = app_->clone();
02332 app2->options()->SetIntegerValue("print_level", (Index) 0);
02333 optimizationStatus_ = app2->OptimizeTNLP(GetRawPtr(feasibilityProblem_));
02334 totalNlpSolveTime_+=CoinCpuTime();
02335 hasBeenOptimized_=true;
02336 return getObjValue();
02337 }
02338
02339 double
02340 OsiTMINLPInterface::solveFeasibilityProblem(size_t n,const double * x_bar,const int *inds,
02341 int L, double cutoff)
02342 {
02343 if(! IsValid(feasibilityProblem_)) {
02344 throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
02345 }
02346 feasibilityProblem_->set_use_feasibility_pump_objective(true);
02347 feasibilityProblem_->set_dist_to_point_obj(n,(const Number *) x_bar,(const Index *) inds);
02348 feasibilityProblem_->setLambda(1.0);
02349 feasibilityProblem_->setSigma(0.0);
02350 feasibilityProblem_->setNorm(L);
02351 feasibilityProblem_->set_use_cutoff_constraint(true);
02352 feasibilityProblem_->set_cutoff(cutoff);
02353 feasibilityProblem_->set_use_local_branching_constraint(false);
02354 nCallOptimizeTNLP_++;
02355 totalNlpSolveTime_-=CoinCpuTime();
02356 SmartPtr<TNLPSolver> app2 = app_->clone();
02357 app2->options()->SetIntegerValue("print_level", (Index) 0);
02358 optimizationStatus_ = app2->OptimizeTNLP(GetRawPtr(feasibilityProblem_));
02359 totalNlpSolveTime_+=CoinCpuTime();
02360 hasBeenOptimized_=true;
02361 return getObjValue();
02362 }
02363
02364 #if 0
02365 double
02366 OsiTMINLPInterface::getFeasibilityOuterApproximation(int n,const double * x_bar,const int *inds, OsiCuts &cs, bool addOnlyViolated, bool global)
02367 {
02368 double ret_val = solveFeasibilityProblem(n, x_bar, inds, 1, 0, 2);
02369 getOuterApproximation(cs, getColSolution(), 0, (addOnlyViolated? x_bar:NULL)
02370 , global);
02371 return ret_val;
02372 }
02373 #endif
02374
02375 static bool WarnedForNonConvexOa=false;
02376
02377 void
02378 OsiTMINLPInterface::extractLinearRelaxation(OsiSolverInterface &si,
02379 const double * x, bool getObj
02380 )
02381 {
02382 if(IsValid(linearizer_)){
02383 linearizer_->extract(&si, x, getObj);
02384 return;
02385 }
02386 int n;
02387 int m;
02388 int nnz_jac_g;
02389 int nnz_h_lag;
02390 TNLP::IndexStyleEnum index_style;
02391
02392 problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
02393
02394
02395
02396 initializeJacobianArrays();
02397
02398
02399 problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
02400
02401
02402 vector<double> g(m);
02403 problem_to_optimize_->eval_g(n, x, 1, m, g());
02404
02405 vector<double> rowLow(m);
02406 vector<double> rowUp(m);
02407 vector<int> nonBindings(m);;
02408 int numNonBindings = 0;
02409 const double * rowLower = getRowLower();
02410 const double * rowUpper = getRowUpper();
02411 vector<double> colLower(n);
02412 vector<double> colUpper(n);
02413 std::copy(getColLower(), getColLower() + n, colLower.begin());
02414 std::copy(getColUpper(), getColUpper() + n, colUpper.begin());
02415 const double * duals = getRowPrice() + 2*n;
02416 assert(m==getNumRows());
02417 double infty = si.getInfinity();
02418 for(int i = 0 ; i < m ; i++) {
02419 if(constTypes_[i] == TNLP::NON_LINEAR) {
02420
02421 if(rowLower[i] > -infty_ && rowUpper[i] < infty_ && fabs(duals[i]) == 0.)
02422 {
02423 nonBindings[numNonBindings++] = i;
02424 continue;
02425 }
02426 else
02427 if(rowLower[i] > - infty_){
02428 rowLow[i] = (rowLower[i] - g[i]) - 1e-07;
02429 if(! WarnedForNonConvexOa && rowUpper[i] < infty_){
02430 messageHandler()->message(WARNING_NON_CONVEX_OA, messages_)<<CoinMessageEol;
02431 WarnedForNonConvexOa = true;
02432 }
02433 }
02434 else
02435 rowLow[i] = - infty;
02436 if(rowUpper[i] < infty_)
02437 rowUp[i] = (rowUpper[i] - g[i]) + 1e-07;
02438 else
02439 rowUp[i] = infty;
02440
02441
02442 if(rowLower[i] > -infty_ && rowUpper[i] < infty_)
02443 {
02444 if(duals[i] >= 0.)
02445 rowLow[i] = - infty;
02446 if(duals[i] <= 0.)
02447 rowUp[i] = infty;
02448 }
02449 }
02450 else {
02451 if(rowLower[i] > -infty_){
02452 rowLow[i] = (rowLower[i]);
02453 }
02454 else
02455 rowLow[i] = - infty;
02456 if(rowUpper[i] < infty_){
02457 rowUp[i] = (rowUpper[i]);
02458 }
02459 else
02460 rowUp[i] = infty;
02461 }
02462 }
02463
02464
02465
02466
02467
02468 for(int i = 0 ; i < nnz_jac_g ; i++) {
02469 if(constTypes_[jRow_[i]] != TNLP::LINEAR){
02470 if(
02471 cleanNnz(jValues_[i],colLower[jCol_[i]], colUpper[jCol_[i]],
02472 rowLower[jRow_[i]], rowUpper[jRow_[i]],
02473 x[jCol_[i]],
02474 rowLow[jRow_[i]],
02475 rowUp[jRow_[i]], tiny_, veryTiny_, infty_)) {
02476 if(rowLow[jRow_[i]] > - infty)
02477 rowLow[jRow_[i]] += jValues_[i] * x[jCol_ [i]];
02478 if(rowUp[jRow_[i]] < infty)
02479 rowUp[jRow_[i]] += jValues_[i] *x[jCol_[i]];
02480 }
02481 }
02482 else {
02483
02484
02485
02486 }
02487 }
02488
02489
02490 CoinPackedMatrix mat(true, jRow_, jCol_, jValues_, nnz_jac_g);
02491 mat.setDimensions(m,n);
02492
02493
02494 mat.deleteRows(numNonBindings, nonBindings());
02495
02496 int numcols=getNumCols();
02497 vector<double> obj(numcols);
02498 for(int i = 0 ; i < numcols ; i++){
02499 obj[i] = 0.;
02500 if(colLower[i] <= - infty_) colLower[i] = - infty;
02501 if(colUpper[i] >= infty_) colUpper[i] = infty;
02502 }
02503
02504
02505
02506 for(int i = 0 ; i < rowLow.size() ; i++){
02507 if(rowLow[i] > infty) rowLow[i] -= rhsRelax_*std::max(fabs(rowLow[i]), 1.);
02508 if(rowUp[i] < infty) rowUp[i] += rhsRelax_*std::max(fabs(rowUp[i]), 1.);
02509 }
02510
02511 si.loadProblem(mat, colLower(), colUpper(), obj(), rowLow(), rowUp());
02512 for(int i = 0 ; i < numcols ; i++) {
02513 if(isInteger(i))
02514 si.setInteger(i);
02515 }
02516 if(getObj) {
02517 bool addObjVar = false;
02518 if(problem_->hasLinearObjective()){
02519 double zero;
02520 vector<double> x0(n,0.);
02521 problem_to_optimize_->eval_f(n, x0(), 1, zero);
02522 si.setDblParam(OsiObjOffset, -zero);
02523
02524 problem_to_optimize_->eval_grad_f(n, x, 1,obj());
02525 si.setObjective(obj());
02526 }
02527 else {
02528 addObjVar = true;
02529 }
02530
02531 if(addObjVar){
02532 addObjectiveFunction(si, x);
02533 }
02534 }
02535
02536
02537 }
02538
02539 void
02540 OsiTMINLPInterface::addObjectiveFunction(OsiSolverInterface &si,
02541 const double *x){
02542 const double * colLower = getColLower();
02543 const double * colUpper = getColUpper();
02544 int numcols = getNumCols();
02545 assert(numcols == si.getNumCols() );
02546 vector<double> obj(numcols);
02547 problem_to_optimize_->eval_grad_f(numcols, x, 1,obj());
02548
02549
02550 CoinPackedVector a;
02551 si.addCol(a,-si.getInfinity(), si.getInfinity(), 1.);
02552
02553
02554
02555 double ub;
02556 problem_to_optimize_->eval_f(numcols, x, 1, ub);
02557 ub*=-1;
02558 double lb = -1e300;
02559 CoinPackedVector objCut;
02560 CoinPackedVector * v = &objCut;
02561 v->reserve(numcols+1);
02562 for(int i = 0; i<numcols ; i++) {
02563 if(si.getNumRows())
02564 {
02565 if(cleanNnz(obj[i],colLower[i], colUpper[i],
02566 -getInfinity(), 0,
02567 x[i],
02568 lb,
02569 ub, tiny_, veryTiny_, infty_)) {
02570 v->insert(i,obj[i]);
02571 lb += obj[i] * x[i];
02572 ub += obj[i] * x[i];
02573 }
02574 }
02575 else
02576 {
02577 if(cleanNnz(obj[i],colLower[i], colUpper[i],
02578 -getInfinity(), 0,
02579 x[i],
02580 lb,
02581 ub, 1e-03, 1e-08, infty_)) {
02582 v->insert(i,obj[i]);
02583 lb += obj[i] * x[i];
02584 ub += obj[i] * x[i];
02585 }
02586 }
02587 }
02588 v->insert(numcols,-1);
02589 si.addRow(objCut, lb, ub);
02590 }
02591
02593 void
02594 OsiTMINLPInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts)
02595 {
02596 if(numberCuts)
02597 freeCachedRowRim();
02598 const OsiRowCut ** cutsPtrs = new const OsiRowCut*[numberCuts];
02599 for(int i = 0 ; i < numberCuts ; i++)
02600 {
02601 cutsPtrs[i] = &cuts[i];
02602 }
02603 problem_->addCuts(numberCuts, cutsPtrs);
02604 delete [] cutsPtrs;
02605 }
02606
02607 void
02608 OsiTMINLPInterface::solveAndCheckErrors(bool warmStarted, bool throwOnFailure,
02609 const char * whereFrom)
02610 {
02611 totalNlpSolveTime_-=CoinCpuTime();
02612 if(warmStarted)
02613 optimizationStatus_ = app_->ReOptimizeTNLP(GetRawPtr(problem_to_optimize_));
02614 else
02615 optimizationStatus_ = app_->OptimizeTNLP(GetRawPtr(problem_to_optimize_));
02616 totalNlpSolveTime_+=CoinCpuTime();
02617 nCallOptimizeTNLP_++;
02618 hasBeenOptimized_ = true;
02619
02620 if(getRowCutDebugger()){
02621
02622 if(! (isProvenOptimal() && getObjValue() <= getRowCutDebugger()->optimalValue())){
02623 std::string probName;
02624 getStrParam(OsiProbName, probName);
02625 fprintf(stderr, "Problem on optimal path is infeasible!\n");
02626 throw newUnsolvedError(app_->errorCode(), problem_, probName);
02627 }
02628 }
02629
02630
02631 if(!hasPrintedOptions) {
02632 hasPrintedOptions = 1;
02633
02634 app_->options()->SetStringValue("print_user_options","no", false, true);
02635 }
02636
02637 bool otherDisagree = false ;
02638 if(!app_->isRecoverable(optimizationStatus_))
02639 {
02640 std::string probName;
02641 getStrParam(OsiProbName, probName);
02642 throw newUnsolvedError(app_->errorCode(), problem_, probName);
02643 }
02644 else if(testOthers_ && !app_->isError(optimizationStatus_)){
02645 Ipopt::SmartPtr<TMINLP2TNLP> problem_copy = problem_->clone();
02646
02647 int f =1;
02648 for(std::list<Ipopt::SmartPtr<TNLPSolver> >::iterator i = debug_apps_.begin();
02649 i != debug_apps_.end() ; i++){
02650 TNLPSolver::ReturnStatus otherStatus = (*i)->OptimizeTNLP(GetRawPtr(problem_copy));
02651 messageHandler()->message(LOG_LINE, messages_)
02652 <<'d'<<f++<<statusAsString(otherStatus)<<problem_copy->obj_value()
02653 <<(*i)->IterationCount()<<(*i)->CPUTime()<<"retry with "+(*i)->solverName()<<CoinMessageEol;
02654 if(!(*i)->isError(otherStatus)){
02655 CoinRelFltEq eq(1e-05);
02656 if(otherStatus != optimizationStatus_){
02657 otherDisagree = true;
02658 messageHandler()->message(SOLVER_DISAGREE_STATUS, messages_)
02659 <<app_->solverName()<<statusAsString()
02660 <<(*i)->solverName()<<statusAsString(otherStatus)<<CoinMessageEol;
02661 }
02662 else if(isProvenOptimal() && !eq(problem_->obj_value(),problem_copy->obj_value()))
02663 {
02664 otherDisagree = true;
02665 messageHandler()->message(SOLVER_DISAGREE_VALUE, messages_)
02666 <<app_->solverName()<<problem_->obj_value()
02667 <<(*i)->solverName()<<problem_copy->obj_value()<<CoinMessageEol;
02668 }
02669 }
02670 }
02671 }
02672 else if(app_->isError(optimizationStatus_) && ! debug_apps_.empty()){
02673 int f =1;
02674 for(std::list<Ipopt::SmartPtr<TNLPSolver> >::iterator i = debug_apps_.begin();
02675 i != debug_apps_.end() && app_->isError(optimizationStatus_) ; i++){
02676 optimizationStatus_ = (*i)->OptimizeTNLP(GetRawPtr(problem_));
02677 messageHandler()->message(LOG_LINE, messages_)
02678 <<'d'<<f++<<statusAsString(optimizationStatus_)<<problem_->obj_value()
02679 <<(*i)->IterationCount()<<(*i)->CPUTime()<<"retry with "+(*i)->solverName()<<CoinMessageEol;
02680 }
02681 }
02682 try{
02683 totalIterations_ += app_->IterationCount();
02684 }
02685 catch(SimpleError &E)
02686 {
02687 if (throwOnFailure)
02688 {
02689 throw SimpleError("No statistics available from Ipopt",whereFrom);
02690 }
02691 else {
02692 return;
02693 }
02694 }
02695 if(problem_->hasUpperBoundingObjective()){
02696 const double * sol = getColSolution();
02697 bool integerSol = true;
02698 double intTol = 1e-08;
02699 if(objects()){
02700 int nObjects = numberObjects();
02701 OsiObject ** object = objects();
02702 for(int i = 0 ; i< nObjects ; i++){
02703 int dummy;
02704 if(object[i]->infeasibility(this,dummy) > intTol)
02705 {
02706 integerSol=false;
02707 break;
02708 }
02709 }
02710 }
02711 else{
02712 int numcols = getNumCols();
02713 for(int i = 0 ; i < numcols ; i++){
02714 if(isInteger(i) || isBinary(i)){
02715 if(fabs(sol[i] - floor(sol[i]+0.5)) > intTol){
02716 integerSol = false;
02717 break;
02718 }
02719 }
02720 }
02721 }
02722 if(integerSol&&isProvenOptimal()){
02723 double help= problem_->evaluateUpperBoundingFunction(sol);
02724
02725
02726 OsiAuxInfo * auxInfo = getAuxiliaryInfo();
02727 Bonmin::AuxInfo * bonInfo = dynamic_cast<Bonmin::AuxInfo *>(auxInfo);
02728 if(bonInfo!=0)
02729 {
02730
02731 if(help<bonInfo->bestObj2())
02732 {
02733 bonInfo->setBestObj2(help);
02734 bonInfo->setBestSolution2(getNumCols(), const_cast<double *>(getColSolution()));
02735
02736 messageHandler()->message(ALTERNATE_OBJECTIVE, messages_)
02737 <<help<<CoinMessageEol;
02738 }
02739 }
02740 else {
02741 printf("\nWARNING: the algorithm selected does not consider the second objective function\n");
02742 }
02743 }
02744 }
02745
02746 messageHandler()->message(IPOPT_SUMMARY, messages_)
02747 <<whereFrom<<optimizationStatus_<<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
02748
02749 if((nCallOptimizeTNLP_ % 20) == 1)
02750 messageHandler()->message(LOG_HEAD, messages_)<<CoinMessageEol;
02751
02752
02753 if ( (numIterationSuspect_ >= 0 && (getIterationCount()>numIterationSuspect_ || isAbandoned())) ||
02754 ( otherDisagree )){
02755 messageHandler()->message(SUSPECT_PROBLEM,
02756 messages_)<<nCallOptimizeTNLP_<<CoinMessageEol;
02757 std::string subProbName;
02758 getStrParam(OsiProbName, subProbName);
02759 std::ostringstream os;
02760 os<<"_"<<nCallOptimizeTNLP_;
02761 subProbName+=os.str();
02762 problem_->outputDiffs(subProbName, NULL);
02763 }
02764
02765 }
02766
02768
02770 void OsiTMINLPInterface::initialSolve()
02771 {
02772 initialSolve("");
02773 }
02774
02776
02778 void OsiTMINLPInterface::initialSolve(const char * whereFrom)
02779 {
02780 assert(IsValid(app_));
02781 assert(IsValid(problem_));
02782
02783
02784 delete warmstart_;
02785 warmstart_ = NULL;
02786
02787 if(!hasPrintedOptions) {
02788 int printOptions;
02789 app_->options()->GetEnumValue("print_user_options",printOptions,app_->prefix());
02790 if(printOptions)
02791 app_->options()->SetStringValue("print_user_options","yes",true,true);
02792 }
02793 if(warmStartMode_ >= Optimum)
02794 app_->disableWarmStart();
02795 solveAndCheckErrors(0,1,"initialSolve");
02796
02797
02798 if(!hasPrintedOptions) {
02799 hasPrintedOptions = 1;
02800 app_->options()->SetStringValue("print_user_options","no");
02801 app_->options()->SetIntegerValue("print_level",0);
02802 }
02803
02804 messageHandler()->message(LOG_LINE, messages_)<<' '<<nCallOptimizeTNLP_
02805 <<statusAsString()
02806 <<getObjValue()
02807 <<app_->IterationCount()
02808 <<app_->CPUTime()
02809 <<whereFrom<<CoinMessageEol;
02810
02811 int numRetry = firstSolve_ ? numRetryInitial_ : numRetryResolve_;
02812 if(isAbandoned() ||
02813 ( isProvenPrimalInfeasible() && getObjValue() < infeasibility_epsilon_)) {
02814 resolveForRobustness(numRetryUnsolved_);
02815 }
02816 else if(numRetry)
02817 {
02818 resolveForCost(numRetry, numRetryInitial_ > 0);
02820 numRetryInitial_ = 0;
02821 }
02822 firstSolve_ = false;
02823
02824
02825
02826 if (! warmstart_ && ! isAbandoned()) {
02827 if (warmStartMode_ >= Optimum) {
02828 warmstart_ = app_->getWarmStart(problem_);
02829 }
02830 }
02831 }
02832
02834 void
02835 OsiTMINLPInterface::resolve(){
02836 resolve("");
02837 }
02840 void
02841 OsiTMINLPInterface::resolve(const char * whereFrom)
02842 {
02843 assert(IsValid(app_));
02844 assert(IsValid(problem_));
02845 int has_warmstart = warmstart_ == NULL ? 0 : 1;
02846 if(warmstart_ == NULL) has_warmstart = 0;
02847 else if(!app_->warmStartIsValid(warmstart_)) has_warmstart = 1;
02848 else has_warmstart = 2;
02849 if (has_warmstart < 2) {
02850
02851 initialSolve(whereFrom);
02852 return;
02853 }
02854 app_->setWarmStart(warmstart_, problem_);
02855 delete warmstart_;
02856 warmstart_ = NULL;
02857
02858 if (INT_BIAS > 0.) {
02859 app_->options()->SetStringValue("warm_start_same_structure", "yes");
02860 }
02861 else {
02862 app_->options()->SetStringValue("warm_start_same_structure", "no");
02863 }
02864
02865 if(problem_->duals_init() != NULL)
02866 app_->enableWarmStart();
02867 else app_->disableWarmStart();
02868 solveAndCheckErrors(1,1,"resolve");
02869
02870 messageHandler()->message(LOG_LINE, messages_)<<' '<<nCallOptimizeTNLP_
02871 <<statusAsString()
02872 <<getObjValue()
02873 <<app_->IterationCount()
02874 <<app_->CPUTime()
02875 <<whereFrom
02876 <<"totot"
02877 <<CoinMessageEol;
02878
02879 if(isAbandoned() ||
02880 ( (getObjValue() < 1e-06) && isProvenPrimalInfeasible())) {
02881 resolveForRobustness(numRetryUnsolved_);
02882 }
02883 else if(numRetryResolve_ ||
02884 (numRetryInfeasibles_ && isProvenPrimalInfeasible() ))
02885 resolveForCost(std::max(numRetryResolve_, numRetryInfeasibles_), 0);
02886
02887
02888
02889 if (! warmstart_ && ! isAbandoned()) {
02890 if (warmStartMode_ >= Optimum) {
02891 warmstart_ = app_->getWarmStart(problem_);
02892 }
02893 }
02894 }
02895
02896
02898
02901 bool OsiTMINLPInterface::isAbandoned() const
02902 {
02903 if (pretendSucceededNext_)
02904 return false;
02905 pretendSucceededNext_ = false;
02906 return (
02907 (optimizationStatus_==TNLPSolver::iterationLimit)||
02908 (optimizationStatus_==TNLPSolver::computationError)||
02909 (optimizationStatus_==TNLPSolver::illDefinedProblem)||
02910 (optimizationStatus_==TNLPSolver::illegalOption)||
02911 (optimizationStatus_==TNLPSolver::externalException)|
02912 (optimizationStatus_==TNLPSolver::exception)
02913 );
02914 }
02915
02917 bool OsiTMINLPInterface::isProvenOptimal() const
02918 {
02919 return (optimizationStatus_==TNLPSolver::solvedOptimal) ||
02920 (optimizationStatus_==TNLPSolver::solvedOptimalTol);
02921 }
02923 bool OsiTMINLPInterface::isProvenPrimalInfeasible() const
02924 {
02925 return (optimizationStatus_ == TNLPSolver::provenInfeasible);
02926 }
02928 bool OsiTMINLPInterface::isProvenDualInfeasible() const
02929 {
02930 return (optimizationStatus_ == TNLPSolver::unbounded);
02931 }
02933 bool OsiTMINLPInterface::isPrimalObjectiveLimitReached() const
02934 {
02935 (*handler_)<<"Warning : isPrimalObjectiveLimitReached not implemented yet"<<CoinMessageEol;
02936 return 0;
02937 }
02939 bool OsiTMINLPInterface::isDualObjectiveLimitReached() const
02940 {
02941
02942 return (optimizationStatus_==TNLPSolver::unbounded);
02943
02944 }
02946 bool OsiTMINLPInterface::isIterationLimitReached() const
02947 {
02948 return (optimizationStatus_==TNLPSolver::iterationLimit);
02949 }
02950
02951 void
02952 OsiTMINLPInterface::extractInterfaceParams()
02953 {
02954 if (IsValid(app_)) {
02955 int logLevel;
02956 app_->options()->GetIntegerValue("nlp_log_level", logLevel,app_->prefix());
02957 messageHandler()->setLogLevel(logLevel);
02958
02959 #ifdef COIN_HAS_FILTERSQP
02960 FilterSolver * filter = dynamic_cast<FilterSolver *>(GetRawPtr(app_));
02961
02962 bool is_given =
02963 #endif
02964 app_->options()->GetNumericValue("max_random_point_radius",maxRandomRadius_,app_->prefix());
02965
02966 #ifdef COIN_HAS_FILTERSQP
02967 if(filter && !is_given){
02968
02969 maxRandomRadius_ = 10.;
02970 }
02971 #endif
02972
02973 int oaCgLogLevel = 0;
02974 app_->options()->GetIntegerValue("oa_cuts_log_level", oaCgLogLevel,app_->prefix());
02975 oaHandler_->setLogLevel(oaCgLogLevel);
02976
02977 int buffy;
02978 app_->options()->GetEnumValue("warm_start", buffy, app_->prefix());
02979 warmStartMode_ = (WarmStartModes) buffy;
02980
02981 app_->options()->GetIntegerValue("num_retry_unsolved_random_point", numRetryUnsolved_,app_->prefix());
02982 app_->options()->GetIntegerValue("num_resolve_at_root", numRetryInitial_,app_->prefix());
02983 app_->options()->GetIntegerValue("num_resolve_at_node", numRetryResolve_,app_->prefix());
02984 app_->options()->GetIntegerValue("num_resolve_at_infeasibles", numRetryInfeasibles_,app_->prefix());
02985 app_->options()->GetIntegerValue("num_iterations_suspect", numIterationSuspect_,app_->prefix());
02986 app_->options()->GetEnumValue("nlp_failure_behavior",pretendFailIsInfeasible_,app_->prefix());
02987 app_->options()->GetNumericValue
02988 ("warm_start_bound_frac" ,pushValue_,app_->prefix());
02989 app_->options()->GetNumericValue("tiny_element",tiny_,app_->prefix());
02990 app_->options()->GetNumericValue("very_tiny_element",veryTiny_,app_->prefix());
02991 app_->options()->GetNumericValue("oa_rhs_relax",rhsRelax_,app_->prefix());
02992 app_->options()->GetNumericValue("random_point_perturbation_interval",max_perturbation_,app_->prefix());
02993 app_->options()->GetEnumValue("random_point_type",randomGenerationType_,app_->prefix());
02994 int cut_strengthening_type;
02995 app_->options()->GetEnumValue("cut_strengthening_type", cut_strengthening_type,app_->prefix());
02996 double lo_inf, up_inf;
02997 app_->options()->GetNumericValue("nlp_lower_bound_inf",lo_inf, app_->prefix());
02998 app_->options()->GetNumericValue("nlp_upper_bound_inf",up_inf, app_->prefix());
02999 infty_ = std::min(fabs(lo_inf), fabs(up_inf));
03000
03001 #ifdef COIN_HAS_FILTERSQP
03002 is_given =
03003 #endif
03004 app_->options()->GetNumericValue("resolve_on_small_infeasibility", infeasibility_epsilon_, app_->prefix());
03005
03006 #ifdef COIN_HAS_FILTERSQP
03007 if(filter && !is_given){
03008
03009 infeasibility_epsilon_ = 1e-06;
03010 std::string o_name = app_->prefix();
03011 o_name += "resolve_on_small_infeasibility";
03012 app_->options()->SetNumericValue(o_name.c_str(), infeasibility_epsilon_, true, true);
03013 }
03014 #endif
03015 if (cut_strengthening_type != CS_None) {
03016
03017 cutStrengthener_ = new CutStrengthener(app_->clone(), app_->options());
03018 }
03019 }
03020 }
03021
03022 void
03023 OsiTMINLPInterface::SetStrongBrachingSolver(SmartPtr<StrongBranchingSolver> strong_branching_solver)
03024 {
03025 strong_branching_solver_ = strong_branching_solver;
03026 }
03027
03028
03029 #ifdef STRONG_COMPARE
03030 static double objorig;
03031 #endif
03032
03033 void
03034 OsiTMINLPInterface::markHotStart()
03035 {
03036 if (IsValid(strong_branching_solver_)) {
03037 #ifdef STRONG_COMPARE
03038
03039 OsiSolverInterface::markHotStart();
03040 objorig = getObjValue();
03041 #endif
03042 optimizationStatusBeforeHotStart_ = optimizationStatus_;
03043 strong_branching_solver_->markHotStart(this);
03044 }
03045 else {
03046
03047 OsiSolverInterface::markHotStart();
03048 }
03049 }
03050
03051 void
03052 OsiTMINLPInterface::solveFromHotStart()
03053 {
03054 if (IsValid(strong_branching_solver_)) {
03055 #ifdef STRONG_COMPARE
03056
03057 OsiSolverInterface::solveFromHotStart();
03058 double obj_nlp = getObjValue() - objorig;
03059 #endif
03060 optimizationStatus_ = strong_branching_solver_->solveFromHotStart(this);
03061 hasBeenOptimized_ = true;
03062 #ifdef STRONG_COMPARE
03063 double obj_other = getObjValue() - objorig;
03064 printf("AWDEBUG: Strong Branching results: NLP = %15.8e Other = %15.8e\n",
03065 obj_nlp, obj_other);
03066 #endif
03067 }
03068 else {
03069
03070 OsiSolverInterface::solveFromHotStart();
03071 }
03072 }
03073
03074 void
03075 OsiTMINLPInterface::unmarkHotStart()
03076 {
03077 if (IsValid(strong_branching_solver_)) {
03078 #ifdef STRONG_COMPARE
03079
03080 OsiSolverInterface::unmarkHotStart();
03081 #endif
03082 strong_branching_solver_->unmarkHotStart(this);
03083 optimizationStatus_ = optimizationStatusBeforeHotStart_;
03084 }
03085 else {
03086
03087 OsiSolverInterface::unmarkHotStart();
03088 }
03089 }
03090
03091 const double * OsiTMINLPInterface::getObjCoefficients() const
03092 {
03093 const int n = getNumCols();
03094 delete [] obj_;
03095 obj_ = NULL;
03096 obj_ = new double[n];
03097
03098 bool new_x = true;
03099 const double* x_sol = problem_->x_sol();
03100 bool retval = problem_->eval_grad_f(n, x_sol, new_x, obj_);
03101
03102 if (!retval) {
03103
03104 fprintf(stderr, "ERROR WHILE EVALUATING GRAD_F in OsiTMINLPInterface::getObjCoefficients()\n");
03105 delete [] obj_;
03106 obj_ = NULL;
03107 }
03108
03109 return obj_;
03110 }
03111
03113 void
03114 OsiTMINLPInterface::use(Ipopt::SmartPtr<TMINLP2TNLP> tminlp2tnlp){
03115 problem_ = tminlp2tnlp;
03116 problem_to_optimize_ = GetRawPtr(problem_);
03117 feasibilityProblem_->use(GetRawPtr(tminlp2tnlp));}
03118
03119 }