conv-exprGroup.cpp
Go to the documentation of this file.
1 /* $Id: conv-exprGroup.cpp 848 2012-05-10 21:47:38Z pbelotti $
2  *
3  * Name: conv-exprGroup.cpp
4  * Author: Pietro Belotti
5  * Purpose: implementation of convexification methods for exprGroup
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "OsiRowCut.hpp"
12 #include "OsiCuts.hpp"
13 
14 #include "CouenneCutGenerator.hpp"
15 
16 #include "CouenneExprGroup.hpp"
17 #include "CouenneExprBound.hpp"
18 #include "CouenneExprMul.hpp"
19 
20 #include "CouenneProblem.hpp"
21 
22 using namespace Couenne;
23 
26 
27  expression
28  **lbnl = new expression * [1],
29  **ubnl = new expression * [1];
30 
31  // TODO: do not aggregate members of exprSum
32 
33  // compute lower/upper bound of nonlinear part
34  exprSum::getBounds (*lbnl, *ubnl);
35 
36  lincoeff
37  *coeL = new lincoeff,
38  *coeU = new lincoeff;
39 
40  // derive linear part (obtain constant)
41  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
42 
43  std::pair <exprVar *, CouNumber> pairL, pairU;
44 
45  CouNumber coeff = el -> second;
46  int ind = el -> first -> Index ();
47 
48  pairL .second = pairU .second = coeff;
49 
50  if (coeff < 0.) {
51  pairL.first = new exprUpperBound (ind, el -> first -> domain ());
52  pairU.first = new exprLowerBound (ind, el -> first -> domain ());
53  } else {
54  pairL.first = new exprLowerBound (ind, el -> first -> domain ());
55  pairU.first = new exprUpperBound (ind, el -> first -> domain ());
56  }
57 
58  coeL -> push_back (pairL);
59  coeU -> push_back (pairU);
60  }
61 
62  lb = new exprGroup (c0_, *coeL, lbnl, 1);
63  ub = new exprGroup (c0_, *coeU, ubnl, 1);
64 
65  delete coeL;
66  delete coeU;
67 }
68 
69 
70 // /// Get expressions of lower and upper bound of an expression (if any)
71 // void exprGroup::getBounds (expression *&lb, expression *&ub) {
72 
73 // expression *lbnl, *ubnl;
74 
75 // // TODO: do not aggregate members of exprSum
76 
77 // // compute lower/upper bound of nonlinear part
78 // exprSum::getBounds (lbnl, ubnl);
79 
80 // // count linear and constant terms
81 // int nlin = lcoeff_.size();
82 // if (fabs (c0_) > COUENNE_EPS) nlin++;
83 // // for (register int *ind = index_; *ind++>=0; nlin++);
84 
85 // expression
86 // **linall = new expression * [nlin + 1], // linear arglist for lower bound
87 // **linalu = new expression * [nlin + 1]; // upper
88 
89 // // add constant to bounds
90 // if (fabs (c0_) > COUENNE_EPS) {
91 // *linall++ = new exprConst (c0_);
92 // *linalu++ = new exprConst (c0_);
93 // }
94 
95 // // TODO: make it another exprGroup!
96 
97 // // derive linear part (obtain constant)
98 // for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
99 
100 // // c0 += el -> second;
101 
102 // CouNumber coeff = el -> second;
103 // int ind = el -> first -> Index ();
104 
105 // expression *l = new exprLowerBound (ind, el -> first -> domain ()),
106 // *u = new exprUpperBound (ind, el -> first -> domain ());
107 
108 // if (fabs (coeff - 1.) < COUENNE_EPS) {
109 // *linall++ = l;
110 // *linalu++ = u;
111 // } else {
112 
113 // expression *c1 = new exprConst (coeff),
114 // *c2 = new exprConst (coeff);
115 
116 // if (coeff < 0) {
117 // *linall++ = new exprMul (c1, u);
118 // *linalu++ = new exprMul (c2, l);
119 // } else {
120 // *linall++ = new exprMul (c1, l);
121 // *linalu++ = new exprMul (c2, u);
122 // }
123 // }
124 // }
125 
126 // *linall = lbnl;
127 // *linalu = ubnl;
128 
129 // lb = new exprSum (linall - nlin, nlin + 1);
130 // ub = new exprSum (linalu - nlin, nlin + 1);
131 // }
132 
133 
134 
137 
138  // compute lower/upper bound of nonlinear part
139 
140  exprSum::getBounds (lb, ub);
141  /*{
142  expression *le, *ue;
143  getBounds (le, ue);
144 
145  lb = (*le) ();
146  ub = (*ue) ();
147 
148  delete le;
149  delete ue;
150  }*/
151 
152  lb += c0_;
153  ub += c0_;
154 
155  // derive linear part (obtain constant)
156  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
157 
158  exprVar *var = el -> first;
159  CouNumber coeff = el -> second, vlb, vub;
160 
161  bool
162  inf_lb = false,
163  inf_ub = false;
164 
165  if ((vlb = var -> lb ()) < -COUENNE_INFINITY) {
166  if (coeff > 0) inf_lb = true;
167  else inf_ub = true;
168  } else {
169  if (coeff > 0) lb += vlb * coeff;
170  else ub += vlb * coeff;
171  }
172 
173  if ((vub = var -> ub ()) > COUENNE_INFINITY) {
174  if (coeff > 0) inf_ub = true;
175  else inf_lb = true;
176  } else {
177  if (coeff > 0) ub += vub * coeff;
178  else lb += vub * coeff;
179  }
180 
181  if (inf_lb)
182  lb = -COUENNE_INFINITY;
183 
184  if (inf_ub) {
185  ub = COUENNE_INFINITY;
186  if (inf_lb)
187  break;
188  }
189  }
190 }
191 
192 
193 // generate equality between *this and *w
195  OsiCuts &cs, const CouenneCutGenerator *cg,
196  t_chg_bounds *chg,
197  int wind, CouNumber lb, CouNumber ub) {
198 
199  // very similar to exprSum::generateCuts. First of all, this has
200  // been standardized into a sum, so it only gets a cut in the
201  // initial relaxation
202  if (!(cg -> isFirst ()))
203  return;
204 
205  // there is one linear term so far: -w
206  int nterms = lcoeff_.size ();
207 
208  OsiRowCut *cut = new OsiRowCut;
209 
210  // If this aux is fixed, don't write
211  //
212  // "- w + ax = -b" but just
213  //
214  // "ax = -b+ w0"
215  //
216  // with w0 its constant value
217 
218  CouNumber vlb, vub;
219  w -> getBounds (vlb, vub);
220  bool uselessAux = (vub < vlb + COUENNE_EPS);
221 
222  // TODO: generalize to sign!= ::EQ
223 
224  int displacement = (wind < 0 && !uselessAux) ? 1: 0;
225 
226  CouNumber *coeff = new CouNumber [nargs_ + nterms + displacement];
227  int *index = new int [nargs_ + nterms + displacement];
228 
229  if (wind < 0 && !uselessAux) {
230  // first, make room for aux variable
231  coeff [0] = -1.;
232  index [0] = w -> Index ();
233  lb = ub = 0.;
234  }
235 
236  if (uselessAux)
237  lb = ub = vlb;
238 
239  lb -= c0_;
240  ub -= c0_;
241 
242  // now add linear terms
243  lincoeff::iterator el = lcoeff_.begin ();
244 
245  nterms = displacement;
246 
247  for (; el != lcoeff_.end (); ++el)
248 
249  if (fabs (el -> second) > 1.e-21) {
250  // why 1.0e-21? Look at CoinPackedMatrix.cpp:2237
251 
252  coeff [nterms] = el -> second;
253  index [nterms++] = el -> first -> Index ();
254  }
255 
256  // scan arglist for (aux) variables and constants
257  for (int i=0; i<nargs_; i++) {
258 
259  expression *curr = arglist_ [i];
260 
261  if (curr -> Type () == CONST) {// constant term in sum
262  lb -= curr -> Value ();
263  ub -= curr -> Value ();
264  }
265  else { // variable
266  coeff [nterms] = 1.;
267  index [nterms++] = curr -> Index ();
268  }
269  }
270 
271  cut -> setRow (nterms, index, coeff);
272 
273  delete [] index;
274  delete [] coeff;
275 
276  enum auxSign sign = expression::AUX_EQ;
277 
278  if (wind < 0)
279  sign = cg -> Problem () -> Var (w -> Index ()) -> sign ();
280 
281  if (lb > -COUENNE_INFINITY && (wind >= 0 || sign != expression::AUX_GEQ)) cut -> setLb (lb);
282  if (ub < COUENNE_INFINITY && (wind >= 0 || sign != expression::AUX_LEQ)) cut -> setUb (ub);
283 
284  cut -> setGloballyValid (); // added only once, it is global
285  cs.insert (cut);
286  delete cut;
287 }
Cut Generator for linear convexifications.
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
CouNumber c0_
constant term
exprGroup(CouNumber, lincoeff &, expression **=NULL, int=0)
Constructor.
virtual enum nodeType Type() const
Node type.
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
auxSign
&quot;sign&quot; of the constraint defining an auxiliary.
virtual void generateCuts(expression *, OsiCuts &, const CouenneCutGenerator *, t_chg_bounds *=NULL, int=-1, CouNumber=-COUENNE_INFINITY, CouNumber=COUENNE_INFINITY)
special version for linear constraints
lincoeff lcoeff_
coefficients and indices of the linear term
virtual void getBounds(expression *&, expression *&)
Get lower and upper bound of an expression (if any)
Definition: exprSum.cpp:118
virtual void getBounds(expression *&, expression *&)
Get lower and upper bound of an expression (if any)
#define COUENNE_EPS
expression ** arglist_
argument list is an array of pointers to other expressions
std::vector< std::pair< exprVar *, CouNumber > > lincoeff
double CouNumber
main number type in Couenne
int nargs_
number of arguments (cardinality of arglist)
#define COUENNE_INFINITY
variable-type operator
Expression base class.
void fint fint fint real fint real real real real real real real real * w
These are bound expression classes.
virtual CouNumber Value() const
value (empty)