CouenneCutGenerator.cpp
Go to the documentation of this file.
1 /* $Id: CouenneCutGenerator.cpp 748 2011-07-28 16:13:32Z pbelotti $
2  *
3  * Name: CouenneCutGenerator.cpp
4  * Author: Pietro Belotti
5  * Purpose: define a class of convexification procedures
6  *
7  * (C) Carnegie-Mellon University, 2006-09.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CglCutGenerator.hpp"
12 
13 #include "CouenneCutGenerator.hpp"
14 
15 #include "CouenneProblem.hpp"
16 #include "CouenneChooseStrong.hpp"
18 
19 #include "CbcTree.hpp"
20 #include "BonCbc.hpp"
21 #include "CouenneRecordBestSol.hpp"
22 
23 using namespace Ipopt;
24 using namespace Couenne;
25 
27 CouenneCutGenerator::CouenneCutGenerator (Bonmin::OsiTMINLPInterface *nlp,
29  CouenneProblem *problem,
30  struct ASL *asl):
31 
32  CglCutGenerator (),
33 
34  firstcall_ (true),
35  problem_ (problem),
36  nrootcuts_ (0),
37  ntotalcuts_ (0),
38  septime_ (0),
39  objValue_ (- DBL_MAX),
40  nlp_ (nlp),
41  BabPtr_ (NULL),
42  infeasNode_ (false),
43  jnlst_ (base ? base -> journalist () : NULL),
44  rootTime_ (-1.) {
45 
46  if (base) {
47 
48  base -> options () -> GetIntegerValue ("convexification_points", nSamples_, "couenne.");
49 
50  std::string s;
51 
52  base -> options () -> GetStringValue ("convexification_type", s, "couenne.");
53  if (s == "current-point-only") convtype_ = CURRENT_ONLY;
54  else if (s == "uniform-grid") convtype_ = UNIFORM_GRID;
56 
57  base -> options () -> GetStringValue ("violated_cuts_only", s, "couenne.");
58  addviolated_ = (s == "yes");
59 
60  base -> options () -> GetStringValue ("check_lp", s, "couenne.");
61  check_lp_ = (s == "yes");
62 
63  base -> options () -> GetStringValue ("enable_lp_implied_bounds", s, "couenne.");
64  enable_lp_implied_bounds_ = (s == "yes");
65 
66  } else {
67 
68  nSamples_ = 4;
70  addviolated_ = true;
71  check_lp_ = false;
73  }
74 
75  lastPrintLine = -1;
76 
77  //if (asl) // deal with problems not originating from AMPL
78  //problem_ = new CouenneProblem (asl, base, jnlst_);
79 }
80 
81 
84 {}//if (problem_) delete problem_;}
85 
86 
89 
90  CglCutGenerator (src),
91 
92  firstcall_ (src. firstcall_),
93  addviolated_ (src. addviolated_),
94  convtype_ (src. convtype_),
95  nSamples_ (src. nSamples_),
96  problem_ (src. problem_),// -> clone ()),
97  nrootcuts_ (src. nrootcuts_),
98  ntotalcuts_ (src. ntotalcuts_),
99  septime_ (src. septime_),
100  objValue_ (src. objValue_),
101  nlp_ (src. nlp_),
102  BabPtr_ (src. BabPtr_),
103  infeasNode_ (src. infeasNode_),
104  jnlst_ (src. jnlst_),
105  rootTime_ (src. rootTime_),
106  check_lp_ (src. check_lp_),
107  enable_lp_implied_bounds_ (src.enable_lp_implied_bounds_),
108  lastPrintLine(src.lastPrintLine)
109 {}
110 
111 
112 #define MAX_SLOPE 1e3
113 
115 int CouenneCutGenerator::addSegment (OsiCuts &cs, int wi, int xi,
116  CouNumber x1, CouNumber y1,
117  CouNumber x2, CouNumber y2, int sign) const {
118 
119  if (fabs (x2-x1) < COUENNE_EPS) {
120  if (fabs (y2-y1) > MAX_SLOPE * COUENNE_EPS)
121  jnlst_->Printf(J_WARNING, J_CONVEXIFYING,
122  "warning, discontinuity of %e over an interval of %e\n", y2-y1, x2-x1);
123  //else return createCut (cs, y2, (int) 0, wi, 1.);
124  }
125 
126  CouNumber dx = x2-x1, dy = y2-y1;
127 
128  // return createCut (cs, y1 + oppslope * x1, sign, wi, 1., xi, oppslope);
129  return createCut (cs, y1*dx - dy*x1, (dx>0) ? sign : -sign, wi, dx, xi, -dy);
130 }
131 
132 
134 int CouenneCutGenerator::addTangent (OsiCuts &cs, int wi, int xi,
136  CouNumber slope, int sign) const
137  {return createCut (cs, w - slope * x, sign, wi, 1., xi, - slope);}
138 
139 
142  {return problem_ -> nVars ();}
143 
144 
147 
148  roptions -> SetRegisteringCategory ("Couenne options", Bonmin::RegisteredOptions::CouenneCategory);
149 
150  roptions -> AddLowerBoundedIntegerOption
151  ("convexification_cuts",
152  "Specify the frequency (in terms of nodes) at which couenne ecp cuts are generated.",
153  -99,1,
154  "A frequency of 0 amounts to never solve the NLP relaxation.");
155 
156  roptions -> AddStringOption2
157  ("check_lp",
158  "Check all LPs through an independent call to OsiClpSolverInterface::initialSolve()",
159  "no",
160  "no","",
161  "yes","");
162 
163  roptions -> AddStringOption3
164  ("convexification_type",
165  "Determines in which point the linear over/under-estimator are generated",
166  "current-point-only",
167  "current-point-only","Only at current optimum of relaxation",
168  "uniform-grid","Points chosen in a uniform grid between the bounds of the problem",
169  "around-current-point","At points around current optimum of relaxation",
170  "For the lower envelopes of convex functions, this is the number of points where a supporting hyperplane is generated. "
171  "This only holds for the initial linearization, as all other linearizations only add at most one cut per expression."
172  );
173 
174  roptions -> AddLowerBoundedIntegerOption
175  ("convexification_points",
176  "Specify the number of points at which to convexify when convexification type "
177  "is uniform-grid or around-current-point.",
178  0,4,
179  "");
180 
181  roptions -> AddStringOption2
182  ("violated_cuts_only",
183  "Yes if only violated convexification cuts should be added",
184  "yes",
185  "no","",
186  "yes","");
187 
188  roptions -> AddStringOption2
189  ("enable_lp_implied_bounds",
190  "Enable OsiSolverInterface::tightenBounds () -- warning: it has caused "
191  "some trouble to Couenne",
192  "no",
193  "no","",
194  "yes","");
195 
196  roptions -> AddStringOption3
197  ("multilinear_separation",
198  "Separation for multilinear terms",
199  "tight",
200  "none", "No separation -- just use the four McCormick inequalities",
201  "simple", "Use one considering lower curve only",
202  "tight", "Use one considering both curves pi(x) = l_{k+1} and pi(x) = u_{k+1}",
203  "Type of separation for multilinear terms where the dependent variable is also bounded"
204  );
205 }
206 
207 /*********************************************************************/
209 
210  double cbcLb = BabPtr_->model().getBestPossibleObjValue();
211  double lpVal = BabPtr_->model().solver()->getObjValue();
212  int nbNodes = BabPtr_->model().getNodeCount();
213  int nbNodesRem = BabPtr_->model().tree()->size();
214  int depth = BabPtr_->model().currentDepth();
216 
217  if(rs->getHasSol()) {
218  double bestSolVal = rs->getVal();
219  printf("%10d %8d %6d %10.6f %10.6f %10.6f\n",
220  nbNodes, nbNodesRem, depth, cbcLb, lpVal, bestSolVal);
221  }
222  else {
223  printf("%10d %8d %6d %10.6f %10.6f ----------\n",
224  nbNodes, nbNodesRem, depth, cbcLb, lpVal);
225  }
226  problem_->doPrint_ = true;
227  if((depth < problem_->minDepthPrint_) ||
228  (nbNodes < problem_->minNodePrint_)) {
229  problem_->doPrint_ = false;
230  }
231  /***
232  if(depth > 200) {
233  printf("CouenneCutGenerator::printLineInfo(): exit on depth\n");
234  exit(1);
235  }
236  ***/
237 } /* printLineInfo */
Cut Generator for linear convexifications.
#define MAX_SLOPE
bool addviolated_
True if we should add the violated cuts only, false if all of them should be added.
CouenneCutGenerator(Bonmin::OsiTMINLPInterface *=NULL, Bonmin::BabSetupBase *base=NULL, CouenneProblem *=NULL, struct ASL *=NULL)
constructor
ULong x2
Definition: OSdtoa.cpp:1776
int lastPrintLine
Running count of printed info lines.
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
enum conv_type convtype_
what kind of sampling should be performed?
bool check_lp_
Check all generated LPs through an independent call to OsiClpSolverInterface::initialSolve() ...
const Ipopt::EJournalCategory J_CONVEXIFYING(Ipopt::J_USER3)
JnlstPtr jnlst_
SmartPointer to the Journalist.
void printLineInfo() const
print node, depth, LB/UB/LP info
int addTangent(OsiCuts &, int, int, CouNumber, CouNumber, CouNumber, int) const
add tangent at given poing (x,w) with given slope
A class to have all elements necessary to setup a branch-and-bound.
ULong x1
Definition: OSdtoa.cpp:1776
CouenneRecordBestSol * getRecordBestSol() const
returns recorded best solution
int createCut(OsiCuts &, CouNumber, CouNumber, int, CouNumber, int=-1, CouNumber=0., int=-1, CouNumber=0., bool=false) const
create cut and check violation. Insert and return status
Definition: createCuts.cpp:32
Class for MINLP problems with symbolic information.
bool enable_lp_implied_bounds_
Take advantage of OsiClpSolverInterface::tightenBounds (), known to have caused some problems some ti...
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
#define COUENNE_EPS
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Add list of options to be read from file.
double CouNumber
main number type in Couenne
int getnvars() const
total number of variables (original + auxiliary)
Bonmin::Bab * BabPtr_
pointer to the Bab object (used to retrieve the current primal bound through bestObj()) ...
CouenneProblem * problem_
pointer to symbolic repr. of constraint, variables, and bounds
int addSegment(OsiCuts &, int, int, CouNumber, CouNumber, CouNumber, CouNumber, int) const
Add half-plane through (x1,y1) and (x2,y2) – resp.
void fint fint fint real fint real real real real real real real real * w
int nSamples_
how many cuts should be added for each function?
const CbcModel & model() const
Get cbc model used to solve.
Definition: BonCbc.hpp:87
void fint fint fint real fint real * x