/home/coin/SVN-release/OS-2.4.2/Couenne/src/convex/operators/conv-exprInv.cpp

Go to the documentation of this file.
00001 /* $Id: conv-exprInv.cpp 577 2011-05-21 20:38:48Z pbelotti $
00002  *
00003  * Name:    conv-exprInv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: convexification and bounding methods for the inverse operator
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CouenneCutGenerator.hpp"
00012 
00013 #include "CouenneTypes.hpp"
00014 
00015 #include "CouenneExprVar.hpp"
00016 #include "CouenneExprInv.hpp"
00017 #include "CouenneExprClone.hpp"
00018 #include "CouenneExprConst.hpp"
00019 #include "CouenneExprMin.hpp"
00020 #include "CouenneExprOpp.hpp"
00021 #include "CouenneExprDiv.hpp"
00022 #include "CouenneExprSum.hpp"
00023 #include "CouenneExprMul.hpp"
00024 #include "CouenneExprPow.hpp"
00025 
00026 #include "CouenneProblem.hpp"
00027 
00028 using namespace Couenne;
00029 
00030 // compute upper- and lower bounds of the expression w = 1/f(x) given
00031 // bounds of f(x)
00032 
00033 void exprInv::getBounds (expression *&lb, expression *&ub) {
00034 
00035   expression *lba, *uba;
00036   argument_ -> getBounds (lba, uba);
00037 
00038   expression **all = new expression * [6];
00039   all [0] = new exprConst (0.);      all [1] = new exprConst (- COUENNE_INFINITY);  // l<0<u
00040   all [2] = new exprOpp   (lba);     all [3] = new exprInv   (uba);                 // 0<l<u
00041   all [4] = new exprClone (uba);     all [5] = new exprInv   (new exprClone (uba)); // l<u<0
00042 
00043   lb = new exprMin (all, 6);
00044 
00045   expression **alu = new expression * [6];
00046   alu [0] = new exprConst (0.);      alu [1] = new exprConst (COUENNE_INFINITY);   // l<0<u
00047   alu [2] = new exprClone (all [2]); alu [3] = new exprInv (new exprClone (lba));  // 0<l<u
00048   alu [4] = new exprClone (uba);     alu [5] = new exprInv (new exprClone (lba));  // l<u<0
00049 
00050   ub = new exprMin (alu, 6);
00051 }
00052 
00053 
00054 // compute VALUE of lower and upper bound of expression
00055 void exprInv::getBounds (CouNumber &lb, CouNumber &ub) {
00056 
00057   register CouNumber lba, uba;
00058 
00059   argument_ -> getBounds (lba, uba);
00060 
00061   if ((uba < 0) || (lba > 0)) {
00062     lb = 1./uba;
00063     ub = 1./lba;
00064   } else {
00065     lb = -COUENNE_INFINITY;
00066     ub =  COUENNE_INFINITY;
00067   }
00068 }
00069 
00070 
00071 #define MIN_DENOMINATOR 1e-6
00072 
00073 // generate convexification cut for constraint w = 1/x
00074 
00075 void exprInv::generateCuts (expression *aux, //const OsiSolverInterface &si, 
00076                             OsiCuts &cs, const CouenneCutGenerator *cg,
00077                             t_chg_bounds *chg, int wind, 
00078                             CouNumber lbw, CouNumber ubw) {
00079 
00080   // TODO: if a<=w<=b, c<=x<=d, there is a diamond enclosing the whole
00081   // convexification
00082 
00083   CouNumber l, u;
00084   argument_ -> getBounds (l, u);
00085 
00086   if ((l < - COUENNE_EPS) && (u > COUENNE_EPS)) // there is no convexification
00087     return;
00088 
00089   int wi = aux       -> Index (), 
00090       xi = argument_ -> Index ();
00091 
00092   bool cL = !chg || (cg -> isFirst ()) || (chg [xi].lower() != t_chg_bounds::UNCHANGED);
00093   bool cR = !chg || (cg -> isFirst ()) || (chg [xi].upper() != t_chg_bounds::UNCHANGED);
00094 
00095   // special case: l and u are very close, replace function with
00096   // linear term
00097 
00098   enum auxSign sign = cg -> Problem () -> Var (wi) -> sign ();
00099 
00100   if (fabs (u - l) < COUENNE_EPS) {
00101 
00102     CouNumber x0 = 0.5 * (u+l);
00103     if (cL || cR) 
00104       cg -> createCut (cs, 2/x0, sign, wi, 1., xi, 1/(x0*x0));
00105     return;
00106   }
00107 
00108   // upper segment (or lower if x<0)
00109 
00110   if (cL || cR) {
00111     // bounding box is within ]0,+inf[
00112     if ((l> COUENNE_EPS) && (u< COU_MAX_COEFF) && sign != expression::AUX_GEQ) cg -> createCut (cs, 1/l+1/u, -1, wi,1., xi,1/(l*u));
00113     if ((u<-COUENNE_EPS) && (l>-COU_MAX_COEFF) && sign != expression::AUX_LEQ) cg -> createCut (cs, 1/l+1/u, +1, wi,1., xi,1/(l*u));
00114     // bounding box is within ]-inf,0[
00115   }
00116 
00117   // choose sampling points. 
00118 
00119   // if unbounded, use a rule of thumb
00120   int ns = cg -> nSamples ();
00121   if      (l < - COUENNE_INFINITY) l = ns * (u-1); // (-infinity, u] where u < 0
00122   else if (u >   COUENNE_INFINITY) u = ns * (l+1); // [l, +infinity) where l > 0
00123 
00124   // make bounds nonzero
00125   if (fabs (l) < COUENNE_EPS) l = (l<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
00126   if (fabs (u) < COUENNE_EPS) u = (u<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
00127 
00128   // bound
00129   if ((l > 0 && sign != expression::AUX_LEQ) ||
00130                (sign != expression::AUX_GEQ))
00131     cg -> addEnvelope 
00132       (cs, (l > 0) ? +1 : -1, 
00133        inv, oppInvSqr, wi, xi, 
00134        (cg -> isFirst ()) ? // is this first call?
00135        // place it somewhere in the interval (we don't care)
00136        ((l > COUENNE_EPS) ? l : u) :
00137        // otherwise, replace it where it gives deepest cut
00138        powNewton ((*argument_) (), (*aux) (), inv, oppInvSqr, inv_dblprime),
00139        l, u, chg);
00140 }

Generated on Wed Nov 30 03:03:58 2011 by  doxygen 1.4.7