/home/coin/SVN-release/OS-2.1.0/Bonmin/src/Interfaces/BonOsiTMINLPInterface.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines Corporation and
00002 // Carnegie Mellon University 2004, 2007
00003 //
00004 // All Rights Reserved.
00005 // This code is published under the Common Public License.
00006 //
00007 // Authors :
00008 // Pierre Bonami, Carnegie Mellon University,
00009 // Carl D. Laird, Carnegie Mellon University,
00010 // Andreas Waechter, International Business Machines Corporation
00011 //
00012 // Date : 12/01/2004
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 //#include "Filter/BonBqpdWarmStart.hpp"
00033 #endif
00034 
00035 #include "OsiBranchingObject.hpp"
00036 #include "BonStrongBranchingSolver.hpp"
00037 
00038 //Macros to try and make messages definition less heavy
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   // We try to register the options - if those have been registered
00251   // already, we catch the exception and don't need to do it again
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     // skipping
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 // Constructors and desctructors                                  //
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 //    constTypesNum_(NULL),
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   //Pass in message handler
00575   if(0 && source.messageHandler())
00576     passInMessageHandler(source.messageHandler());
00577    //Copy options from old application
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     // Copy options from old application
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       if(constTypesNum_ != NULL) {
00661         delete [] constTypesNum_;
00662         constTypesNum_ = NULL;
00663       }
00664       if(rhs.constTypesNum_ != NULL) {
00665         constTypesNum_ = new int[getNumRows()];
00666         CoinCopyN(rhs.constTypesNum_, getNumRows(), constTypesNum_);
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   //   if(dualsol_!=NULL)
00796   //     {
00797   //       delete []  dualsol_; dualsol_ = NULL;
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 // WarmStart Information                                                                           //
00816 
00817 
00818 void
00819 OsiTMINLPInterface::resolveForCost(int numsolve, bool keepWarmStart)
00820 {
00821   // This method assumes that a problem has just been solved and we try for a
00822   // different solution. So disregard (in fact, clear out) any warmstart info
00823   // we might have, and acquire a new one before returning.
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     //if warm start is not exposed, we need to store the current starting point to
00836     //restore it at the end of the method
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     //Is solution better than previous
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      //calculate the mean
00931      mean=mean/(numsolve-num_failed-num_infeas);
00932      
00933      std_dev = 0;
00934      
00935      //calculate the std deviation
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      //calculate coeff of variation
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   // This method assumes that a problem has just been solved and we try for a
00979   // different solution. So disregard (in fact, clear out) any warmstart info
00980   // we might have, and acquire a new one before returning.
00981   delete warmstart_;
00982   warmstart_ = NULL;
00983   
00984 
00985   CoinWarmStart * ws_backup = NULL;
00986   if(!exposeWarmStart_){
00987     //if warm start is not exposed, we need to store the current starting point to
00988     //restore it at the end of the method
00989     ws_backup = app_->getUsedWarmStart(problem_);
00990   }
00991   //std::cerr<<"Resolving the problem for robustness"<<std::endl;
00992   //First remove warm start point and resolve
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     // re-enable warmstart and get it
01013     app_->enableWarmStart();
01014     if (!exposeWarmStart_) {
01015       app_->setWarmStart(ws_backup, problem_);
01016       delete ws_backup;
01017     }
01018     return; //we won go on
01019   }
01020 
01021   //still unsolved try again with different random starting points
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       // re-enable warmstart and get it
01048       app_->enableWarmStart();
01049       if (!exposeWarmStart_) {
01050         app_->setWarmStart(ws_backup, problem_);
01051         delete ws_backup;
01052       }
01053         
01054       return; //we have found a solution and continue
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   // Do NOT get warmstart in other cases
01079 }
01080 
01082 // Problem information methods                                    //
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   //  if(fabs(problem_->x_l()[elementIndex]-elementValue)>1e-06)
01304   problem_->SetVariableLowerBound(elementIndex,elementValue);
01305   hasBeenOptimized_ = false;
01306 }
01307 
01310 void
01311 OsiTMINLPInterface::setColUpper( int elementIndex, double elementValue )
01312 {
01313   //  if(fabs(problem_->x_u()[elementIndex]-elementValue)>1e-06)
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   // See if it is anything else than the CoinWarmStartBasis that all others
01473   // derive from
01474   const CoinWarmStartPrimalDual* pdws =
01475     dynamic_cast<const CoinWarmStartPrimalDual*>(ws);
01476   if (pdws) {
01477     // Must be an IpoptWarmStart, since the others do not derive from this.
01478     // Accept it.
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 // Parameter related methods
01513 //#############################################################################
01514 
01515 bool
01516 OsiTMINLPInterface::setIntParam(OsiIntParam key, int value)
01517 {
01518   //  debugMessage("OsiCpxSolverInterface::setIntParam(%d, %d)\n", key, value);
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   //  debugMessage("OsiTMINLPInterface::setDblParam(%d, %g)\n", key, value);
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   //  debugMessage("OsiTMINLPInterface::setStrParam(%d, %s)\n", key, value.c_str());
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   //  debugMessage("OsiTMINLPInterface::getIntParam(%d)\n", key);
01608 
01609   value = -COIN_INT_MAX; // Give a dummy value
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   //  debugMessage("OsiTMINLPInterface::getDblParam(%d)\n", key);
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   //  debugMessage("OsiTMINLPInterface::getStrParam(%d)\n", key);
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)//put C-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 //  if(constTypesNum_ != NULL) delete [] constTypesNum_;
01763 
01764   constTypes_ = new TNLP::LinearityType[getNumRows()];
01765   problem_to_optimize_->get_constraints_linearity(getNumRows(), constTypes_);
01766 //  constTypesNum_ = new int[getNumRows()];
01767   for(int i = 0; i < getNumRows() ; i++) {
01768     if(constTypes_[i]==TNLP::NON_LINEAR) {
01769       //constTypesNum_[i] = 
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 //A procedure to try to remove small coefficients in OA cuts (or make it non small
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;//Take the risk?
01828 
01829   //try and remove
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   //can not remove coefficient increase it to smallest non zero
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   //As jacobian is stored by cols fill OsiCuts with cuts
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);//store correspondance between index of row and index of cut (some cuts are not generated for rows because linear, or not binding). -1 if constraint does not generate a cut, otherwise index in cuts.
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)// <= inequality
01910           lb[numCuts] = - infty;
01911         if(duals[rowIdx] <= 0)// >= inequality
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       //"clean" coefficient
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);// Store correspondance between indices of cut and indices of rows. For each cut
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     //Compute cut violation
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     //    if(lb[i]>-1e20) assert (ub[i]>1e20);
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         //exit(-2);
01980       }
01981     }
01982     if(global) {
01983       newCut.setGloballyValidAsInteger(1);
01984     }
01985     //newCut.setEffectiveness(99.99e99);
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())) { // Get the objective cuts
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     //double minCoeff = 1e50;
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         //            minCoeff = min(fabs(obj[i]), minCoeff);
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     //Compute cut violation
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           //exit(-2);
02037         }
02038       }
02039       OsiRowCut newCut;
02040       if(global)
02041         newCut.setGloballyValidAsInteger(1);
02042       //newCut.setEffectiveness(99.99e99);
02043       newCut.setRow(v);
02044       newCut.setLb(-COIN_DBL_MAX/*Infinity*/);
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   //As jacobian is stored by cols fill OsiCuts with cuts
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   //double infty = getInfinity();
02078   //double nlp_infty = infty_;
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     //"clean" coefficient
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()) { // Get the objective cuts
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     //double minCoeff = 1e50;
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/*Infinity*/);
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)// <= inequality
02185       lb = - infty;
02186     if(dual <= 0)// >= inequality
02187       ub = infty;
02188   }
02189 
02190   for(int i = 0 ; i < nnz; i++) {
02191      const int &colIdx = indices[i];
02192       //"clean" coefficient
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   //newCut.setEffectiveness(99.99e99);
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   //Get problem information
02332   problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
02333 
02334   //if not allocated allocate spaced for stroring jacobian
02335   //if(jRow_ == NULL || jCol_ == NULL || jValues_ == NULL)
02336     initializeJacobianArrays();
02337 
02338   //get Jacobian
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);;//store non binding constraints (which are to be removed from OA)
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       //If constraint is range not binding prepare to remove it
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       //If equality or ranged constraint only add one side by looking at sign of dual multiplier
02382       if(rowLower[i] > -nlp_infty && rowUpper[i] < nlp_infty)
02383       {
02384         if(duals[i] >= 0.)// <= inequality
02385           rowLow[i] = - infty;
02386         if(duals[i] <= 0.)// >= inequality
02387           rowUp[i] = infty;
02388       }
02389     }
02390     else {
02391       if(rowLower[i] > -nlp_infty){
02392       //   printf("Lower %g ", rowLower[i]);
02393          rowLow[i] = (rowLower[i] - g[i]);
02394       }
02395       else
02396         rowLow[i] = - infty;
02397       if(rowUpper[i] < nlp_infty){
02398       //   printf("Upper %g ", rowUpper[i]);
02399          rowUp[i] =  (rowUpper[i] - g[i]);
02400       }
02401       else
02402         rowUp[i] = infty;
02403     }
02404   }
02405 
02406   
02407   
02408   //Then convert everything to a CoinPackedMatrix
02409   //Go through values, clean coefficients and fix bounds
02410   for(int i = 0 ; i < nnz_jac_g ; i++) {
02411     if(constTypes_[jRow_[i]] != TNLP::LINEAR){//For linear just copy is fine.
02412        if(//For other clean tinys
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); // In case matrix was empty, this should be enough
02430   
02431   //remove non-bindings equality constraints
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        //Copy the linear objective and don't create a dummy variable.
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 //  si.writeMpsNative("OA.mps",NULL, NULL, 1);
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       //add variable alpha
02477       //(alpha should be empty in the matrix with a coefficient of -1 and unbounded)
02478       CoinPackedVector a;
02479       si.addCol(a,-si.getInfinity(), si.getInfinity(), 1.);
02480   
02481       // Now get the objective cuts
02482       // get the gradient, pack it and add the cut
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 //Unconstrained problem can not put clean coefficient
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   //Options should have been printed if not done already turn off Ipopt output
02550   if(!hasPrintedOptions) {
02551     hasPrintedOptions = 1;
02552     //app_->Options()->SetIntegerValue("print_level",0, true, true);
02553     app_->options()->SetStringValue("print_user_options","no", false, true);
02554   }
02555   
02556   bool otherDisagree = false ;
02557 #if 0
02558   if(optimizationStatus_ == TNLPSolver::notEnoughFreedom)//Too few degrees of freedom
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     //restore
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_))//Solver failed and the error can not be recovered, throw it
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       //Try other solvers and see if they agree
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)//something failed throw
02668     {
02669       throw SimpleError("No statistics available from Ipopt",whereFrom);
02670     }
02671     else {
02672       return;
02673     }
02674   }
02675   if(problem_->hasUpperBoundingObjective()){//Check if solution is integer and recompute objective value using alternative objective function
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{//Only works for integer constraints
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/*getVarNames()*/);
02742   }
02743   
02744 }
02745 
02747 // Solve Methods                                                  //
02749 void OsiTMINLPInterface::initialSolve()
02750 {
02751    initialSolve("");
02752 }
02753 
02755 // Solve Methods                                                  //
02757 void OsiTMINLPInterface::initialSolve(const char * whereFrom)
02758 {
02759   assert(IsValid(app_));
02760   assert(IsValid(problem_));
02761 
02762   // Discard warmstart_ if we had one
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   //Options should have been printed if not done already turn off Ipopt output
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   // if warmstart_ is not empty then had to use resolveFor... and that created
02803   // the warmstart at the end, and we have nothing to do here. Otherwise...
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     // empty (or unrecognized) warmstart
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   // if warmstart_ is not empty then had to use resolveFor... and that created
02865   // the warmstart at the end, and we have nothing to do here. Otherwise...
02866   if (! warmstart_ && ! isAbandoned()) {
02867     if (exposeWarmStart_) {
02868       warmstart_ = app_->getWarmStart(problem_);
02869     }
02870   }
02871 }
02872 
02873 
02875 // Methods returning info on how the solution process terminated  //
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   //  (*messageHandler_)<<"Warning : isDualObjectiveLimitReached not implemented yet"<<CoinMessageEol;
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       // overwriting default for filter
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       // TNLP solver to be used in the cut strengthener
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   //#define STRONG_COMPARE
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     // AWDEBUG
02994     OsiSolverInterface::markHotStart();
02995     objorig = getObjValue();
02996 #endif
02997     optimizationStatusBeforeHotStart_ = optimizationStatus_;
02998     strong_branching_solver_->markHotStart(this);
02999   }
03000   else {
03001     // Default Implementation
03002     OsiSolverInterface::markHotStart();
03003   }
03004 }
03005 
03006 void
03007 OsiTMINLPInterface::solveFromHotStart()
03008 {
03009   if (IsValid(strong_branching_solver_)) {
03010 #ifdef STRONG_COMPARE
03011     // AWDEBUG
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     // Default Implementation
03025     OsiSolverInterface::solveFromHotStart();
03026   }
03027 }
03028 
03029 void
03030 OsiTMINLPInterface::unmarkHotStart()
03031 {
03032   if (IsValid(strong_branching_solver_)) {
03033 #ifdef STRONG_COMPARE
03034     // AWDEBUG
03035     OsiSolverInterface::unmarkHotStart();
03036 #endif
03037     strong_branching_solver_->unmarkHotStart(this);
03038     optimizationStatus_ = optimizationStatusBeforeHotStart_;
03039   }
03040   else {
03041     // Default Implementation
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     // Let's see if that happens - it will cause a crash
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 }

Generated on Tue Mar 30 03:04:35 2010 by  doxygen 1.4.7