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

Generated on Thu Oct 8 03:02:55 2009 by  doxygen 1.4.7