/home/coin/SVN-release/OS-2.4.1/Bonmin/src/Interfaces/Ipopt/BonIpoptSolver.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines (IBM) 2005, 2007
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // Pierre Bonami, IBM
00007 //
00008 // Date : 26/09/2006
00009 
00010 
00011 #include "BonIpoptSolver.hpp"
00012 #include "IpSolveStatistics.hpp"
00013 #include "CoinError.hpp"
00014 
00015 #include "BonIpoptInteriorWarmStarter.hpp"
00016 #include "BonIpoptWarmStart.hpp"
00017 
00018 
00019 extern bool BonminAbortAll;
00020 
00021 namespace Bonmin
00022 {
00023 
00024   std::string IpoptSolver::solverName_ = "Ipopt";
00025 
00027   IpoptSolver::IpoptSolver(bool createEmpty /*= false*/):
00028       TNLPSolver(),
00029       problemHadZeroDimension_(false),
00030       warmStartStrategy_(1),
00031       enable_warm_start_(false),
00032       optimized_before_(false)
00033   {
00034     if (createEmpty) return;
00035     app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions_), options_, journalist_);
00036   }
00037 
00039   IpoptSolver::IpoptSolver(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00040       Ipopt::SmartPtr<Ipopt::OptionsList> options,
00041       Ipopt::SmartPtr<Ipopt::Journalist> journalist,
00042       const std::string & prefix):
00043       TNLPSolver(roptions, options, journalist, prefix),
00044       problemHadZeroDimension_(false),
00045       warmStartStrategy_(1),
00046       enable_warm_start_(false),
00047       optimized_before_(false)
00048   {
00049     roptions_ = roptions;
00050     app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
00051   }
00052 
00054   IpoptSolver::IpoptSolver(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
00055       Ipopt::SmartPtr<Ipopt::OptionsList> options,
00056       Ipopt::SmartPtr<Ipopt::Journalist> journalist):
00057       TNLPSolver(roptions, options, journalist, "bonmin."),
00058       problemHadZeroDimension_(false),
00059       warmStartStrategy_(1),
00060       enable_warm_start_(false),
00061       optimized_before_(false)
00062   {
00063     roptions_ = roptions;
00064     app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
00065   }
00066 
00067   IpoptSolver::~IpoptSolver()
00068   {}
00069 
00070   IpoptSolver::IpoptSolver(const IpoptSolver &other):
00071     TNLPSolver(other),
00072     optimizationStatus_(other.optimizationStatus_),
00073     problemHadZeroDimension_(other.problemHadZeroDimension_),
00074     warmStartStrategy_(other.warmStartStrategy_),
00075     enable_warm_start_(false),
00076     optimized_before_(false){
00077       app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions_), options_, journalist_);
00078   }
00079 
00081   Ipopt::SmartPtr<TNLPSolver>
00082   IpoptSolver::clone()
00083   {
00084     Ipopt::SmartPtr<IpoptSolver> retval = new IpoptSolver(*this);
00085     retval->app_->Initialize("");
00086     retval->default_log_level_ = default_log_level_;
00087     return GetRawPtr(retval);
00088   }
00089 
00090 
00091   bool
00092   IpoptSolver::Initialize(std::string params_file)
00093   {
00094     Ipopt::ApplicationReturnStatus status =
00095       app_->Initialize(params_file);
00096     if (status != Ipopt::Solve_Succeeded) {
00097       return false;
00098     }
00099     options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
00100     setMinlpDefaults(options_);
00101     optimized_before_ = false;
00102     return true;
00103   }
00104 
00105   bool
00106   IpoptSolver::Initialize(std::istream &is)
00107   {
00108     Ipopt::ApplicationReturnStatus status =
00109       app_->Initialize(is);
00110     if (status != Ipopt::Solve_Succeeded) {
00111       return false;
00112     }
00113     options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
00114     setMinlpDefaults(app_->Options());
00115     optimized_before_ = false;
00116     return true;
00117   }
00118 
00119   TNLPSolver::ReturnStatus
00120   IpoptSolver::OptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
00121   {
00122 #if 0
00123     printf("Global Time limit set to %g\n", time_limit_);
00124     double local_time_limit = time_limit_ - 
00125                               CoinCpuTime() + start_time_;
00126     printf("Time limit set to %g\n", local_time_limit);
00127     if(local_time_limit <= 0.){
00128        optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
00129        return solverReturnStatus(optimizationStatus_);
00130     }
00131 #endif
00132     TNLPSolver::ReturnStatus ret_status;
00133     if (!zeroDimension(tnlp, ret_status)) {
00134 #if 0
00135       if(time_limit_ < DBL_MAX){
00136            options_->SetNumericValue("max_cpu_time", local_time_limit,
00137                                   true, true);
00138       }
00139 #endif
00140       if (enable_warm_start_ && optimized_before_) {
00141         optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
00142       }
00143       else {
00144         optimizationStatus_ = app_->OptimizeTNLP(tnlp);
00145       }
00146       optimized_before_ = true;
00147       problemHadZeroDimension_ = false;
00148     }
00149     else {
00150       problemHadZeroDimension_ = true;
00151       if (ret_status == solvedOptimal)
00152         optimizationStatus_ = Ipopt::Solve_Succeeded;
00153       else if (ret_status == provenInfeasible)
00154         optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00155     }
00156 
00157     if (BonminAbortAll)
00158       optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00159 
00160     return solverReturnStatus(optimizationStatus_);
00161   }
00162 
00163 
00164   TNLPSolver::ReturnStatus
00165   IpoptSolver::ReOptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
00166   {
00167 #if 0
00168     printf("Global Time limit set to %g\n", time_limit_);
00169     double local_time_limit = time_limit_ - 
00170                               CoinCpuTime() + start_time_;
00171     printf("Time limit set to %g\n", local_time_limit);
00172     if(local_time_limit <= 0.){
00173        optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
00174        return solverReturnStatus(optimizationStatus_);
00175     }
00176 #endif
00177     TNLPSolver::ReturnStatus ret_status;
00178     if (!zeroDimension(tnlp, ret_status)) {
00179 #if 0
00180       if(time_limit_ < DBL_MAX){
00181         options_->SetNumericValue("max_cpu_time", 
00182                                   std::max(0., local_time_limit),
00183                                   true, true);
00184       }
00185 #endif
00186       if (optimized_before_) {
00187         optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
00188       }
00189       else {
00190         optimizationStatus_ = app_->OptimizeTNLP(tnlp);
00191       }
00192       problemHadZeroDimension_ = false;
00193       optimized_before_ = true;
00194     }
00195     else {
00196       problemHadZeroDimension_ = true;
00197       if (ret_status == solvedOptimal)
00198         optimizationStatus_ = Ipopt::Solve_Succeeded;
00199       else if (ret_status == provenInfeasible)
00200         optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00201     }
00202     if (BonminAbortAll)
00203       optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00204     return solverReturnStatus(optimizationStatus_);
00205   }
00206 
00208   double
00209   IpoptSolver::CPUTime()
00210   {
00211     if (problemHadZeroDimension_) {
00212       return 0.;
00213     }
00214     else {
00215       const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_->Statistics();
00216       if (IsValid(stats)) {
00217         return stats->TotalCpuTime();
00218       }
00219       else {
00220         app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "TODO: No statistics available from Ipopt in Bonmin::IpoptSolver::CPUTime\n");
00221         return 0.;
00222         //throw CoinError("No statistics available from Ipopt","CPUTime","Bonmin::IpoptSolver");
00223       }
00224     }
00225   }
00226 
00228   int
00229   IpoptSolver::IterationCount()
00230   {
00231     if (problemHadZeroDimension_) {
00232       return 0;
00233     }
00234     else {
00235       const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_->Statistics();
00236       if (IsValid(stats)) {
00237         return stats->IterationCount();
00238       }
00239       else {
00240         app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "TODO: No statistics available from Ipopt in Bonmin::IpoptSolver::IterationCount\n");
00241         return 0;
00242         //throw CoinError("No statistics available from Ipopt","IterationCount","Bonmin::IpoptSolver");
00243       }
00244 
00245     }
00246   }
00247 
00248 
00249   void
00250   IpoptSolver::setMinlpDefaults(Ipopt::SmartPtr<Ipopt::OptionsList> Options)
00251   {
00252     bool set = false;
00253     double dummy_dbl;
00254     int dummy_int;
00255     set = Options->GetNumericValue("gamma_phi", dummy_dbl, "");
00256     if(!set)
00257     Options->SetNumericValue("gamma_phi", 1e-8, true, true);
00258     set = Options->GetNumericValue("gamma_theta", dummy_dbl, "");
00259     if(!set)
00260     Options->SetNumericValue("gamma_theta", 1e-4, true, true);
00261     set = Options->GetNumericValue("required_infeasibility_reduction", dummy_dbl, "");
00262     if(!set)
00263     Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
00264     set = Options->GetEnumValue("expect_infeasible_problem",dummy_int, "");
00265     if(!set)
00266     Options->SetStringValue("expect_infeasible_problem","yes", true, true);
00267     set = Options->GetEnumValue("mu_strategy", dummy_int, "");
00268     if(!set)
00269     Options->SetStringValue("mu_strategy", "adaptive", true, true);
00270     set = Options->GetEnumValue("mu_oracle",dummy_int, "");
00271     if(!set)
00272     Options->SetStringValue("mu_oracle","probing", true, true);
00273     if(!Options->GetIntegerValue("print_level",default_log_level_,"")) {
00274       default_log_level_ = 1;
00275       Options->SetIntegerValue("print_level",1, true, true);
00276     }
00277   }
00278 
00279 
00281   // Methods returning info on how the solution process terminated  //
00284   TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
00285   {
00286 
00287     switch (optimization_status) {
00288     case Ipopt::Maximum_Iterations_Exceeded:
00289     case Ipopt::User_Requested_Stop:
00290     case Ipopt::Restoration_Failed:
00291       return iterationLimit;
00292     case Ipopt::Error_In_Step_Computation:
00293     case Ipopt::Unrecoverable_Exception:
00294     case Ipopt::Insufficient_Memory:
00295       return computationError;
00296     case Ipopt::Not_Enough_Degrees_Of_Freedom:
00297       return notEnoughFreedom;
00298     case Ipopt::Invalid_Problem_Definition:
00299       return illDefinedProblem;
00300     case Ipopt::Invalid_Option:
00301     case Ipopt::Invalid_Number_Detected:
00302       return illegalOption;
00303     case Ipopt::NonIpopt_Exception_Thrown:
00304       return externalException;
00305     case Ipopt::Internal_Error:
00306       return exception;
00307     case Ipopt::Solve_Succeeded:
00308     case Ipopt::Feasible_Point_Found:
00309       return solvedOptimal;
00310     case Ipopt::Search_Direction_Becomes_Too_Small:
00311       return doesNotConverge;
00312     case Ipopt::Solved_To_Acceptable_Level:
00313       return solvedOptimalTol;
00314     case Ipopt::Infeasible_Problem_Detected:
00315       return provenInfeasible;
00316     case Ipopt::Diverging_Iterates:
00317       return unbounded;
00318     case Ipopt::Maximum_CpuTime_Exceeded:
00319       return timeLimit;
00320     default:
00321       return exception;
00322     }
00323   }
00324 
00326 CoinWarmStart *
00327 IpoptSolver::getUsedWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00328 {
00329   if(tnlp->x_init() == NULL || tnlp->duals_init() == NULL)
00330     return NULL;
00331   return  new IpoptWarmStart(tnlp->num_variables(),
00332                              2*tnlp->num_variables() + 
00333                              tnlp->num_constraints(),
00334                              tnlp->x_init(), tnlp->duals_init());
00335 }
00337   CoinWarmStart*
00338   IpoptSolver::getWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00339   {
00340       if (warmStartStrategy_==2) {
00341         Ipopt::SmartPtr<IpoptInteriorWarmStarter> warm_starter =
00342           Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
00343         return new IpoptWarmStart(tnlp, warm_starter);
00344       }
00345       else  return new IpoptWarmStart(tnlp, NULL);
00346   }
00347 
00348 
00349   bool
00350   IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
00351       Ipopt::SmartPtr<TMINLP2TNLP> tnlp)
00352   {
00353     if (!warmstart && warmStartStrategy_)
00354       return 0;
00355     const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
00356     if(ws == NULL) return 0;
00357     if (ws->empty())//reset initial point and leave
00358     {
00359       disableWarmStart();
00360       return 1;
00361     }
00362     if(ws->dualSize() > 0){
00363       tnlp->setDualsInit(ws->dualSize(), ws->dual());
00364       enableWarmStart();
00365     }
00366     else
00367       disableWarmStart();
00368 #ifndef NDEBUG
00369     int numcols = tnlp->num_variables();
00370     int numrows = tnlp->num_constraints();
00371 #endif
00372 
00373     assert(numcols == ws->primalSize());
00374     assert(2*numcols + numrows == ws->dualSize());
00375     tnlp->setxInit(ws->primalSize(), ws->primal());
00376 
00377     if (IsValid(ws->warm_starter()))
00378       tnlp->SetWarmStarter(ws->warm_starter());
00379 
00380     return 1;
00381   }
00382 
00383   bool 
00384   IpoptSolver::warmStartIsValid(const CoinWarmStart * ws) const{
00385     const IpoptWarmStart* iws = dynamic_cast<const IpoptWarmStart*>(ws);
00386     if (iws && !iws->empty()) {
00387       return true;
00388     }
00389     return false;
00390   }
00391 
00392   CoinWarmStart *
00393   IpoptSolver::getEmptyWarmStart() const
00394   {
00395     return new IpoptWarmStart(1);
00396   }
00397 
00398   void
00399   IpoptSolver::enableWarmStart()
00400   {
00401     enable_warm_start_ = true;
00402     options_->SetStringValue("warm_start_init_point", "yes");
00403   }
00404 
00405   void
00406   IpoptSolver::disableWarmStart()
00407   {
00408     enable_warm_start_ = false;
00409     options_->SetStringValue("warm_start_init_point", "no");
00410   }
00411 
00412 
00413   void
00414   IpoptSolver::setOutputToDefault()
00415   {
00416      options_->SetIntegerValue("print_level", default_log_level_, true, true);
00417   }
00418 
00419 
00420   void
00421   IpoptSolver::forceSolverOutput(int log_level)
00422   {
00423      options_->SetIntegerValue("print_level", log_level, true, true);
00424   }
00425 
00426 
00427   /*******************************************************************************/
00428 // Class for throwing errors reported from Ipopt
00429   /******************************************************************************/
00430 
00431   std::string
00432   IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
00433       "Solved to acceptable level",
00434       "Infeasible problem detected",
00435       "Search direction becomes too small",
00436       "Diverging iterates",
00437       "User requested stop",
00438       "Maximum iterations exceeded",
00439       "Restoration failed",
00440       "Error in step computation",
00441       "Not enough degrees of freedom",
00442       "Invalid problem definition",
00443       "Invalid option",
00444       "Invalid number detected",
00445       "Unrecoverable exception",
00446       "NonIpopt exception thrown",
00447       "Insufficient memory",
00448       "Internal error"};
00449 
00450   const std::string &
00451   IpoptSolver::UnsolvedIpoptError::errorName() const
00452   {
00453     if (errorNum() >=0)
00454       return errorNames[errorNum()];
00455     if (errorNum() == -1) return errorNames[6];
00456     else if (errorNum() == -2) return errorNames[7];
00457     else if (errorNum() == -3) return errorNames[8];
00458     else if (errorNum() == -10) return errorNames[9];
00459     else if (errorNum() == -11) return errorNames[10];
00460     else if (errorNum() == -12) return errorNames[11];
00461     else if (errorNum() == -13) return errorNames[12];
00462     else if (errorNum() == -100) return errorNames[13];
00463     else if (errorNum() == -101) return errorNames[14];
00464     else if (errorNum() == -102) return errorNames[15];
00465     else if (errorNum() == -199) return errorNames[16];
00466     throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
00467   }
00468 
00469   std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
00470 
00471   const std::string &
00472   IpoptSolver::UnsolvedIpoptError::solverName() const
00473   {
00474     return solverName_;
00475   }
00476 
00477 
00478 
00479 
00480 }//end namespace Bonmin

Generated on Thu Nov 10 03:05:42 2011 by  doxygen 1.4.7