00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneExprPow.hpp"
00012 #include "CouenneExpression.hpp"
00013 #include "CouenneConfig.h"
00014 #include "CoinFinite.hpp"
00015 #include "CoinHelperFunctions.hpp"
00016
00017 using namespace Couenne;
00018
00021
00022 void invPowImplBounds (int, int, CouNumber *, CouNumber *, CouNumber, bool &, bool &, enum expression::auxSign);
00023
00024
00027
00028 bool exprPow::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum expression::auxSign sign) {
00029
00030
00031
00032
00033 bool resL, resU = resL = false;
00034
00035 if (arglist_ [0] -> Type () == CONST)
00036 return false;
00037
00038 assert (arglist_ [1] -> Type () == CONST);
00039
00040 int index = arglist_ [0] -> Index ();
00041
00042 CouNumber k = arglist_ [1] -> Value ();
00043
00044 if ((fabs (k) < COUENNE_EPS) ||
00045 (fabs (k) > COUENNE_INFINITY))
00046 return false;
00047
00048 int intk;
00049
00050 bool
00051 isint = ( fabs (k - (intk = COUENNE_round (k))) < COUENNE_EPS),
00052 isinvint = !isint && (k != 0. && (fabs (1./k - (intk = COUENNE_round (1./k))) < COUENNE_EPS));
00053
00054 CouNumber
00055 wl = ((sign == expression::AUX_GEQ) ? -COIN_DBL_MAX : l [wind]),
00056 wu = ((sign == expression::AUX_LEQ) ? COIN_DBL_MAX : u [wind]);
00057
00058 if ((isint || isinvint) && (intk % 2)) {
00059
00060
00061
00062
00063 if (k > 0.) {
00064
00065 if (wl > - COUENNE_INFINITY) resL = updateBound (-1, l + index, safe_pow (wl, 1./k));
00066 if (wu < COUENNE_INFINITY) resU = updateBound (+1, u + index, safe_pow (wu, 1./k));
00067
00068 } else
00069 invPowImplBounds (wind, index, l, u, 1./k, resL, resU, sign);
00070 }
00071 else
00072 if (isint) {
00073
00074 CouNumber bound = (k<0) ? wl : wu;
00075
00076
00077
00078
00079 if (bound > COUENNE_EPS) {
00080
00081 if (fabs (bound) < COUENNE_INFINITY) {
00082 resL = updateBound (-1, l + index, - safe_pow (bound, 1./k));
00083 resU = updateBound (+1, u + index, safe_pow (bound, 1./k));
00084 }
00085
00086
00087
00088 }
00089
00090
00091
00092 bound = (k>0) ? wl : wu;
00093
00094 CouNumber xl = l [index],
00095 xu = u [index],
00096 xb = safe_pow (bound, 1./k);
00097
00098 if (xl > - xb + COUENNE_EPS) resL = updateBound (-1, l + index, xb) || resL;
00099 else if (xu < xb - COUENNE_EPS) resU = updateBound ( 1, u + index, - xb) || resU;
00100
00101 } else {
00102
00103
00104
00105
00106
00107 CouNumber lb = wl, ub = wu;
00108
00109 if (k < 0) {
00110 lb = wu;
00111 ub = wl;
00112 }
00113
00114 if (lb > 0. || k > 0.) resL = updateBound (-1, l + index, safe_pow (lb, 1./k));
00115
00116 if ((fabs (ub) < COUENNE_INFINITY) && (ub > 0 || k > 0.))
00117 resU = updateBound (+1, u + index, safe_pow (ub, 1./k));
00118
00119 }
00120
00121 if (resL) chg [index].setLower(t_chg_bounds::CHANGED);
00122 if (resU) chg [index].setUpper(t_chg_bounds::CHANGED);
00123
00124 bool xInt = arglist_ [0] -> isInteger ();
00125
00126 if ((resL || resU) && xInt) {
00127
00128
00129 if (resL && (fabs (l [index]) > COUENNE_EPS)) l [index] = ceil (l [index] - COUENNE_EPS);
00130 if (resU && (fabs (u [index]) > COUENNE_EPS)) u [index] = floor (u [index] + COUENNE_EPS);
00131 }
00132
00133 return (resL || resU);
00134 }