00001
00002
00003
00004
00005
00006
00007
00008
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
00026
00027
00028
00029
00030 bool resL, resU = resL = false;
00031
00032 if (arglist_ [0] -> Type () == CONST)
00033 return false;
00034
00035 assert (arglist_ [1] -> Type () == CONST);
00036
00037 int index = arglist_ [0] -> Index ();
00038
00039 CouNumber k = arglist_ [1] -> Value ();
00040
00041 if ((fabs (k) < COUENNE_EPS) ||
00042 (fabs (k) > COUENNE_INFINITY))
00043 return false;
00044
00045 int intk;
00046
00047 bool
00048 isint = (fabs (k - (intk = COUENNE_round (k))) < COUENNE_EPS),
00049 isinvint = !isint && (fabs (1./k - (intk = COUENNE_round (1./k))) < COUENNE_EPS);
00050
00051 CouNumber wl = l [wind],
00052 wu = u [wind];
00053
00054 if ((isint || isinvint) && (intk % 2)) {
00055
00056
00057
00058
00059 if (k > 0.) {
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
00065 invPowImplBounds (wind, index, l, u, 1./k, resL, resU);
00066 }
00067 else
00068 if (isint) {
00069
00070 CouNumber bound = (k<0) ? wl : wu;
00071
00072
00073
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 }
00081
00082
00083
00084 }
00085
00086
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
00100
00101
00102
00103 CouNumber lb = wl, ub = wu;
00104
00105 if (k < 0) {
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
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
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 }