00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012
00013 #include "OsiSolverInterface.hpp"
00014 #include "CouenneTypes.hpp"
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneExprAbs.hpp"
00017 #include "CouenneExprAux.hpp"
00018
00019 using namespace Couenne;
00020
00021
00022
00023 void exprAbs::generateCuts (expression *w,
00024 OsiCuts &cs, const CouenneCutGenerator *cg,
00025 t_chg_bounds *chg, int wind,
00026 CouNumber lbw, CouNumber ubw) {
00027
00028 int w_ind = w -> Index (),
00029 x_ind = argument_ -> Index ();
00030
00031 CouNumber l, u;
00032 argument_ -> getBounds (l, u);
00033
00034 enum auxSign sign = cg -> Problem () -> Var (w_ind) -> sign ();
00035
00036 bool
00037 cbase = !chg || cg -> isFirst (),
00038 cLeft = cbase || (chg [x_ind].lower() != t_chg_bounds::UNCHANGED),
00039 cRight = cbase || (chg [x_ind].upper() != t_chg_bounds::UNCHANGED);
00040
00041
00042
00043 if (l >= -0) {if (cLeft) cg -> createCut (cs, 0., sign, w_ind, 1., x_ind, -1.);}
00044 else if (u <= 0) {if (cRight) cg -> createCut (cs, 0., sign, w_ind, 1., x_ind, +1.);}
00045 else {
00046
00047
00048 if (cg -> isFirst () && sign != expression::AUX_LEQ) {
00049 cg -> createCut (cs, 0., +1, w_ind, 1., x_ind, -1.);
00050 cg -> createCut (cs, 0., +1, w_ind, 1., x_ind, 1.);
00051 }
00052
00053
00054
00055
00056
00057 if (sign != expression::AUX_GEQ) {
00058
00059 if (l > - COUENNE_INFINITY) {
00060 if (u < COUENNE_INFINITY) {
00061
00062 CouNumber slope = (u+l) / (u-l);
00063
00064
00065 if (cLeft || cRight)
00066 cg -> createCut (cs, -l*(slope+1.), -1, w_ind, 1., x_ind, -slope);
00067 }
00068 else
00069 if (cLeft) cg -> createCut (cs, -2*l, -1, w_ind, 1., x_ind, -1.);
00070 }
00071 else if (u < COUENNE_INFINITY)
00072 if (cRight) cg -> createCut (cs, 2*u, -1, w_ind, 1., x_ind, 1.);
00073 }
00074 }
00075 }