/home/coin/SVN-release/OS-2.4.1/Couenne/src/expression/operators/exprDiv.cpp

Go to the documentation of this file.
00001 /* $Id: exprDiv.cpp 617 2011-06-09 09:09:07Z pbelotti $
00002  *
00003  * Name:    exprDiv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: definition of divisions
00006  *
00007  * (C) Carnegie-Mellon University, 2006-11. 
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "assert.h"
00012 
00013 #include "CouenneExprDiv.hpp"
00014 #include "CouenneExprConst.hpp"
00015 #include "CouenneExprClone.hpp"
00016 #include "CouenneExprMul.hpp"
00017 #include "CouenneExprOpp.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneExprInv.hpp"
00020 #include "CouenneExprSub.hpp"
00021 #include "CouenneExprBDiv.hpp"
00022 
00023 #include "CouennePrecisions.hpp"
00024 
00025 #include "CoinFinite.hpp"
00026 
00027 using namespace Couenne;
00028 
00029 // simplify division
00030 
00031 expression *exprDiv::simplify () {
00032 
00033   exprOp:: simplify ();
00034 
00035   if ((*arglist_) -> Type () == CONST) { // expr = a / y 
00036 
00037     CouNumber c0 = (*arglist_) -> Value ();
00038 
00039     if (arglist_ [1] -> Type () == CONST) { // expr = a / b
00040 
00041       CouNumber c1 = arglist_ [1] -> Value ();
00042 
00043       delete arglist_ [0]; 
00044       delete arglist_ [1];
00045       arglist_ [0] = arglist_ [1] = NULL;
00046 
00047       return new exprConst (c0 / c1);
00048     }
00049     else {
00050       if (fabs (c0) < COUENNE_EPS_SIMPL) // expr = 0/y
00051         return new exprConst (0.);
00052 
00053       // otherwise, expression = k/y, return k*inv(y)
00054 
00055       expression *ret;
00056 
00057       if (fabs (arglist_ [0] -> Value () - 1.) < COUENNE_EPS) {
00058         delete *arglist_;
00059         *arglist_ = NULL;
00060         ret = new exprInv (arglist_ [1]);
00061       }
00062       else ret = new exprMul (arglist_ [0], new exprInv (arglist_ [1]));
00063 
00064       arglist_ = NULL;
00065       return ret;
00066     }
00067   }
00068   else // only need to check if f2 == 0
00069 
00070     if (arglist_ [1] -> Type () == CONST) { // expression = x/h,
00071                                             // transform into (1/h)*x
00072 
00073       expression *ret = new exprMul (new exprConst (1. / (arglist_ [1] -> Value ())), 
00074                                      arglist_ [0]);
00075       delete arglist_ [1];
00076       arglist_ = NULL;
00077       return ret;
00078     }
00079 
00080   return NULL;
00081 }
00082 
00083 
00084 // differentiate quotient of expressions
00085 //
00086 // d (f/g) / dx = df/dx / g - f/g^2 * dg/dx = 1/g (f' - f/g g')
00087 expression *exprDiv::differentiate (int index) {
00088 
00089   bool 
00090     diffNum = arglist_ [0] -> dependsOn (index),
00091     diffDen = arglist_ [1] -> dependsOn (index);
00092 
00093   if (diffNum) {
00094 
00095     if (diffDen) {
00096 
00097       // more general case
00098 
00099       return new exprDiv (new exprSub (new exprMul (arglist_ [1] -> differentiate (index),
00100                                                     arglist_ [0] -> clone ()),
00101                                        new exprMul (arglist_ [1] -> clone (),
00102                                                     arglist_ [0] -> differentiate (index))),
00103                           new exprPow (arglist_ [1] -> clone (), new exprConst (2.)));
00104 
00105     } else { // derive numerator and divide by den
00106 
00107       return new exprDiv (arglist_ [0] -> differentiate (index),
00108                           arglist_ [1] -> clone ());
00109     }
00110 
00111   } else {
00112 
00113     if (diffDen) { // = - f/g^2 * g' or, for (future) simplification purposes, - (f * g')/g^2
00114 
00115       return new exprOpp (new exprDiv (new exprMul (arglist_ [0] -> clone (),
00116                                                     arglist_ [1] -> differentiate (index)),
00117                                        new exprPow (arglist_ [1] -> clone (),
00118                                                     new exprConst (2.))));
00119 
00120     } else // quotient does not depend on index
00121       return new exprConst (0.);
00122   }
00123 
00124   // expression **alm2 = new expression * [3];
00125 
00126   // exprInv *invg = new exprInv (arglist_ [1] -> clone ());
00127 
00128   // alm2 [0] = arglist_ [0] -> clone ();
00129   // alm2 [1] = arglist_ [1] -> differentiate (index);
00130   // alm2 [2] = new exprClone (invg);
00131 
00132   // return new exprMul (invg, new exprSub (arglist_ [0] -> differentiate (index),
00133   //                                     new exprMul (alm2, 3)));
00134 
00135   // in alternative:
00136 
00137   // return new exprDiv (new exprSub (new exprMul (arglist_ [1] -> differentiate (index),
00138   //                                            arglist_ [0] -> clone ()),
00139   //                               new exprMul (arglist_ [1] -> clone (),
00140   //                                            arglist_ [0] -> differentiate (index))),
00141   //                  new exprPow (arglist_ [1] -> clone (), new exprConst (2.)));
00142 }
00143 
00144 
00145 // get lower/upper bounds as a function of the arguments' lower/upper
00146 // bounds
00147 void exprDiv::getBounds (expression *&lb, expression *&ub) {
00148 
00149   expression **almin = new expression * [4];
00150   expression **almax = new expression * [4];
00151 
00152   arglist_ [0] -> getBounds (almin [0], almin [1]);
00153   arglist_ [1] -> getBounds (almin [2], almin [3]);
00154 
00155   almax [0] = new exprClone (almin [0]);
00156   almax [1] = new exprClone (almin [1]);
00157   almax [2] = new exprClone (almin [2]);
00158   almax [3] = new exprClone (almin [3]);
00159 
00160   lb = new exprLBDiv (almin, 4);
00161   ub = new exprUBDiv (almax, 4);
00162 }
00163 
00164 
00165 // get lower/upper bounds as a function of the arguments' lower/upper
00166 // bounds
00167 void exprDiv::getBounds (CouNumber &lb, CouNumber &ub) {
00168 
00169   // lower
00170 
00171   CouNumber ln, un, ld, ud;
00172 
00173   arglist_ [0] -> getBounds (ln, un);
00174   arglist_ [1] -> getBounds (ld, ud);
00175 
00176   if (ld > 0)                                      // (?,?,+,+)
00177     if   (ln > 0)    lb = safeDiv (ln,ud,-1);      // (+,+,+,+) --> ln/ud
00178     else             lb = safeDiv (ln,ld,-1);      // (-,?,+,+) --> ln/ld
00179   else { // ld <= 0
00180     if      (ud > 0) lb = - COUENNE_INFINITY;      // (?,?,-,+) --> unbounded
00181     else if (un > 0) lb = safeDiv (un,ud,-1);      // (?,+,-,-) --> un/ud
00182     else             lb = safeDiv (un,ld,-1);      // (-,-,-,-) --> un/ld
00183   }
00184 
00185   // upper
00186 
00187   if (ld > 0)                                     // (ln,un,ld,ud)     lb 
00188     if   (un < 0) ub = safeDiv (un,ud,1);         // (-,-,+,+) --> un/ud
00189     else          ub = safeDiv (un,ld,1);         // (?,+,+,+) --> un/ld
00190   else { // ld <= 0
00191     if      (ud > 0) ub = + COUENNE_INFINITY;     // (?,?,-,+) --> unbounded
00192     else if (ln < 0) ub = safeDiv (ln,ud,1);      // (-,?,-,-) --> ln/ud
00193     else             ub = safeDiv (ln,ld,1);      // (+,+,-,-) --> ln/ld
00194   }
00195 }
00196 
00198 bool exprDiv::isInteger () {
00199 
00200   // only check if arguments (specifically, the denominator) are, *at
00201   // this point in the algorithm*, constant -- due to branching rules,
00202   // for instance. If so, check if the corresponding evaluated
00203   // expression is integer. Otherwise, check if denominator is +1 or
00204   // -1.
00205 
00206   CouNumber dl, du, nl, nu;
00207 
00208   arglist_ [1] -> getBounds (dl, du);
00209   arglist_ [0] -> getBounds (nl, nu);
00210 
00211   //register CouNumber 
00212   //num = (*nl) (), 
00213   //den = (*dl) ();
00214 
00215   bool
00216     denzero  = (fabs (dl)      < COUENNE_EPS),
00217     numconst = (fabs (nl - nu) < COUENNE_EPS);
00218 
00219   if ((fabs (nl) < COUENNE_EPS)  && // numerator is zero
00220       numconst                   && // constant
00221       !denzero)                     // and denominator is nonzero
00222 
00223     return true;
00224 
00225   // otherwise...
00226 
00227   if (fabs (dl - du) < COUENNE_EPS) { // denominator is constant
00228 
00229     if (fabs (fabs (dl) - 1) < COUENNE_EPS) // it is +1 or -1, check numerator
00230       return arglist_ [0] -> isInteger ();
00231 
00232     if (denzero) // it is zero, better leave...
00233       return false;
00234 
00235     if (numconst) { // numerator is constant, too
00236 
00237       CouNumber quot = nl / dl;
00238 
00239       if (fabs (COUENNE_round (quot) - quot) < COUENNE_EPS)
00240         return true;
00241     }
00242   }
00243 
00244   return false;
00245 }
00246 
00247 
00249 void exprDiv::closestFeasible (expression *varind,
00250                                expression *vardep, 
00251                                CouNumber &left,
00252                                CouNumber &right) const {
00253 
00254   expression *varoth = arglist_ [0]; // assume y = c/x
00255 
00256   bool numerator = false;
00257 
00258   if (varoth -> Index () == varind -> Index ()) { // actually y = x/c
00259     varoth = arglist_ [1];
00260     numerator = true;
00261   } else assert (arglist_ [1] -> Index () == varind -> Index ()); // right to assume y = c/x
00262 
00263   CouNumber 
00264     x = (*varind) (),
00265     y = (*vardep) (),
00266     c = (*varoth) ();
00267 
00268   if (numerator) // checking y = x/c
00269 
00270     if (c < 0.)
00271       if (c*y > x) {assert (c*y > right); right = c*y;}
00272       else         {assert (c*y < left);  left  = c*y;}
00273     else if (c > 0.)
00274       if (c*y < x) {assert (c*y < left);  left  = c*y;}
00275       else         {assert (c*y > right); right = c*y;}
00276     else left = - (right = COIN_DBL_MAX);
00277 
00278   else           // checking y = c/x
00279 
00280     if      (y < 0.)
00281       if (x*y > c) {assert (c/y > right); right = c/y;} // convex area in third orthant
00282       else         {assert (c/y < left);  left  = c/y;} // remaining of third+fourth orthant
00283     else if (y > 0.) 
00284       if (x*y > c) {assert (c/y < left);  left  = c/y;} // convex area in first orthant
00285       else         {assert (c/y > right); right = c/y;} // remaining of first+second orthant
00286     else left = - (right = COIN_DBL_MAX);
00287 }
00288 
00289 
00291 CouNumber exprDiv::gradientNorm (const double *x) {
00292 
00293   int 
00294     ind0 = arglist_ [0] -> Index (),
00295     ind1 = arglist_ [1] -> Index ();
00296 
00297   CouNumber
00298     x0 = (ind0 < 0) ? fabs (arglist_ [0] -> Value ()) : fabs (x [ind0]),
00299     x1 = (ind1 < 0) ? fabs (arglist_ [1] -> Value ()) : fabs (x [ind1]),
00300     x1sq = x1 * x1;
00301 
00302   if (x1sq < 1/COUENNE_INFINITY) {
00303     x1sq = 1/COUENNE_INFINITY;
00304     if (x1 < 1/COUENNE_INFINITY) // implied
00305       x1 = 1/COUENNE_INFINITY;
00306   }
00307 
00308   if (ind0 < 0)
00309     if (ind1 < 0) return 0.;                // c/d
00310     else          return fabs (x0/(x1sq)); // c/y
00311   else 
00312     if (ind1 < 0) return 1. / x1;                                // x/d
00313     else          return sqrt (1. / x1sq + x0*x0 / (x1sq * x1sq)); // x/y
00314 }

Generated on Thu Nov 10 03:05:44 2011 by  doxygen 1.4.7