00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012
00013 #include "CouenneTypes.hpp"
00014 #include "CouennePrecisions.hpp"
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneExprDiv.hpp"
00017 #include "CouenneExprMul.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneFunTriplets.hpp"
00020
00021 namespace Couenne {
00022
00024
00025 void contourCut (const CouenneCutGenerator *cg,
00026 OsiCuts &cs,
00027 CouNumber xp, CouNumber yp,
00028 CouNumber wb,
00029 int sign,
00030 CouNumber x0, CouNumber y0,
00031 CouNumber x1, CouNumber y1,
00032 int xi, int yi, int wi) {
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 int xsign = (x1 >= 0) ? 1 : -1,
00043 ysign = (y1 >= 0) ? 1 : -1;
00044
00045 if (((xsign > 0) ? xp : -xp) <= COUENNE_EPS)
00046 if (((ysign > 0) ? yp : -yp) <= COUENNE_EPS) {
00047
00048
00049 xp = yp = sqrt (fabs (wb))/2;
00050 if (xsign<0) xp = -xp;
00051 if (ysign<0) yp = -yp;
00052 }
00053 else {xp = sqrt (fabs(wb/yp)); if (xsign<0) xp=-xp;}
00054 else if (((ysign > 0) ? yp : -yp) <= COUENNE_EPS) {yp = sqrt (fabs(wb/xp)); if (ysign<0) yp=-yp;}
00055
00056
00057 kpowertriplet pt (-1, wb);
00058
00059 CouNumber
00060
00061 xt = powNewton (xp, yp, &pt),
00062 *lb = cg -> Problem () -> Lb (),
00063 *ub = cg -> Problem () -> Ub (),
00064 xL = lb [xi], xU = ub [xi],
00065 yL = lb [yi], yU = ub [yi];
00066
00067 if (xt == 0.)
00068 return;
00069
00070
00071
00072 if ((xt < xL) && (xL != 0.)) xt = xL;
00073 if ((xt > xU) && (xU != 0.)) xt = xU;
00074
00075 if ((wb / xt < yL) && (yL != 0.)) xt = wb / yL;
00076 if ((wb / xt > yU) && (yU != 0.)) xt = wb / yU;
00077
00078
00079 CouNumber
00080 alpha = ((fabs (x1) < COUENNE_INFINITY) &&
00081 (fabs (y1) < COUENNE_INFINITY) &&
00082 (fabs (x1*y1 - wb) > 0.)) ?
00083 ((2*wb/xt - y1 - wb*x1 / (xt*xt)) / (x1*y1 - wb)) : 0;
00084
00085
00086
00087
00088 if (alpha != 0)
00089 cg -> createCut (cs, alpha*wb + 2*wb/xt, sign, wi, alpha, yi, 1., xi, wb/(xt*xt));
00090 else cg -> createCut (cs, 2*wb/xt, sign, yi, 1., xi, wb/(xt*xt));
00091 }
00092
00093
00094
00095
00096 void unifiedProdCuts (const CouenneCutGenerator *cg, OsiCuts &cs,
00097 int xi, CouNumber x0, CouNumber xl, CouNumber xu,
00098 int yi, CouNumber y0, CouNumber yl, CouNumber yu,
00099 int wi, CouNumber w0, CouNumber wl, CouNumber wu,
00100 t_chg_bounds *chg, enum expression::auxSign sign) {
00101
00102 bool cLX, cRX, cLY, cRY, cLW, cRW =
00103 cLX = cRX = cLY = cRY = cLW = true;
00104
00105 if (!(cg -> isFirst ()) && chg) {
00106 cLX= chg[xi].lower() != t_chg_bounds::UNCHANGED; cRX= chg[xi].upper() != t_chg_bounds::UNCHANGED;
00107 cLY= chg[yi].lower() != t_chg_bounds::UNCHANGED; cRY= chg[yi].upper() != t_chg_bounds::UNCHANGED;
00108 cLW= chg[wi].lower() != t_chg_bounds::UNCHANGED; cRW= chg[wi].upper() != t_chg_bounds::UNCHANGED;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 if (sign != expression::AUX_LEQ) {
00122 if ((cLX || cLY) && is_boundbox_regular (yl, xl)) cg -> createCut (cs,yl*xl,-1,wi,-1.,xi,yl,yi,xl);
00123 if ((cRX || cRY) && is_boundbox_regular (yu, xu)) cg -> createCut (cs,yu*xu,-1,wi,-1.,xi,yu,yi,xu);
00124 }
00125
00126 if (sign != expression::AUX_GEQ) {
00127 if ((cRX || cLY) && is_boundbox_regular (yl, xu)) cg -> createCut (cs,yl*xu,+1,wi,-1.,xi,yl,yi,xu);
00128 if ((cLX || cRY) && is_boundbox_regular (yu, xl)) cg -> createCut (cs,yu*xl,+1,wi,-1.,xi,yu,yi,xl);
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 if (cg -> Problem () -> MultilinSep () == CouenneProblem::MulSepSimple ||
00164 fabs (wu - wl) < COUENNE_EPS) {
00165
00166 if ((x0 > xl + COUENNE_EPS) && (y0 > yl + COUENNE_EPS) &&
00167 (x0 < xu + COUENNE_EPS) && (y0 < yu + COUENNE_EPS)) {
00168
00169 if (cLW && (wl > 0) && (x0*y0 < wl) && (sign != expression::AUX_GEQ)) {
00170
00171 CouNumber xyl = xl * yl;
00172
00173
00174 if ((xyl < wl) && (xu*yu >= wl)) contourCut (cg,cs, x0,y0, wl, +1, xl,yl, xu,yu, xi,yi,wi);
00175 else if ((xyl >= wl) && (xu*yu < wl)) contourCut (cg,cs, x0,y0, wl, -1, xu,yu, xl,yl, xi,yi,wi);
00176 }
00177
00178
00179
00180 if (cRW && (wu < 0) && (x0*y0 > wu) && (sign != expression::AUX_LEQ)) {
00181
00182 CouNumber xuyl = xl * yu;
00183
00184
00185 if ((xuyl > wu) && (xl*yu <= wu)) contourCut (cg,cs, x0,y0, wu, +1, xu,yl, xl,yu, xi,yi,wi);
00186 else if ((xuyl <=wu) && (xl*yu > wu)) contourCut (cg,cs, x0,y0, wu, -1, xl,yu, xu,yl, xi,yi,wi);
00187 }
00188 }
00189 } else
00190 if (cg -> Problem () -> MultilinSep () == CouenneProblem::MulSepTight)
00191 upperEnvHull (cg, cs,
00192 xi, x0, xl, xu,
00193 yi, y0, yl, yu,
00194 wi, w0, wl, wu);
00195 }
00196
00197 }