BonIpoptSolver.cpp
Go to the documentation of this file.
1 // (C) Copyright International Business Machines (IBM) 2005, 2007
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // Pierre Bonami, IBM
7 //
8 // Date : 26/09/2006
9 
10 
11 #include "BonIpoptSolver.hpp"
12 #include "IpSolveStatistics.hpp"
13 #include "CoinError.hpp"
14 
16 #include "BonIpoptWarmStart.hpp"
17 
18 
19 extern bool BonminAbortAll;
20 
21 namespace Bonmin
22 {
23 
24  std::string IpoptSolver::solverName_ = "Ipopt";
25 
27  IpoptSolver::IpoptSolver(bool createEmpty /*= false*/):
28  TNLPSolver(),
29  problemHadZeroDimension_(false),
30  warmStartStrategy_(1),
31  enable_warm_start_(false),
32  optimized_before_(false)
33  {
34  if (createEmpty) return;
35  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions_), options_, journalist_);
36 #ifdef NO_CATCH_ALL
37  app_->RethrowNonIpoptException(true);
38 #endif
39  }
40 
45  const std::string & prefix):
46  TNLPSolver(roptions, options, journalist, prefix),
47  problemHadZeroDimension_(false),
48  warmStartStrategy_(1),
49  enable_warm_start_(false),
50  optimized_before_(false)
51  {
53  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
54 #ifdef NO_CATCH_ALL
55  app_->RethrowNonIpoptException(true);
56 #endif
57  }
58 
63  TNLPSolver(roptions, options, journalist, "bonmin."),
64  problemHadZeroDimension_(false),
65  warmStartStrategy_(1),
66  enable_warm_start_(false),
67  optimized_before_(false)
68  {
70  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
71 #ifdef NO_CATCH_ALL
72  app_->RethrowNonIpoptException(true);
73 #endif
74  }
75 
77  {}
78 
80  TNLPSolver(other),
81  optimizationStatus_(other.optimizationStatus_),
82  problemHadZeroDimension_(other.problemHadZeroDimension_),
83  warmStartStrategy_(other.warmStartStrategy_),
84  enable_warm_start_(false),
85  optimized_before_(false){
86  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions_), options_, journalist_);
87 #ifdef NO_CATCH_ALL
88  app_->RethrowNonIpoptException(true);
89 #endif
90  }
91 
95  {
96  Ipopt::SmartPtr<IpoptSolver> retval = new IpoptSolver(*this);
97  retval->app_->Initialize("");
98  retval->default_log_level_ = default_log_level_;
99  return GetRawPtr(retval);
100  }
101 
102 
103  bool
104  IpoptSolver::Initialize(std::string params_file)
105  {
106  Ipopt::ApplicationReturnStatus status =
107  app_->Initialize(params_file);
108  if (status != Ipopt::Solve_Succeeded) {
109  return false;
110  }
111  options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
113  optimized_before_ = false;
114  return true;
115  }
116 
117  bool
118  IpoptSolver::Initialize(std::istream &is)
119  {
120  Ipopt::ApplicationReturnStatus status =
121  app_->Initialize(is);
122  if (status != Ipopt::Solve_Succeeded) {
123  return false;
124  }
125  options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
126  setMinlpDefaults(app_->Options());
127  optimized_before_ = false;
128  return true;
129  }
130 
133  {
134 #if 0
135  printf("Global Time limit set to %g\n", time_limit_);
136  double local_time_limit = time_limit_ -
137  CoinCpuTime() + start_time_;
138  printf("Time limit set to %g\n", local_time_limit);
139  if(local_time_limit <= 0.){
140  optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
142  }
143 #endif
144  TNLPSolver::ReturnStatus ret_status;
145  if (!zeroDimension(tnlp, ret_status)) {
146 #if 0
147  if(time_limit_ < DBL_MAX){
148  options_->SetNumericValue("max_cpu_time", local_time_limit,
149  true, true);
150  }
151 #endif
153  optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
154  }
155  else {
156  optimizationStatus_ = app_->OptimizeTNLP(tnlp);
157  }
158  optimized_before_ = true;
159  problemHadZeroDimension_ = false;
160  }
161  else {
163  if (ret_status == solvedOptimal)
164  optimizationStatus_ = Ipopt::Solve_Succeeded;
165  else if (ret_status == provenInfeasible)
166  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
167  }
168 
169  if (BonminAbortAll)
170  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
171 
173  }
174 
175 
178  {
179 #if 0
180  printf("Global Time limit set to %g\n", time_limit_);
181  double local_time_limit = time_limit_ -
182  CoinCpuTime() + start_time_;
183  printf("Time limit set to %g\n", local_time_limit);
184  if(local_time_limit <= 0.){
185  optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
187  }
188 #endif
189  TNLPSolver::ReturnStatus ret_status;
190  if (!zeroDimension(tnlp, ret_status)) {
191 #if 0
192  if(time_limit_ < DBL_MAX){
193  options_->SetNumericValue("max_cpu_time",
194  std::max(0., local_time_limit),
195  true, true);
196  }
197 #endif
198  if (optimized_before_) {
199  optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
200  }
201  else {
202  optimizationStatus_ = app_->OptimizeTNLP(tnlp);
203  }
204  problemHadZeroDimension_ = false;
205  optimized_before_ = true;
206  }
207  else {
209  if (ret_status == solvedOptimal)
210  optimizationStatus_ = Ipopt::Solve_Succeeded;
211  else if (ret_status == provenInfeasible)
212  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
213  }
214  if (BonminAbortAll)
215  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
217  }
218 
220  double
222  {
224  return 0.;
225  }
226  else {
227  const Ipopt::SmartPtr<Ipopt::SolveStatistics> stats = app_->Statistics();
228  if (IsValid(stats)) {
229  return stats->TotalCpuTime();
230  }
231  else {
232  app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "No statistics available from Ipopt in Bonmin::IpoptSolver::CPUTime\n");
233  return 0.;
234  //throw CoinError("No statistics available from Ipopt","CPUTime","Bonmin::IpoptSolver");
235  }
236  }
237  }
238 
240  int
242  {
244  return 0;
245  }
246  else {
247  const Ipopt::SmartPtr<Ipopt::SolveStatistics> stats = app_->Statistics();
248  if (IsValid(stats)) {
249  return stats->IterationCount();
250  }
251  else {
252  app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "No statistics available from Ipopt in Bonmin::IpoptSolver::IterationCount\n");
253  return 0;
254  //throw CoinError("No statistics available from Ipopt","IterationCount","Bonmin::IpoptSolver");
255  }
256 
257  }
258  }
259 
260 
261  void
263  {
264  bool set = false;
265  double dummy_dbl;
266  int dummy_int;
267  set = Options->GetNumericValue("gamma_phi", dummy_dbl, "");
268  if(!set)
269  Options->SetNumericValue("gamma_phi", 1e-8, true, true);
270  set = Options->GetNumericValue("gamma_theta", dummy_dbl, "");
271  if(!set)
272  Options->SetNumericValue("gamma_theta", 1e-4, true, true);
273  set = Options->GetNumericValue("required_infeasibility_reduction", dummy_dbl, "");
274  if(!set)
275  Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
276  set = Options->GetEnumValue("expect_infeasible_problem",dummy_int, "");
277  if(!set)
278  Options->SetStringValue("expect_infeasible_problem","yes", true, true);
279  set = Options->GetEnumValue("mu_strategy", dummy_int, "");
280  if(!set)
281  Options->SetStringValue("mu_strategy", "adaptive", true, true);
282  set = Options->GetEnumValue("mu_oracle",dummy_int, "");
283  if(!set)
284  Options->SetStringValue("mu_oracle","probing", true, true);
285  if(!Options->GetIntegerValue("print_level",default_log_level_,"")) {
286  default_log_level_ = 1;
287  Options->SetIntegerValue("print_level",1, true, true);
288  }
289  }
290 
291 
293  // Methods returning info on how the solution process terminated //
296  TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
297  {
298 
299  switch (optimization_status) {
300  case Ipopt::Maximum_Iterations_Exceeded:
301  case Ipopt::User_Requested_Stop:
302  case Ipopt::Restoration_Failed:
303  return iterationLimit;
304  case Ipopt::Error_In_Step_Computation:
305  case Ipopt::Unrecoverable_Exception:
306  case Ipopt::Insufficient_Memory:
307  return computationError;
308  case Ipopt::Not_Enough_Degrees_Of_Freedom:
309  return notEnoughFreedom;
310  case Ipopt::Invalid_Problem_Definition:
311  return illDefinedProblem;
312  case Ipopt::Invalid_Option:
313  case Ipopt::Invalid_Number_Detected:
314  return illegalOption;
315  case Ipopt::NonIpopt_Exception_Thrown:
316  return externalException;
317  case Ipopt::Internal_Error:
318  return exception;
319  case Ipopt::Solve_Succeeded:
320  case Ipopt::Feasible_Point_Found:
321  return solvedOptimal;
322  case Ipopt::Search_Direction_Becomes_Too_Small:
323  return doesNotConverge;
324  case Ipopt::Solved_To_Acceptable_Level:
325  return solvedOptimalTol;
326  case Ipopt::Infeasible_Problem_Detected:
327  return provenInfeasible;
328  case Ipopt::Diverging_Iterates:
329  return unbounded;
330  case Ipopt::Maximum_CpuTime_Exceeded:
331  return timeLimit;
332  default:
333  return exception;
334  }
335  }
336 
338 CoinWarmStart *
340 {
341  if(tnlp->x_init() == NULL || tnlp->duals_init() == NULL)
342  return NULL;
343  return new IpoptWarmStart(tnlp->num_variables(),
344  2*tnlp->num_variables() +
345  tnlp->num_constraints(),
346  tnlp->x_init(), tnlp->duals_init());
347 }
349  CoinWarmStart*
351  {
352  if (warmStartStrategy_==2) {
354  Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
355  return new IpoptWarmStart(tnlp, warm_starter);
356  }
357  else return new IpoptWarmStart(tnlp, NULL);
358  }
359 
360 
361  bool
362  IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
364  {
365  if (!warmstart && warmStartStrategy_)
366  return 0;
367  const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
368  if(ws == NULL) return 0;
369  if (ws->empty())//reset initial point and leave
370  {
372  return 1;
373  }
374  if(ws->dualSize() > 0){
375  tnlp->setDualsInit(ws->dualSize(), ws->dual());
376  enableWarmStart();
377  }
378  else
380 #ifndef NDEBUG
381  int numcols = tnlp->num_variables();
382  int numrows = tnlp->num_constraints();
383 #endif
384 
385  assert(numcols == ws->primalSize());
386  assert(2*numcols + numrows == ws->dualSize());
387  tnlp->setxInit(ws->primalSize(), ws->primal());
388 
389  if (IsValid(ws->warm_starter()))
390  tnlp->SetWarmStarter(ws->warm_starter());
391 
392  return 1;
393  }
394 
395  bool
396  IpoptSolver::warmStartIsValid(const CoinWarmStart * ws) const{
397  const IpoptWarmStart* iws = dynamic_cast<const IpoptWarmStart*>(ws);
398  if (iws && !iws->empty()) {
399  return true;
400  }
401  return false;
402  }
403 
404  CoinWarmStart *
406  {
407  return new IpoptWarmStart(1);
408  }
409 
410  void
412  {
413  enable_warm_start_ = true;
414  options_->SetStringValue("warm_start_init_point", "yes");
415  }
416 
417  void
419  {
420  enable_warm_start_ = false;
421  options_->SetStringValue("warm_start_init_point", "no");
422  }
423 
424 
425  void
427  {
428  options_->SetIntegerValue("print_level", default_log_level_, true, true);
429  }
430 
431 
432  void
434  {
435  options_->SetIntegerValue("print_level", log_level, true, true);
436  }
437 
438 
439  /*******************************************************************************/
440 // Class for throwing errors reported from Ipopt
441  /******************************************************************************/
442 
443  std::string
444  IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
445  "Solved to acceptable level",
446  "Infeasible problem detected",
447  "Search direction becomes too small",
448  "Diverging iterates",
449  "User requested stop",
450  "Maximum iterations exceeded",
451  "Restoration failed",
452  "Error in step computation",
453  "Not enough degrees of freedom",
454  "Invalid problem definition",
455  "Invalid option",
456  "Invalid number detected",
457  "Unrecoverable exception",
458  "NonIpopt exception thrown",
459  "Insufficient memory",
460  "Internal error"};
461 
462  const std::string &
464  {
465  if (errorNum() >=0)
466  return errorNames[errorNum()];
467  if (errorNum() == -1) return errorNames[6];
468  else if (errorNum() == -2) return errorNames[7];
469  else if (errorNum() == -3) return errorNames[8];
470  else if (errorNum() == -10) return errorNames[9];
471  else if (errorNum() == -11) return errorNames[10];
472  else if (errorNum() == -12) return errorNames[11];
473  else if (errorNum() == -13) return errorNames[12];
474  else if (errorNum() == -100) return errorNames[13];
475  else if (errorNum() == -101) return errorNames[14];
476  else if (errorNum() == -102) return errorNames[15];
477  else if (errorNum() == -199) return errorNames[16];
478  throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
479  }
480 
481  std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
482 
483  const std::string &
485  {
486  return solverName_;
487  }
488 
489 
490 
491 
492 }//end namespace Bonmin
virtual ~IpoptSolver()
Virtual destructor.
int default_log_level_
To record default log level.
virtual void setOutputToDefault()
turn off all output from the solver
Ipopt::SmartPtr< Ipopt::Journalist > journalist_
Storage of Journalist for output.
Class for storing warm start informations for Ipopt.
virtual bool setWarmStart(const CoinWarmStart *warm, Ipopt::SmartPtr< TMINLP2TNLP > tnlp)
Set the warm start in the solver.
Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions()
Get a pointer to RegisteredOptions (generally used to add new ones)
virtual void forceSolverOutput(int log_level)
turn on all output from the solver
virtual TNLPSolver::ReturnStatus OptimizeTNLP(const Ipopt::SmartPtr< Ipopt::TNLP > &tnlp)
Solves a problem expresses as a TNLP.
bool problemHadZeroDimension_
Flag to indicate if last problem solved had 0 dimension.
virtual int IterationCount()
Get the iteration count of the last optimization.
bool IsValid(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:465
This is a generic class for calling an NLP solver to solve a TNLP.
virtual const std::string & solverName() const
Return the name of the solver.
Ipopt::SmartPtr< IpoptInteriorWarmStarter > warm_starter() const
Accessor to warm start information obecjt.
double start_time_
Global start time.
double time_limit_
Global time limit.
virtual CoinWarmStart * getEmptyWarmStart() const
Solves a problem expresses as a TNLP.
static std::string solverName_
virtual Ipopt::SmartPtr< TNLPSolver > clone()
virtual copy constructor
void setMinlpDefaults(Ipopt::SmartPtr< Ipopt::OptionsList > Options)
Set default Ipopt parameters for use in a MINLP.
void fint fint fint real fint real real real real real real real real real * e
TNLPSolver::ReturnStatus solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
get Bonmin return status from Ipopt one.
int errorNum() const
Return error number.
virtual CoinWarmStart * getUsedWarmStart(Ipopt::SmartPtr< TMINLP2TNLP > tnlp) const
Get warm start used in last optimization.
virtual bool warmStartIsValid(const CoinWarmStart *ws) const
Check that warm start object is valid.
Ipopt::ApplicationReturnStatus optimizationStatus_
return status of last optimization.
virtual const std::string & errorName() const
Get the string corresponding to error.
Ipopt::SmartPtr< Ipopt::IpoptApplication > app_
Ipopt application.
virtual double CPUTime()
Get the CpuTime of the last optimization.
bool enable_warm_start_
flag remembering if we want to use warm start option
U * GetRawPtr(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:452
Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions_
Registered Options.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
ReturnStatus
Standard return statuses for a solver.
bool optimized_before_
flag remembering if we have call the Optimize method of the IpoptInterface before ...
virtual void enableWarmStart()
Enable the warm start options in the solver.
IpoptSolver(bool createEmpty=false)
Constructor.
bool BonminAbortAll
Definition: BonCbc.cpp:37
virtual CoinWarmStart * getWarmStart(Ipopt::SmartPtr< Bonmin::TMINLP2TNLP > tnlp) const
Get the warm start form the solver.
virtual TNLPSolver::ReturnStatus ReOptimizeTNLP(const Ipopt::SmartPtr< Ipopt::TNLP > &tnlp)
Resolves a problem expresses as a TNLP.
virtual bool Initialize(std::string params_file)
Initialize the TNLPSolver (read options from params_file)
static char prefix[100]
Definition: BM_lp.cpp:26
bool empty() const
Is this an empty warm start?
bool zeroDimension(const Ipopt::SmartPtr< Ipopt::TNLP > &tnlp, ReturnStatus &optimization_status)
Determine if problem is of dimension zero and if it is check if solution is feasible.
int warmStartStrategy_
Warm start strategy :
virtual void disableWarmStart()
Disable the warm start options in the solver.
Ipopt::SmartPtr< Ipopt::OptionsList > options_
List of Options.
const char * prefix()
Get the prefix.