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

Go to the documentation of this file.
00001 /* $Id: exprInv.cpp 154 2009-06-16 18:52:53Z pbelotti $ */
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. 
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "exprInv.hpp"
00012 #include "exprClone.hpp"
00013 #include "exprMul.hpp"
00014 #include "CouenneProblem.hpp"
00015 
00016 
00017 // differentiation
00018 expression *exprInv::differentiate (int index) {
00019 
00020   expression **alm = new expression * [3];
00021   
00022   alm [0] = new exprInv (new exprClone (argument_));
00023   alm [1] = new exprClone (alm [0]);
00024   alm [2] = argument_ -> differentiate (index);
00025 
00026   return new exprMul (alm, 3);
00027 }
00028 
00029 
00030 // printing
00031 void exprInv::print (std::ostream &out, 
00032                      bool descend) const {
00033   out << "(1/";
00034   argument_ -> print (out, descend);
00035   out << ")";
00036 }
00037 //  exprUnary::print (out, "1/", PRE);}
00038 
00039 
00042 void invPowImplBounds (int wind, int index, 
00043                        CouNumber *l, CouNumber *u, CouNumber k,
00044                        bool &resL, bool &resU) {
00045 
00046   CouNumber wl = l [wind], 
00047             wu = u [wind];
00048 
00049   // 0 <= l <= w <= u
00050 
00051   if (wl >= 0.) {
00052     if (wu > COUENNE_EPS) {
00053       if (wu < COUENNE_INFINITY) resL = updateBound (-1, l + index, pow (wu, k));
00054       else                       resL = updateBound (-1, l + index, 0.);
00055     }
00056     if (wl > COUENNE_EPS)        resU = updateBound (+1, u + index, pow (wl, k));
00057   }
00058 
00059   // l <= w <= u <= 0
00060 
00061   if (wu <= -0.) {
00062     if (wl < - COUENNE_EPS) {
00063       if (wl > - COUENNE_INFINITY) resU = updateBound (+1, u + index, pow (wl, k)) || resU;
00064       else                         resU = updateBound (+1, u + index, 0.)          || resU;
00065     }
00066     if (wu < - COUENNE_EPS)        resL = updateBound (-1, l + index, pow (wu, k)) || resL;
00067   }
00068 }
00069 
00070 
00073 bool exprInv::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00074 
00075   // Expression w = 1/x: we can only improve the bounds if 
00076   //
00077   //    0 <= l <= w <= u         or
00078   //         l <= w <= u <= 0. 
00079   //
00080   // Then 1/u <= x <= 1/l (given l, u finite and nonzero)
00081 
00082   int index = argument_ -> Index ();
00083 
00084   bool resL, resU = resL = false;
00085 
00086   invPowImplBounds (wind, index, l, u, -1., resL, resU);
00087 
00088   bool argInt = argument_ -> isInteger ();
00089 
00090   if (resL) {
00091     chg [index].setLower(t_chg_bounds::CHANGED);
00092     if (argInt) l [index] = ceil  (l [index] - COUENNE_EPS);
00093   }
00094 
00095   if (resU) {
00096     chg [index].setUpper(t_chg_bounds::CHANGED);
00097     if (argInt) u [index] = floor (u [index] + COUENNE_EPS);
00098   }
00099 
00100   return (resL || resU);
00101 }
00102 
00103 
00105 CouNumber exprInv::gradientNorm (const double *x) {
00106   int ind = argument_ -> Index ();
00107   CouNumber xx;
00108   if (ind < 0) return 0.;
00109   else {
00110     xx = x [argument_ -> Index ()];
00111     return 1. / (xx*xx);
00112   }
00113 }
00114 
00115 
00118 bool exprInv::isCuttable (CouenneProblem *problem, int index) const {
00119 
00120   int xind = argument_ -> Index ();
00121 
00122   double 
00123     x = problem -> X (xind),
00124     y = problem -> X (index);
00125 
00126   return ((problem -> Lb (xind) >= 0) && (x > 0) && (y*x <= 1) ||
00127           (problem -> Ub (xind) <= 0) && (x < 0) && (y*x <= 1));
00128 }

Generated on Tue Mar 30 03:04:37 2010 by  doxygen 1.4.7