1 /* $Id$
2 *
3 * Name: exprLog.cpp
4 * Author: Pietro Belotti
5 * Purpose: methods for class logarithm
6 *
7 * (C) Carnegie-Mellon University, 2006-10.
8 * This file is licensed under the Eclipse Public License (EPL)
9 */
10
11 #include <math.h>
12
13 #include "CouenneExprLog.hpp"
14 #include "CouenneExprConst.hpp"
15 #include "CouenneExprClone.hpp"
16 #include "CouenneExprMax.hpp"
17 #include "CouenneExprMin.hpp"
18 #include "CouenneExprDiv.hpp"
19 #include "CouenneProblem.hpp"
20
21 #include "CoinHelperFunctions.hpp"
22 #include "CoinFinite.hpp"
23
24 using namespace Couenne;
25
26 /// get bounds of log (x) based on bounds of x
27
getBounds(expression * & lb,expression * & ub)28 void exprLog::getBounds (expression *&lb, expression *&ub) {
29
30 expression *lba, *uba;
31 argument_ -> getBounds (lba, uba);
32
33 // [low|upp]er bound of w=log(x) is log (max (0, [low|upp]er (x)))
34 // lb = new exprLog (new exprMax (new exprConst (1e-100), lba));
35 // ub = new exprLog (new exprMax (new exprConst (1e-100), uba));
36
37 expression **all = new expression * [4];
38
39 all [0] = new exprClone (lba); all [1] = new exprLog (lba);
40 all [2] = new exprConst (0); all [3] = new exprConst (- COUENNE_INFINITY);
41 lb = new exprMax (all, 4);
42
43 expression **alu = new expression * [4],
44 **alum = new expression * [4];
45
46 alum [0] = new exprConst (COUENNE_INFINITY);
47 alum [1] = new exprConst (COUENNE_INFINITY);
48 alum [2] = new exprClone (uba);
49 alum [3] = new exprLog (uba);
50
51 alu [0] = new exprClone (uba); alu [1] = new exprMin (alum, 4);
52 alu [2] = new exprConst (0.); alu [3] = new exprConst (- COUENNE_INFINITY);
53 ub = new exprMax (alu, 4);
54 }
55
56
57 /// get bounds of log (x) based on bounds of x
58
getBounds(CouNumber & lb,CouNumber & ub)59 void exprLog::getBounds (CouNumber &lb, CouNumber &ub) {
60
61 CouNumber lba, uba;
62 argument_ -> getBounds (lba, uba);
63
64 lb = log (CoinMax (1e-50, lba));
65 ub = log (CoinMax (1e-50, uba));
66 }
67
68
69 /// differentiation
differentiate(int index)70 expression *exprLog::differentiate (int index) {
71 return new exprDiv (argument_ -> differentiate (index),
72 new exprClone (argument_));
73 }
74
75
76 /// implied bound processing for expression w = log(x), upon change in
77 /// lower- and/or upper bound of w, whose index is wind
impliedBound(int wind,CouNumber * l,CouNumber * u,t_chg_bounds * chg,enum auxSign sign)78 bool exprLog::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg, enum auxSign sign) {
79
80 int ind = argument_ -> Index ();
81
82 bool
83 res = false,
84 isint = argument_ -> isInteger();
85
86 CouNumber
87 wl = sign == expression::AUX_GEQ ? -COIN_DBL_MAX : l [wind],
88 wu = sign == expression::AUX_LEQ ? COIN_DBL_MAX : u [wind];
89
90 if (updateBound (-1, l+ind, isint ? ceil (exp (wl) - COUENNE_EPS) : exp (wl))) {
91 res = true;
92 chg [ind].setLower (t_chg_bounds::CHANGED);
93 }
94
95 if (updateBound ( 1, u+ind, isint? floor (exp (wu) + COUENNE_EPS) : exp (wu))) {
96 res = true;
97 chg [ind].setUpper (t_chg_bounds::CHANGED);
98 }
99
100 return res;
101 }
102
103
104 /// return l-2 norm of gradient at given point
gradientNorm(const double * x)105 CouNumber exprLog::gradientNorm (const double *x) {
106 return (argument_ -> Index () < 0) ? 0. :
107 1. / (CoinMax (1. / COUENNE_INFINITY, x [argument_ -> Index ()]));
108 }
109
110
111 /// can this expression be further linearized or are we on its
112 /// concave ("bad") side
isCuttable(CouenneProblem * problem,int index) const113 bool exprLog::isCuttable (CouenneProblem *problem, int index) const {
114
115 double
116 x = problem -> X (argument_ -> Index ()),
117 y = problem -> X (index);
118
119 return ((x == 0.) || (y > log (x)));
120 }
121