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  }
37 
42  const std::string & prefix):
43  TNLPSolver(roptions, options, journalist, prefix),
44  problemHadZeroDimension_(false),
45  warmStartStrategy_(1),
46  enable_warm_start_(false),
47  optimized_before_(false)
48  {
50  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
51  }
52 
57  TNLPSolver(roptions, options, journalist, "bonmin."),
58  problemHadZeroDimension_(false),
59  warmStartStrategy_(1),
60  enable_warm_start_(false),
61  optimized_before_(false)
62  {
64  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions), options, journalist);
65  }
66 
68  {}
69 
71  TNLPSolver(other),
72  optimizationStatus_(other.optimizationStatus_),
73  problemHadZeroDimension_(other.problemHadZeroDimension_),
74  warmStartStrategy_(other.warmStartStrategy_),
75  enable_warm_start_(false),
76  optimized_before_(false){
77  app_ = new Ipopt::IpoptApplication(GetRawPtr(roptions_), options_, journalist_);
78  }
79 
83  {
84  Ipopt::SmartPtr<IpoptSolver> retval = new IpoptSolver(*this);
85  retval->app_->Initialize("");
86  retval->default_log_level_ = default_log_level_;
87  return GetRawPtr(retval);
88  }
89 
90 
91  bool
92  IpoptSolver::Initialize(std::string params_file)
93  {
94  Ipopt::ApplicationReturnStatus status =
95  app_->Initialize(params_file);
96  if (status != Ipopt::Solve_Succeeded) {
97  return false;
98  }
99  options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
101  optimized_before_ = false;
102  return true;
103  }
104 
105  bool
106  IpoptSolver::Initialize(std::istream &is)
107  {
108  Ipopt::ApplicationReturnStatus status =
109  app_->Initialize(is);
110  if (status != Ipopt::Solve_Succeeded) {
111  return false;
112  }
113  options_->GetEnumValue("warm_start",warmStartStrategy_,prefix());
114  setMinlpDefaults(app_->Options());
115  optimized_before_ = false;
116  return true;
117  }
118 
121  {
122 #if 0
123  printf("Global Time limit set to %g\n", time_limit_);
124  double local_time_limit = time_limit_ -
125  CoinCpuTime() + start_time_;
126  printf("Time limit set to %g\n", local_time_limit);
127  if(local_time_limit <= 0.){
128  optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
130  }
131 #endif
132  TNLPSolver::ReturnStatus ret_status;
133  if (!zeroDimension(tnlp, ret_status)) {
134 #if 0
135  if(time_limit_ < DBL_MAX){
136  options_->SetNumericValue("max_cpu_time", local_time_limit,
137  true, true);
138  }
139 #endif
141  optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
142  }
143  else {
144  optimizationStatus_ = app_->OptimizeTNLP(tnlp);
145  }
146  optimized_before_ = true;
147  problemHadZeroDimension_ = false;
148  }
149  else {
151  if (ret_status == solvedOptimal)
152  optimizationStatus_ = Ipopt::Solve_Succeeded;
153  else if (ret_status == provenInfeasible)
154  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
155  }
156 
157  if (BonminAbortAll)
158  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
159 
161  }
162 
163 
166  {
167 #if 0
168  printf("Global Time limit set to %g\n", time_limit_);
169  double local_time_limit = time_limit_ -
170  CoinCpuTime() + start_time_;
171  printf("Time limit set to %g\n", local_time_limit);
172  if(local_time_limit <= 0.){
173  optimizationStatus_ = Ipopt::Maximum_CpuTime_Exceeded;
175  }
176 #endif
177  TNLPSolver::ReturnStatus ret_status;
178  if (!zeroDimension(tnlp, ret_status)) {
179 #if 0
180  if(time_limit_ < DBL_MAX){
181  options_->SetNumericValue("max_cpu_time",
182  std::max(0., local_time_limit),
183  true, true);
184  }
185 #endif
186  if (optimized_before_) {
187  optimizationStatus_ = app_->ReOptimizeTNLP(tnlp);
188  }
189  else {
190  optimizationStatus_ = app_->OptimizeTNLP(tnlp);
191  }
192  problemHadZeroDimension_ = false;
193  optimized_before_ = true;
194  }
195  else {
197  if (ret_status == solvedOptimal)
198  optimizationStatus_ = Ipopt::Solve_Succeeded;
199  else if (ret_status == provenInfeasible)
200  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
201  }
202  if (BonminAbortAll)
203  optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
205  }
206 
208  double
210  {
212  return 0.;
213  }
214  else {
215  const Ipopt::SmartPtr<Ipopt::SolveStatistics> stats = app_->Statistics();
216  if (IsValid(stats)) {
217  return stats->TotalCpuTime();
218  }
219  else {
220  app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "No statistics available from Ipopt in Bonmin::IpoptSolver::CPUTime\n");
221  return 0.;
222  //throw CoinError("No statistics available from Ipopt","CPUTime","Bonmin::IpoptSolver");
223  }
224  }
225  }
226 
228  int
230  {
232  return 0;
233  }
234  else {
235  const Ipopt::SmartPtr<Ipopt::SolveStatistics> stats = app_->Statistics();
236  if (IsValid(stats)) {
237  return stats->IterationCount();
238  }
239  else {
240  app_->Jnlst()->Printf(Ipopt::J_WARNING, Ipopt::J_STATISTICS, "No statistics available from Ipopt in Bonmin::IpoptSolver::IterationCount\n");
241  return 0;
242  //throw CoinError("No statistics available from Ipopt","IterationCount","Bonmin::IpoptSolver");
243  }
244 
245  }
246  }
247 
248 
249  void
251  {
252  bool set = false;
253  double dummy_dbl;
254  int dummy_int;
255  set = Options->GetNumericValue("gamma_phi", dummy_dbl, "");
256  if(!set)
257  Options->SetNumericValue("gamma_phi", 1e-8, true, true);
258  set = Options->GetNumericValue("gamma_theta", dummy_dbl, "");
259  if(!set)
260  Options->SetNumericValue("gamma_theta", 1e-4, true, true);
261  set = Options->GetNumericValue("required_infeasibility_reduction", dummy_dbl, "");
262  if(!set)
263  Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
264  set = Options->GetEnumValue("expect_infeasible_problem",dummy_int, "");
265  if(!set)
266  Options->SetStringValue("expect_infeasible_problem","yes", true, true);
267  set = Options->GetEnumValue("mu_strategy", dummy_int, "");
268  if(!set)
269  Options->SetStringValue("mu_strategy", "adaptive", true, true);
270  set = Options->GetEnumValue("mu_oracle",dummy_int, "");
271  if(!set)
272  Options->SetStringValue("mu_oracle","probing", true, true);
273  if(!Options->GetIntegerValue("print_level",default_log_level_,"")) {
274  default_log_level_ = 1;
275  Options->SetIntegerValue("print_level",1, true, true);
276  }
277  }
278 
279 
281  // Methods returning info on how the solution process terminated //
284  TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
285  {
286 
287  switch (optimization_status) {
288  case Ipopt::Maximum_Iterations_Exceeded:
289  case Ipopt::User_Requested_Stop:
290  case Ipopt::Restoration_Failed:
291  return iterationLimit;
292  case Ipopt::Error_In_Step_Computation:
293  case Ipopt::Unrecoverable_Exception:
294  case Ipopt::Insufficient_Memory:
295  return computationError;
296  case Ipopt::Not_Enough_Degrees_Of_Freedom:
297  return notEnoughFreedom;
298  case Ipopt::Invalid_Problem_Definition:
299  return illDefinedProblem;
300  case Ipopt::Invalid_Option:
301  case Ipopt::Invalid_Number_Detected:
302  return illegalOption;
303  case Ipopt::NonIpopt_Exception_Thrown:
304  return externalException;
305  case Ipopt::Internal_Error:
306  return exception;
307  case Ipopt::Solve_Succeeded:
308  case Ipopt::Feasible_Point_Found:
309  return solvedOptimal;
310  case Ipopt::Search_Direction_Becomes_Too_Small:
311  return doesNotConverge;
312  case Ipopt::Solved_To_Acceptable_Level:
313  return solvedOptimalTol;
314  case Ipopt::Infeasible_Problem_Detected:
315  return provenInfeasible;
316  case Ipopt::Diverging_Iterates:
317  return unbounded;
318  case Ipopt::Maximum_CpuTime_Exceeded:
319  return timeLimit;
320  default:
321  return exception;
322  }
323  }
324 
326 CoinWarmStart *
328 {
329  if(tnlp->x_init() == NULL || tnlp->duals_init() == NULL)
330  return NULL;
331  return new IpoptWarmStart(tnlp->num_variables(),
332  2*tnlp->num_variables() +
333  tnlp->num_constraints(),
334  tnlp->x_init(), tnlp->duals_init());
335 }
337  CoinWarmStart*
339  {
340  if (warmStartStrategy_==2) {
342  Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
343  return new IpoptWarmStart(tnlp, warm_starter);
344  }
345  else return new IpoptWarmStart(tnlp, NULL);
346  }
347 
348 
349  bool
350  IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
352  {
353  if (!warmstart && warmStartStrategy_)
354  return 0;
355  const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
356  if(ws == NULL) return 0;
357  if (ws->empty())//reset initial point and leave
358  {
360  return 1;
361  }
362  if(ws->dualSize() > 0){
363  tnlp->setDualsInit(ws->dualSize(), ws->dual());
364  enableWarmStart();
365  }
366  else
368 #ifndef NDEBUG
369  int numcols = tnlp->num_variables();
370  int numrows = tnlp->num_constraints();
371 #endif
372 
373  assert(numcols == ws->primalSize());
374  assert(2*numcols + numrows == ws->dualSize());
375  tnlp->setxInit(ws->primalSize(), ws->primal());
376 
377  if (IsValid(ws->warm_starter()))
378  tnlp->SetWarmStarter(ws->warm_starter());
379 
380  return 1;
381  }
382 
383  bool
384  IpoptSolver::warmStartIsValid(const CoinWarmStart * ws) const{
385  const IpoptWarmStart* iws = dynamic_cast<const IpoptWarmStart*>(ws);
386  if (iws && !iws->empty()) {
387  return true;
388  }
389  return false;
390  }
391 
392  CoinWarmStart *
394  {
395  return new IpoptWarmStart(1);
396  }
397 
398  void
400  {
401  enable_warm_start_ = true;
402  options_->SetStringValue("warm_start_init_point", "yes");
403  }
404 
405  void
407  {
408  enable_warm_start_ = false;
409  options_->SetStringValue("warm_start_init_point", "no");
410  }
411 
412 
413  void
415  {
416  options_->SetIntegerValue("print_level", default_log_level_, true, true);
417  }
418 
419 
420  void
422  {
423  options_->SetIntegerValue("print_level", log_level, true, true);
424  }
425 
426 
427  /*******************************************************************************/
428 // Class for throwing errors reported from Ipopt
429  /******************************************************************************/
430 
431  std::string
432  IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
433  "Solved to acceptable level",
434  "Infeasible problem detected",
435  "Search direction becomes too small",
436  "Diverging iterates",
437  "User requested stop",
438  "Maximum iterations exceeded",
439  "Restoration failed",
440  "Error in step computation",
441  "Not enough degrees of freedom",
442  "Invalid problem definition",
443  "Invalid option",
444  "Invalid number detected",
445  "Unrecoverable exception",
446  "NonIpopt exception thrown",
447  "Insufficient memory",
448  "Internal error"};
449 
450  const std::string &
452  {
453  if (errorNum() >=0)
454  return errorNames[errorNum()];
455  if (errorNum() == -1) return errorNames[6];
456  else if (errorNum() == -2) return errorNames[7];
457  else if (errorNum() == -3) return errorNames[8];
458  else if (errorNum() == -10) return errorNames[9];
459  else if (errorNum() == -11) return errorNames[10];
460  else if (errorNum() == -12) return errorNames[11];
461  else if (errorNum() == -13) return errorNames[12];
462  else if (errorNum() == -100) return errorNames[13];
463  else if (errorNum() == -101) return errorNames[14];
464  else if (errorNum() == -102) return errorNames[15];
465  else if (errorNum() == -199) return errorNames[16];
466  throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
467  }
468 
469  std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
470 
471  const std::string &
473  {
474  return solverName_;
475  }
476 
477 
478 
479 
480 }//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.