/* $Id$ * * Name: exprSub.cpp * Author: Pietro Belotti * Purpose: definition of subtractions * * (C) Carnegie-Mellon University, 2006-10. * This file is licensed under the Eclipse Public License (EPL) */ #include "CouenneExprSub.hpp" #include "CouenneExprConst.hpp" #include "CouenneExprOpp.hpp" #include "CouennePrecisions.hpp" #include "CoinFinite.hpp" using namespace Couenne; // simplify subtractions expression *exprSub::simplify () { exprOp:: simplify (); // check for (f(x) - f(x)) if (arglist_ [0] -> compare (*(arglist_ [1])) == 0) { // delete arglist_ [0]; arglist_ [0] = NULL; // delete arglist_ [1]; arglist_ [1] = NULL; return new exprConst (0.); } // check for other special cases if ((*arglist_) -> Type () == CONST) { // expr = c1 - f2 CouNumber c0 = (*arglist_) -> Value (); if (arglist_ [1] -> Type () == CONST) { // expr = c1 - c2 CouNumber c1 = arglist_ [1] -> Value (); // delete arglist_ [0]; arglist_ [0] = NULL; // delete arglist_ [1]; arglist_ [1] = NULL; return new exprConst (c0 - c1); } else if (fabs (c0) == 0.) { // expr = opp (f2) expression *ret = new exprOpp (arglist_ [1]); // delete arglist_ [0]; arglist_ [1] = NULL; return ret; } } else // only need to check if f2 == 0 if ((arglist_ [1] -> Type () == CONST) && (fabs (arglist_ [1] -> Value ()) < COUENNE_EPS_SIMPL)) { // expr = f1 - 0 --> return f1 expression *ret = arglist_ [0]; //delete arglist_ [1]; arglist_ [0] = NULL; return ret; } return NULL; } // differentiate product of expressions expression *exprSub::differentiate (int index) { expression **arglist = new expression * [nargs_]; for (int i = 0; i < nargs_; i++) if (arglist_ [i] -> dependsOn (index)) arglist [i] = arglist_ [i] -> differentiate (index); else arglist [i] = new exprConst (0.); return new exprSub (arglist, nargs_); } // Get lower and upper bound of an expression (if any) void exprSub::getBounds (expression *&lb, expression *&ub) { expression **alsl = new expression * [2]; expression **alsu = new expression * [2]; arglist_ [0] -> getBounds (alsl [0], alsu [0]); arglist_ [1] -> getBounds (alsu [1], alsl [1]); lb = new exprSub (alsl, 2); ub = new exprSub (alsu, 2); } // Get value of lower and upper bound of an expression (if any) void exprSub::getBounds (CouNumber &lb, CouNumber &ub) { CouNumber lba0, uba0, lba1, uba1; arglist_ [0] -> getBounds (lba0, uba0); arglist_ [1] -> getBounds (lba1, uba1); lb = ((lba0 < -COUENNE_INFINITY) || (uba1 > COUENNE_INFINITY)) ? -COUENNE_INFINITY : (lba0 - uba1); ub = ((uba0 > COUENNE_INFINITY) || (lba1 < -COUENNE_INFINITY)) ? COUENNE_INFINITY : (uba0 - lba1); } /// implied bound processing for expression w = x-y, upon change in /// lower- and/or upper bound of w, whose index is wind bool exprSub::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) { // caution, xi or yi might be -1 int xi = arglist_ [0] -> Index (), yi = arglist_ [1] -> Index (); if ((xi == -1) && (yi == -1)) // both x and y are constant return false; CouNumber xl, xu, yl, yu, wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind], wu = sign == expression::AUX_LEQ ? COIN_DBL_MAX : u [wind]; if (xi==-1) xl = xu = arglist_ [0] -> Value (); else {xl = l [xi]; xu = u [xi];} if (yi==-1) yl = yu = arglist_ [1] -> Value (); else {yl = l [yi]; yu = u [yi];} bool res = false; // w >= l bool xInt = arglist_ [0] -> isInteger (), yInt = arglist_ [1] -> isInteger (); if (wl > -COUENNE_INFINITY) { if ((xi>=0) && (updateBound (-1, l + xi, xInt ? ceil (yl + wl - COUENNE_EPS) : (yl + wl)))) { res = true; chg [xi].setLower(t_chg_bounds::CHANGED); } if ((yi>=0) && (updateBound (+1, u + yi, yInt ? floor (xu - wl + COUENNE_EPS) : (xu - wl)))) { res = true; chg [yi].setUpper(t_chg_bounds::CHANGED); } } // w <= u if (wu < COUENNE_INFINITY) { if ((xi>=0) && (updateBound (+1, u + xi, xInt ? floor (yu + wu + COUENNE_EPS) : (yu + wu)))) { res = true; chg [xi].setUpper(t_chg_bounds::CHANGED); } if ((yi>=0) && (updateBound (-1, l + yi, yInt ? ceil (xl - wu - COUENNE_EPS) : (xl - wu)))) { res = true; chg [yi].setLower(t_chg_bounds::CHANGED); } } return res; }