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