00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneCutGenerator.hpp"
00012
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneExprExp.hpp"
00015 #include "CouenneExprConst.hpp"
00016 #include "CouenneExprAux.hpp"
00017 #include "CouenneExprPow.hpp"
00018
00019 #include "CouenneProblem.hpp"
00020
00021 using namespace Couenne;
00022
00023
00024
00025 void exprExp::generateCuts (expression *aux,
00026 OsiCuts &cs, const CouenneCutGenerator *cg,
00027 t_chg_bounds *chg, int wind,
00028 CouNumber lbw, CouNumber ubw) {
00029 CouNumber l, u;
00030 argument_ -> getBounds (l, u);
00031
00032 int w_ind = aux -> Index (),
00033 x_ind = argument_ -> Index ();
00034
00035 bool cL = !chg || (chg [x_ind].lower() != t_chg_bounds::UNCHANGED) || cg -> isFirst ();
00036 bool cR = !chg || (chg [x_ind].upper() != t_chg_bounds::UNCHANGED) || cg -> isFirst ();
00037
00038 enum auxSign sign = cg -> Problem () -> Var (w_ind) -> sign ();
00039
00040 if (fabs (u-l) < COUENNE_EPS) {
00041
00042 CouNumber x0 = 0.5 * (u+l), ex0 = exp (x0);
00043 if (cL || cR)
00044 cg -> createCut (cs, ex0 * (1 - x0), sign, w_ind, 1., x_ind, - ex0);
00045
00046 return;
00047 }
00048
00049 CouNumber x = (cg -> isFirst ()) ?
00050 0 : powNewton ((*argument_) (), (*aux) (), exp, exp, exp);
00051
00052
00053
00054 if ((sign != expression::AUX_GEQ)
00055 && (cL || cR)
00056 && (u < log (COUENNE_INFINITY) )
00057 && (l > - COUENNE_INFINITY / 1e4)) {
00058
00059 CouNumber expl = exp (l),
00060 oppslope = (expl - exp (u)) / (u - l);
00061
00062 cg -> createCut (cs, expl + oppslope*l, -1,
00063 w_ind, 1.,
00064 x_ind, oppslope);
00065 }
00066
00067
00068
00069 if (sign == expression::AUX_LEQ)
00070 return;
00071
00072
00073
00074 const CouNumber logMC = log (COU_MAX_COEFF);
00075
00076
00077 if (l < - logMC) l = - logMC;
00078 if (u > logMC) u = logMC;
00079
00080
00081 cg -> addEnvelope (cs, +1, exp, exp, w_ind, x_ind, x, l, u, chg, true);
00082 }