exprAux.cpp
Go to the documentation of this file.
1 /* $Id: exprAux.cpp 592 2011-06-01 10:40:25Z pbelotti $
2  *
3  * Name: exprAux.cpp
4  * Author: Pietro Belotti
5  * Purpose: methods of the class of auxiliary variables
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExprAux.hpp"
12 #include "CouenneExprBound.hpp"
13 #include "CouenneExprMax.hpp"
14 #include "CouenneExprMin.hpp"
15 #include "CouenneCutGenerator.hpp"
16 #include "CouenneComplObject.hpp"
17 #include "CouenneJournalist.hpp"
18 
19 using namespace Couenne;
20 
21 namespace Couenne {
23 class Domain;
24 }
25 
26 //#define DEBUG
27 
28 // auxiliary expression Constructor
29 exprAux::exprAux (expression *image, int index, int rank,
30  enum intType isInteger, Domain *d,
31  enum auxSign sign):
32 
33  exprVar (index, d),
34  image_ (image),
35  rank_ (rank),
36  multiplicity_ (1),
37  integer_ (isInteger),
38  top_level_ (false),
39  sign_ (sign) {
40 
41  // do this later, in standardize()
42  // image_ -> getBounds (lb_, ub_);
43 
44  // getBounds (lb_, ub_); // !!!!!!!!
45 
46  // image_ -> getBounds (lb_, ub_);
47  // getBounds (lb_, ub_);
48 
49  // lb_ = new exprMax (new exprLowerBound (varIndex_), lb_);
50  // ub_ = new exprMin (new exprUpperBound (varIndex_), ub_);
53 }
54 
55 
58  enum auxSign sign):
59 
60  exprVar (-1, d),
61  image_ (image),
62  lb_ (NULL),
63  ub_ (NULL),
64  rank_ (-1),
65  multiplicity_ (0),
66  integer_ (Unset),
67  top_level_ (false),
68  sign_ (sign) {}
69 //(image -> isInteger () ? Integer : Continuous)
70 
71 
74  exprVar (e.varIndex_, d), // variables ? (*variables) [0] -> domain () : NULL),
75  image_ (e.image_ -> clone (d)),
76  rank_ (e.rank_),
77  multiplicity_ (e.multiplicity_),
78  integer_ (e.integer_),
79  top_level_ (e.top_level_),
80  sign_ (e.sign_) {
81 
82  // image_ -> getBounds (lb_, ub_);
83  // getBounds (lb_, ub_);
84 
85  // lb_ = new exprMax (new exprLowerBound (varIndex_), lb_);
86  // ub_ = new exprMin (new exprUpperBound (varIndex_), ub_);
87 
90 
91  //crossBounds ();
92 }
93 
94 
97  //printf ("deleting %x: ", this); fflush (stdout); print (); fflush (stdout);
98  if (image_) {
99  //printf (" [%x] ", image_); fflush (stdout); image_ -> print (); fflush (stdout);
100  //printf ("\n");
101  delete image_;
102  }
103  if (lb_) delete lb_;
104  if (ub_) delete ub_;
105 }
106 
107 
109 //void exprAux::getBounds (expression *&lb, expression *&ub) {
110 
111  // this replaces the previous
112  //
113  // image_ -> getBounds (lb0, ub0);
114  //
115  // which created large expression trees, now useless since all
116  // auxiliaries are standardized.
117 
118  // lb = lb_ -> clone ();//new exprLowerBound (varIndex_);
119  // ub = ub_ -> clone ();//new exprUpperBound (varIndex_);
120 // lb = new exprLowerBound (varIndex_, domain_);
121 // ub = new exprUpperBound (varIndex_, domain_);
122 //}
123 
124 
128 
129  expression *l0, *u0;
130 
131  image_ -> getBounds (l0, u0);
132 
133  //image_ -> getBounds (lb_, ub_);
134 
135  if (sign_ != expression::AUX_LEQ) lb_ = new exprMax (lb_, l0);
136  if (sign_ != expression::AUX_GEQ) ub_ = new exprMin (ub_, u0);
137 }
138 
139 
141 void exprAux::print (std::ostream &out, bool descend) const {
142 
143  if (descend)
144  image_ -> print (out, descend);
145  else {
146  if (integer_) out << "z_"; // TODO: should be isInteger instead of
147  // integer_. Change all "isInteger()"
148  // to "isInteger() const"
149  else out << "w_";
150  out << varIndex_;// << "<" << this << ">";
151  }
152 }
153 
154 
157 int exprAux::DepList (std::set <int> &deplist,
158  enum dig_type type) {
159 
160  if (type == ORIG_ONLY)
161  return image_ -> DepList (deplist, type);
162 
163  if (deplist.find (varIndex_) == deplist.end ())
164  deplist.insert (varIndex_);
165  else return 0;
166 
167  if (type == STOP_AT_AUX)
168  return 1;
169 
170  return 1 + image_ -> DepList (deplist, type);
171 }
172 
173 
176 
177  if (((image_ -> Type () == AUX) ||
178  (image_ -> Type () == VAR)) &&
180 
181  --multiplicity_;
182  expression *ret = image_;
183  image_ = NULL;
184  return ret;
185  }
186 
187  return NULL;
188 }
189 
190 
191 // generate cuts for expression associated with this auxiliary
192 
193 void exprAux::generateCuts (OsiCuts &cs, const CouenneCutGenerator *cg,
194  t_chg_bounds *chg, int,
195  CouNumber, CouNumber) {
196  //#ifdef DEBUG
197  static bool warned_large_coeff = false;
198  int nrc = cs.sizeRowCuts (), ncc = cs.sizeColCuts ();
199  //#endif
200 
201  /*
202  if ((!(cg -> isFirst ())) &&
203  ((l = domain_ -> lb (varIndex_)) > -COUENNE_INFINITY) &&
204  ((u = domain_ -> ub (varIndex_)) < COUENNE_INFINITY) &&
205  (fabs (u-l) < COUENNE_EPS))
206  cg -> createCut (cs, (l+u)/2., 0, varIndex_, 1.);
207  else
208  */
209  image_ -> generateCuts (this, /*si,*/ cs, cg, chg);
210 
211  // check if cuts have coefficients, rhs too large or too small
212 
213  //#ifdef DEBUG
214 
215  if (cg -> Jnlst () -> ProduceOutput (Ipopt::J_DETAILED, J_CONVEXIFYING)) {
216  if (cg -> Jnlst () -> ProduceOutput (Ipopt::J_STRONGWARNING, J_CONVEXIFYING) &&
217  (warned_large_coeff)) {
218  for (int jj=nrc; jj < cs.sizeRowCuts (); jj++) {
219 
220  OsiRowCut *cut = cs.rowCutPtr (jj);
221  CoinPackedVector row = cut -> row ();
222 
223  int n = cut -> row (). getNumElements();
224  const double *el = row. getElements ();
225  const int *ind = row. getIndices ();
226  double rhs = cut -> rhs ();
227 
228  while (n--) {
229  if (fabs (el [n]) > COU_MAX_COEFF) {
230  printf ("Couenne, warning: coefficient too large %g x%d: ", el [n], ind [n]);
231  cut -> print ();
232  warned_large_coeff = true;
233  break;
234  }
235 
236  if (fabs (rhs) > COU_MAX_COEFF) {
237  printf ("Couenne, warning: rhs too large (%g): ", rhs);
238  cut -> print ();
239  warned_large_coeff = true;
240  break;
241  }
242  }
243  }
244  }
245 
246  // if (!(cg -> isFirst ()))
247  if ((nrc < cs.sizeRowCuts ()) ||
248  (ncc < cs.sizeColCuts ()))
249  {
250  printf ("---------------- ConvCut: ");
251  print (std::cout);
252  printf (" %c= ",
253  sign () == expression::AUX_EQ ? ':' :
254  sign () == expression::AUX_LEQ ? '<' : '>');
255  image_ -> print (std::cout);
256 
257  printf (" %g [%g,%g]. ",
258  domain_ -> x (varIndex_),
259  domain_ -> lb (varIndex_),
260  domain_ -> ub (varIndex_));
261 
262  int index;
263  if ((image_ -> Argument ()) &&
264  ((index = image_ -> Argument () -> Index ()) >= 0))
265  printf ("%g [%g,%g] ",
266  domain_ -> x (index),
267  domain_ -> lb (index),
268  domain_ -> ub (index));
269  else if (image_ -> ArgList ())
270  for (int i=0; i<image_ -> nArgs (); i++)
271  if ((index = image_ -> ArgList () [i] -> Index ()) >= 0)
272  printf ("%g [%g,%g] ",
273  domain_ -> x (index),
274  domain_ -> lb (index),
275  domain_ -> ub (index));
276  printf ("\n");
277 
278  for (int jj = nrc; jj < cs.sizeRowCuts (); jj++) cs.rowCutPtr (jj) -> print ();
279  for (int jj = ncc; jj < cs.sizeColCuts (); jj++) cs.colCutPtr (jj) -> print ();
280  }
281  }
282  //#endif
283 
285 
286 #if 0
287  draw_cuts (cs, cg, nrc, this, image_);
288 #endif
289 }
290 
291 
295  CouenneProblem *p,
296  Bonmin::BabSetupBase *base,
297  JnlstPtr jnlst) {
298 
299  // todo: this is an expression method
300 
301  // create Complementary objects for variable if:
302 
303  if ((image_ -> code () == COU_EXPRMUL) && // it's a product x3 = x1 x2
304 
305  (image_ -> ArgList () [0] -> Index () >= 0) && // first operand is a variable
306  (image_ -> ArgList () [1] -> Index () >= 0) && // second operand is a variable
307 
308  (
309  ((fabs (lb ()) < COUENNE_EPS) && (fabs (ub ()) < COUENNE_EPS)) // it's defined as x1 x2 = 0
310  || // OR
311  (top_level_ && // x3 is the lhs of a constraint
312  ((((fabs (lb ()) < COUENNE_EPS) && ( ub () > COUENNE_INFINITY)) || // and (x1 x2 >= 0
313  (( lb () < -COUENNE_INFINITY) && (fabs (ub ()) < COUENNE_EPS ))))) // or x1 x2 <= 0)
314  )
315  ) {
316 
317  // it's a complementarity constraint object!
318 
319  // generalizing: now a complementarity constraint object is any
320  // constraint of the form
321  //
322  // x_i * x_j >= 0 or
323  // x_i * x_j <= 0 or
324  // x_i * x_j = 0
325  //
326  // In fact, for all these cases branching is as straightforward as
327  // the old one, which was defined on equality only.
328  //
329  // Define the "sign" of the object as
330  //
331  // -1: <=
332  // +1: >=
333  // 0: =
334 
335  return new CouenneComplObject (c, p, this, base, jnlst,
336  lb () < -1 ? -1 :
337  ub () > 1 ? 1 : 0);
338  }
339  else
340  return new CouenneObject (c, p, this, base, jnlst);
341 }
Cut Generator for linear convexifications.
enum intType integer_
is this variable integer?
int multiplicity_
number of appearances of this aux in the formulation.
OsiObject for auxiliary variables $w=f(x)$.
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void crossBounds()
Get lower and upper bound of an expression (if any)
Definition: exprAux.cpp:127
enum auxSign sign_
&quot;sign&quot; of the defining constraint
virtual enum expr_type code()
code for comparison
void draw_cuts(OsiCuts &, const CouenneCutGenerator *, int, expression *, expression *)
allow to draw function within intervals and cuts introduced
Definition: drawCuts.cpp:21
Domain * domain_
Pointer to a descriptor of the current point/bounds.
OsiObject for complementarity constraints .
void generateCuts(OsiCuts &, const CouenneCutGenerator *, t_chg_bounds *=NULL, int=-1, CouNumber=-COUENNE_INFINITY, CouNumber=COUENNE_INFINITY)
generate cuts for expression associated with this auxiliary
Definition: exprAux.cpp:193
const Ipopt::EJournalCategory J_CONVEXIFYING(Ipopt::J_USER3)
expression * simplify()
simplify
Definition: exprAux.cpp:175
virtual expression * Argument() const
return argument (when applicable, i.e., with univariate functions)
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.
auxSign
&quot;sign&quot; of the constraint defining an auxiliary.
virtual ~exprAux()
Destructor.
Definition: exprAux.cpp:96
virtual CouNumber & ub()
Get/set upper bound value.
virtual void print(std::ostream &=std::cout, bool=false) const
Print expression.
Definition: exprAux.cpp:141
enum nodeType Type() const
Node type.
Class for MINLP problems with symbolic information.
#define COU_MAX_COEFF
intType
integrality type of an auxiliary variable: unset, continuous, integer
#define COUENNE_EPS
int DepList(std::set< int > &deplist, enum dig_type type=ORIG_ONLY)
fill in the set with all indices of variables appearing in the expression
Definition: exprAux.cpp:157
expression * lb_
lower bound, a function of the associated expression and the bounds on the variables in the expressio...
virtual void getBounds(expression *&, expression *&)
Get expressions of lower and upper bound of an expression (if any)
Definition: exprVar.cpp:22
virtual enum auxSign sign() const
return its sign in the definition constraint
CouenneObject * properObject(CouenneCutGenerator *c, CouenneProblem *p, Bonmin::BabSetupBase *base, JnlstPtr jnlst)
return proper object to handle expression associated with this variable (NULL if this is not an auxil...
Definition: exprAux.cpp:294
double CouNumber
main number type in Couenne
int Index() const
Get variable index in problem.
#define COUENNE_INFINITY
Auxiliary variable.
dig_type
type of digging when filling the dependence list
variable-type operator
virtual int nArgs() const
return number of arguments (when applicable, that is, with N-ary functions)
Expression base class.
exprAux(expression *, int, int, intType=Unset, Domain *=NULL, enum auxSign=expression::AUX_EQ)
Constructor.
Definition: exprAux.cpp:29
bool top_level_
True if this variable replaces the lhs of a constraint, i.e., if it is a top level variable in the DA...
expression * ub_
upper bound, a function of the associated expression and the bounds on the variables in the expressio...
int varIndex_
The index of the variable.
expression * image_
The expression associated with this auxiliary variable.
void fint * n
These are bound expression classes.
real c
virtual expression ** ArgList() const
return arglist (when applicable, that is, with N-ary functions)
Define a dynamic point+bounds, with a way to save and restore previous points+bounds through a LIFO s...
virtual CouNumber & lb()
Get/set lower bound value.
void fint fint fint real fint real * x
bool isInteger(CouNumber x)
is this number integer?