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

Go to the documentation of this file.
00001 /* $Id: impliedBounds-exprMul.cpp 746 2011-07-22 21:56:44Z pbelotti $
00002  *
00003  * Name:    impliedBounds-exprMul.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implied bounds for multiplications
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>
00012 #include <stdlib.h>
00013 
00014 #include "CouenneExprMul.hpp"
00015 #include "CouennePrecisions.hpp"
00016 #include "CouenneConfig.h"
00017 #include "CoinFinite.hpp"
00018 
00019 //#define FM_CHECK
00020 //#define FM_MOD
00021 
00022 using namespace Couenne;
00023 
00024 
00027 
00028 bool exprMul::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
00029 
00030   bool resL, resU = resL = false;
00031   int ind;
00032 
00033   CouNumber 
00034     wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
00035     wu = sign == expression::AUX_LEQ ?  COIN_DBL_MAX : u [wind];
00036 
00037   if ((arglist_ [ind=0] -> Type () <= CONST) || 
00038       (arglist_ [ind=1] -> Type () <= CONST)) {
00039 
00040     // at least one constant in product w=cx:
00041     //
00042     // wl/c <= x <= wu/c, if c is positive
00043     // wu/c <= x <= wl/c, if c is negative
00044 
00045     CouNumber c = arglist_ [ind] -> Value ();
00046 
00047     bool argInt = arglist_ [1-ind] -> isInteger ();
00048 
00049     // get the index of the nonconstant part
00050     ind = arglist_ [1-ind] -> Index ();
00051 
00052     if (ind==-1) // should not happen, it is a product of constants
00053       return false;
00054 
00055     if        (c >   COUENNE_EPS) {
00056 
00057       resL = (wl > - COUENNE_INFINITY) && updateBound (-1, l + ind, argInt ? ceil  (wl / c - COUENNE_EPS) : (wl / c));
00058       resU = (wu <   COUENNE_INFINITY) && updateBound ( 1, u + ind, argInt ? floor (wu / c + COUENNE_EPS) : (wu / c));
00059 
00060     } else if (c < - COUENNE_EPS) {
00061 
00062       resL = (wu <   COUENNE_INFINITY) && updateBound (-1, l + ind, argInt ? ceil  (wu / c - COUENNE_EPS) : (wu / c));
00063       resU = (wl > - COUENNE_INFINITY) && updateBound ( 1, u + ind, argInt ? floor (wl / c + COUENNE_EPS) : (wl / c));
00064     } 
00065 
00066     if (resL) chg [ind].setLower(t_chg_bounds::CHANGED);
00067     if (resU) chg [ind].setUpper(t_chg_bounds::CHANGED);
00068 
00069       /*printf ("w_%d [%g,%g] -------> x_%d in [%g,%g] ", 
00070               wind, l [wind], u [wind], 
00071               ind,  l [ind],  u [ind]);*/
00072   } else {
00073 
00074     // these bounds would be implied by McCormick's convexification,
00075     // however we write them explicitly for internal use within bound
00076     // tightening, as otherwise they would be known to Clp only.
00077 
00078     int xi = arglist_ [0] -> Index (),
00079         yi = arglist_ [1] -> Index ();
00080 
00081     CouNumber
00082       *xl = l + xi, *yl = l + yi,
00083       *xu = u + xi, *yu = u + yi;
00084 
00085     // w's lower bound ///////////////////////////////////////////
00086 
00087     bool resxL,  resxU,  resyL, resyU = 
00088          resxL = resxU = resyL = false;
00089 
00090     bool xlIsZero = (fabs(*xl) < COUENNE_EPS);
00091     bool xuIsZero = (fabs(*xu) < COUENNE_EPS);
00092     bool ylIsZero = (fabs(*yl) < COUENNE_EPS);
00093     bool yuIsZero = (fabs(*yu) < COUENNE_EPS);
00094     bool wlIsZero = (fabs(wl)  < COUENNE_EPS);
00095     bool wuIsZero = (fabs(wu)  < COUENNE_EPS);
00096 
00097 #ifdef FM_MOD
00098 
00099     if(wlIsZero) {
00100       if ((!xuIsZero) && (!yuIsZero) && (*xu * *yu < wl)) {
00101         if (!ylIsZero) {
00102           resxU = (*xu * *yl < wl) && updateBound (+1, xu, wl / *yl);
00103           xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);                
00104         } 
00105         if (!xlIsZero) {
00106           resyU = (*xl * *yu < wl) && updateBound (+1, yu, wl / *xl);
00107           yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00108         }
00109       }
00110 
00111       // point C in central infeasible area
00112 
00113       if ((!xlIsZero) && (!ylIsZero) && (*xl * *yl < wl)) {
00114         if (!yuIsZero) {
00115           resxL = (*xl * *yu < wl) && updateBound (-1, xl, wl / *yu);
00116           xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false); 
00117         }
00118         if (!xuIsZero) {
00119           resyL = (*xu * *yl < wl) && updateBound (-1, yl, wl / *xu);
00120           ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00121         }
00122       }
00123     }
00124     else // wl is not zero
00125 
00126 #endif
00127     {
00128       if (wl >= 0.) {
00129         // point B in central infeasible area
00130         if (*xu * *yu < wl) {
00131 
00132 #ifdef FM_CHECK  
00133           if((*xu * *yl < wl) && (ylIsZero)) {
00134             printf("ylIsZero (A): %g\n", *yl);
00135             exit(1);
00136           }
00137           if((*xl * *yu < wl) && (xlIsZero)) {
00138             printf("xlIsZero (B): %g\n", *xl);
00139             exit(1);
00140           }
00141 #endif
00142 
00143           resxU = (*xu * *yl < wl) && updateBound (+1, xu, wl / *yl);
00144           xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false); 
00145           resyU = (*xl * *yu < wl) && updateBound (+1, yu, wl / *xl);
00146           yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00147         }
00148         
00149         // point C in central infeasible area
00150         
00151         if (*xl * *yl < wl) {
00152 
00153 #ifdef FM_CHECK
00154           if((*xl * *yu < wl) && (yuIsZero)) {
00155             printf("yuIsZero (C): %g\n", *yu);
00156             exit(1);
00157           }
00158           if((*xu * *yl < wl) && (xuIsZero)) {
00159             printf("xuIsZero (D): %g\n", *xu);
00160             exit(1);
00161           }
00162 #endif
00163           resxL = (*xl * *yu < wl) && (!yuIsZero) && updateBound (-1, xl, wl / *yu);
00164           xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00165           resyL = (*xu * *yl < wl) && (!xuIsZero) && updateBound (-1, yl, wl / *xu);
00166           ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00167         }
00168         
00169       } else if (wl > -COUENNE_INFINITY) {
00170         
00171         // the infeasible set is a hyperbola with two branches
00172         
00173         // upper left
00174 
00175 #ifdef FM_CHECK
00176         if(((*xl * *yl < wl) && (*yl > 0)) && (ylIsZero)) {
00177           printf("ylIsZero (E): %g\n", *yl);
00178         }
00179         if(((*xu * *yu < wl) && (*yu > 0)) && (xuIsZero)) {
00180           printf("xuIsZero (F): %g\n", *xu);                                  
00181           exit(1);
00182         }
00183         if(((*xl * *yl < wl) && (*yl < 0)) && (xlIsZero)) {
00184           printf("xlIsZero (G): %g\n", *xl);                                  
00185           exit(1);
00186         }
00187         if(( (*xu * *yu < wl) && (*yu < 0)) && (yuIsZero)) {
00188           printf("yuIsZero (H): %g\n", *yu);                                  
00189         }
00190 #endif
00191 
00192         resxL = (*xl * *yl < wl) && (*yl > 0.) && (!ylIsZero) && updateBound (-1, xl, wl / *yl); // point C
00193         xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00194         resyU = (*xu * *yu < wl) && (*yu > 0.) && (!xuIsZero) && updateBound (+1, yu, wl / *xu); // point B
00195         yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false); 
00196         
00197         // lower right
00198         resyL = (*xl * *yl < wl) && (*yl < 0.) && (!xlIsZero) && updateBound (-1, yl, wl / *xl); // point C
00199         ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00200         resxU = (*xu * *yu < wl) && (*yu < 0.) && (!yuIsZero) && updateBound (+1, xu, wl / *yu); // point B
00201         xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);
00202       }
00203     }
00204 
00205     bool
00206       xInt = arglist_ [0] -> isInteger (),
00207       yInt = arglist_ [1] -> isInteger ();
00208     
00209     if (resxL && xInt) *xl = ceil  (*xl - COUENNE_EPS);
00210     if (resxU && xInt) *xu = floor (*xu + COUENNE_EPS);
00211     if (resyL && yInt) *yl = ceil  (*yl - COUENNE_EPS);
00212     if (resyU && yInt) *yu = floor (*yu + COUENNE_EPS);
00213     
00214     // w's upper bound ///////////////////////////////////////////
00215 #ifdef FM_MOD
00216     
00217     if(wuIsZero) {
00218 
00219       if((!xuIsZero) && (!ylIsZero) && (*xu * *yl > wu)) {
00220         if(!yuIsZero) {
00221           resxU = (*xu * *yu > wu) && updateBound (+1, xu, wu / *yu) || resxU;
00222           xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);
00223         }
00224         if(!xlIsZero) {
00225           resyL = (*xl * *yl > wu) && updateBound (-1, yl, wu / *xl) || resyL;
00226           ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00227         }
00228       }
00229 
00230       if((!xlIsZero) && (!yuIsZero) && (*xl * *yu > wu)) {
00231         if(!ylIsZero) {
00232           resxL = (*xl * *yl > wu) && updateBound (-1, xl, wu / *yl) || resxL;
00233           xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00234         }
00235         if(!xuIsZero) {
00236           resyU = (*xu * *yu > wu) && updateBound (+1, yu, wu / *xu) || resyU;
00237           yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00238         }
00239       }
00240     }
00241 
00242     else // wu is not zero 
00243 
00244 #endif /* FM_MOD */
00245 
00246     {
00247       if (wu >= 0.) {
00248         if (wu < COUENNE_INFINITY) {
00249           // the infeasible set is a hyperbola with two branches
00250 
00251 #ifdef FM_CHECK
00252           if(((*xu * *yl > wu) && (*yl > 0)) && (ylIsZero)) {
00253             printf("ylIsZero (A2): yl: %g xu: %g wu: %g\n", *yl, *xu, wu);
00254             exit(1);
00255           }
00256           if(((*xl * *yu > wu) && (*yu > 0)) && (xlIsZero)) {
00257             printf("xlIsZero (B2): %g\n", *xl);
00258             exit(1);
00259           }
00260 #endif
00261           
00262           // upper right
00263           resxU = ((*xu * *yl > wu) && (*yl > 0.) && (!ylIsZero) && updateBound (+1, xu, wu / *yl)) || resxU; // point D
00264           xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);
00265           resyU = ((*xl * *yu > wu) && (*yu > 0.) && (!xlIsZero) && updateBound (+1, yu, wu / *xl)) || resyU; // point A
00266           yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00267           
00268 #ifdef FM_CHECK
00269           if(((*xl * *yu > wu) && (*yu < 0)) && (yuIsZero)) {
00270             printf("yuIsZero (C2): %g\n", *yu);
00271            }
00272           if(((*xu * *yl > wu) && (*yl < 0)) && (xuIsZero)) {
00273             printf("xuIsZero (D2): %g\n", *xu);
00274             exit(1);
00275           }
00276 #endif
00277 
00278           // lower left
00279           resxL = ((*xl * *yu > wu) && (*yu < 0.) && (!yuIsZero) && updateBound (-1, xl, wu / *yu)) || resxL; // point A
00280           xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false); 
00281           resyL = ((*xu * *yl > wu) && (*yl < 0.) && (!xuIsZero) && updateBound (-1, yl, wu / *xu)) || resyL; // point D
00282           ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00283         }
00284         
00285       } else {
00286         
00287         // point D in central infeasible area
00288         
00289         if (*xu * *yl > wu) {
00290 
00291 #ifdef FM_CHECK
00292           if((*xu * *yu > wu) && (yuIsZero)) {
00293             printf("yuIsZero (E2): %g\n", *yu);
00294             exit(1);
00295           }
00296           if((*xl * *yl > wu) && (xlIsZero)) {
00297             printf("xlIsZero (F2): %g\n", *xl);
00298             exit(1);
00299           }
00300 #endif
00301 
00302           resxU = ((*xu * *yu > wu) && (!yuIsZero) && updateBound (+1, xu, wu / *yu)) || resxU;
00303           xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);
00304           resyL = ((*xl * *yl > wu) && (!xlIsZero) && updateBound (-1, yl, wu / *xl)) || resyL;
00305           ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00306         }
00307         
00308         // point A in central infeasible area
00309         
00310         if (*xl * *yu > wu) {
00311 
00312 #ifdef FM_CHECK
00313           if((*xl * *yl > wu) && (ylIsZero)) {
00314             printf("ylIsZero (G2): %g\n", *yl);
00315             exit(1);
00316           }
00317           if((*xu * *yu > wu) && (xuIsZero)) {
00318             printf("xuIsZero (H2): %g\n", *xu);
00319             exit(1);
00320           }
00321 #endif
00322 
00323           resxL = ((*xl * *yl > wu) && (!ylIsZero) && updateBound (-1, xl, wu / *yl)) || resxL;
00324           xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00325           resyU = ((*xu * *yu > wu) && (!xuIsZero) && updateBound (+1, yu, wu / *xu)) || resyU;
00326           yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00327         }
00328       }
00329     }
00330 
00331     // extra integrality check
00332 
00333     if (resxL) {chg [xi].setLower(t_chg_bounds::CHANGED); if (xInt) *xl = ceil  (*xl - COUENNE_EPS);}
00334     if (resxU) {chg [xi].setUpper(t_chg_bounds::CHANGED); if (xInt) *xu = floor (*xu + COUENNE_EPS);}
00335     if (resyL) {chg [yi].setLower(t_chg_bounds::CHANGED); if (yInt) *yl = ceil  (*yl - COUENNE_EPS);}
00336     if (resyU) {chg [yi].setUpper(t_chg_bounds::CHANGED); if (yInt) *yu = floor (*yu + COUENNE_EPS);}
00337 
00338     resL = resxL || resyL;
00339     resU = resxU || resyU;
00340   }
00341 
00342   return (resL || resU);
00343 }

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