/home/coin/SVN-release/OS-2.0.1/Couenne/src/expression/operators/exprSub.cpp

Go to the documentation of this file.
00001 /* $Id: exprSub.cpp 154 2009-06-16 18:52:53Z pbelotti $ */
00002 /*
00003  * Name:    exprSub.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: definition of subtractions
00006  *
00007  * (C) Carnegie-Mellon University, 2006-08.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "exprSub.hpp"
00012 #include "exprOpp.hpp"
00013 #include "CouennePrecisions.hpp"
00014 
00015 
00016 // simplify subtractions
00017 
00018 expression *exprSub::simplify () {
00019 
00020   exprOp:: simplify ();
00021 
00022   // check for (f(x) - f(x))
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   // check for other special cases
00032   if ((*arglist_) -> Type () == CONST) { // expr = c1 - f2 
00033 
00034     CouNumber c0 = (*arglist_) -> Value ();
00035 
00036     if (arglist_ [1] -> Type () == CONST) { // expr = c1 - c2
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) { // expr = opp (f2)
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 // only need to check if f2 == 0
00054 
00055     if ((arglist_ [1] -> Type () == CONST) &&
00056         (fabs (arglist_ [1] -> Value ()) < COUENNE_EPS_SIMPL)) {
00057       // expr = f1 - 0 --> return f1
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 // differentiate product of expressions
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 // Get lower and upper bound of an expression (if any)
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 // Get value of lower and upper bound of an expression (if any)
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   // caution, xi or yi might be -1
00122   int xi = arglist_ [0] -> Index (),
00123       yi = arglist_ [1] -> Index ();
00124 
00125   if ((xi == -1) && (yi == -1)) // both x and y are constant
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   // w >= l
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   // w <= u
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 }

Generated on Thu Oct 8 03:02:57 2009 by  doxygen 1.4.7