00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneTypes.hpp"
00012 #include "CouennePrecisions.hpp"
00013 #include "CouenneCutGenerator.hpp"
00014 #include "exprDiv.hpp"
00015 #include "exprMul.hpp"
00016 #include "exprPow.hpp"
00017 #include "funtriplets.hpp"
00018
00019
00021
00022 void contourCut (const CouenneCutGenerator *cg,
00023 OsiCuts &cs,
00024 CouNumber xp, CouNumber yp,
00025 CouNumber wb,
00026 int sign,
00027 CouNumber x0, CouNumber y0,
00028 CouNumber x1, CouNumber y1,
00029 int xi, int yi, int wi) {
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 int xsign = (x1 >= 0) ? 1 : -1,
00042 ysign = (y1 >= 0) ? 1 : -1;
00043
00044 if (((xsign > 0) ? xp : -xp) <= COUENNE_EPS)
00045 if (((ysign > 0) ? yp : -yp) <= COUENNE_EPS) {
00046
00047
00048 xp = yp = sqrt (fabs (wb))/2;
00049 if (xsign<0) xp = -xp;
00050 if (ysign<0) yp = -yp;
00051 }
00052 else {xp = sqrt (fabs(wb/yp)); if (xsign<0) xp=-xp;}
00053 else if (((ysign > 0) ? yp : -yp) <= COUENNE_EPS) {yp = sqrt (fabs(wb/xp)); if (ysign<0) yp=-yp;}
00054
00055 kpowertriplet pt (-1, wb);
00056
00057 CouNumber
00058
00059 xt = powNewton (xp, yp, &pt),
00060
00061 alpha = ((fabs (x1) < COUENNE_INFINITY) &&
00062 (fabs (y1) < COUENNE_INFINITY)) ?
00063 ((2*wb/xt - y1 - wb*x1 / (xt*xt)) / (x1*y1 - wb)) : 0;
00064
00065
00066
00067
00068 if (alpha != 0)
00069 cg -> createCut (cs, alpha*wb + 2*wb/xt, sign, wi, alpha, yi, 1., xi, wb/(xt*xt));
00070 else cg -> createCut (cs, 2*wb/xt, sign, yi, 1., xi, wb/(xt*xt));
00071 }
00072
00073
00074
00075
00076 void unifiedProdCuts (const CouenneCutGenerator *cg, OsiCuts &cs,
00077 int xi, CouNumber x0, CouNumber xl, CouNumber xu,
00078 int yi, CouNumber y0, CouNumber yl, CouNumber yu,
00079 int wi, CouNumber w0, CouNumber wl, CouNumber wu,
00080 t_chg_bounds *chg) {
00081
00082 bool cLX, cRX, cLY, cRY, cLW, cRW =
00083 cLX = cRX = cLY = cRY = cLW = true;
00084
00085 if (!(cg -> isFirst ()) && chg) {
00086 cLX= chg[xi].lower() != t_chg_bounds::UNCHANGED; cRX= chg[xi].upper() != t_chg_bounds::UNCHANGED;
00087 cLY= chg[yi].lower() != t_chg_bounds::UNCHANGED; cRY= chg[yi].upper() != t_chg_bounds::UNCHANGED;
00088 cLW= chg[wi].lower() != t_chg_bounds::UNCHANGED; cRW= chg[wi].upper() != t_chg_bounds::UNCHANGED;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 if ((cLX || cLY) && is_boundbox_regular (yl, xl)) cg -> createCut (cs, yl*xl,-1,wi,-1.,xi,yl,yi,xl);
00102 if ((cRX || cRY) && is_boundbox_regular (yu, xu)) cg -> createCut (cs, yu*xu,-1,wi,-1.,xi,yu,yi,xu);
00103 if ((cRX || cLY) && is_boundbox_regular (yl, xu)) cg -> createCut (cs, yl*xu,+1,wi,-1.,xi,yl,yi,xu);
00104 if ((cLX || cRY) && is_boundbox_regular (yu, xl)) cg -> createCut (cs, yu*xl,+1,wi,-1.,xi,yu,yi,xl);
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 if ((x0 > xl + COUENNE_EPS) && (y0 > yl + COUENNE_EPS) &&
00139 (x0 < xu + COUENNE_EPS) && (y0 < yu + COUENNE_EPS)) {
00140
00141 if (cLW && (wl > 0) && (x0*y0 < wl)) {
00142
00143 CouNumber xyl = xl * yl;
00144
00145
00146 if ((xyl < wl) && (xu*yu >=wl)) contourCut (cg,cs, x0,y0, wl, +1, xl,yl, xu,yu, xi,yi,wi);
00147 else if ((xyl >= wl) && (xu*yu < wl)) contourCut (cg,cs, x0,y0, wl, -1, xu,yu, xl,yl, xi,yi,wi);
00148 }
00149
00150
00151
00152 if (cRW && (wu < 0) && (x0*y0 > wu)) {
00153
00154 CouNumber xuyl = xl * yu;
00155
00156
00157 if ((xuyl > wu) && (xl*yu <=wu)) contourCut (cg,cs, x0,y0, wu, +1, xu,yl, xl,yu, xi,yi,wi);
00158 else if ((xuyl <=wu) && (xl*yu > wu)) contourCut (cg,cs, x0,y0, wu, -1, xl,yu, xu,yl, xi,yi,wi);
00159 }
00160 }
00161 }