impliedBounds-exprPow.cpp
Go to the documentation of this file.
1 /* $Id: impliedBounds-exprPow.cpp 1047 2014-01-20 00:22:31Z pbelotti $
2  *
3  * Name: impliedBounds-exprPow.cpp
4  * Author: Pietro Belotti
5  * Purpose: implied bounds for power operators
6  *
7  * (C) Carnegie-Mellon University, 2008-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExprPow.hpp"
12 #include "CouenneExpression.hpp"
13 #include "CouenneConfig.h"
14 #include "CoinFinite.hpp"
15 #include "CoinHelperFunctions.hpp"
16 
17 using namespace Couenne;
18 
21 
22 void invPowImplBounds (int, int, CouNumber *, CouNumber *, CouNumber, bool &, bool &, enum expression::auxSign);
23 
24 
27 
28 bool exprPow::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum expression::auxSign sign) {
29 
30  //int xi = arglist_ [0] -> Index ();
31  //if (xi>=0) printf ("in implBound-pow: %g,%g\n", l [xi], u [xi]);
32 
33  bool resL, resU = resL = false;
34 
35  if (arglist_ [0] -> Type () == CONST) // base is constant or zero, nothing to do
36  return false;
37 
38  assert (arglist_ [1] -> Type () == CONST);
39 
40  int index = arglist_ [0] -> Index ();
41 
42  CouNumber k = arglist_ [1] -> Value (); // exponent
43 
44  if ((fabs (k) < COUENNE_EPS) ||
45  (fabs (k) > COUENNE_INFINITY)) // a null or infinite k is of little use
46  return false;
47 
48  int intk; // integer (or integer inverse of) exponent
49 
50  bool
51  isint = ( fabs (k - (intk = COUENNE_round (k))) < COUENNE_EPS), // k integer
52  isinvint = !isint && (k != 0. && (fabs (1./k - (intk = COUENNE_round (1./k))) < COUENNE_EPS)); // 1/k integer
53 
54  CouNumber
55  wl = ((sign == expression::AUX_GEQ) ? -COIN_DBL_MAX : l [wind]), // lower w
56  wu = ((sign == expression::AUX_LEQ) ? COIN_DBL_MAX : u [wind]); // upper w
57 
58  if ((isint || isinvint) && (intk % 2 || issignpower_)) {
59 
60  // k or 1/k integer and odd, or non-integer --> it is a monotone
61  // increasing function, apart when k negative
62 
63  if (k > 0.) { // simple, just follow bounds
64 
65  if (wl > - COUENNE_INFINITY) resL = updateBound (-1, l + index, safe_pow (wl, 1./k, issignpower_));
66  if (wu < COUENNE_INFINITY) resU = updateBound (+1, u + index, safe_pow (wu, 1./k, issignpower_));
67 
68  } else {// slightly more complicated, resort to same method as in exprInv
69  invPowImplBounds (wind, index, l, u, 1./k, resL, resU, sign);
70  assert (!issignpower_);
71  }
72  }
73  else
74  if (isint) { // x^k, k integer and even --> non monotone
75 
76  CouNumber bound = (k<0) ? wl : wu;
77 
78  // |x| <= b^(1/k), where b is wl or wu depending on k negative
79  // or positive, respectively
80 
81  if (bound > COUENNE_EPS) {
82 
83  if (fabs (bound) < COUENNE_INFINITY) {
84  resL = updateBound (-1, l + index, - safe_pow (bound, 1./k, issignpower_));
85  resU = updateBound (+1, u + index, safe_pow (bound, 1./k, issignpower_));
86  } /*else {
87  resL = updateBound (-1, l + index, - COUENNE_INFINITY);
88  resU = updateBound (+1, u + index, COUENNE_INFINITY);
89  }*/
90  }
91 
92  // invert check, if bounds on x do not contain 0 we may improve them
93 
94  bound = (k>0) ? wl : wu;
95 
96  if (bound > 0.) {
97 
98  CouNumber
99  xl = l [index],
100  xu = u [index],
101  xb = safe_pow (bound, 1./k, issignpower_);
102 
103  if (xl > - xb + COUENNE_EPS) resL = updateBound (-1, l + index, xb) || resL;
104  else if (xu < xb - COUENNE_EPS) resU = updateBound ( 1, u + index, - xb) || resU;
105  }
106 
107  } else {
108 
109  // Two cases:
110  // 1) x^k, k=(1/h), h integer and even, or
111  // 2) x^k, neither k nor 1/k integer
112 
113  CouNumber lb = wl, ub = wu;
114 
115  if (k < 0) { // swap bounds as they swap on the curve x^k when
116  lb = wu;
117  ub = wl;
118  }
119 
120  if ((lb > 0. || k > 0.) && (sign != expression::AUX_GEQ))
121  resL = updateBound (-1, l + index, safe_pow (lb, 1./k, issignpower_));
122 
123  if ((fabs (ub) < COUENNE_INFINITY) &&
124  (ub > 0 || k > 0.) &&
125  (sign != expression::AUX_LEQ))
126  resU = updateBound (+1, u + index, safe_pow (ub, 1./k, issignpower_));
127  //else resU = updateBound (+1, u + index, COUENNE_INFINITY);
128  }
129 
130  if (resL) chg [index].setLower(t_chg_bounds::CHANGED);
131  if (resU) chg [index].setUpper(t_chg_bounds::CHANGED);
132 
133  bool xInt = arglist_ [0] -> isInteger ();
134 
135  if ((resL || resU) && xInt) {
136 
137  // careful with what "integer" means when a bound is 1e-8 (see minlplib/deb[789].nl)
138  if (resL && (fabs (l [index]) > COUENNE_EPS)) l [index] = ceil (l [index] - COUENNE_EPS);
139  if (resU && (fabs (u [index]) > COUENNE_EPS)) u [index] = floor (u [index] + COUENNE_EPS);
140  }
141 
142  return (resL || resU);
143 }
virtual bool isInteger()
is this expression integer?
Definition: exprPow.cpp:235
#define COUENNE_round(x)
bool updateBound(register int sign, register CouNumber *dst, register CouNumber src)
updates maximum violation.
virtual bool impliedBound(int, CouNumber *, CouNumber *, t_chg_bounds *, enum auxSign=expression::AUX_EQ)
implied bound processing
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
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.
void fint fint * k
#define COUENNE_EPS
void invPowImplBounds(int, int, CouNumber *, CouNumber *, CouNumber, bool &, bool &, enum expression::auxSign)
set implied bounds for function w = x^k, k negative, integer or inverse integer, and odd ...
Definition: exprInv.cpp:47
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
virtual CouNumber Value() const
value (empty)