00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneExprSub.hpp"
00012 #include "CouenneExprConst.hpp"
00013 #include "CouenneExprOpp.hpp"
00014 #include "CouennePrecisions.hpp"
00015
00016 #include "CoinFinite.hpp"
00017
00018 using namespace Couenne;
00019
00020
00021
00022 expression *exprSub::simplify () {
00023
00024 exprOp:: simplify ();
00025
00026
00027 if (arglist_ [0] -> compare (*(arglist_ [1])) == 0) {
00028
00029 delete arglist_ [0]; arglist_ [0] = NULL;
00030 delete arglist_ [1]; arglist_ [1] = NULL;
00031
00032 return new exprConst (0.);
00033 }
00034
00035
00036 if ((*arglist_) -> Type () == CONST) {
00037
00038 CouNumber c0 = (*arglist_) -> Value ();
00039
00040 if (arglist_ [1] -> Type () == CONST) {
00041
00042 CouNumber c1 = arglist_ [1] -> Value ();
00043
00044 delete arglist_ [0]; arglist_ [0] = NULL;
00045 delete arglist_ [1]; arglist_ [1] = NULL;
00046
00047 return new exprConst (c0 - c1);
00048 }
00049 else if (fabs (c0) < COUENNE_EPS_SIMPL) {
00050
00051 expression *ret = new exprOpp (arglist_ [1]);
00052 delete arglist_ [0];
00053 arglist_ [0] = arglist_ [1] = NULL;
00054 return ret;
00055 }
00056 }
00057 else
00058
00059 if ((arglist_ [1] -> Type () == CONST) &&
00060 (fabs (arglist_ [1] -> Value ()) < COUENNE_EPS_SIMPL)) {
00061
00062
00063 expression *ret = arglist_ [0];
00064 delete arglist_ [1];
00065 arglist_ [0] = arglist_ [1] = NULL;
00066 return ret;
00067 }
00068
00069 return NULL;
00070 }
00071
00072
00073
00074
00075 expression *exprSub::differentiate (int index) {
00076
00077 expression **arglist = new expression * [nargs_];
00078
00079 for (int i = 0; i < nargs_; i++)
00080 if (arglist_ [i] -> dependsOn (index))
00081 arglist [i] = arglist_ [i] -> differentiate (index);
00082 else arglist [i] = new exprConst (0.);
00083
00084 return new exprSub (arglist, nargs_);
00085 }
00086
00087
00088
00089 void exprSub::getBounds (expression *&lb, expression *&ub) {
00090
00091 expression **alsl = new expression * [2];
00092 expression **alsu = new expression * [2];
00093
00094 arglist_ [0] -> getBounds (alsl [0], alsu [0]);
00095 arglist_ [1] -> getBounds (alsu [1], alsl [1]);
00096
00097 lb = new exprSub (alsl, 2);
00098 ub = new exprSub (alsu, 2);
00099 }
00100
00101
00102
00103 void exprSub::getBounds (CouNumber &lb, CouNumber &ub) {
00104
00105 CouNumber lba0, uba0, lba1, uba1;
00106
00107 arglist_ [0] -> getBounds (lba0, uba0);
00108 arglist_ [1] -> getBounds (lba1, uba1);
00109
00110 lb = ((lba0 < -COUENNE_INFINITY) || (uba1 > COUENNE_INFINITY)) ?
00111 -COUENNE_INFINITY :
00112 (lba0 - uba1);
00113
00114 ub = ((uba0 > COUENNE_INFINITY) || (lba1 < -COUENNE_INFINITY)) ?
00115 COUENNE_INFINITY :
00116 (uba0 - lba1);
00117 }
00118
00119
00122
00123 bool exprSub::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
00124
00125
00126 int xi = arglist_ [0] -> Index (),
00127 yi = arglist_ [1] -> Index ();
00128
00129 if ((xi == -1) && (yi == -1))
00130 return false;
00131
00132 CouNumber xl, xu, yl, yu,
00133 wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
00134 wu = sign == expression::AUX_LEQ ? COIN_DBL_MAX : u [wind];
00135
00136 if (xi==-1) xl = xu = arglist_ [0] -> Value ();
00137 else {xl = l [xi]; xu = u [xi];}
00138
00139 if (yi==-1) yl = yu = arglist_ [1] -> Value ();
00140 else {yl = l [yi]; yu = u [yi];}
00141
00142 bool res = false;
00143
00144
00145
00146 bool
00147 xInt = arglist_ [0] -> isInteger (),
00148 yInt = arglist_ [1] -> isInteger ();
00149
00150 if (wl > -COUENNE_INFINITY) {
00151
00152 if ((xi>=0) && (updateBound (-1, l + xi, xInt ? ceil (yl + wl - COUENNE_EPS) : (yl + wl)))) {
00153 res = true;
00154 chg [xi].setLower(t_chg_bounds::CHANGED);
00155 }
00156
00157 if ((yi>=0) && (updateBound (+1, u + yi, yInt ? floor (xu - wl + COUENNE_EPS) : (xu - wl)))) {
00158 res = true;
00159 chg [yi].setUpper(t_chg_bounds::CHANGED);
00160 }
00161 }
00162
00163
00164
00165 if (wu < COUENNE_INFINITY) {
00166
00167 if ((xi>=0) && (updateBound (+1, u + xi, xInt ? floor (yu + wu + COUENNE_EPS) : (yu + wu)))) {
00168 res = true;
00169 chg [xi].setUpper(t_chg_bounds::CHANGED);
00170 }
00171
00172 if ((yi>=0) && (updateBound (-1, l + yi, yInt ? ceil (xl - wu - COUENNE_EPS) : (xl - wu)))) {
00173 res = true;
00174 chg [yi].setLower(t_chg_bounds::CHANGED);
00175 }
00176 }
00177
00178 return res;
00179 }