source: branches/devel/Bonmin/src/Interfaces/Ipopt/BonIpoptSolver.cpp @ 104

Last change on this file since 104 was 104, checked in by pbonami, 13 years ago

Fixes too few degrees of freedom

File size: 9.4 KB
Line 
1// (C) Copyright International Business Machines (IBM) 2005
2// All Rights Reserved.
3// This code is published under the Common 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
15#include "BonIpoptInteriorWarmStarter.hpp"
16#include "BonIpoptWarmStart.hpp"
17
18namespace Bonmin{
19
20  std::string IpoptSolver::solverName_ = "Ipopt";
21
22
23  IpoptSolver::~IpoptSolver(){}
24
25  ///virtual constructor
26  TNLPSolver * 
27  IpoptSolver::createNew()
28  { return new IpoptSolver();}
29
30
31  void
32  IpoptSolver::Initialize(std::string params_file)
33  {
34    app_.Initialize(params_file);
35    app_.Options()->GetEnumValue("warm_start",warmStartStrategy_,"bonmin.");
36    setMinlpDefaults(app_.Options());
37  }
38
39  void
40  IpoptSolver::Initialize(std::istream &is)
41  {
42    app_.Initialize(is);
43    app_.Options()->GetEnumValue("warm_start",warmStartStrategy_,"bonmin.");
44    setMinlpDefaults(app_.Options());
45  }
46
47  TNLPSolver::ReturnStatus
48  IpoptSolver::OptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
49  {
50    TNLPSolver::ReturnStatus ret_status;
51    if(!zeroDimension(tnlp, ret_status))
52      {
53        optimizationStatus_ = app_.OptimizeTNLP(tnlp);
54      }
55    else
56      {
57        if(ret_status == solvedOptimal)
58          optimizationStatus_ = Ipopt::Solve_Succeeded;
59        else if(ret_status == provenInfeasible)
60          optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
61      }
62
63
64
65    return solverReturnStatus(optimizationStatus_);
66  }
67
68
69  TNLPSolver::ReturnStatus
70  IpoptSolver::ReOptimizeTNLP(const Ipopt::SmartPtr<Ipopt::TNLP> &tnlp)
71  {
72    TNLPSolver::ReturnStatus ret_status;
73    if(!zeroDimension(tnlp, ret_status))
74      {
75        optimizationStatus_ = app_.ReOptimizeTNLP(tnlp);
76      }
77    else
78      {
79        if(ret_status == solvedOptimal)
80          optimizationStatus_ = Ipopt::Solve_Succeeded;
81        else if(ret_status == provenInfeasible)
82          optimizationStatus_ = Ipopt::Infeasible_Problem_Detected;
83      }
84      return solverReturnStatus(optimizationStatus_);
85  }
86
87  Ipopt::SmartPtr<Ipopt::Journalist>
88  IpoptSolver::Jnlst()
89  {return app_.Jnlst();}
90
91  Ipopt::SmartPtr<Ipopt::RegisteredOptions>
92  IpoptSolver::RegOptions()
93  {
94    return app_.RegOptions();
95  }
96
97  Ipopt::SmartPtr<const Ipopt::OptionsList>
98  IpoptSolver::Options() const
99  {
100    return app_.Options();
101  }
102
103  Ipopt::SmartPtr<Ipopt::OptionsList>
104  IpoptSolver::Options()
105  {
106    return app_.Options();
107  }
108
109  /// Get the CpuTime of the last optimization.
110  double 
111  IpoptSolver::CPUTime()
112  {
113    const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_.Statistics();
114    if(IsValid(stats))
115      {
116        return stats->TotalCPUTime();
117      }
118    else
119      {
120        throw CoinError("No statistics available from Ipopt","CPUTime","Bonmin::IpoptSolver");
121      }
122  }
123
124  /// Get the iteration count of the last optimization.
125  int
126  IpoptSolver::IterationCount()
127  {
128    const Ipopt::SmartPtr<Ipopt::SolveStatistics>  stats = app_.Statistics();
129    if(IsValid(stats))
130      {
131        return stats->IterationCount();
132      }
133    else
134      {
135        throw CoinError("No statistics available from Ipopt","IterationCount","Bonmin::IpoptSolver");
136      }
137  }
138
139
140  void 
141  IpoptSolver::setMinlpDefaults(Ipopt::SmartPtr<Ipopt::OptionsList> Options){
142    Options->SetNumericValue("gamma_phi", 1e-8, true, true);
143    Options->SetNumericValue("gamma_theta", 1e-4, true, true);
144    Options->SetNumericValue("required_infeasibility_reduction", 0.1, true, true);
145    Options->SetStringValue("expect_infeasible_problem","yes", true, true);
146    Options->SetStringValue("mu_strategy", "adaptive", true, true);
147    Options->SetStringValue("mu_oracle","probing", true, true);
148    Options->SetIntegerValue("print_level",1, true, true);
149  }
150
151
152  ////////////////////////////////////////////////////////////////////
153  // Methods returning info on how the solution process terminated  //
154  ////////////////////////////////////////////////////////////////////
155  /// Are there a numerical difficulties?
156  TNLPSolver::ReturnStatus IpoptSolver::solverReturnStatus(Ipopt::ApplicationReturnStatus optimization_status) const
157  {
158 
159    switch(optimization_status){
160    case Ipopt::Maximum_Iterations_Exceeded:
161    case Ipopt::User_Requested_Stop:
162      return iterationLimit;
163    case Ipopt::Restoration_Failed:
164    case Ipopt::Error_In_Step_Computation:
165    case Ipopt::Unrecoverable_Exception:
166      return computationError;
167    case Ipopt::Not_Enough_Degrees_Of_Freedom:
168      return notEnoughFreedom;
169    case Ipopt::Invalid_Problem_Definition:
170      return illDefinedProblem;
171    case Ipopt::Invalid_Option:
172    case Ipopt::Invalid_Number_Detected:
173      return illegalOption;
174    case Ipopt::NonIpopt_Exception_Thrown:
175      return externalException;
176    case Ipopt::Insufficient_Memory:
177    case Ipopt::Internal_Error:
178      return exception;
179    case Ipopt::Solve_Succeeded:
180      return solvedOptimal;
181    case Ipopt::Search_Direction_Becomes_Too_Small:
182      std::cerr<<"Warning : need to verify that Search_Direction_Becomes_Too_Small is indeed Ok"<<std::endl;
183    case Ipopt::Solved_To_Acceptable_Level:
184      return solvedOptimalTol;
185    case Ipopt::Infeasible_Problem_Detected:
186      return provenInfeasible;
187    case Ipopt::Diverging_Iterates:
188      return unbounded;
189    default:
190      return exception;
191    }
192  }
193
194/// Get warmstarting information
195CoinWarmStart*
196IpoptSolver::getWarmStart(Ipopt::SmartPtr<TMINLP2TNLP> tnlp) const
197{
198  if(warmStartStrategy_) {
199    if(warmStartStrategy_==2) {
200        Ipopt::SmartPtr<IpoptInteriorWarmStarter> warm_starter =
201        Ipopt::SmartPtr<IpoptInteriorWarmStarter>(tnlp->GetWarmStarter());
202        return new IpoptWarmStart(tnlp, warm_starter);
203    }
204    else  return new IpoptWarmStart(tnlp, NULL);
205  }
206  else
207     return new IpoptWarmStart(tnlp->num_variables(), tnlp->num_constraints());
208}
209
210
211bool
212IpoptSolver::setWarmStart(const CoinWarmStart* warmstart,
213                          Ipopt::SmartPtr<TMINLP2TNLP> tnlp)
214{
215  if(!warmstart && warmStartStrategy_)
216    return 0;
217  const IpoptWarmStart * ws = dynamic_cast<const IpoptWarmStart*> (warmstart);
218  if(ws->empty())//reset initial point and leave
219  {
220    disableWarmStart();
221    return 1;
222  }
223  enableWarmStart();
224  int numcols = tnlp->num_variables();
225  int numrows = tnlp->num_constraints();
226  const double * colLow = tnlp->x_l();
227  const double * colUp = tnlp->x_u();
228  for(int i = 0; i < numcols ; i++) {
229    CoinWarmStartBasis::Status status = ws->getStructStatus(i);
230    if(status == CoinWarmStartBasis::atLowerBound) {
231      tnlp->setxInit(i,colLow[i]);
232      tnlp->setDualInit(i + numcols + numrows,0.);
233    }
234    else if(status == CoinWarmStartBasis::atUpperBound) {
235      tnlp->setxInit(i,colUp[i]);
236      tnlp->setDualInit(i + numrows,0.);
237    }
238    else {
239      tnlp->setDualInit(i + numrows,0.);
240      tnlp->setDualInit(i + numcols + numrows, 0.);
241    }
242  }
243  for(int i = 0; i < numrows ; i++) {
244    CoinWarmStartBasis::Status status = ws->getArtifStatus(i);
245    if(status == CoinWarmStartBasis::atLowerBound) {
246      tnlp->setDualInit(i,0.);
247    }
248  }
249  int nElem = ws->values()->getNumElements();
250  const int * inds = ws->values()->getIndices();
251  const double * elems = ws->values()->getElements();
252
253  for(int i = 0 ; i < nElem ; i++) {
254    tnlp->setxInit(inds[i],elems[i]);
255  }
256
257  if(IsValid(ws->warm_starter()))
258    tnlp->SetWarmStarter(ws->warm_starter());
259  return 1;
260}
261
262
263CoinWarmStart * 
264IpoptSolver::getEmptyWarmStart() const
265{return new IpoptWarmStart(1);}
266
267  void 
268  IpoptSolver::enableWarmStart()
269  {
270    Options()->SetStringValue("warm_start_init_point", "yes");
271  }
272
273  void 
274  IpoptSolver::disableWarmStart()
275  {
276    Options()->SetStringValue("warm_start_init_point", "no");
277  }
278
279
280  void
281  IpoptSolver::turnOffOutput(){
282  }
283
284
285  void
286  IpoptSolver::turnOnOutput(){
287  }
288
289
290/*******************************************************************************/
291// Class for throwing errors reported from Ipopt
292/******************************************************************************/
293
294std::string
295IpoptSolver::UnsolvedIpoptError::errorNames[17] ={"Solve succeeded",
296    "Solved to acceptable level",
297    "Infeasible problem detected",
298    "Search direction becomes too small",
299    "Diverging iterates",
300    "User requested stop",
301    "Maximum iterations exceeded",
302    "Restoration failed",
303    "Error in step computation",
304    "Not enough degrees of freedom",
305    "Invalid problem definition",
306    "Invalid option",
307    "Invalid number detected",
308    "Unrecoverable exception",
309    "NonIpopt exception thrown",
310    "Insufficient memory",
311    "Internal error"};
312
313const std::string &
314IpoptSolver::UnsolvedIpoptError::errorName() const
315{
316  if(errorNum() >=0)
317    return errorNames[errorNum()];
318  if(errorNum() == -1) return errorNames[6];
319  else if(errorNum() == -2) return errorNames[7];
320  else if(errorNum() == -3) return errorNames[8];
321  else if(errorNum() == -10) return errorNames[9];
322  else if(errorNum() == -11) return errorNames[10];
323  else if(errorNum() == -12) return errorNames[11];
324  else if(errorNum() == -13) return errorNames[12];
325  else if(errorNum() == -100) return errorNames[13];
326  else if(errorNum() == -101) return errorNames[14];
327  else if(errorNum() == -102) return errorNames[15];
328  else if(errorNum() == -199) return errorNames[16];
329  throw CoinError("UnsolvedError", "UnsolvedError::errorName()","Unrecognized optimization status in ipopt.");
330}
331
332std::string IpoptSolver::UnsolvedIpoptError::solverName_ = "Ipopt";
333
334const std::string &
335IpoptSolver::UnsolvedIpoptError::solverName() const
336{
337   return solverName_;
338}
339
340
341
342
343}//end namespace Bonmin
Note: See TracBrowser for help on using the repository browser.