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