00001
00002
00003
00004
00005
00006
00007
00008
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
00020
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
00041
00042
00043
00044
00045 CouNumber c = arglist_ [ind] -> Value ();
00046
00047 bool argInt = arglist_ [1-ind] -> isInteger ();
00048
00049
00050 ind = arglist_ [1-ind] -> Index ();
00051
00052 if (ind==-1)
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
00070
00071
00072 } else {
00073
00074
00075
00076
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
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
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
00125
00126 #endif
00127 {
00128 if (wl >= 0.) {
00129
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
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
00172
00173
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);
00193 xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00194 resyU = (*xu * *yu < wl) && (*yu > 0.) && (!xuIsZero) && updateBound (+1, yu, wl / *xu);
00195 yuIsZero = (fabs(*yu) < COUENNE_EPS ? true : false);
00196
00197
00198 resyL = (*xl * *yl < wl) && (*yl < 0.) && (!xlIsZero) && updateBound (-1, yl, wl / *xl);
00199 ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00200 resxU = (*xu * *yu < wl) && (*yu < 0.) && (!yuIsZero) && updateBound (+1, xu, wl / *yu);
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
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
00243
00244 #endif
00245
00246 {
00247 if (wu >= 0.) {
00248 if (wu < COUENNE_INFINITY) {
00249
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
00263 resxU = ((*xu * *yl > wu) && (*yl > 0.) && (!ylIsZero) && updateBound (+1, xu, wu / *yl)) || resxU;
00264 xuIsZero = (fabs(*xu) < COUENNE_EPS ? true : false);
00265 resyU = ((*xl * *yu > wu) && (*yu > 0.) && (!xlIsZero) && updateBound (+1, yu, wu / *xl)) || resyU;
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
00279 resxL = ((*xl * *yu > wu) && (*yu < 0.) && (!yuIsZero) && updateBound (-1, xl, wu / *yu)) || resxL;
00280 xlIsZero = (fabs(*xl) < COUENNE_EPS ? true : false);
00281 resyL = ((*xu * *yl > wu) && (*yl < 0.) && (!xuIsZero) && updateBound (-1, yl, wu / *xu)) || resyL;
00282 ylIsZero = (fabs(*yl) < COUENNE_EPS ? true : false);
00283 }
00284
00285 } else {
00286
00287
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
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
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 }