00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "exprInv.hpp"
00012 #include "exprClone.hpp"
00013 #include "exprMul.hpp"
00014 #include "CouenneProblem.hpp"
00015
00016
00017
00018 expression *exprInv::differentiate (int index) {
00019
00020 expression **alm = new expression * [3];
00021
00022 alm [0] = new exprInv (new exprClone (argument_));
00023 alm [1] = new exprClone (alm [0]);
00024 alm [2] = argument_ -> differentiate (index);
00025
00026 return new exprMul (alm, 3);
00027 }
00028
00029
00030
00031 void exprInv::print (std::ostream &out,
00032 bool descend) const {
00033 out << "(1/";
00034 argument_ -> print (out, descend);
00035 out << ")";
00036 }
00037
00038
00039
00042 void invPowImplBounds (int wind, int index,
00043 CouNumber *l, CouNumber *u, CouNumber k,
00044 bool &resL, bool &resU) {
00045
00046 CouNumber wl = l [wind],
00047 wu = u [wind];
00048
00049
00050
00051 if (wl >= 0.) {
00052 if (wu > COUENNE_EPS) {
00053 if (wu < COUENNE_INFINITY) resL = updateBound (-1, l + index, pow (wu, k));
00054 else resL = updateBound (-1, l + index, 0.);
00055 }
00056 if (wl > COUENNE_EPS) resU = updateBound (+1, u + index, pow (wl, k));
00057 }
00058
00059
00060
00061 if (wu <= -0.) {
00062 if (wl < - COUENNE_EPS) {
00063 if (wl > - COUENNE_INFINITY) resU = updateBound (+1, u + index, pow (wl, k)) || resU;
00064 else resU = updateBound (+1, u + index, 0.) || resU;
00065 }
00066 if (wu < - COUENNE_EPS) resL = updateBound (-1, l + index, pow (wu, k)) || resL;
00067 }
00068 }
00069
00070
00073 bool exprInv::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00074
00075
00076
00077
00078
00079
00080
00081
00082 int index = argument_ -> Index ();
00083
00084 bool resL, resU = resL = false;
00085
00086 invPowImplBounds (wind, index, l, u, -1., resL, resU);
00087
00088 bool argInt = argument_ -> isInteger ();
00089
00090 if (resL) {
00091 chg [index].setLower(t_chg_bounds::CHANGED);
00092 if (argInt) l [index] = ceil (l [index] - COUENNE_EPS);
00093 }
00094
00095 if (resU) {
00096 chg [index].setUpper(t_chg_bounds::CHANGED);
00097 if (argInt) u [index] = floor (u [index] + COUENNE_EPS);
00098 }
00099
00100 return (resL || resU);
00101 }
00102
00103
00105 CouNumber exprInv::gradientNorm (const double *x) {
00106 int ind = argument_ -> Index ();
00107 CouNumber xx;
00108 if (ind < 0) return 0.;
00109 else {
00110 xx = x [argument_ -> Index ()];
00111 return 1. / (xx*xx);
00112 }
00113 }
00114
00115
00118 bool exprInv::isCuttable (CouenneProblem *problem, int index) const {
00119
00120 int xind = argument_ -> Index ();
00121
00122 double
00123 x = problem -> X (xind),
00124 y = problem -> X (index);
00125
00126 return ((problem -> Lb (xind) >= 0) && (x > 0) && (y*x <= 1) ||
00127 (problem -> Ub (xind) <= 0) && (x < 0) && (y*x <= 1));
00128 }