00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneExpression.hpp"
00015 #include "CouenneExprAux.hpp"
00016 #include "CouenneExprOp.hpp"
00017 #include "CouenneExprDiv.hpp"
00018 #include "CouenneExprMul.hpp"
00019 #include "CouenneProblem.hpp"
00020
00021 using namespace Couenne;
00022
00023
00024 exprAux *exprDiv::standardize (CouenneProblem *p, bool addAux) {
00025
00026 exprOp::standardize (p);
00027 return (addAux ? (p -> addAuxiliary (this)) : new exprAux (this, p -> domain ()));
00028 }
00029
00030
00031
00032 void exprDiv::generateCuts (expression *w,
00033 OsiCuts &cs, const CouenneCutGenerator *cg,
00034 t_chg_bounds *chg, int wind,
00035 CouNumber lbw, CouNumber ubw) {
00036
00037
00038 CouNumber yl, yu;
00039 arglist_ [1] -> getBounds (yl, yu);
00040
00041 int xi = arglist_ [0] -> Index (),
00042 yi = arglist_ [1] -> Index (),
00043 wi = w -> Index ();
00044
00045 bool cLW, cRW, cLY, cRY =
00046 cLW = cRW = cLY = true;
00047
00048 if (!(cg -> isFirst ()) && chg) {
00049 cLW = (chg [wi].lower() != t_chg_bounds::UNCHANGED);
00050 cRW = (chg [wi].upper() != t_chg_bounds::UNCHANGED);
00051 cLY = (chg [yi].lower() != t_chg_bounds::UNCHANGED);
00052 cRY = (chg [yi].upper() != t_chg_bounds::UNCHANGED);
00053 }
00054
00055
00056
00057
00058 if ((yl < -0.) &&
00059 (yu > 0.)) return;
00060
00061 CouNumber k;
00062
00063 enum auxSign sign = cg -> Problem () -> Var (wi) -> sign ();
00064
00065
00066
00067 if ((fabs (yl-yu) < COUENNE_EPS) &&
00068 ((fabs (k = ((yl+yu) / 2)) > COUENNE_EPS))) {
00069 if (cLY || cRY)
00070 cg -> createCut (cs, 0., sign, wi, 1., xi, -1./k);
00071 return;
00072 }
00073
00074 CouNumber wl, wu;
00075 w -> getBounds (wl, wu);
00076
00077 if (lbw > wl) wl = lbw;
00078 if (ubw < wu) wu = ubw;
00079
00080
00081
00082
00083 if ((fabs (wl-wu) < COUENNE_EPS) &&
00084 ((k = fabs (wl+wu) / 2) > COUENNE_EPS) &&
00085
00086
00087 ((sign==expression::AUX_EQ) || (yl > 0.) || (yu < 0.))) {
00088
00089 if (cLW || cRW) {
00090 if (sign==expression::AUX_EQ || (yl > 0.)) cg -> createCut (cs, 0., sign, yi, k, xi, -1.);
00091 else cg -> createCut (cs, 0., sign, yi, -k, xi, 1.);
00092 }
00093
00094 return;
00095 }
00096
00097 CouNumber xl, xu;
00098 arglist_ [0] -> getBounds (xl, xu);
00099
00100 if ((fabs (xl-xu) < COUENNE_EPS) &&
00101 (fabs (yl-yu) < COUENNE_EPS) &&
00102 (fabs (wl-wu) < COUENNE_EPS))
00103 return;
00104
00105
00106
00107
00108 CouNumber *x = cg -> Problem () -> X ();
00109
00110 bool
00111 ineqFullOrthantF = (((sign == expression::AUX_LEQ) && (yl > 0.)) || ((sign == expression::AUX_GEQ) && (yu < -0.))),
00112 ineqFullOrthantB = (((sign == expression::AUX_LEQ) && (yu < -0.)) || ((sign == expression::AUX_GEQ) && (yl > 0.)));
00113
00114 unifiedProdCuts (cg, cs,
00115 wi, x [wi], wl, wu,
00116 yi, x [yi], yl, yu,
00117 xi, x [xi],
00118 ineqFullOrthantF ? -COIN_DBL_MAX : xl,
00119 ineqFullOrthantB ? COIN_DBL_MAX : xu,
00120 chg,
00121 ineqFullOrthantF ? expression::AUX_GEQ :
00122 ineqFullOrthantB ? expression::AUX_LEQ :
00123 expression::AUX_EQ);
00124 }