/home/coin/SVN-release/OS-2.4.0/Couenne/src/expression/operators/exprInv.cpp

Go to the documentation of this file.
00001 /* $Id: exprInv.cpp 560 2011-04-17 10:01:15Z stefan $
00002  *
00003  * Name:    exprInv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: definition of inverse of a function (1/f(x))
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include <stdio.h> // ! must go
00012 
00013 #include "CouenneExprInv.hpp"
00014 #include "CouenneExprClone.hpp"
00015 #include "CouenneExprMul.hpp"
00016 #include "CouenneExprOpp.hpp"
00017 #include "CouenneExprDiv.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneProblem.hpp"
00020 #include "CouenneExpression.hpp"
00021 
00022 #include "CoinFinite.hpp"
00023 
00024 using namespace Couenne;
00025 
00026 // differentiation
00027 expression *exprInv::differentiate (int index) {
00028 
00029   return new exprOpp (new exprDiv (argument_ -> differentiate (index),
00030                                    new exprPow (new exprClone (argument_),
00031                                                 new exprConst (2.))));
00032 }
00033 
00034 
00035 // printing
00036 void exprInv::print (std::ostream &out, 
00037                      bool descend) const {
00038   out << "(1/";
00039   argument_ -> print (out, descend);
00040   out << ")";
00041 }
00042 //  exprUnary::print (out, "1/", PRE);}
00043 
00044 
00047 void invPowImplBounds (int wind, int index, 
00048                        CouNumber *l, CouNumber *u, CouNumber k,
00049                        bool &resL, bool &resU, 
00050                        enum expression::auxSign sign) {
00051 
00052   CouNumber wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
00053             wu = sign == expression::AUX_LEQ ?  COIN_DBL_MAX : u [wind];
00054 
00055   // 0 <= l <= w <= u
00056 
00057   if (wl >= 0.) {
00058     if (wu > COUENNE_EPS) {
00059       if (wu < COUENNE_INFINITY) resL = updateBound (-1, l + index, pow (wu, k));
00060       else                       resL = updateBound (-1, l + index, 0.);
00061     }
00062     if (wl > COUENNE_EPS)        resU = updateBound (+1, u + index, pow (wl, k));
00063   }
00064 
00065   // l <= w <= u <= 0
00066 
00067   if (wu <= -0.) {
00068     if (wl < - COUENNE_EPS) {
00069       if (wl > - COUENNE_INFINITY) resU = updateBound (+1, u + index, pow (wl, k)) || resU;
00070       else                         resU = updateBound (+1, u + index, 0.)          || resU;
00071     }
00072     if (wu < - COUENNE_EPS)        resL = updateBound (-1, l + index, pow (wu, k)) || resL;
00073   }
00074 }
00075 
00076 
00079 bool exprInv::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
00080 
00081   // Expression w = 1/x: we can only improve the bounds if 
00082   //
00083   //    0 <= l <= w <= u         or
00084   //         l <= w <= u <= 0. 
00085   //
00086   // Then 1/u <= x <= 1/l (given l, u finite and nonzero)
00087 
00088   int index = argument_ -> Index ();
00089 
00090   bool resL, resU = resL = false;
00091 
00092   invPowImplBounds (wind, index, l, u, -1., resL, resU, sign);
00093 
00094   bool argInt = argument_ -> isInteger ();
00095 
00096   if (resL) {
00097     chg [index].setLower(t_chg_bounds::CHANGED);
00098     if (argInt) l [index] = ceil  (l [index] - COUENNE_EPS);
00099   }
00100 
00101   if (resU) {
00102     chg [index].setUpper(t_chg_bounds::CHANGED);
00103     if (argInt) u [index] = floor (u [index] + COUENNE_EPS);
00104   }
00105 
00106   return (resL || resU);
00107 }
00108 
00109 
00111 CouNumber exprInv::gradientNorm (const double *x) {
00112   int ind = argument_ -> Index ();
00113   CouNumber xx;
00114   if (ind < 0) return 0.;
00115   else {
00116     xx = x [argument_ -> Index ()];
00117     return 1. / (xx*xx);
00118   }
00119 }
00120 
00121 
00124 bool exprInv::isCuttable (CouenneProblem *problem, int index) const {
00125 
00126   int xind = argument_ -> Index ();
00127 
00128   double 
00129     x = problem -> X (xind),
00130     y = problem -> X (index);
00131 
00132   return (((problem -> Lb (xind) >= 0) && (x > 0) && (y*x <= 1)) ||
00133           ((problem -> Ub (xind) <= 0) && (x < 0) && (y*x <= 1)));
00134 }

Generated on Thu Sep 22 03:05:58 2011 by  doxygen 1.4.7