/home/coin/SVN-release/OS-2.2.0/Couenne/src/bound_tightening/operators/impliedBounds-exprPow.cpp

Go to the documentation of this file.
00001 /* $Id: impliedBounds-exprPow.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * Name:    impliedBounds-exprPow.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implied bounds for power operators
00006  *
00007  * (C) Carnegie-Mellon University, 2008. 
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "exprPow.hpp"
00012 #include "CoinHelperFunctions.hpp"
00013 
00016 
00017 void invPowImplBounds (int, int, CouNumber *, CouNumber *, CouNumber, bool &, bool &);
00018 
00019 
00022 
00023 bool exprPow::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00024 
00025   //int xi = arglist_ [0] -> Index ();
00026   //if (xi>=0) printf ("in implBound-pow: %g,%g\n", l [xi], u [xi]);
00027 
00028   //return false; // !!!
00029 
00030   bool resL, resU = resL = false;
00031 
00032   if (arglist_ [0] -> Type () == CONST)   // base is constant or zero, nothing to do
00033     return false;
00034 
00035   assert (arglist_ [1] -> Type () == CONST);
00036 
00037   int index = arglist_ [0] -> Index ();
00038 
00039   CouNumber k = arglist_ [1] -> Value (); // exponent
00040 
00041   if ((fabs (k) < COUENNE_EPS) || 
00042       (fabs (k) > COUENNE_INFINITY)) // a null or infinite k is of little use
00043     return false;
00044 
00045   int intk; // integer (or integer inverse of) exponent
00046 
00047   bool 
00048     isint    =           (fabs (k    - (intk = COUENNE_round (k)))    < COUENNE_EPS), // k   integer
00049     isinvint = !isint && (fabs (1./k - (intk = COUENNE_round (1./k))) < COUENNE_EPS); // 1/k integer
00050 
00051   CouNumber wl = l [wind], // lower w
00052             wu = u [wind]; // upper w
00053 
00054   if ((isint || isinvint) && (intk % 2)) { 
00055 
00056     // k or 1/k integer and odd, or non-integer --> it is a monotone
00057     // increasing function
00058 
00059     if (k > 0.) { // simple, just follow bounds
00060 
00061       if (wl > - COUENNE_INFINITY) resL = updateBound (-1, l + index, safe_pow (wl, 1./k)); 
00062       if (wu <   COUENNE_INFINITY) resU = updateBound (+1, u + index, safe_pow (wu, 1./k));
00063 
00064     } else // slightly more complicated, resort to same method as in exprInv
00065       invPowImplBounds (wind, index, l, u, 1./k, resL, resU);
00066   } 
00067   else 
00068     if (isint) { // x^k, k integer and even --> non monotone
00069 
00070       CouNumber bound = (k<0) ? wl : wu;
00071 
00072       // |x| <= b^(1/k), where b is wl or wu depending on k negative
00073       // or positive, respectively
00074 
00075       if (bound > COUENNE_EPS) {
00076 
00077         if (fabs (bound) < COUENNE_INFINITY) {
00078           resL = updateBound (-1, l + index, - safe_pow (bound, 1./k));
00079           resU = updateBound (+1, u + index,   safe_pow (bound, 1./k));
00080         } /*else {
00081           resL = updateBound (-1, l + index, - COUENNE_INFINITY);
00082           resU = updateBound (+1, u + index,   COUENNE_INFINITY);
00083           }*/
00084       }
00085 
00086       // invert check, if bounds on x do not contain 0 we may improve them
00087 
00088       bound = (k>0) ? wl : wu;
00089 
00090       CouNumber xl = l [index], 
00091                 xu = u [index],
00092                 xb = safe_pow (bound, 1./k);
00093 
00094       if      (xl > - xb + COUENNE_EPS) resL = updateBound (-1, l + index,   xb) || resL;
00095       else if (xu <   xb - COUENNE_EPS) resU = updateBound ( 1, u + index, - xb) || resU;
00096 
00097     } else { 
00098 
00099       // Two cases:
00100       // 1) x^k, k=(1/h), h integer and even, or 
00101       // 2) x^k, neither k nor 1/k integer
00102 
00103       CouNumber lb = wl, ub = wu;
00104 
00105       if (k < 0) { // swap bounds as they swap on the curve x^k when 
00106         lb = wu;
00107         ub = wl;
00108       }
00109 
00110       if (lb > 0. || k > 0.) resL = updateBound (-1, l + index, safe_pow (lb, 1./k));
00111 
00112       if ((fabs (ub) < COUENNE_INFINITY) && (ub > 0 || k > 0.)) 
00113         resU = updateBound (+1, u + index, safe_pow (ub, 1./k));
00114       //else                  resU = updateBound (+1, u + index, COUENNE_INFINITY);
00115     }
00116 
00117   if (resL) chg [index].setLower(t_chg_bounds::CHANGED);
00118   if (resU) chg [index].setUpper(t_chg_bounds::CHANGED);
00119 
00120   bool xInt = arglist_ [0] -> isInteger ();
00121 
00122   if ((resL || resU) && xInt) {
00123     int xi = arglist_ [0] -> Index ();
00124     assert (xi >= 0);
00125     // careful with what "integer" means when a bound is 1e-8 (see minlp/deb[789].nl)
00126     if (resL && (fabs (l [xi]) > COUENNE_EPS)) l [xi] = ceil  (l [xi] - COUENNE_EPS);
00127     if (resU && (fabs (u [xi]) > COUENNE_EPS)) u [xi] = floor (u [xi] + COUENNE_EPS);
00128   }
00129 
00130   return (resL || resU);
00131 }

Generated on Thu Aug 5 03:02:56 2010 by  doxygen 1.4.7