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