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