00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012 #include <assert.h>
00013
00014 #include "CoinHelperFunctions.hpp"
00015
00016 #include "CouennePrecisions.hpp"
00017 #include "exprPow.hpp"
00018 #include "exprSum.hpp"
00019 #include "exprMul.hpp"
00020 #include "exprDiv.hpp"
00021 #include "exprLog.hpp"
00022 #include "exprConst.hpp"
00023 #include "CouenneProblem.hpp"
00024
00025
00027
00028 expression *exprPow::simplify () {
00029
00030 exprOp:: simplify ();
00031
00032 if ((*arglist_) -> Type () == CONST) {
00033
00034 CouNumber c0 = (*arglist_) -> Value ();
00035
00036 if (arglist_ [1] -> Type () == CONST) {
00037
00038 CouNumber c1 = arglist_ [1] -> Value ();
00039
00040 delete arglist_ [0];
00041 delete arglist_ [1];
00042
00043 arglist_ [0] = arglist_ [1] = NULL;
00044
00045 return new exprConst (pow (c0, c1));
00046 }
00047 else
00048 if (fabs (c0) < COUENNE_EPS_SIMPL)
00049 return new exprConst (0.);
00050 }
00051 else
00052
00053 if (arglist_ [1] -> Type () == CONST) {
00054
00055 CouNumber expon = arglist_ [1] -> Value ();
00056
00057 if (fabs (expon) < COUENNE_EPS_SIMPL)
00058 return new exprConst (1.);
00059
00060 else if (fabs (expon - 1) < COUENNE_EPS_SIMPL) {
00061
00062 delete arglist_ [1];
00063 expression *ret = arglist_ [0];
00064 arglist_ [0] = arglist_ [1] = NULL;
00065 return ret;
00066 }
00067
00068 else if (fabs (expon + 1) < COUENNE_EPS_SIMPL) {
00069
00070 delete arglist_ [1];
00071 expression *ret = new exprInv (arglist_ [0]);
00072 arglist_ [0] = arglist_ [1] = NULL;
00073 return ret;
00074 }
00075 }
00076
00077 return NULL;
00078 }
00079
00080
00082
00083 expression *exprPow::differentiate (int index) {
00084
00085 if (!(arglist_ [0] -> dependsOn (&index, 1)) &&
00086 !(arglist_ [1] -> dependsOn (&index, 1)))
00087 return new exprConst (0.);
00088
00089
00090
00091 expression **alm = new expression * [2];
00092 expression **alp = new expression * [2];
00093 expression **als = new expression * [2];
00094 expression **alm1 = new expression * [2];
00095 expression **alm2 = new expression * [2];
00096 expression **ald = new expression * [2];
00097
00098 alp [0] = new exprClone (arglist_ [0]);
00099 alp [1] = new exprClone (arglist_ [1]);
00100
00101 alm [0] = new exprPow (alp, 2);
00102
00103 alm1 [0] = arglist_ [1] -> differentiate (index);
00104 alm1 [1] = new exprLog (new exprClone (arglist_ [0]));
00105
00106 als [0] = new exprMul (alm1, 2);
00107
00108 ald [0] = new exprClone (arglist_ [1]);
00109 ald [1] = new exprClone (arglist_ [0]);
00110
00111 alm2 [0] = new exprDiv (ald, 2);
00112 alm2 [1] = arglist_ [0] -> differentiate (index);
00113
00114 als [1] = new exprMul (alm2, 2);
00115
00116 alm [1] = new exprSum (als, 2);
00117
00118 return new exprMul (alm, 2);
00119 }
00120
00121
00129
00130 int exprPow::Linearity () {
00131
00132 if (arglist_ [0] -> Type () == CONST) {
00133
00134 if (arglist_ [1] -> Type () == CONST) return CONSTANT;
00135 else return NONLINEAR;
00136 }
00137 else {
00138
00139 double exponent = arglist_ [1] -> Value ();
00140
00141 if (fabs (exponent - COUENNE_round (exponent)) > COUENNE_EPS)
00142 return NONLINEAR;
00143
00144 if (arglist_ [1] -> Type () == CONST) {
00145
00146 int expInt = (int) COUENNE_round (exponent);
00147
00148 if (arglist_ [0] -> Linearity () == LINEAR) {
00149
00150 switch (expInt) {
00151
00152 case 0: return CONSTANT;
00153 case 1: return LINEAR;
00154 case 2: return QUADRATIC;
00155
00156 default: return NONLINEAR;
00157 }
00158 }
00159 else
00160 if (arglist_ [0] -> Linearity () == QUADRATIC)
00161 switch (expInt) {
00162
00163 case 0: return CONSTANT;
00164 case 1: return QUADRATIC;
00165
00166 default: return NONLINEAR;
00167 }
00168 else return NONLINEAR;
00169 }
00170 else return NONLINEAR;
00171 }
00172 }
00173
00174
00176 bool exprPow::isInteger () {
00177
00178
00179
00180 if (!(arglist_ [0] -> isInteger ())) {
00181
00182
00183 CouNumber lb, ub;
00184 arglist_ [0] -> getBounds (lb, ub);
00185
00186 if ((fabs (lb - ub) > COUENNE_EPS) ||
00187 !::isInteger (lb))
00188 return false;
00189 }
00190
00191
00192
00193 if (!(arglist_ [1] -> isInteger ())) {
00194
00195
00196 CouNumber lb, ub;
00197 arglist_ [1] -> getBounds (lb, ub);
00198
00199 if ((fabs (lb - ub) > COUENNE_EPS) ||
00200 !::isInteger (lb))
00201 return false;
00202
00203 if (lb < 0) {
00204
00205 arglist_ [0] -> getBounds (lb, ub);
00206
00207 if ((fabs (lb - ub) > COUENNE_EPS) ||
00208 (fabs (lb) < COUENNE_EPS) ||
00209 !::isInteger (1. / lb))
00210 return false;
00211 }
00212 }
00213
00214 return true;
00215 }
00216
00217
00219 void exprPow::closestFeasible (expression *varind,
00220 expression *vardep,
00221 CouNumber &left,
00222 CouNumber &right) const {
00223 CouNumber
00224 x = (*varind) (),
00225 y = (*vardep) (),
00226 k = arglist_ [1] -> Value (),
00227 xk = safe_pow (x, k),
00228 yk = safe_pow (y, 1./k);
00229
00230 int intk = 0;
00231
00232 bool isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
00233 isInvInt = !isInt && (fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS);
00234
00235
00236
00237
00238
00239
00240 if (isInt || isInvInt)
00241
00242 if (intk % 2)
00243
00244 if (k > 0)
00245 ((y < xk) ? left : right) = yk;
00246
00247 else
00248
00249 if (y < 0.)
00250 if (y < xk) right = yk;
00251 else left = yk;
00252
00253 else
00254 if (y > xk) left = yk;
00255 else right = yk;
00256
00257 else
00258
00259 if (y <= 0.)
00260 left = - (right = COIN_DBL_MAX);
00261
00262 else
00263
00264 if (k > 0)
00265
00266 if (k < 1)
00267
00268 if (x > yk) left = yk;
00269 else right = yk;
00270
00271 else
00272
00273 if (x > yk) left = yk;
00274 else if (x < -yk) right = -yk;
00275 else left = - (right = yk);
00276
00277 else
00278 if (y < xk)
00279 left = - (right = yk);
00280 else
00281 if (x > 0) left = yk;
00282 else right = -yk;
00283
00284 else
00285
00286 if (k > 0) ((y < xk) ? left : right) = yk;
00287 else ((y > xk) ? left : right) = yk;
00288 }
00289
00290
00292 CouNumber exprPow::gradientNorm (const double *x) {
00293
00294 int ind0 = arglist_ [0] -> Index ();
00295 CouNumber exponent = arglist_ [1] -> Value ();
00296 return (ind0 < 0) ? 0. : fabs (exponent * safe_pow (x [ind0], exponent - 1));
00297 }
00298
00299
00302 bool exprPow::isCuttable (CouenneProblem *problem, int index) const {
00303
00304 CouNumber exponent = arglist_ [1] -> Value ();
00305
00306 bool
00307 isInt = ::isInteger (exponent),
00308 isInvInt = (exponent != 0.) && ::isInteger (1. / exponent);
00309
00310 int intExp = (isInt ? COUENNE_round (exponent) : (isInvInt ? COUENNE_round (1. / exponent) : 0));
00311
00312 if (exponent > 0.) {
00313
00314 if (isInt || isInvInt) {
00315
00316 if (intExp % 2) return false;
00317
00318 CouNumber
00319 x = problem -> X (arglist_ [0] -> Index ()),
00320 y = problem -> X (index);
00321
00322 if (isInt) return (y <= safe_pow (x, exponent));
00323
00324 return (y >= safe_pow (x, exponent));
00325 } else {
00326
00327
00328 CouNumber
00329 x = problem -> X (arglist_ [0] -> Index ()),
00330 y = problem -> X (index);
00331
00332 return ((exponent <= 1.) && (y >= safe_pow (x, exponent)) ||
00333 (exponent >= 1.) && (y <= safe_pow (x, exponent)));
00334 }
00335 } else {
00336
00337
00338 CouNumber
00339 x = problem -> X (arglist_ [0] -> Index ()),
00340 y = problem -> X (index),
00341 lb = problem -> Lb (index),
00342 ub = problem -> Ub (index);
00343
00344 if (isInt || isInvInt)
00345
00346 if (!(intExp % 2)) return (((lb > 0) || (ub < 0)) && (y * safe_pow (fabs (x), -exponent) <= 1.));
00347 else return (((lb > 0) || (ub < 0)) && (y * safe_pow (x, -exponent) <= 1.));
00348 else return (y * safe_pow (x, -exponent) <= 1.);
00349 }
00350 }