impliedBounds-exprDiv.cpp
Go to the documentation of this file.
1 /* $Id: impliedBounds-exprDiv.cpp 560 2011-04-17 10:01:15Z stefan $
2  *
3  * Name: impliedBounds-exprDiv.cpp
4  * Author: Pietro Belotti
5  * Purpose: implied bounds for division operators
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExprDiv.hpp"
12 #include "CouennePrecisions.hpp"
13 #include "CouenneConfig.h"
14 #include "CoinHelperFunctions.hpp"
15 #include "CoinFinite.hpp"
16 
17 using namespace Couenne;
18 
21 
22 bool exprDiv::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
23 
24  bool resx, resy = resx = false;
25 
26  CouNumber
27  wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
28  wu = sign == expression::AUX_LEQ ? COIN_DBL_MAX : u [wind];
29 
30  // y is a constant
31  if (arglist_ [1] -> Type () == CONST) {
32 
33  int ind = arglist_ [0] -> Index ();
34 
35  if (ind < 0) {
36  printf ("exprDiv::impliedBound: Error, w = c/d constants\n");
37  exit (-1);
38  }
39 
40  CouNumber c = arglist_ [1] -> Value ();
41 
42  if (fabs (c) < COUENNE_EPS) {
43  printf ("exprDiv::impliedBound: Error, division by zero\n");
44  exit (-1);
45  }
46 
47  // a copy of exprMul::impliedBound for the case where y is a constant
48 
49  bool xInt = arglist_ [0] -> isInteger ();
50 
51  if (c > COUENNE_EPS) {
52 
53  if (updateBound (-1, l+ind, xInt ? ceil (wl*c - COUENNE_EPS) : (wl*c))) {
54  resx = true;
55  chg [ind].setLower (t_chg_bounds::CHANGED);
56  }
57 
58  if (updateBound (+1, u+ind, xInt ? floor (wu*c + COUENNE_EPS) : (wu*c))) {
59  resx = true;
60  chg [ind].setUpper (t_chg_bounds::CHANGED);
61  }
62  }
63  else if (c < - COUENNE_EPS) {
64 
65  if (updateBound (-1, l+ind, xInt ? ceil (wu*c - COUENNE_EPS) : (wu*c))) {
66  resx = true;
67  chg [ind].setLower (t_chg_bounds::CHANGED);
68  }
69 
70  if (updateBound (+1, u+ind, xInt ? floor (wl*c + COUENNE_EPS) : (wl*c))) {
71  resx = true;
72  chg [ind].setUpper (t_chg_bounds::CHANGED);
73  }
74  }
75  } else {
76 
77  // deal with all other cases
78 
79  // Each bound on w is represented on the xy plane with two cones,
80  // such that joining the extreme rays of both one obtains two
81  // lines, or in other words, the second cone is obtained through
82  // the transformation (x',y') = (-x,-y) applied to the first cone.
83  //
84  // Bounds can be tightened according to four different cases,
85  // depending on which corner of the bounding box belongs to which
86  // of the cones and on the sign of the bounds.
87  //
88  // Define wl <= w <= wu,
89  // xl <= x <= xu,
90  // yl <= y <= yu.
91  //
92  // Then the "tightenable" bounds are, depending on the corner:
93  //
94  // _______________________________________________________
95  // | w >= wl | w <= wu |
96  // |___________________________|___________________________|
97  // | l<0 | l>0 | u<0 | u>0 |
98  // |_____________|_____________|_____________|_____________|
99  // Cone |upper |lower |upper |lower |upper |lower |upper |lower |
100  // | | | | | | | | |
101  // 1 xl,yl | INF | - | xl | yl |xl,yl?| yl | yl | - |
102  // 2 xl,yu | yu | xl | - | INF | - | yu | yu |yu,xl?|
103  // 3 xu,yl | xu | yl | INF | - | yl | - |yl,xu?| yl |
104  // 4 xu,yu | - | INF | yu | xu | yu |xu,yu?| - | yu |
105  // |______|______|______|______|______|______|______|______|
106  //
107  // Where "INF" stands for "infeasible subproblem", "-" for
108  // "nothing to improve", and the rest is improved (those with "?"
109  // may improve).
110 
111  int xi = arglist_ [0] -> Index (),
112  yi = arglist_ [1] -> Index ();
113 
114  CouNumber x0 = 0,
115  *xl = l + xi, *yl = l + yi,
116  *xu = u + xi, *yu = u + yi;
117 
118  /*printf ("from : w[%d] [%e %e], x%d [%e %e] / y%d [%e %e]",
119  wind, wl, wu, xi, *xl, *xu, yi, *yl, *yu);*/
120 
121  // avoid changing bounds if x is constant
122  if (xi == -1)
123  xl = xu = &x0;
124 
126 
127  // simple case wl = wu = 0
128 
129  if ((fabs (wl) < COUENNE_EPS) &&
130  (fabs (wu) < COUENNE_EPS)) {
131 
132  resx = updateBound (-1, xl, 0.) || resx;
133  resx = updateBound (+1, xl, 0.) || resx;
134  return resx || resy;
135  }
136 
137  bool resxL, resxU, resyL,
138  resyU = resxL = resxU = resyL = false;
139 
140  // general case
141 
142  if (wl < - COUENNE_EPS && wl > - COUENNE_INFINITY / 10) { // w >= wl, wl negative
143 
144  // point C: (xl,yl)
145 
146  resyL = ((*yl<0) && (*yl > *xl/wl + COUENNE_EPS) && updateBound (-1, yl, 0)) || resyL;
147  resxL = ((*yl>0) && (*yu < *xl/wl) && updateBound (-1, xl, *yu*wl)) || resxL; // new
148  resyL = ((*yl>0) && (*xu < *yl*wl) && updateBound (-1, yl, *xu/wl)) || resyL; // new
149 
150  // if ((*yl>0) && (*yl < *xl/wl)) { // point C violates x/y >= wl, down
151  // resxL = updateBound (-1, xl, *yu*wl) || resxL; //
152  // resyL = updateBound (-1, yl, *xu/wl) || resyL; //
153  // }
154  // point B: (xu,yu)
155  // if ((*yu<0) && (*yu > *xu/wl)) { // point B violates x/y >= wl, down
156  // resxU = updateBound (+1, xu, *yl*wl) || resxU;
157  // resyU = updateBound (+1, yu, *xl/wl) || resyU;
158  // }
159 
160  resyU = ((*yu>0) && (*yu < *xu/wl - COUENNE_EPS) && updateBound (+1, yu, 0)) || resyU;
161  resxU = ((*yu<0) && (*yl > *xu/wl) && updateBound (+1, xu, *yl*wl)) || resxU; // new
162  resyU = ((*yu<0) && (*xl > *yu*wl) && updateBound (+1, yu, *xl/wl)) || resyU; // new
163 
164  } else if (wl > COUENNE_EPS) { // w >= wl, wl positive
165 
166  //
167 
168  resyL = ((*yl<0) && (*yl < *xl/wl) && updateBound (-1, yl, CoinMin (*xl/wl, 0.))) || resyL;
169  resxL = ((*yl>0) && (*yl > *xl/wl) && updateBound (-1, xl, *yl*wl)) || resxL;
170  //
171  resyU = ((*yu>0) && (*yu > *xu/wl) && updateBound (+1, yu, CoinMax (*xu/wl, 0.))) || resyU;
172  resxU = ((*yu<0) && (*yu < *xu/wl) && updateBound (+1, xu, *yu*wl)) || resxU;
173  }
174 
176 
177 
178  if (wu > COUENNE_EPS && wu < COUENNE_INFINITY / 10) { // w <= wu, wu positive
179 
180  //
181  resyL = ((*yl<0) && (*yl > *xu/wu + COUENNE_EPS) && updateBound (-1, yl, 0)) || resyL;
182  resxU = ((*yl>0) && (*xu > *yu*wu) && updateBound (+1, xu, *yu*wu)) || resxU;
183  resyL = ((*yl>0) && (*yl < *xl/wu) && updateBound (-1, yl, *xl/wu)) || resyL;
184 
185  // if ((*yl>0) && (*yl < *xu/wu)) {
186  // resxU = updateBound (+1, xu, *yu*wu) || resxU;
187  // resyL = updateBound (-1, yl, *xl/wu) || resyL;
188  // }
189 
190  // //
191 
192  // if ((*yu<0) && (*yu > *xl/wu)) {
193  // resxL = updateBound (-1, xl, *yl*wu) || resxL;
194  // resyU = updateBound (+1, yu, *xu/wu) || resyU;
195  // }
196 
197  resyU = ((*yu>0) && (*yu < *xl/wu - COUENNE_EPS) && updateBound (+1, yu, 0)) || resyU;
198  resxL = ((*yu<0) && (*xl < *yl*wu) && updateBound (-1, xl, *yl*wu)) || resxL;
199  resyU = ((*yu<0) && (*yu > *xu/wu) && updateBound (+1, yu, *xu/wu)) || resyU;
200 
201  } else if (wu < - COUENNE_EPS) { // w <= wu, wu negative
202 
203  //
204 
205  resyL = ((*yl<0) && (*yl < *xu/wu) && updateBound (-1, yl, CoinMin (*xu/wu,0.))) || resyL;//
206  resxL = ((*yu<0) && (*yu < *xl/wu) && updateBound (-1, xl, *yu*wu)) || resxL;
207 
208  //
209 
210  resyU = ((*yu>0) && (*yu > *xl/wu) && updateBound (+1, yu, CoinMax (*xl/wu,0.))) || resyU;
211  resxU = ((*yl>0) && (*yl > *xu/wu) && updateBound (+1, xu, *yl*wu)) || resxU;
212  }
213 
214  if (resxL) chg [xi].setLower(t_chg_bounds::CHANGED);
215  if (resxU) chg [xi].setUpper(t_chg_bounds::CHANGED);
216  if (resyL) chg [yi].setLower(t_chg_bounds::CHANGED);
217  if (resyU) chg [yi].setUpper(t_chg_bounds::CHANGED);
218 
219  /*if (resx || resy)
220  printf (" \ntightened division: w[%d] [%e %e], x%d [%e %e] / y%d [%e %e]\n",
221  wind, wl, wu, xi, *xl, *xu, yi, *yl, *yu);
222  else printf (" \r");*/
223 
224  resx = resxL || resxU;
225  resy = resyL || resyU;
226  }
227 
228  bool
229  xInt = arglist_ [0] -> isInteger (),
230  yInt = arglist_ [1] -> isInteger ();
231 
232  if (resx && xInt) {
233  int xi = arglist_ [0] -> Index ();
234  assert (xi >= 0);
235  u [xi] = floor (u [xi] + COUENNE_EPS);
236  l [xi] = ceil (l [xi] - COUENNE_EPS);
237  }
238 
239  if (resy && yInt) {
240  int yi = arglist_ [1] -> Index ();
241  assert (yi >= 0);
242  u [yi] = floor (u [yi] + COUENNE_EPS);
243  l [yi] = ceil (l [yi] - COUENNE_EPS);
244  }
245 
246  return (resx || resy);
247 }
bool updateBound(register int sign, register CouNumber *dst, register CouNumber src)
updates maximum violation.
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
ULong * x0
Definition: OSdtoa.cpp:1776
void setUpper(ChangeStatus upper)
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.
#define COUENNE_EPS
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
bool impliedBound(int, CouNumber *, CouNumber *, t_chg_bounds *, enum auxSign=expression::AUX_EQ)
Implied bound processing.
bool isInteger()
is this expression integer?
Definition: exprDiv.cpp:210
#define COUENNE_INFINITY
virtual CouNumber Value() const
value (empty)
real c