00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012
00013 #include "CouenneExprMul.hpp"
00014 #include "CouennePrecisions.hpp"
00015
00016 namespace Couenne {
00017
00018
00019
00020 int findIntersection (CouNumber x0, CouNumber y0,
00021 CouNumber x1, CouNumber y1,
00022 CouNumber *wl, CouNumber *wu,
00023 CouNumber *xA, CouNumber *yA,
00024 CouNumber *xB, CouNumber *yB);
00025
00026 int genMulCoeff (CouNumber x1, CouNumber y1,
00027 CouNumber x2, CouNumber y2,
00028 char whichUse,
00029 CouNumber &cX, CouNumber &cY, CouNumber &cW);
00030
00031
00032
00033 inline void invertInterval (register double &l, register double &u, register double x) {
00034
00035 register double tmp = l;
00036 l = -u;
00037 u = -tmp;
00038
00039 x = -x;
00040 }
00041
00042 void upperEnvHull (const CouenneCutGenerator *cg, OsiCuts &cs,
00043 int xi, CouNumber x0, CouNumber xl, CouNumber xu,
00044 int yi, CouNumber y0, CouNumber yl, CouNumber yu,
00045 int wi, CouNumber w0, CouNumber wl, CouNumber wu) {
00046
00047
00048
00049
00050
00051 #ifdef DEBUG
00052 printf ("entering points: ===================================================\n");
00053 printf ("x [%d]: %9g\t[%9g\t%9g]\n", xi, x0, xl, xu);
00054 printf ("y [%d]: %9g\t[%9g\t%9g]\n", yi, y0, yl, yu);
00055 printf ("w [%d]: %9g\t[%9g\t%9g]\n", wi, w0, wl, wu);
00056 #endif
00057
00058
00059
00060 if ((wl < 0 && wu > 0))
00061 return;
00062
00063
00064 if (x0 < xl) x0 = xl; if (x0 > xu) x0 = xu;
00065 if (y0 < yl) y0 = yl; if (y0 > yu) y0 = yu;
00066
00067
00068 if (wl >= 0) {
00069 if ((xl >= 0) || (yl >= 0) || (xl * yl < wl - COUENNE_EPS)) {
00070 if (xl < 0) xl = 0;
00071 if (yl < 0) yl = 0;
00072 } else if ((xu <= 0) || (yu <= 0) || (xu * yu < wl - COUENNE_EPS)) {
00073 if (xu > 0) xu = 0;
00074 if (yu > 0) yu = 0;
00075 }
00076 } else {
00077 if ((xl >= 0) || (yu <= 0) || (xl * yu > wu + COUENNE_EPS)) {
00078 if (xl < 0) xl = 0;
00079 if (yu > 0) yu = 0;
00080 } else if ((xu <= 0) || (yl >= 0) || (xu * yl > wu + COUENNE_EPS)) {
00081 if (xu > 0) xu = 0;
00082 if (yl < 0) yl = 0;
00083 }
00084 }
00085
00086
00087
00088 bool
00089 flipX = xl < 0,
00090 flipY = yl < 0,
00091 flipW = false;
00092
00093 if (flipX && flipY) {
00094
00095 invertInterval (xl,xu,x0);
00096 invertInterval (yl,yu,y0);
00097
00098 } else if (flipX) {
00099
00100 invertInterval (xl,xu,x0);
00101 invertInterval (wl,wu,w0);
00102
00103 flipW = true;
00104
00105 } else if (flipY) {
00106
00107 invertInterval (yl,yu,y0);
00108 invertInterval (wl,wu,w0);
00109
00110 flipW = true;
00111 }
00112
00113 #ifdef DEBUG
00114 printf ("reduced points:\n");
00115 printf ("x: %9g\t[%9g\t%9g]\n", x0, xl, xu);
00116 printf ("y: %9g\t[%9g\t%9g]\n", y0, yl, yu);
00117 printf ("w: %9g\t[%9g\t%9g]\n", w0, wl, wu);
00118 #endif
00119
00120
00121
00122
00123 if (((xl*yl >= wl) &&
00124 (xu*yu <= wu)) ||
00125 (x0*y0 >= w0))
00126 return;
00127
00128
00129
00130 CouNumber xLow, yLow, xUpp, yUpp;
00131 if (findIntersection (0., 0., x0, y0, &wl, &wu, &xLow, &yLow, &xUpp, &yUpp))
00132 return;
00133
00134 #ifdef DEBUG
00135 printf ("intersections:\n");
00136 printf ("lower: %9g\t%9g\tprod %9g\n", xLow, yLow, xLow*yLow);
00137 printf ("upper: %9g\t%9g\tprod %9g\n", xUpp, yUpp, xUpp*yUpp);
00138 #endif
00139
00140
00141
00142 if ((xLow <= xl && yUpp >= yu) ||
00143 (yLow <= yl && xUpp >= xu))
00144 return;
00145
00146
00147
00148
00149 CouNumber
00150 cX, cY, cW, c0, c0X, c0Y, c0W;
00151
00152 if (xLow >= xl && xUpp <= xu &&
00153 yLow >= yl && yUpp <= yu) {
00154
00155 #ifdef DEBUG
00156 printf ("easy lifting:\n");
00157 #endif
00158
00159
00160 if (genMulCoeff (xLow, yLow, xUpp, yUpp, 0, cX, cY, cW))
00161 return;
00162
00163 c0X = cX * xLow;
00164 c0Y = cY * yLow;
00165 c0W = cW * wl;
00166
00167 } else if (xLow >= xl && yLow >= yl &&
00168 (xUpp > xu || yUpp > yu)) {
00169
00170 #ifdef DEBUG
00171 printf ("through lower, not upper:\n");
00172 #endif
00173
00174
00175
00176 if (yUpp > yu) {
00177 yUpp = yu;
00178 xUpp = wu / yu;
00179 } else {
00180 xUpp = xu;
00181 yUpp = wu / xu;
00182 }
00183
00184
00185 if ((findIntersection (xUpp, yUpp, x0, y0, &wl, NULL, &xLow, &yLow, NULL, NULL)) ||
00186 (xLow < xl || yLow < yl) ||
00187 (genMulCoeff (xLow, yLow, xUpp, yUpp, 0, cX, cY, cW)))
00188 return;
00189
00190 c0X = cX * xLow;
00191 c0Y = cY * yLow;
00192 c0W = cW * wl;
00193
00194 } else if (xUpp <= xu && yUpp <= yu &&
00195 (xLow < xl || yLow < yl)) {
00196
00197 #ifdef DEBUG
00198 printf ("through upper, not lower:\n");
00199 #endif
00200
00201
00202
00203 if (yLow < yl) {
00204 yLow = yl;
00205 xLow = wl / yl;
00206 } else {
00207 xLow = xl;
00208 yLow = wl / xl;
00209 }
00210
00211
00212 if (findIntersection (xLow, yLow, x0, y0, NULL, &wu, NULL, NULL, &xUpp, &yUpp))
00213 return;
00214
00215 if (xUpp > xu || yUpp > yu)
00216 return;
00217
00218
00219 if (genMulCoeff (xLow, yLow, xUpp, yUpp, 1, cX, cY, cW))
00220 return;
00221
00222 c0X = cX * xUpp;
00223 c0Y = cY * yUpp;
00224 c0W = cW * wu;
00225
00226 } else if ((xLow < xl && xUpp > xu) ||
00227 (yLow < yl && yUpp > yu)) {
00228
00229 #ifdef DEBUG
00230 printf ("between lower and upper:\n");
00231 #endif
00232
00233
00234
00235
00236 if (yLow < yl) {
00237 yLow = yl; xLow = wl / yl;
00238 yUpp = yu; xUpp = wu / yu;
00239 } else {
00240 xLow = xl; yLow = wl / xl;
00241 xUpp = xu; yUpp = wu / xu;
00242 }
00243
00244 #ifdef DEBUG
00245 printf ("New intersections:\n");
00246 printf ("lower: %9g\t%9g\tprod %9g\n", xLow, yLow, xLow*yLow);
00247 printf ("upper: %9g\t%9g\tprod %9g\n", xUpp, yUpp, xUpp*yUpp);
00248 #endif
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 CouNumber xLow2, yLow2, xUpp2, yUpp2;
00262
00263 if ((findIntersection (xLow, yLow, x0, y0, NULL, &wu, NULL, NULL, &xUpp2, &yUpp2) || genMulCoeff (xLow, yLow, xUpp, yUpp, 0, cX, cY, cW)) &&
00264 (findIntersection (xUpp, yUpp, x0, y0, &wl, NULL, &xLow2, &yLow2, NULL, NULL) || genMulCoeff (xLow, yLow, xUpp, yUpp, 1, cX, cY, cW)))
00265 return;
00266
00267 #ifdef DEBUG
00268 printf ("coeffs: (%g,%g,%g)\n",
00269 cX,cY,cW);
00270 #endif
00271
00272 c0X = cX * xLow;
00273 c0Y = cY * yLow;
00274 c0W = cW * wl;
00275
00276
00277
00278 } else {
00279
00280 #ifdef DEBUG
00281 printf ("points are in a weird position:\n");
00282 printf ("lower: %9g\t%9g\tprod %9g\n", xLow, yLow, xLow*yLow);
00283 printf ("upper: %9g\t%9g\tprod %9g\n", xUpp, yUpp, xUpp*yUpp);
00284 #endif
00285
00286 return;
00287 }
00288
00289
00290
00291 if (flipX) {cX = -cX; c0X = -c0X;}
00292 if (flipY) {cY = -cY; c0Y = -c0Y;}
00293 if (flipW) {cW = -cW; c0W = -c0W;}
00294
00295 c0 = c0X + c0Y + c0W;
00296
00297 #ifdef DEBUG
00298 printf ("there are cuts\n");
00299 #endif
00300
00301
00302 cg -> createCut (cs, c0, 1, wi, cW, yi, cY, xi, cX);
00303 }
00304
00305
00306
00307
00308
00309 int findIntersection (CouNumber x0, CouNumber y0,
00310 CouNumber x1, CouNumber y1,
00311 CouNumber *wl, CouNumber *wu,
00312 CouNumber *xA, CouNumber *yA,
00313 CouNumber *xB, CouNumber *yB) {
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 CouNumber
00332 a = (x1-x0) * (y1-y0),
00333 c = x0 * y0,
00334 b = x0*y1 + y0*x1 - 2*c;
00335
00336 if (fabs (a) < COUENNE_EPS)
00337 return 1;
00338
00339
00340
00341 CouNumber tL1, tL2, tU1, tU2, tL=0., tU=0.;
00342
00343 if (wl) {
00344 tL1 = (- b - sqrt (b*b - 4*a*(c-*wl))) / (2*a);
00345 tL2 = (- b + sqrt (b*b - 4*a*(c-*wl))) / (2*a);
00346
00347 tL = (tL1 < 0) ? tL2 : tL1;
00348 }
00349
00350 if (wu) {
00351 tU1 = (- b - sqrt (b*b - 4*a*(c-*wu))) / (2*a);
00352 tU2 = (- b + sqrt (b*b - 4*a*(c-*wu))) / (2*a);
00353
00354 tU = (tU1 < 0) ? tU2 : tU1;
00355 }
00356
00357 if (xA) *xA = x0 + tL * (x1-x0); if (yA) *yA = y0 + tL * (y1-y0);
00358 if (xB) *xB = x0 + tU * (x1-x0); if (yB) *yB = y0 + tU * (y1-y0);
00359
00360 return 0;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 int genMulCoeff (CouNumber x1, CouNumber y1,
00370 CouNumber x2, CouNumber y2,
00371 char whichUse,
00372 CouNumber &cX, CouNumber &cY, CouNumber &cW) {
00373
00374
00375
00376
00377 CouNumber xD, yD, xO, yO;
00378
00379 if (!whichUse) {
00380 xD = x1; xO = x2;
00381 yD = y1; yO = y2;
00382 } else {
00383 xD = x2; xO = x1;
00384 yD = y2; yO = y1;
00385 }
00386
00387 cX = yD;
00388 cY = xD;
00389
00390
00391 #ifdef DEBUG
00392 printf ("points: (%g,%g) (%g,%g), cW = (%g - %g) / %g = %g\n",
00393 xD,yD, xO,yO, 2*xD*yD, (cX*xO + cY*yO), (xO*yO - xD*yD),
00394 (2*xD*yD - (cX*xO + cY*yO)) / (xO*yO - xD*yD));
00395 #endif
00396
00397
00398
00399 if (fabs (xO*yO - xD*xD) < COUENNE_EPS)
00400 return 1;
00401
00402
00403 cW = (2*xD*yD - (cX*xO + cY*yO)) / (xO*yO - xD*yD);
00404
00405 return 0;
00406 }
00407
00408 }