conv-exprPow-getBounds.cpp
Go to the documentation of this file.
1 /* $Id: conv-exprPow-getBounds.cpp 1184 2015-08-17 12:55:35Z stefan $
2  *
3  * Name: conv-exprPow-getBounds.cpp
4  * Author: Pietro Belotti
5  * Purpose: method to get lower and upper bounds of a power x^y
6  *
7  * (C) Carnegie-Mellon University, 2006-09.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include <math.h>
12 
13 #include "CouenneTypes.hpp"
14 #include "CouenneExprPow.hpp"
15 #include "CouenneExprConst.hpp"
16 #include "CouenneExprClone.hpp"
17 #include "CouenneExprMax.hpp"
18 #include "CouenneExprMin.hpp"
19 #include "CouenneExprOpp.hpp"
20 #include "CouennePrecisions.hpp"
21 #include "CouenneProblem.hpp"
22 
23 #include "CoinHelperFunctions.hpp"
24 #include "CoinFinite.hpp"
25 
26 using namespace Couenne;
27 
28 // compute expressions for lower and upper bounds of a power x^y,
29 // based on the lower/upper bounds of x and y
30 
32 
33  // We have a standardized expression of the form w = x^y, where x or
34  // y could be constant. Let us study each case separately.
35 
36  assert (arglist_ [0] -> Type () != CONST);
37 
38  // x is not constant, so it has (possibly different) lower and
39  // upper bounds. The expression is x^b, b constant (the case x^y
40  // has been decomposed by simplify() into exp(y log x).
41 
42  expression *lbbase, *ubbase;
43  arglist_ [0] -> getBounds (lbbase, ubbase);
44 
45  // printf ("ubbase = "); ubbase -> print (std::cout); printf ("\n");
46 
47  if (arglist_ [1] -> Type () == CONST) {
48 
49  // expression = x^b, b!=0. There are four cases:
50  //
51  // 1) b is integer and odd or signpower (cube, x^5, etc)
52  // 2) b is integer and even (square, x^8, etc)
53  // 3) 1/b is integer and odd (cube root, x^(1/7), etc)
54  // 4) 1/b is integer and even (square root, x^(1/4), etc)
55  // 5) none of the above
56  //
57  // For all of these, need to check if the exponent is negative...
58 
59  CouNumber expon = arglist_ [1] -> Value ();
60  int rndexp;
61 
62  bool isInt = fabs (expon - (rndexp = COUENNE_round (expon))) < COUENNE_EPS,
63  isInvInt = !isInt &&
64  ((fabs (expon) > COUENNE_EPS) &&
65  (fabs (1/expon - (rndexp = COUENNE_round (1/expon))) < COUENNE_EPS));
66 
67  if (issignpower_ || ((isInt || isInvInt) && (rndexp % 2) && (rndexp > 0))) {
68 
69  // the exponent is integer (or inverse integer), odd or signpower and
70  // positive, hence the function is monotone non decreasing
71 
72  lb = new exprPow (lbbase, new exprConst (expon), issignpower_);
73  ub = new exprPow (ubbase, new exprConst (expon), issignpower_);
74  }
75  else {
76 
77  // the exponent is either negative, integer even and not signpower, or fractional
78  assert(!issignpower_);
79 
80  expression **all = new expression * [6];
81 
82  all [0] = new exprOpp (lbbase);
83  all [2] = new exprConst (0.);
84  all [4] = ubbase;
85 
86  if (expon > 0)
87  all [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
88  else all [1] = new exprPow (new exprClone (ubbase), new exprConst (expon));
89 
90  // all [3] is lower bound when lbbase <= 0 <= ubbase
91 
92  if (expon > COUENNE_EPS) all [3] = new exprConst (0.);
93  else if (isInt || isInvInt) {
94  if (rndexp % 2)
95  all [3] = new exprConst (-COUENNE_INFINITY);
96  else all [3] = new exprMin (new exprClone (all [1]),
97  new exprPow (new exprClone (lbbase),
98  new exprConst (expon)));
99  }
100  else all [3] = new exprClone (all [1]);
101 
102  // all [5] is the lower bound value when lbbase <= ubbase <= 0
103 
104  if (expon > COUENNE_EPS) {
105  if (isInt && !(rndexp % 2))
106  all [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
107  else all [5] = new exprConst (0.);
108  }
109  else {
110  if (isInt || isInvInt) {
111  if (rndexp % 2)
112  all [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
113  else all [5] = new exprPow (new exprClone (lbbase), new exprConst (expon));
114  }
115  else all [5] = new exprConst (0.);
116  }
117 
118  lb = new exprMin (all, 6);
119 
120  // And now the upper bound ///////////////////////////////////
121 
122  if (expon > 0) {
123 
124  // special case: upper bound depends to variable bounds only:
125  // $max {lb^k, ub^k}$
126 
127  ub = new exprMax (new exprPow (new exprClone (lbbase), new exprConst (expon)),
128  new exprPow (new exprClone (ubbase), new exprConst (expon)));
129 
130  } else { // from this point on, expon < 0
131 
132  expression **alu = new expression * [6];
133 
134  alu [0] = new exprClone (all [0]);
135  alu [2] = new exprConst (0.);
136  alu [4] = new exprClone (ubbase);
137 
138  //if ((isInt || isInvInt) && !(rndexp % 2))
139  //alu [1] = new exprPow (new exprClone (ubbase), new exprConst (expon));
140  //else
141 
142  // if negative exponent and base has nonnegative lower bound,
143  // the upper bound can only be lb^k
144  alu [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
145 
146  // alu [3] is upper bound when lbbase <= 0 <= ubbase
147 
148  //if (expon < - COUENNE_EPS)
149  alu [3] = new exprConst (COUENNE_INFINITY);
150  //else if (isInt && !(rndexp % 2))
151  //alu [3] = new exprPow (new exprMax (new exprClone (lbbase), new exprClone (ubbase)),
152  //new exprConst (expon));
153  //else alu [3] = new exprPow (new exprClone (ubbase), new exprConst (expon));
154 
155  // alu [5] is the upper bound value when lbbase <= ubbase <= 0
156 
157  /*if (expon > COUENNE_EPS) {
158 
159  if (isInt && !(rndexp % 2))
160  alu [5] = new exprPow (new exprClone(ubbase), new exprConst(expon));
161  else alu [5] = new exprConst (0.);
162  }
163  else {*/
164  if (isInt || isInvInt)
165  alu [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
166  else alu [5] = new exprConst (COUENNE_INFINITY);
167  //}
168 
169  ub = new exprMin (alu, 6);
170  }
171  }
172  }
173  else // should NOT happen, exponent is not constant...
174  printf ("exprPow::getBounds(): Warning, exponent not constant\n");
175 
176  /*CouNumber l, u;
177  arglist_ [0] -> getBounds (l,u);
178 
179  printf ("pow::bound: [");
180  lb -> print (); printf ("=%g, ", (*lb) ());
181  ub -> print (); printf ("=%g [%g,%g]\n", (*ub) (), l, u);*/
182 }
183 
184 
185 // get value of lower and upper bound for the expression
187 
188  CouNumber lba, uba, k = (*(arglist_ [1])) ();
189  arglist_ [0] -> getBounds (lba, uba);
190  int intk;
191 
192  bool
193  isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
194  isInvInt = !isInt && fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS;
195 
196  if (!isInt && (!isInvInt || !(intk % 2 || issignpower_))) {
197 
198  // if exponent is fractional or 1/even, the base better be nonnegative
199 
200  if (lba < 0.) lba = 0.;
201  if (uba < 0.) uba = 0.;
202  }
203 
204  if (isInt && !(intk % 2 || issignpower_) && (k > 0)) { // x^{2h}
205 
206  if (uba < 0) {
207  lb = safe_pow (-uba, k);
208  ub = safe_pow (-lba, k);
209  } else if (lba > 0) {
210  lb = safe_pow (lba, k);
211  ub = safe_pow (uba, k);
212  } else {
213  lb = 0;
214  ub = safe_pow (CoinMax (-lba, uba), k);
215  }
216 
217  } else if (k > 0) { // monotone increasing: x^{2h+1} with h integer, or x^h with h real, or signpower
218 
219  lb = safe_pow (lba, k, issignpower_);
220  ub = safe_pow (uba, k, issignpower_);
221 
222  } else if (isInt && !(intk % 2 || issignpower_)) { // x^{-2h} or x^{-1/2h} with h integer
223 
224  if (uba < 0) {
225  lb = safe_pow (-lba, k);
226  ub = safe_pow (-uba, k);
227  } else if (lba > 0) {
228  lb = safe_pow (uba, k);
229  ub = safe_pow (lba, k);
230  } else {
231  lb = safe_pow (CoinMax (-lba, uba), k);
232  ub = COUENNE_INFINITY;
233  }
234 
235  } else { // x^k, k<0
236  assert(!issignpower_);
237  if (uba < 0) {
238  lb = safe_pow (uba, k);
239  ub = safe_pow (lba, k);
240  } else if (lba > 0) {
241  lb = safe_pow (uba, k);
242  ub = safe_pow (lba, k);
243  } else {
244  lb = -COIN_DBL_MAX; // !!! may not be reached
245  ub = COIN_DBL_MAX;
246  }
247  }
248 }
#define COUENNE_round(x)
class opposite,
Power of an expression (binary operator), with constant.
exprPow(expression **al, int n=2, bool signpower=false)
Constructor.
constant-type operator
virtual enum nodeType Type() const
Node type.
virtual void getBounds(expression *&, expression *&)
Get lower and upper bound of an expression (if any)
void fint fint * k
expression clone (points to another expression)
#define COUENNE_EPS
bool issignpower_
do we mean a signed power function: sign(arg0) * |arg0|^arg1 (assumes that arg1 is constant) ...
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
CouNumber safe_pow(CouNumber base, CouNumber exponent, bool signpower=false)
compute power and check for integer-and-odd inverse exponent
Expression base class.
virtual CouNumber Value() const
value (empty)