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