/home/coin/SVN-release/OS-2.1.0/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     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         printf("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         printf("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     Options->SetNumericValue("gamma_phi", 1e-8, true, true);
00253     Options->SetNumericValue("gamma_theta", 1e-4, true, true);
00254     Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
00255     Options->SetStringValue("expect_infeasible_problem","yes", true, true);
00256     Options->SetStringValue("mu_strategy", "adaptive", true, true);
00257     Options->SetStringValue("mu_oracle","probing", true, true);
00258     if(!Options->GetIntegerValue("print_level",default_log_level_,""))
00259       default_log_level_ = 1;
00260     Options->SetIntegerValue("print_level",1, true, true);
00261   }
00262 
00263 
00265   // Methods returning info on how the solution process terminated  //
00268   TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
00269   {
00270 
00271     switch (optimization_status) {
00272     case Ipopt::Maximum_Iterations_Exceeded:
00273     case Ipopt::User_Requested_Stop:
00274     case Ipopt::Restoration_Failed:
00275       return iterationLimit;
00276     case Ipopt::Error_In_Step_Computation:
00277     case Ipopt::Unrecoverable_Exception:
00278     case Ipopt::Insufficient_Memory:
00279       return computationError;
00280     case Ipopt::Not_Enough_Degrees_Of_Freedom:
00281       return notEnoughFreedom;
00282     case Ipopt::Invalid_Problem_Definition:
00283       return illDefinedProblem;
00284     case Ipopt::Invalid_Option:
00285     case Ipopt::Invalid_Number_Detected:
00286       return illegalOption;
00287     case Ipopt::NonIpopt_Exception_Thrown:
00288       return externalException;
00289     case Ipopt::Internal_Error:
00290       return exception;
00291     case Ipopt::Solve_Succeeded:
00292     case Ipopt::Feasible_Point_Found:
00293       return solvedOptimal;
00294     case Ipopt::Search_Direction_Becomes_Too_Small:
00295       return doesNotConverge;
00296     case Ipopt::Solved_To_Acceptable_Level:
00297       return solvedOptimalTol;
00298     case Ipopt::Infeasible_Problem_Detected:
00299       return provenInfeasible;
00300     case Ipopt::Diverging_Iterates:
00301       return unbounded;
00302     case Ipopt::Maximum_CpuTime_Exceeded:
00303       return timeLimit;
00304     default:
00305       return exception;
00306     }
00307   }
00308 
00310 CoinWarmStart *
00311 IpoptSolver::getUsedWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00312 {
00313   return  new IpoptWarmStart(tnlp->num_variables(),
00314                              2*tnlp->num_variables() + 
00315                              tnlp->num_constraints(),
00316                              tnlp->x_init(), tnlp->duals_init());
00317 }
00319   CoinWarmStart*
00320   IpoptSolver::getWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00321   {
00322       if (warmStartStrategy_==2) {
00323         Ipopt::SmartPtr<IpoptInteriorWarmStarter> warm_starter =
00324           Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
00325         return new IpoptWarmStart(tnlp, warm_starter);
00326       }
00327       else  return new IpoptWarmStart(tnlp, NULL);
00328   }
00329 
00330 
00331   bool
00332   IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
00333       Ipopt::SmartPtr<TMINLP2TNLP> tnlp)
00334   {
00335     if (!warmstart && warmStartStrategy_)
00336       return 0;
00337     const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
00338     if (ws->empty())//reset initial point and leave
00339     {
00340       disableWarmStart();
00341       return 1;
00342     }
00343     if(ws->dualSize() > 0){
00344       tnlp->setDualsInit(ws->dualSize(), ws->dual());
00345       enableWarmStart();
00346     }
00347     else
00348       disableWarmStart();
00349 #ifndef NDEBUG
00350     int numcols = tnlp->num_variables();
00351     int numrows = tnlp->num_constraints();
00352 #endif
00353 
00354     assert(numcols == ws->primalSize());
00355     assert(2*numcols + numrows == ws->dualSize());
00356     tnlp->setxInit(ws->primalSize(), ws->primal());
00357 
00358     if (IsValid(ws->warm_starter()))
00359       tnlp->SetWarmStarter(ws->warm_starter());
00360 
00361     return 1;
00362   }
00363 
00364   bool 
00365   IpoptSolver::warmStartIsValid(const CoinWarmStart * ws) const{
00366     const IpoptWarmStart* iws = dynamic_cast<const IpoptWarmStart*>(ws);
00367     if (iws && !iws->empty()) {
00368       return true;
00369     }
00370     return false;
00371   }
00372 
00373   CoinWarmStart *
00374   IpoptSolver::getEmptyWarmStart() const
00375   {
00376     return new IpoptWarmStart(1);
00377   }
00378 
00379   void
00380   IpoptSolver::enableWarmStart()
00381   {
00382     enable_warm_start_ = true;
00383     options_->SetStringValue("warm_start_init_point", "yes");
00384   }
00385 
00386   void
00387   IpoptSolver::disableWarmStart()
00388   {
00389     enable_warm_start_ = false;
00390     options_->SetStringValue("warm_start_init_point", "no");
00391   }
00392 
00393 
00394   void
00395   IpoptSolver::setOutputToDefault()
00396   {
00397      options_->SetIntegerValue("print_level", default_log_level_, true, true);
00398   }
00399 
00400 
00401   void
00402   IpoptSolver::forceSolverOutput(int log_level)
00403   {
00404      options_->SetIntegerValue("print_level", log_level, true, true);
00405   }
00406 
00407 
00408   /*******************************************************************************/
00409 // Class for throwing errors reported from Ipopt
00410   /******************************************************************************/
00411 
00412   std::string
00413   IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
00414       "Solved to acceptable level",
00415       "Infeasible problem detected",
00416       "Search direction becomes too small",
00417       "Diverging iterates",
00418       "User requested stop",
00419       "Maximum iterations exceeded",
00420       "Restoration failed",
00421       "Error in step computation",
00422       "Not enough degrees of freedom",
00423       "Invalid problem definition",
00424       "Invalid option",
00425       "Invalid number detected",
00426       "Unrecoverable exception",
00427       "NonIpopt exception thrown",
00428       "Insufficient memory",
00429       "Internal error"};
00430 
00431   const std::string &
00432   IpoptSolver::UnsolvedIpoptError::errorName() const
00433   {
00434     if (errorNum() >=0)
00435       return errorNames[errorNum()];
00436     if (errorNum() == -1) return errorNames[6];
00437     else if (errorNum() == -2) return errorNames[7];
00438     else if (errorNum() == -3) return errorNames[8];
00439     else if (errorNum() == -10) return errorNames[9];
00440     else if (errorNum() == -11) return errorNames[10];
00441     else if (errorNum() == -12) return errorNames[11];
00442     else if (errorNum() == -13) return errorNames[12];
00443     else if (errorNum() == -100) return errorNames[13];
00444     else if (errorNum() == -101) return errorNames[14];
00445     else if (errorNum() == -102) return errorNames[15];
00446     else if (errorNum() == -199) return errorNames[16];
00447     throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
00448   }
00449 
00450   std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
00451 
00452   const std::string &
00453   IpoptSolver::UnsolvedIpoptError::solverName() const
00454   {
00455     return solverName_;
00456   }
00457 
00458 
00459 
00460 
00461 }//end namespace Bonmin

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