exprDiv.cpp
Go to the documentation of this file.
1 /* $Id: exprDiv.cpp 1147 2015-05-04 14:01:51Z stefan $
2  *
3  * Name: exprDiv.cpp
4  * Author: Pietro Belotti
5  * Purpose: definition of divisions
6  *
7  * (C) Carnegie-Mellon University, 2006-11.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "assert.h"
12 
13 #include <stdio.h>
14 
15 #include "CouenneExprDiv.hpp"
16 #include "CouenneExprConst.hpp"
17 #include "CouenneExprClone.hpp"
18 #include "CouenneExprMul.hpp"
19 #include "CouenneExprOpp.hpp"
20 #include "CouenneExprPow.hpp"
21 #include "CouenneExprInv.hpp"
22 #include "CouenneExprSub.hpp"
23 #include "CouenneExprBDiv.hpp"
24 
25 #include "CouennePrecisions.hpp"
26 
27 #include "CoinFinite.hpp"
28 
29 using namespace Couenne;
30 
31 // simplify division
32 
34 
36  expression *ret = NULL;
37 
38  if ((*arglist_) -> Type () == CONST) { // expr = a / y
39 
40  CouNumber c0 = (*arglist_) -> Value ();
41 
42  if (arglist_ [1] -> Type () == CONST) { // expr = a / b
43 
44  CouNumber c1 = arglist_ [1] -> Value ();
45 
46  if (fabs (c1) == 0.) {
47  printf ("Couenne: Warning, division by zero -- "); print (); printf ("\n");
48  }
49  else {
50  // delete arglist_ [0];
51  // delete arglist_ [1];
52  ret = new exprConst (c0 / c1);
53  //arglist_ [0] = arglist_ [1] = NULL;
54  }
55  }
56  else {
57  if (fabs (c0) == 0.) // expr = 0/y
58  return new exprConst (0.);
59 
60  // otherwise, expression = k/y, return k*inv(y)
61 
62  //expression *ret;
63 
64  if (fabs (arglist_ [0] -> Value () - 1.) == 0.) {
65  //delete *arglist_;
66  //*arglist_ = NULL;
67  ret = new exprInv (arglist_ [1]);
68  arglist_ [1] = NULL;
69  }
70  else {
71 
72  ret = new exprMul (arglist_ [0], new exprInv (arglist_ [1]));
73  arglist_ [0] = arglist_ [1] = NULL; // unlinking both arguments of useless expressions
74  }
75 
76  //arglist_ = NULL;
77  //return ret;
78  }
79  }
80  else // only need to check if f2 == 0
81 
82  if (arglist_ [1] -> Type () == CONST) { // expression = x/h,
83  // transform into (1/h)*x
84 
85  ret = new exprMul (new exprConst (1. / (arglist_ [1] -> Value ())), arglist_ [0]);
86 
87  //delete arglist_ [1];
88  arglist_ [0] = NULL;
89  //return ret;
90  }
91 
92  return ret;
93 }
94 
95 
96 // differentiate quotient of expressions
97 //
98 // d (f/g) / dx = df/dx / g - f/g^2 * dg/dx = 1/g (f' - f/g g')
100 
101  bool
102  diffNum = arglist_ [0] -> dependsOn (index),
103  diffDen = arglist_ [1] -> dependsOn (index);
104 
105  if (diffNum) {
106 
107  if (diffDen) {
108 
109  // more general case
110 
111  return new exprDiv (new exprSub (new exprMul (arglist_ [1] -> differentiate (index),
112  arglist_ [0] -> clone ()),
113  new exprMul (arglist_ [1] -> clone (),
114  arglist_ [0] -> differentiate (index))),
115  new exprPow (arglist_ [1] -> clone (), new exprConst (2.)));
116 
117  } else { // derive numerator and divide by den
118 
119  return new exprDiv (arglist_ [0] -> differentiate (index),
120  arglist_ [1] -> clone ());
121  }
122 
123  } else {
124 
125  if (diffDen) { // = - f/g^2 * g' or, for (future) simplification purposes, - (f * g')/g^2
126 
127  return new exprOpp (new exprDiv (new exprMul (arglist_ [0] -> clone (),
128  arglist_ [1] -> differentiate (index)),
129  new exprPow (arglist_ [1] -> clone (),
130  new exprConst (2.))));
131 
132  } else // quotient does not depend on index
133  return new exprConst (0.);
134  }
135 
136  // expression **alm2 = new expression * [3];
137 
138  // exprInv *invg = new exprInv (arglist_ [1] -> clone ());
139 
140  // alm2 [0] = arglist_ [0] -> clone ();
141  // alm2 [1] = arglist_ [1] -> differentiate (index);
142  // alm2 [2] = new exprClone (invg);
143 
144  // return new exprMul (invg, new exprSub (arglist_ [0] -> differentiate (index),
145  // new exprMul (alm2, 3)));
146 
147  // in alternative:
148 
149  // return new exprDiv (new exprSub (new exprMul (arglist_ [1] -> differentiate (index),
150  // arglist_ [0] -> clone ()),
151  // new exprMul (arglist_ [1] -> clone (),
152  // arglist_ [0] -> differentiate (index))),
153  // new exprPow (arglist_ [1] -> clone (), new exprConst (2.)));
154 }
155 
156 
157 // get lower/upper bounds as a function of the arguments' lower/upper
158 // bounds
160 
161  expression **almin = new expression * [4];
162  expression **almax = new expression * [4];
163 
164  arglist_ [0] -> getBounds (almin [0], almin [1]);
165  arglist_ [1] -> getBounds (almin [2], almin [3]);
166 
167  almax [0] = new exprClone (almin [0]);
168  almax [1] = new exprClone (almin [1]);
169  almax [2] = new exprClone (almin [2]);
170  almax [3] = new exprClone (almin [3]);
171 
172  lb = new exprLBDiv (almin, 4);
173  ub = new exprUBDiv (almax, 4);
174 }
175 
176 
177 // get lower/upper bounds as a function of the arguments' lower/upper
178 // bounds
180 
181  // lower
182 
183  CouNumber ln, un, ld, ud;
184 
185  arglist_ [0] -> getBounds (ln, un);
186  arglist_ [1] -> getBounds (ld, ud);
187 
188  if (ld > 0) // (?,?,+,+)
189  if (ln > 0) lb = safeDiv (ln,ud,-1); // (+,+,+,+) --> ln/ud
190  else lb = safeDiv (ln,ld,-1); // (-,?,+,+) --> ln/ld
191  else { // ld <= 0
192  if (ud > 0) lb = - COUENNE_INFINITY; // (?,?,-,+) --> unbounded
193  else if (un > 0) lb = safeDiv (un,ud,-1); // (?,+,-,-) --> un/ud
194  else lb = safeDiv (un,ld,-1); // (-,-,-,-) --> un/ld
195  }
196 
197  // upper
198 
199  if (ld > 0) // (ln,un,ld,ud) lb
200  if (un < 0) ub = safeDiv (un,ud,1); // (-,-,+,+) --> un/ud
201  else ub = safeDiv (un,ld,1); // (?,+,+,+) --> un/ld
202  else { // ld <= 0
203  if (ud > 0) ub = + COUENNE_INFINITY; // (?,?,-,+) --> unbounded
204  else if (ln < 0) ub = safeDiv (ln,ud,1); // (-,?,-,-) --> ln/ud
205  else ub = safeDiv (ln,ld,1); // (+,+,-,-) --> ln/ld
206  }
207 }
208 
211 
212  // only check if arguments (specifically, the denominator) are, *at
213  // this point in the algorithm*, constant -- due to branching rules,
214  // for instance. If so, check if the corresponding evaluated
215  // expression is integer. Otherwise, check if denominator is +1 or
216  // -1.
217 
218  CouNumber dl, du, nl, nu;
219 
220  arglist_ [1] -> getBounds (dl, du);
221  arglist_ [0] -> getBounds (nl, nu);
222 
223  //register CouNumber
224  //num = (*nl) (),
225  //den = (*dl) ();
226 
227  bool
228  denzero = (fabs (dl) < COUENNE_EPS),
229  numconst = (fabs (nl - nu) < COUENNE_EPS);
230 
231  if ((fabs (nl) < COUENNE_EPS) && // numerator is zero
232  numconst && // constant
233  !denzero) // and denominator is nonzero
234 
235  return true;
236 
237  // otherwise...
238 
239  if (fabs (dl - du) < COUENNE_EPS) { // denominator is constant
240 
241  if (fabs (fabs (dl) - 1) < COUENNE_EPS) // it is +1 or -1, check numerator
242  return arglist_ [0] -> isInteger ();
243 
244  if (denzero) // it is zero, better leave...
245  return false;
246 
247  if (numconst) { // numerator is constant, too
248 
249  CouNumber quot = nl / dl;
250 
251  if (fabs (COUENNE_round (quot) - quot) < COUENNE_EPS)
252  return true;
253  }
254  }
255 
256  return false;
257 }
258 
259 
262  expression *vardep,
263  CouNumber &left,
264  CouNumber &right) const {
265 
266  expression *varoth = arglist_ [0]; // assume y = c/x
267 
268  bool numerator = false;
269 
270  if (varoth -> Index () == varind -> Index ()) { // actually y = x/c
271  varoth = arglist_ [1];
272  numerator = true;
273  } else assert (arglist_ [1] -> Index () == varind -> Index ()); // right to assume y = c/x
274 
275  CouNumber
276  x = (*varind) (),
277  y = (*vardep) (),
278  c = (*varoth) ();
279 
280  if (numerator) // checking y = x/c
281 
282  if (c < 0.)
283  if (c*y > x) {assert (c*y > right); right = c*y;}
284  else {assert (c*y < left); left = c*y;}
285  else if (c > 0.)
286  if (c*y < x) {assert (c*y < left); left = c*y;}
287  else {assert (c*y > right); right = c*y;}
288  else left = - (right = COIN_DBL_MAX);
289 
290  else // checking y = c/x
291 
292  if (y < 0.)
293  if (x*y > c) {assert (c/y > right); right = c/y;} // convex area in third orthant
294  else {assert (c/y < left); left = c/y;} // remaining of third+fourth orthant
295  else if (y > 0.)
296  if (x*y > c) {assert (c/y < left); left = c/y;} // convex area in first orthant
297  else {assert (c/y > right); right = c/y;} // remaining of first+second orthant
298  else left = - (right = COIN_DBL_MAX);
299 }
300 
301 
304 
305  int
306  ind0 = arglist_ [0] -> Index (),
307  ind1 = arglist_ [1] -> Index ();
308 
309  CouNumber
310  x0 = (ind0 < 0) ? fabs (arglist_ [0] -> Value ()) : fabs (x [ind0]),
311  x1 = (ind1 < 0) ? fabs (arglist_ [1] -> Value ()) : fabs (x [ind1]),
312  x1sq = x1 * x1;
313 
314  if (x1sq < 1/COUENNE_INFINITY) {
315  x1sq = 1/COUENNE_INFINITY;
316  if (x1 < 1/COUENNE_INFINITY) // implied
317  x1 = 1/COUENNE_INFINITY;
318  }
319 
320  if (ind0 < 0)
321  if (ind1 < 0) return 0.; // c/d
322  else return fabs (x0/(x1sq)); // c/y
323  else
324  if (ind1 < 0) return 1. / x1; // x/d
325  else return sqrt (1. / x1sq + x0*x0 / (x1sq * x1sq)); // x/y
326 }
exprDiv(expression **al, int n=2)
Constructor.
class inverse:
virtual void print(std::ostream &out=std::cout, bool=false) const
I/O.
Definition: exprOp.cpp:42
virtual int dependsOn(int *ind, int n, enum dig_type type=STOP_AT_AUX)
dependence on variable set: return cardinality of subset of the set of indices in first argument whic...
Definition: expression.cpp:172
#define COUENNE_round(x)
class for subtraction,
class to compute upper bound of a fraction based on the bounds of both numerator and denominator ...
class opposite,
void getBounds(expression *&lb, expression *&ub)
Get lower and upper bound of an expression (if any)
Definition: exprDiv.cpp:159
expression * clone(Domain *d=NULL) const
Cloning method.
Power of an expression (binary operator), with constant.
constant-type operator
class for divisions,
ULong * x0
Definition: OSdtoa.cpp:1776
virtual enum nodeType Type() const
Node type.
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
ULong x1
Definition: OSdtoa.cpp:1776
expression clone (points to another expression)
#define COUENNE_EPS
virtual expression * simplify()
simplification
Definition: exprOp.cpp:243
expression * simplify()
Simplification.
Definition: exprDiv.cpp:33
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
CouNumber gradientNorm(const double *x)
return l-2 norm of gradient at given point
Definition: exprDiv.cpp:303
bool isInteger()
is this expression integer?
Definition: exprDiv.cpp:210
#define COUENNE_INFINITY
expression * differentiate(int index)
Differentiation.
Definition: exprDiv.cpp:99
virtual void closestFeasible(expression *varind, expression *vardep, CouNumber &left, CouNumber &right) const
compute $y^{lv}$ and $y^{uv}$ for Violation Transfer algorithm
Definition: exprDiv.cpp:261
Expression base class.
static CouNumber safeDiv(register CouNumber a, register CouNumber b, int sign)
division that avoids NaN&#39;s and considers a sign when returning infinity
fint nu
virtual CouNumber Value() const
value (empty)
real c
class to compute lower bound of a fraction based on the bounds of both numerator and denominator ...
void fint fint fint real fint real * x
class for multiplications,