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