00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "assert.h"
00012
00013 #include "CouenneExprDiv.hpp"
00014 #include "CouenneExprConst.hpp"
00015 #include "CouenneExprClone.hpp"
00016 #include "CouenneExprMul.hpp"
00017 #include "CouenneExprOpp.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneExprInv.hpp"
00020 #include "CouenneExprSub.hpp"
00021 #include "CouenneExprBDiv.hpp"
00022
00023 #include "CouennePrecisions.hpp"
00024
00025 #include "CoinFinite.hpp"
00026
00027 using namespace Couenne;
00028
00029
00030
00031 expression *exprDiv::simplify () {
00032
00033 exprOp:: simplify ();
00034
00035 if ((*arglist_) -> Type () == CONST) {
00036
00037 CouNumber c0 = (*arglist_) -> Value ();
00038
00039 if (arglist_ [1] -> Type () == CONST) {
00040
00041 CouNumber c1 = arglist_ [1] -> Value ();
00042
00043 delete arglist_ [0];
00044 delete arglist_ [1];
00045 arglist_ [0] = arglist_ [1] = NULL;
00046
00047 return new exprConst (c0 / c1);
00048 }
00049 else {
00050 if (fabs (c0) < COUENNE_EPS_SIMPL)
00051 return new exprConst (0.);
00052
00053
00054
00055 expression *ret;
00056
00057 if (fabs (arglist_ [0] -> Value () - 1.) < COUENNE_EPS) {
00058 delete *arglist_;
00059 *arglist_ = NULL;
00060 ret = new exprInv (arglist_ [1]);
00061 }
00062 else ret = new exprMul (arglist_ [0], new exprInv (arglist_ [1]));
00063
00064 arglist_ = NULL;
00065 return ret;
00066 }
00067 }
00068 else
00069
00070 if (arglist_ [1] -> Type () == CONST) {
00071
00072
00073 expression *ret = new exprMul (new exprConst (1. / (arglist_ [1] -> Value ())),
00074 arglist_ [0]);
00075 delete arglist_ [1];
00076 arglist_ = NULL;
00077 return ret;
00078 }
00079
00080 return NULL;
00081 }
00082
00083
00084
00085
00086
00087 expression *exprDiv::differentiate (int index) {
00088
00089 bool
00090 diffNum = arglist_ [0] -> dependsOn (index),
00091 diffDen = arglist_ [1] -> dependsOn (index);
00092
00093 if (diffNum) {
00094
00095 if (diffDen) {
00096
00097
00098
00099 return new exprDiv (new exprSub (new exprMul (arglist_ [1] -> differentiate (index),
00100 arglist_ [0] -> clone ()),
00101 new exprMul (arglist_ [1] -> clone (),
00102 arglist_ [0] -> differentiate (index))),
00103 new exprPow (arglist_ [1] -> clone (), new exprConst (2.)));
00104
00105 } else {
00106
00107 return new exprDiv (arglist_ [0] -> differentiate (index),
00108 arglist_ [1] -> clone ());
00109 }
00110
00111 } else {
00112
00113 if (diffDen) {
00114
00115 return new exprOpp (new exprDiv (new exprMul (arglist_ [0] -> clone (),
00116 arglist_ [1] -> differentiate (index)),
00117 new exprPow (arglist_ [1] -> clone (),
00118 new exprConst (2.))));
00119
00120 } else
00121 return new exprConst (0.);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 }
00143
00144
00145
00146
00147 void exprDiv::getBounds (expression *&lb, expression *&ub) {
00148
00149 expression **almin = new expression * [4];
00150 expression **almax = new expression * [4];
00151
00152 arglist_ [0] -> getBounds (almin [0], almin [1]);
00153 arglist_ [1] -> getBounds (almin [2], almin [3]);
00154
00155 almax [0] = new exprClone (almin [0]);
00156 almax [1] = new exprClone (almin [1]);
00157 almax [2] = new exprClone (almin [2]);
00158 almax [3] = new exprClone (almin [3]);
00159
00160 lb = new exprLBDiv (almin, 4);
00161 ub = new exprUBDiv (almax, 4);
00162 }
00163
00164
00165
00166
00167 void exprDiv::getBounds (CouNumber &lb, CouNumber &ub) {
00168
00169
00170
00171 CouNumber ln, un, ld, ud;
00172
00173 arglist_ [0] -> getBounds (ln, un);
00174 arglist_ [1] -> getBounds (ld, ud);
00175
00176 if (ld > 0)
00177 if (ln > 0) lb = safeDiv (ln,ud,-1);
00178 else lb = safeDiv (ln,ld,-1);
00179 else {
00180 if (ud > 0) lb = - COUENNE_INFINITY;
00181 else if (un > 0) lb = safeDiv (un,ud,-1);
00182 else lb = safeDiv (un,ld,-1);
00183 }
00184
00185
00186
00187 if (ld > 0)
00188 if (un < 0) ub = safeDiv (un,ud,1);
00189 else ub = safeDiv (un,ld,1);
00190 else {
00191 if (ud > 0) ub = + COUENNE_INFINITY;
00192 else if (ln < 0) ub = safeDiv (ln,ud,1);
00193 else ub = safeDiv (ln,ld,1);
00194 }
00195 }
00196
00198 bool exprDiv::isInteger () {
00199
00200
00201
00202
00203
00204
00205
00206 CouNumber dl, du, nl, nu;
00207
00208 arglist_ [1] -> getBounds (dl, du);
00209 arglist_ [0] -> getBounds (nl, nu);
00210
00211
00212
00213
00214
00215 bool
00216 denzero = (fabs (dl) < COUENNE_EPS),
00217 numconst = (fabs (nl - nu) < COUENNE_EPS);
00218
00219 if ((fabs (nl) < COUENNE_EPS) &&
00220 numconst &&
00221 !denzero)
00222
00223 return true;
00224
00225
00226
00227 if (fabs (dl - du) < COUENNE_EPS) {
00228
00229 if (fabs (fabs (dl) - 1) < COUENNE_EPS)
00230 return arglist_ [0] -> isInteger ();
00231
00232 if (denzero)
00233 return false;
00234
00235 if (numconst) {
00236
00237 CouNumber quot = nl / dl;
00238
00239 if (fabs (COUENNE_round (quot) - quot) < COUENNE_EPS)
00240 return true;
00241 }
00242 }
00243
00244 return false;
00245 }
00246
00247
00249 void exprDiv::closestFeasible (expression *varind,
00250 expression *vardep,
00251 CouNumber &left,
00252 CouNumber &right) const {
00253
00254 expression *varoth = arglist_ [0];
00255
00256 bool numerator = false;
00257
00258 if (varoth -> Index () == varind -> Index ()) {
00259 varoth = arglist_ [1];
00260 numerator = true;
00261 } else assert (arglist_ [1] -> Index () == varind -> Index ());
00262
00263 CouNumber
00264 x = (*varind) (),
00265 y = (*vardep) (),
00266 c = (*varoth) ();
00267
00268 if (numerator)
00269
00270 if (c < 0.)
00271 if (c*y > x) {assert (c*y > right); right = c*y;}
00272 else {assert (c*y < left); left = c*y;}
00273 else if (c > 0.)
00274 if (c*y < x) {assert (c*y < left); left = c*y;}
00275 else {assert (c*y > right); right = c*y;}
00276 else left = - (right = COIN_DBL_MAX);
00277
00278 else
00279
00280 if (y < 0.)
00281 if (x*y > c) {assert (c/y > right); right = c/y;}
00282 else {assert (c/y < left); left = c/y;}
00283 else if (y > 0.)
00284 if (x*y > c) {assert (c/y < left); left = c/y;}
00285 else {assert (c/y > right); right = c/y;}
00286 else left = - (right = COIN_DBL_MAX);
00287 }
00288
00289
00291 CouNumber exprDiv::gradientNorm (const double *x) {
00292
00293 int
00294 ind0 = arglist_ [0] -> Index (),
00295 ind1 = arglist_ [1] -> Index ();
00296
00297 CouNumber
00298 x0 = (ind0 < 0) ? fabs (arglist_ [0] -> Value ()) : fabs (x [ind0]),
00299 x1 = (ind1 < 0) ? fabs (arglist_ [1] -> Value ()) : fabs (x [ind1]),
00300 x1sq = x1 * x1;
00301
00302 if (x1sq < 1/COUENNE_INFINITY) {
00303 x1sq = 1/COUENNE_INFINITY;
00304 if (x1 < 1/COUENNE_INFINITY)
00305 x1 = 1/COUENNE_INFINITY;
00306 }
00307
00308 if (ind0 < 0)
00309 if (ind1 < 0) return 0.;
00310 else return fabs (x0/(x1sq));
00311 else
00312 if (ind1 < 0) return 1. / x1;
00313 else return sqrt (1. / x1sq + x0*x0 / (x1sq * x1sq));
00314 }