/home/coin/SVN-release/OS-2.0.0/Couenne/src/bound_tightening/operators/impliedBounds-exprMul.cpp

Go to the documentation of this file.
00001 /* $Id: impliedBounds-exprMul.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * Name:    impliedBounds-exprMul.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implied bounds for multiplications
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "exprMul.hpp"
00012 #include "CouennePrecisions.hpp"
00013 
00014 
00017 
00018 bool exprMul::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00019 
00020   //return false; // !!!
00021 
00022   bool resL, resU = resL = false;
00023   int ind;
00024 
00025   if ((arglist_ [ind=0] -> Type () <= CONST) || 
00026       (arglist_ [ind=1] -> Type () <= CONST)) {
00027 
00028     // at least one constant in product w=cx:
00029     //
00030     // wl/c <= x <= wu/c, if c is positive
00031     // wu/c <= x <= wl/c, if c is negative
00032 
00033     CouNumber c = arglist_ [ind] -> Value ();
00034 
00035     bool argInt = arglist_ [1-ind] -> isInteger ();
00036 
00037     // get the index of the nonconstant part
00038     ind = arglist_ [1-ind] -> Index ();
00039 
00040     if (ind==-1) // should not happen, it is a product of constants
00041       return false;
00042 
00043     if (c > COUENNE_EPS) {
00044 
00045       resL = (l [wind] > - COUENNE_INFINITY) && 
00046         updateBound (-1, l + ind, argInt ? ceil  (l [wind] / c - COUENNE_EPS) : (l [wind] / c));
00047       resU = (u [wind] <   COUENNE_INFINITY) && 
00048         updateBound ( 1, u + ind, argInt ? floor (u [wind] / c + COUENNE_EPS) : (u [wind] / c));
00049     } 
00050     else if (c < - COUENNE_EPS) {
00051 
00052       //      printf ("w_%d [%g,%g] = %g x_%d [%g,%g]\n", 
00053       //              wind, l [wind], u [wind], c, ind, l [ind], u [ind]);
00054 
00055       resL = (u [wind] <   COUENNE_INFINITY) && 
00056         updateBound (-1, l + ind, argInt ? ceil  (u [wind] / c - COUENNE_EPS) : (u [wind] / c));
00057       resU = (l [wind] > - COUENNE_INFINITY) && 
00058         updateBound ( 1, u + ind, argInt ? floor (l [wind] / c + COUENNE_EPS) : (l [wind] / c));
00059     } 
00060 
00061     if (resL) chg [ind].setLower(t_chg_bounds::CHANGED);
00062     if (resU) chg [ind].setUpper(t_chg_bounds::CHANGED);
00063 
00064       /*printf ("w_%d [%g,%g] -------> x_%d in [%g,%g] ", 
00065               wind, l [wind], u [wind], 
00066               ind,  l [ind],  u [ind]);*/
00067   } else {
00068 
00069     // these bounds would be implied by McCormick's convexification,
00070     // however we write them explicitly for internal use within bound
00071     // tightening, as otherwise they would be known to Clp only.
00072 
00073     int xi = arglist_ [0] -> Index (),
00074         yi = arglist_ [1] -> Index ();
00075 
00076     CouNumber *xl = l + xi, *yl = l + yi, wl = l [wind],
00077               *xu = u + xi, *yu = u + yi, wu = u [wind];
00078 
00079 
00080     // w's lower bound ///////////////////////////////////////////
00081 
00082     bool resxL,  resxU,  resyL, resyU = 
00083          resxL = resxU = resyL = false;
00084 
00085     if (wl >= 0.) {
00086 
00087       // point B in central infeasible area
00088 
00089       if (*xu * *yu < wl) {
00090         resxU = (*xu * *yl < wl) && updateBound (+1, xu, wl / *yl);
00091         resyU = (*xl * *yu < wl) && updateBound (+1, yu, wl / *xl);
00092       }
00093 
00094       // point C in central infeasible area
00095 
00096       if (*xl * *yl < wl) {
00097         resxL = (*xl * *yu < wl) && updateBound (-1, xl, wl / *yu);
00098         resyL = (*xu * *yl < wl) && updateBound (-1, yl, wl / *xu);
00099       }
00100     } else if (wl > -COUENNE_INFINITY) {
00101 
00102       // the infeasible set is a hyperbola with two branches
00103 
00104       // upper left
00105       resxL = (*xl * *yl < wl) && (*yl > 0.) && updateBound (-1, xl, wl / *yl); // point C
00106       resyU = (*xu * *yu < wl) && (*yu > 0.) && updateBound (+1, yu, wl / *xu); // point B
00107 
00108       // lower right
00109       resyL = (*xl * *yl < wl) && (*yl < 0.) && updateBound (-1, yl, wl / *xl); // point C
00110       resxU = (*xu * *yu < wl) && (*yu < 0.) && updateBound (+1, xu, wl / *yu); // point B
00111     }
00112 
00113 
00114     // w's upper bound ///////////////////////////////////////////
00115 
00116     if (wu >= 0.) {
00117 
00118       if (wu < COUENNE_INFINITY) {
00119         // the infeasible set is a hyperbola with two branches
00120 
00121         // upper right
00122         resxU = (*xu * *yl > wu) && (*yl > 0.) && updateBound (+1, xu, wu / *yl) || resxU; // point D
00123         resyU = (*xl * *yu > wu) && (*yu > 0.) && updateBound (+1, yu, wu / *xl) || resyU; // point A
00124 
00125         // lower left
00126         resxL = (*xl * *yu > wu) && (*yu < 0.) && updateBound (-1, xl, wu / *yu) || resxL; // point A
00127         resyL = (*xu * *yl > wu) && (*yl < 0.) && updateBound (-1, yl, wu / *xu) || resyL; // point D
00128       }
00129 
00130     } else {
00131 
00132       // point D in central infeasible area
00133 
00134       if (*xu * *yl > wu) {
00135         resxU = (*xu * *yu > wu) && updateBound (+1, xu, wu / *yu) || resxU;
00136         resyL = (*xl * *yl > wu) && updateBound (-1, yl, wu / *xl) || resyL;
00137       }
00138 
00139       // point A in central infeasible area
00140 
00141       if (*xl * *yu > wu) {
00142         resxL = (*xl * *yl > wu) && updateBound (-1, xl, wu / *yl) || resxL;
00143         resyU = (*xu * *yu > wu) && updateBound (+1, yu, wu / *xu) || resyU;
00144       }
00145     }
00146 
00147     bool
00148       xInt = arglist_ [0] -> isInteger (),
00149       yInt = arglist_ [1] -> isInteger ();
00150 
00151     if (resxL) {chg [xi].setLower(t_chg_bounds::CHANGED); if (xInt) *xl = ceil  (*xl - COUENNE_EPS);}
00152     if (resxU) {chg [xi].setUpper(t_chg_bounds::CHANGED); if (xInt) *xu = floor (*xu + COUENNE_EPS);}
00153     if (resyL) {chg [yi].setLower(t_chg_bounds::CHANGED); if (yInt) *yl = ceil  (*yl - COUENNE_EPS);}
00154     if (resyU) {chg [yi].setUpper(t_chg_bounds::CHANGED); if (yInt) *yu = floor (*yu + COUENNE_EPS);}
00155 
00156     resL = resxL || resyL;
00157     resU = resxU || resyU;
00158   }
00159 
00160   return (resL || resU);
00161 }

Generated on Mon Aug 3 03:02:19 2009 by  doxygen 1.4.7