/home/coin/SVN-release/OS-2.4.0/Couenne/src/bound_tightening/operators/impliedBounds-exprDiv.cpp

Go to the documentation of this file.
00001 /* $Id: impliedBounds-exprDiv.cpp 560 2011-04-17 10:01:15Z stefan $
00002  *
00003  * Name:    impliedBounds-exprDiv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implied bounds for division operators
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CouenneExprDiv.hpp"
00012 #include "CouennePrecisions.hpp"
00013 #include "CouenneConfig.h"
00014 #include "CoinHelperFunctions.hpp"
00015 #include "CoinFinite.hpp"
00016 
00017 using namespace Couenne;
00018 
00021 
00022 bool exprDiv::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
00023 
00024   bool resx, resy = resx = false;
00025 
00026   CouNumber 
00027     wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
00028     wu = sign == expression::AUX_LEQ ?  COIN_DBL_MAX : u [wind];
00029 
00030   // y is a constant
00031   if (arglist_ [1] -> Type () == CONST) {
00032 
00033     int ind = arglist_ [0] -> Index ();
00034 
00035     if (ind < 0) {
00036       printf ("exprDiv::impliedBound: Error, w = c/d constants\n");
00037       exit (-1);
00038     }
00039 
00040     CouNumber c = arglist_ [1] -> Value ();
00041 
00042     if (fabs (c) < COUENNE_EPS) {
00043       printf ("exprDiv::impliedBound: Error, division by zero\n");
00044       exit (-1);
00045     }
00046 
00047     // a copy of exprMul::impliedBound for the case where y is a constant
00048 
00049     bool xInt = arglist_ [0] -> isInteger ();
00050 
00051     if (c > COUENNE_EPS) {
00052 
00053       if (updateBound (-1, l+ind, xInt ? ceil (wl*c - COUENNE_EPS) : (wl*c))) {
00054         resx = true; 
00055         chg [ind].setLower (t_chg_bounds::CHANGED);
00056       }
00057 
00058       if (updateBound (+1, u+ind, xInt ? floor (wu*c + COUENNE_EPS) : (wu*c))) {
00059         resx = true; 
00060         chg [ind].setUpper (t_chg_bounds::CHANGED);
00061       }
00062     } 
00063     else if (c < - COUENNE_EPS) {
00064 
00065       if (updateBound (-1, l+ind, xInt ? ceil  (wu*c - COUENNE_EPS) : (wu*c))) {
00066         resx = true; 
00067         chg [ind].setLower (t_chg_bounds::CHANGED);
00068       }
00069 
00070       if (updateBound (+1, u+ind, xInt ? floor (wl*c + COUENNE_EPS) : (wl*c))) {
00071         resx = true; 
00072         chg [ind].setUpper (t_chg_bounds::CHANGED);
00073       }
00074     } 
00075   } else {
00076 
00077     // deal with all other cases
00078 
00079     // Each bound on w is represented on the xy plane with two cones,
00080     // such that joining the extreme rays of both one obtains two
00081     // lines, or in other words, the second cone is obtained through
00082     // the transformation (x',y') = (-x,-y) applied to the first cone.
00083     //
00084     // Bounds can be tightened according to four different cases,
00085     // depending on which corner of the bounding box belongs to which
00086     // of the cones and on the sign of the bounds.
00087     //
00088     // Define wl <= w <= wu,
00089     //        xl <= x <= xu,
00090     //        yl <= y <= yu.
00091     //
00092     // Then the "tightenable" bounds are, depending on the corner:
00093     //
00094     //             _______________________________________________________
00095     //            |           w >= wl         |          w <= wu          |
00096     //            |___________________________|___________________________|
00097     //            |     l<0     |    l>0      |     u<0     |     u>0     |
00098     //            |_____________|_____________|_____________|_____________|
00099     //   Cone     |upper |lower |upper |lower |upper |lower |upper |lower |
00100     //            |      |      |      |      |      |      |      |      |
00101     // 1 xl,yl    | INF  |  -   |  xl  |  yl  |xl,yl?|  yl  |  yl  |  -   |
00102     // 2 xl,yu    |  yu  |  xl  |  -   | INF  |  -   |  yu  |  yu  |yu,xl?|
00103     // 3 xu,yl    |  xu  |  yl  | INF  |  -   |  yl  |  -   |yl,xu?|  yl  |
00104     // 4 xu,yu    |  -   | INF  |  yu  |  xu  |  yu  |xu,yu?|  -   |  yu  |
00105     //            |______|______|______|______|______|______|______|______|
00106     //
00107     // Where "INF" stands for "infeasible subproblem", "-" for
00108     // "nothing to improve", and the rest is improved (those with "?"
00109     // may improve).
00110  
00111     int xi = arglist_ [0] -> Index (),
00112         yi = arglist_ [1] -> Index ();
00113 
00114     CouNumber x0 = 0, 
00115       *xl = l + xi, *yl = l + yi,
00116       *xu = u + xi, *yu = u + yi;
00117 
00118     /*printf ("from              : w[%d] [%e %e], x%d [%e %e] / y%d [%e %e]",
00119       wind, wl, wu, xi, *xl, *xu, yi, *yl, *yu);*/
00120 
00121     // avoid changing bounds if x is constant
00122     if (xi == -1) 
00123       xl = xu = &x0;
00124 
00126 
00127     // simple case wl = wu = 0
00128 
00129     if ((fabs (wl) < COUENNE_EPS) && 
00130         (fabs (wu) < COUENNE_EPS)) {
00131 
00132       resx = updateBound (-1, xl, 0.) || resx;
00133       resx = updateBound (+1, xl, 0.) || resx;
00134       return resx || resy;
00135     }
00136 
00137     bool resxL, resxU, resyL, 
00138       resyU = resxL = resxU = resyL = false;
00139 
00140     // general case
00141 
00142     if        (wl < - COUENNE_EPS && wl > - COUENNE_INFINITY / 10) { // w >= wl, wl negative
00143 
00144       // point C: (xl,yl)
00145 
00146       resyL = ((*yl<0) && (*yl > *xl/wl + COUENNE_EPS) && updateBound (-1, yl,      0)) || resyL;
00147       resxL = ((*yl>0) && (*yu < *xl/wl)               && updateBound (-1, xl, *yu*wl)) || resxL; // new
00148       resyL = ((*yl>0) && (*xu < *yl*wl)               && updateBound (-1, yl, *xu/wl)) || resyL; // new
00149 
00150       // if ((*yl>0) && (*yl < *xl/wl)) { // point C violates x/y >= wl, down
00151       //        resxL = updateBound (-1, xl, *yu*wl) || resxL; //
00152       //        resyL = updateBound (-1, yl, *xu/wl) || resyL; //
00153       // }
00154       // point B: (xu,yu)
00155       // if ((*yu<0) && (*yu > *xu/wl)) { // point B violates x/y >= wl, down
00156       //        resxU = updateBound (+1, xu, *yl*wl) || resxU;
00157       //        resyU = updateBound (+1, yu, *xl/wl) || resyU;
00158       // }
00159 
00160       resyU = ((*yu>0) && (*yu < *xu/wl - COUENNE_EPS) && updateBound (+1, yu,      0)) || resyU;
00161       resxU = ((*yu<0) && (*yl > *xu/wl)               && updateBound (+1, xu, *yl*wl)) || resxU; // new
00162       resyU = ((*yu<0) && (*xl > *yu*wl)               && updateBound (+1, yu, *xl/wl)) || resyU; // new
00163 
00164     } else if (wl >   COUENNE_EPS) { // w >= wl, wl positive
00165 
00166       //
00167 
00168       resyL = ((*yl<0) && (*yl < *xl/wl) && updateBound (-1, yl, CoinMin (*xl/wl, 0.))) || resyL;
00169       resxL = ((*yl>0) && (*yl > *xl/wl) && updateBound (-1, xl, *yl*wl))               || resxL;
00170       //
00171       resyU = ((*yu>0) && (*yu > *xu/wl) && updateBound (+1, yu, CoinMax (*xu/wl, 0.))) || resyU;
00172       resxU = ((*yu<0) && (*yu < *xu/wl) && updateBound (+1, xu, *yu*wl))               || resxU;
00173     }
00174 
00176 
00177 
00178     if        (wu >   COUENNE_EPS && wu < COUENNE_INFINITY / 10) { // w <= wu, wu positive
00179 
00180       //
00181       resyL = ((*yl<0) && (*yl > *xu/wu + COUENNE_EPS) && updateBound (-1, yl,      0)) || resyL;
00182       resxU = ((*yl>0) && (*xu > *yu*wu)               && updateBound (+1, xu, *yu*wu)) || resxU;
00183       resyL = ((*yl>0) && (*yl < *xl/wu)               && updateBound (-1, yl, *xl/wu)) || resyL;
00184 
00185       // if ((*yl>0) && (*yl < *xu/wu)) {
00186       //        resxU = updateBound (+1, xu, *yu*wu) || resxU;
00187       //        resyL = updateBound (-1, yl, *xl/wu) || resyL;
00188       // }
00189 
00190       // //
00191 
00192       // if ((*yu<0) && (*yu > *xl/wu)) {
00193       //        resxL = updateBound (-1, xl, *yl*wu) || resxL;
00194       //        resyU = updateBound (+1, yu, *xu/wu) || resyU;
00195       // }
00196 
00197       resyU = ((*yu>0) && (*yu < *xl/wu - COUENNE_EPS) && updateBound (+1, yu,      0)) || resyU;
00198       resxL = ((*yu<0) && (*xl < *yl*wu)               && updateBound (-1, xl, *yl*wu)) || resxL;
00199       resyU = ((*yu<0) && (*yu > *xu/wu)               && updateBound (+1, yu, *xu/wu)) || resyU;
00200 
00201     } else if (wu < - COUENNE_EPS) { // w <= wu, wu negative
00202 
00203       //
00204 
00205       resyL = ((*yl<0) && (*yl < *xu/wu) && updateBound (-1, yl, CoinMin (*xu/wu,0.)))  || resyL;//
00206       resxL = ((*yu<0) && (*yu < *xl/wu) && updateBound (-1, xl, *yu*wu))               || resxL;
00207 
00208       //
00209 
00210       resyU = ((*yu>0) && (*yu > *xl/wu) && updateBound (+1, yu, CoinMax (*xl/wu,0.)))  || resyU;
00211       resxU = ((*yl>0) && (*yl > *xu/wu) && updateBound (+1, xu, *yl*wu))               || resxU;
00212     }
00213 
00214     if (resxL) chg [xi].setLower(t_chg_bounds::CHANGED);
00215     if (resxU) chg [xi].setUpper(t_chg_bounds::CHANGED);
00216     if (resyL) chg [yi].setLower(t_chg_bounds::CHANGED);
00217     if (resyU) chg [yi].setUpper(t_chg_bounds::CHANGED);
00218 
00219     /*if (resx || resy) 
00220       printf ("                 \ntightened division: w[%d] [%e %e], x%d [%e %e] / y%d [%e %e]\n",
00221               wind, wl, wu, xi, *xl, *xu, yi, *yl, *yu);
00222               else printf ("                                                 \r");*/
00223 
00224     resx = resxL || resxU;
00225     resy = resyL || resyU;
00226   }
00227 
00228   bool 
00229     xInt = arglist_ [0] -> isInteger (),
00230     yInt = arglist_ [1] -> isInteger ();
00231 
00232   if (resx && xInt) {
00233     int xi = arglist_ [0] -> Index ();
00234     assert (xi >= 0);
00235     u [xi] = floor (u [xi] + COUENNE_EPS);
00236     l [xi] = ceil  (l [xi] - COUENNE_EPS);
00237   }
00238 
00239   if (resy && yInt) {
00240     int yi = arglist_ [1] -> Index ();
00241     assert (yi >= 0);
00242     u [yi] = floor (u [yi] + COUENNE_EPS);
00243     l [yi] = ceil  (l [yi] - COUENNE_EPS);
00244   }
00245 
00246   return (resx || resy);
00247 }

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