BonOaNlpOptim.cpp
Go to the documentation of this file.
1 // (C) Copyright Carnegie Mellon University 2005
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // P. Bonami, Carnegie Mellon University
7 //
8 // Date : 05/26/2005
9 
10 #include "BonOaNlpOptim.hpp"
11 #include "OsiAuxInfo.hpp"
12 #include "CbcModel.hpp"
13 #include "BonBabInfos.hpp"
14 #include "BonCbc.hpp"
15 
16 namespace Bonmin
17 {
18  static const char * txt_id = "NLP relax. for OA";
19 
22  int maxDepth, bool addOnlyViolated, bool global)
23  :
24  CglCutGenerator(),
25  nlp_(si),
26  maxDepth_(maxDepth),
27  nSolve_(0),
28  addOnlyViolated_(addOnlyViolated),
29  global_(global)
30  {
31  handler_ = new CoinMessageHandler();
32  handler_ -> setLogLevel(1);
34  }
35 
37  CglCutGenerator(),
38  nlp_(b.nonlinearSolver()),
39  maxDepth_(1000),
40  nSolve_(0)
41  {
42  int ivalue;
43  b.options()->GetEnumValue("add_only_violated_oa", ivalue,b.prefix());
44  addOnlyViolated_ = ivalue;
45  b.options()->GetEnumValue("oa_cuts_scope", ivalue,b.prefix());
46  global_ = ivalue;
47 
48  b.options()->GetIntegerValue("nlp_solve_max_depth", maxDepth_,b.prefix());
49  b.options()->GetNumericValue("nlp_solves_per_depth", solves_per_level_,b.prefix());
50  handler_ = new CoinMessageHandler();
51  handler_ -> setLogLevel(1);
53  }
55  void
57 
58  {
59  nlp_ = si;
60  }
62  void
63  OaNlpOptim::generateCuts( const OsiSolverInterface & si, OsiCuts & cs,
64  const CglTreeInfo info) {
65  if (nlp_ == NULL) {
66  CoinError("Error in cut generator for outer approximation no ipopt NLP assigned", "generateCuts", "OaNlpOptim");
67  }
68 
69  int numcols = nlp_->getNumCols();
70 
71  //Get the continuous solution
72  //const double *colsol = si.getColSolution();
73  //Check for integer feasibility
74  if(!info.inTree || info.pass > 0) return;
75 #if 1
76  BabInfo * babInfo = dynamic_cast<BabInfo *> (si.getAuxiliaryInfo());
77  assert(babInfo);
78  assert(babInfo->babPtr());
79  const CbcNode * node = babInfo->babPtr()->model().currentNode();
80  int level = (node == NULL) ? 0 : babInfo->babPtr()->model().currentNode()->depth();
81  if (info.level > maxDepth_)
82  return;
83  if(solves_per_level_ < 1e10){
84  double rand = CoinDrand48();
85  double score = pow(2.,-level)*solves_per_level_;
86  //printf("depth %i, score %g , rand %g\n", level, score, rand);
87  if (score <= rand)
88  return;
89  }
90 #endif
91  //Fix the variable which have to be fixed, after having saved the bounds
92  double * saveColLb = new double[numcols];
93  double * saveColUb = new double[numcols];
94  CoinCopyN(nlp_->getColLower(), numcols , saveColLb);
95  CoinCopyN(nlp_->getColUpper(), numcols , saveColUb);
96  for (int i = 0; i < numcols ; i++) {
97  if (nlp_->isInteger(i)) {
98  nlp_->setColBounds(i,si.getColLower()[i],si.getColUpper()[i]);
99  }
100  }
101 
102  //Now solve the NLP get the cuts, reset bounds and get out
103 
104  // nlp_->turnOnIpoptOutput();
105  nSolve_++;
106  nlp_->resolve(txt_id);
107  const double * violatedPoint = (addOnlyViolated_)? si.getColSolution():
108  NULL;
109  nlp_->getOuterApproximation(cs, 1, violatedPoint,global_);
110  if (nlp_->isProvenOptimal()) {
111  handler_->message(LP_ERROR,messages_)
112  <<nlp_->getObjValue()-si.getObjValue()<<CoinMessageEol;
113  bool feasible = 1;
114  const double * colsol2 = nlp_->getColSolution();
115  for (int i = 0 ; i < numcols && feasible; i++) {
116  if (nlp_->isInteger(i)) {
117  if (fabs(colsol2[i] - floor(colsol2[i] + 0.5) ) > 1e-07)
118  feasible = 0;
119  }
120  }
121  if (feasible ) {
122 #if 1
123  // Also store into solver
124  OsiAuxInfo * auxInfo = si.getAuxiliaryInfo();
125  OsiBabSolver * auxiliaryInfo = dynamic_cast<OsiBabSolver *> (auxInfo);
126  if (auxiliaryInfo) {
127  double * lpSolution = new double[numcols + 1];
128  CoinCopyN(colsol2, numcols, lpSolution);
129  lpSolution[numcols] = nlp_->getObjValue();
130  auxiliaryInfo->setSolution(lpSolution, numcols + 1, lpSolution[numcols]);
131  delete [] lpSolution;
132  }
133  else
134  fprintf(stderr,"No auxiliary info in nlp solve!\n");
135 #endif
136 
137  }
138  }
139  else if (nlp_->isAbandoned() || nlp_->isIterationLimitReached()) {
140  throw CoinError("Unsolved NLP ... exit", "generateCuts", "OaNlpOptim");
141  }
142  else {
143  // //Add an infeasibility local constraint
144  // CoinPackedVector v;
145  // double rhs = 1.;
146  // for(int i = 0; i < numcols ; i++)
147  // {
148  // if(nlp_->isInteger(i) && (si.getColUpper()[i] - si.getColLower()[i] < 0.9))
149  // {
150  // double value = floor(colsol[i] + 0.5);
151  // assert(fabs(colsol[i]-value)<1e-8 && value >= -1e-08 && value <= 1+ 1e08);
152  // v.insert(i, -(2*value - 1));
153  // rhs -= value;
154  // }
155  // }
156  // OsiRowCut cut;
157  // cut.setRow(v);
158  // cut.setLb(rhs);
159  // cut.setUb(1e300);
160  // cut.setGloballyValid();
161  // cs.insert(cut);
162  }
163  for (int i = 0; i < numcols ; i++) {
164  if (nlp_->isInteger(i)) {
165  nlp_->setColBounds(i,saveColLb[i],saveColUb[i]);
166  }
167  }
168 #if 0
169  nlp_->deleteLastRows(numberCuts);
170 #endif
171  delete [] saveColLb;
172  delete [] saveColUb;
173  }
174 
175  void
177  {
178  roptions->SetRegisteringCategory("NLP solves in hybrid algorithm (B-Hyb)", RegisteredOptions::BonminCategory);
179  roptions->AddLowerBoundedIntegerOption("nlp_solve_frequency",
180  "Specify the frequency (in terms of nodes) at which NLP relaxations are solved in B-Hyb.",
181  0,10,
182  "A frequency of 0 amounts to to never solve the NLP relaxation.");
183  roptions->setOptionExtraInfo("nlp_solve_frequency",1);
184  roptions->AddLowerBoundedIntegerOption("nlp_solve_max_depth",
185  "Set maximum depth in the tree at which NLP relaxations are solved in B-Hyb.",
186  0,10,
187  "A depth of 0 amounts to to never solve the NLP relaxation.");
188  roptions->setOptionExtraInfo("nlp_solve_max_depth",1);
189  roptions->AddLowerBoundedNumberOption("nlp_solves_per_depth",
190  "Set average number of nodes in the tree at which NLP relaxations are solved in B-Hyb for each depth.",
191  0.,false,1e100);
192  roptions->setOptionExtraInfo("nlp_solves_per_depth",1);
193  }
194 
195 
196 }/* End namespace Bonmin. */
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register OaNlpOptim options.
bool addOnlyViolated_
Add only violated cuts?
virtual bool isAbandoned() const
Are there a numerical difficulties?
void getOuterApproximation(OsiCuts &cs, int getObj, const double *x2, bool global)
Get the outer approximation constraints at the current optimal point.
void assignInterface(OsiTMINLPInterface *si)
Assign an OsiTMINLPInterface.
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
virtual bool isInteger(int columnNumber) const
Return true if column is integer.
void setLogLevel(int value)
set log level
virtual int getNumCols() const
Get number of columns.
virtual bool isProvenOptimal() const
Is optimality proven?
double solves_per_level_
Average number of nodes per level in tree.
virtual double getObjValue() const
Get objective function value (can&#39;t use default)
OsiTMINLPInterface * nlp_
Pointer to the Ipopt interface.
virtual const double * getColSolution() const
Get pointer to array[getNumCols()] of primal solution vector.
void fint fint fint real fint real real real real real real real real real * e
A class to have all elements necessary to setup a branch-and-bound.
bool global_
Add cuts as global?
CoinMessageHandler * handler_
messages handler.
virtual void resolve()
Resolve the continuous relaxation after problem modification.
virtual bool isIterationLimitReached() const
Iteration limit reached?
CoinMessages messages_
handler
Bab * babPtr()
Pointer to the branch-and-bound algorithm (to access CbcModel).
Definition: BonBabInfos.hpp:44
int nSolve_
Number of NLP resolution done.
virtual const double * getColUpper() const
Get pointer to array[getNumCols()] of column upper bounds.
int maxDepth_
maximum depth at which generate cuts
Output messages for Outer approximation cutting planes.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
static const char * txt_id
OaNlpOptim(OsiTMINLPInterface *si=NULL, int maxDepth=10, bool addOnlyViolated=false, bool globalCuts=true)
Default constructor.
return b
Definition: OSdtoa.cpp:1719
const char * prefix() const
Get prefix to use for options.
const CbcModel & model() const
Get cbc model used to solve.
Definition: BonCbc.hpp:87
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info)
cut generation method