/home/coin/SVN-release/OS-2.0.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       TNLPSolver(roptions, options, journalist),
00043       problemHadZeroDimension_(false),
00044       warmStartStrategy_(1),
00045       enable_warm_start_(false),
00046       optimized_before_(false)
00047   {
00048     roptions_ = roptions;
00049     app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
00050   }
00051 
00052   IpoptSolver::~IpoptSolver()
00053   {}
00054 
00056   Ipopt::SmartPtr<TNLPSolver>
00057   IpoptSolver::clone()
00058   {
00059     SmartPtr<IpoptSolver> retval = new IpoptSolver(GetRawPtr(roptions_), new Ipopt::OptionsList(), journalist_);
00060     *retval->options_ = *options_;
00061     retval->warmStartStrategy_ = warmStartStrategy_;
00062     retval->problemHadZeroDimension_ = problemHadZeroDimension_;
00063     retval->optimizationStatus_ = optimizationStatus_;
00064 
00065     enable_warm_start_ = false;
00066     optimized_before_ = false;
00067     return GetRawPtr(retval);
00068   }
00069 
00070 
00071   bool
00072   IpoptSolver::Initialize(std::string params_file)
00073   {
00074     Ipopt::ApplicationReturnStatus status =
00075       app_->Initialize(params_file);
00076     if (status != Ipopt::Solve_Succeeded) {
00077       return false;
00078     }
00079     options_->GetEnumValue("warm_start",warmStartStrategy_,"bonmin.");
00080     setMinlpDefaults(options_);
00081     optimized_before_ = false;
00082     return true;
00083   }
00084 
00085   bool
00086   IpoptSolver::Initialize(std::istream &is)
00087   {
00088     Ipopt::ApplicationReturnStatus status =
00089       app_->Initialize(is);
00090     if (status != Ipopt::Solve_Succeeded) {
00091       return false;
00092     }
00093     options_->GetEnumValue("warm_start",warmStartStrategy_,"bonmin.");
00094     setMinlpDefaults(app_->Options());
00095     optimized_before_ = false;
00096     return true;
00097   }
00098 
00099   TNLPSolver::ReturnStatus
00100   IpoptSolver::OptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
00101   {
00102     TNLPSolver::ReturnStatus ret_status;
00103     if (!zeroDimension(tnlp, ret_status)) {
00104       if (enable_warm_start_ && optimized_before_) {
00105         optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
00106       }
00107       else {
00108         optimizationStatus_ = app_->OptimizeTNLP(tnlp);
00109       }
00110       optimized_before_ = true;
00111       problemHadZeroDimension_ = false;
00112     }
00113     else {
00114       problemHadZeroDimension_ = true;
00115       if (ret_status == solvedOptimal)
00116         optimizationStatus_ = Ipopt::Solve_Succeeded;
00117       else if (ret_status == provenInfeasible)
00118         optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00119     }
00120 
00121     if (BonminAbortAll)
00122       optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00123 
00124     return solverReturnStatus(optimizationStatus_);
00125   }
00126 
00127 
00128   TNLPSolver::ReturnStatus
00129   IpoptSolver::ReOptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
00130   {
00131     TNLPSolver::ReturnStatus ret_status;
00132     if (!zeroDimension(tnlp, ret_status)) {
00133       if (optimized_before_) {
00134         optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
00135       }
00136       else {
00137         optimizationStatus_ = app_->OptimizeTNLP(tnlp);
00138       }
00139       problemHadZeroDimension_ = false;
00140       optimized_before_ = true;
00141     }
00142     else {
00143       problemHadZeroDimension_ = true;
00144       if (ret_status == solvedOptimal)
00145         optimizationStatus_ = Ipopt::Solve_Succeeded;
00146       else if (ret_status == provenInfeasible)
00147         optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00148     }
00149     if (BonminAbortAll)
00150       optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
00151     return solverReturnStatus(optimizationStatus_);
00152   }
00153 
00155   double
00156   IpoptSolver::CPUTime()
00157   {
00158     if (problemHadZeroDimension_) {
00159       return 0.;
00160     }
00161     else {
00162       const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_->Statistics();
00163       if (IsValid(stats)) {
00164         return stats->TotalCPUTime();
00165       }
00166       else {
00167         printf("TODO: No statistics available from Ipopt in Bonmin::IpoptSolver::CPUTime\n");
00168         return 0.;
00169         //throw CoinError("No statistics available from Ipopt","CPUTime","Bonmin::IpoptSolver");
00170       }
00171     }
00172   }
00173 
00175   int
00176   IpoptSolver::IterationCount()
00177   {
00178     if (problemHadZeroDimension_) {
00179       return 0;
00180     }
00181     else {
00182       const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_->Statistics();
00183       if (IsValid(stats)) {
00184         return stats->IterationCount();
00185       }
00186       else {
00187         printf("TODO: No statistics available from Ipopt in Bonmin::IpoptSolver::IterationCount\n");
00188         return 0;
00189         //throw CoinError("No statistics available from Ipopt","IterationCount","Bonmin::IpoptSolver");
00190       }
00191 
00192     }
00193   }
00194 
00195 
00196   void
00197   IpoptSolver::setMinlpDefaults(Ipopt::SmartPtr<Ipopt::OptionsList> Options)
00198   {
00199     Options->SetNumericValue("gamma_phi", 1e-8, true, true);
00200     Options->SetNumericValue("gamma_theta", 1e-4, true, true);
00201     Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
00202     Options->SetStringValue("expect_infeasible_problem","yes", true, true);
00203     Options->SetStringValue("mu_strategy", "adaptive", true, true);
00204     Options->SetStringValue("mu_oracle","probing", true, true);
00205     Options->SetIntegerValue("print_level",1, true, true);
00206   }
00207 
00208 
00210   // Methods returning info on how the solution process terminated  //
00213   TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
00214   {
00215 
00216     switch (optimization_status) {
00217     case Ipopt::Maximum_Iterations_Exceeded:
00218     case Ipopt::User_Requested_Stop:
00219     case Ipopt::Restoration_Failed:
00220       return iterationLimit;
00221     case Ipopt::Error_In_Step_Computation:
00222     case Ipopt::Unrecoverable_Exception:
00223     case Ipopt::Insufficient_Memory:
00224       return computationError;
00225     case Ipopt::Not_Enough_Degrees_Of_Freedom:
00226       return notEnoughFreedom;
00227     case Ipopt::Invalid_Problem_Definition:
00228       return illDefinedProblem;
00229     case Ipopt::Invalid_Option:
00230     case Ipopt::Invalid_Number_Detected:
00231       return illegalOption;
00232     case Ipopt::NonIpopt_Exception_Thrown:
00233       return externalException;
00234     case Ipopt::Internal_Error:
00235       return exception;
00236     case Ipopt::Solve_Succeeded:
00237     case Ipopt::Feasible_Point_Found:
00238       return solvedOptimal;
00239     case Ipopt::Search_Direction_Becomes_Too_Small:
00240       return doesNotConverge;
00241     case Ipopt::Solved_To_Acceptable_Level:
00242       return solvedOptimalTol;
00243     case Ipopt::Infeasible_Problem_Detected:
00244       return provenInfeasible;
00245     case Ipopt::Diverging_Iterates:
00246       return unbounded;
00247     default:
00248       return exception;
00249     }
00250   }
00251 
00253 CoinWarmStart *
00254 IpoptSolver::getUsedWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00255 {
00256   return  new IpoptWarmStart(tnlp->num_variables(),
00257                              2*tnlp->num_variables() + 
00258                              tnlp->num_constraints(),
00259                              tnlp->x_init(), tnlp->duals_init());
00260 }
00262   CoinWarmStart*
00263   IpoptSolver::getWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
00264   {
00265       if (warmStartStrategy_==2) {
00266         Ipopt::SmartPtr<IpoptInteriorWarmStarter> warm_starter =
00267           Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
00268         return new IpoptWarmStart(tnlp, warm_starter);
00269       }
00270       else  return new IpoptWarmStart(tnlp, NULL);
00271   }
00272 
00273 
00274   bool
00275   IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
00276       Ipopt::SmartPtr<TMINLP2TNLP> tnlp)
00277   {
00278     if (!warmstart && warmStartStrategy_)
00279       return 0;
00280     const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
00281     if (ws->empty())//reset initial point and leave
00282     {
00283       disableWarmStart();
00284       return 1;
00285     }
00286     if(ws->dualSize() > 0){
00287       tnlp->setDualsInit(ws->dualSize(), ws->dual());
00288       enableWarmStart();
00289     }
00290     else
00291       disableWarmStart();
00292 #ifndef NDEBUG
00293     int numcols = tnlp->num_variables();
00294     int numrows = tnlp->num_constraints();
00295 #endif
00296 
00297     assert(numcols == ws->primalSize());
00298     assert(2*numcols + numrows == ws->dualSize());
00299     tnlp->setxInit(ws->primalSize(), ws->primal());
00300 
00301     if (IsValid(ws->warm_starter()))
00302       tnlp->SetWarmStarter(ws->warm_starter());
00303 
00304     return 1;
00305   }
00306 
00307   bool 
00308   IpoptSolver::warmStartIsValid(const CoinWarmStart * ws) const{
00309     const IpoptWarmStart* iws = dynamic_cast<const IpoptWarmStart*>(ws);
00310     if (iws && !iws->empty()) {
00311       return true;
00312     }
00313     return false;
00314   }
00315 
00316   CoinWarmStart *
00317   IpoptSolver::getEmptyWarmStart() const
00318   {
00319     return new IpoptWarmStart(1);
00320   }
00321 
00322   void
00323   IpoptSolver::enableWarmStart()
00324   {
00325     enable_warm_start_ = true;
00326     options_->SetStringValue("warm_start_init_point", "yes");
00327   }
00328 
00329   void
00330   IpoptSolver::disableWarmStart()
00331   {
00332     enable_warm_start_ = false;
00333     options_->SetStringValue("warm_start_init_point", "no");
00334   }
00335 
00336 
00337   void
00338   IpoptSolver::turnOffOutput()
00339   {}
00340 
00341 
00342   void
00343   IpoptSolver::turnOnOutput()
00344   {}
00345 
00346 
00347   /*******************************************************************************/
00348 // Class for throwing errors reported from Ipopt
00349   /******************************************************************************/
00350 
00351   std::string
00352   IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
00353       "Solved to acceptable level",
00354       "Infeasible problem detected",
00355       "Search direction becomes too small",
00356       "Diverging iterates",
00357       "User requested stop",
00358       "Maximum iterations exceeded",
00359       "Restoration failed",
00360       "Error in step computation",
00361       "Not enough degrees of freedom",
00362       "Invalid problem definition",
00363       "Invalid option",
00364       "Invalid number detected",
00365       "Unrecoverable exception",
00366       "NonIpopt exception thrown",
00367       "Insufficient memory",
00368       "Internal error"};
00369 
00370   const std::string &
00371   IpoptSolver::UnsolvedIpoptError::errorName() const
00372   {
00373     if (errorNum() >=0)
00374       return errorNames[errorNum()];
00375     if (errorNum() == -1) return errorNames[6];
00376     else if (errorNum() == -2) return errorNames[7];
00377     else if (errorNum() == -3) return errorNames[8];
00378     else if (errorNum() == -10) return errorNames[9];
00379     else if (errorNum() == -11) return errorNames[10];
00380     else if (errorNum() == -12) return errorNames[11];
00381     else if (errorNum() == -13) return errorNames[12];
00382     else if (errorNum() == -100) return errorNames[13];
00383     else if (errorNum() == -101) return errorNames[14];
00384     else if (errorNum() == -102) return errorNames[15];
00385     else if (errorNum() == -199) return errorNames[16];
00386     throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
00387   }
00388 
00389   std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
00390 
00391   const std::string &
00392   IpoptSolver::UnsolvedIpoptError::solverName() const
00393   {
00394     return solverName_;
00395   }
00396 
00397 
00398 
00399 
00400 }//end namespace Bonmin

Generated on Mon Aug 3 03:02:19 2009 by  doxygen 1.4.7