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 || issignpower_)) {
00059
00060
00061
00062
00063 if (k > 0.) {
00064
00065 if (wl > - COUENNE_INFINITY) resL = updateBound (-1, l + index, safe_pow (wl, 1./k, issignpower_));
00066 if (wu < COUENNE_INFINITY) resU = updateBound (+1, u + index, safe_pow (wu, 1./k, issignpower_));
00067
00068 } else {
00069 invPowImplBounds (wind, index, l, u, 1./k, resL, resU, sign);
00070 assert (!issignpower_);
00071 }
00072 }
00073 else
00074 if (isint) {
00075
00076 CouNumber bound = (k<0) ? wl : wu;
00077
00078
00079
00080
00081 if (bound > COUENNE_EPS) {
00082
00083 if (fabs (bound) < COUENNE_INFINITY) {
00084 resL = updateBound (-1, l + index, - safe_pow (bound, 1./k, issignpower_));
00085 resU = updateBound (+1, u + index, safe_pow (bound, 1./k, issignpower_));
00086 }
00087
00088
00089
00090 }
00091
00092
00093
00094 bound = (k>0) ? wl : wu;
00095
00096 if (bound > 0.) {
00097
00098 CouNumber
00099 xl = l [index],
00100 xu = u [index],
00101 xb = safe_pow (bound, 1./k, issignpower_);
00102
00103 if (xl > - xb + COUENNE_EPS) resL = updateBound (-1, l + index, xb) || resL;
00104 else if (xu < xb - COUENNE_EPS) resU = updateBound ( 1, u + index, - xb) || resU;
00105 }
00106
00107 } else {
00108
00109
00110
00111
00112
00113 CouNumber lb = wl, ub = wu;
00114
00115 if (k < 0) {
00116 lb = wu;
00117 ub = wl;
00118 }
00119
00120 if ((lb > 0. || k > 0.) && (sign != expression::AUX_GEQ))
00121 resL = updateBound (-1, l + index, safe_pow (lb, 1./k, issignpower_));
00122
00123 if ((fabs (ub) < COUENNE_INFINITY) &&
00124 (ub > 0 || k > 0.) &&
00125 (sign != expression::AUX_LEQ))
00126 resU = updateBound (+1, u + index, safe_pow (ub, 1./k, issignpower_));
00127
00128 }
00129
00130 if (resL) chg [index].setLower(t_chg_bounds::CHANGED);
00131 if (resU) chg [index].setUpper(t_chg_bounds::CHANGED);
00132
00133 bool xInt = arglist_ [0] -> isInteger ();
00134
00135 if ((resL || resU) && xInt) {
00136
00137
00138 if (resL && (fabs (l [index]) > COUENNE_EPS)) l [index] = ceil (l [index] - COUENNE_EPS);
00139 if (resU && (fabs (u [index]) > COUENNE_EPS)) u [index] = floor (u [index] + COUENNE_EPS);
00140 }
00141
00142 return (resL || resU);
00143 }