1 /* $Id$
2  *
3  * Name:    conv-exprMul.cpp
4  * Author:  Pietro Belotti
5  * Purpose: utility methods to convexify multiplications
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include <queue>
12 
13 #include "CouenneTypes.hpp"
14 #include "CouenneExprMul.hpp"
15 #include "CouenneExprTrilinear.hpp"
16 #include "CouenneExprBMul.hpp"
17 #include "CouenneExprConst.hpp"
18 #include "CouenneExprPow.hpp"
19 #include "CouenneExprAux.hpp"
20 #include "CouenneExprClone.hpp"
21 #include "CouenneProblem.hpp"
22 
23 using namespace Couenne;
24 
25 
26 /// get lower/upper bounds of product f(x) g(x) in expression form
27 
getBounds(expression * & lb,expression * & ub)28 void exprMul::getBounds (expression *&lb, expression *&ub) {
29 
30   int i;
31 
32   if ((arglist_ [i=0] -> Type () == CONST) ||
33       (arglist_ [i=1] -> Type () == CONST)) {
34 
35     CouNumber c = arglist_ [i] -> Value ();
36 
37     if (!i && (arglist_ [1] -> Type () == CONST)) {
38 
39       // !i means i==0, or the first is constant. If you are here,
40       // both are constant, which should not happen...
41 
42       CouNumber prod = c * arglist_ [1] -> Value ();
43 
44       lb = new exprConst (prod);
45       ub = new exprConst (prod);
46 
47       return;
48     }
49     else {
50 
51       // expression is of the type c*x
52 
53       expression *lbi, *ubi;
54       arglist_ [1-i] -> getBounds (lbi, ubi);
55 
56       if (c >= 0) {
57 	lb = new exprMul (new exprConst (c), lbi);
58 	ub = new exprMul (new exprConst (c), ubi);
59       } else {
60 	lb = new exprMul (new exprConst (c), ubi);
61 	ub = new exprMul (new exprConst (c), lbi);
62       }
63     }
64   }
65   else {
66 
67     // expression is of the type x*y
68 
69     expression **almin = new expression * [4];
70     expression **almax = new expression * [4];
71 
72     arglist_ [0] -> getBounds (almin [0], almin [1]);
73     arglist_ [1] -> getBounds (almin [2], almin [3]);
74 
75     almax [0] = new exprClone (almin [0]);
76     almax [1] = new exprClone (almin [1]);
77     almax [2] = new exprClone (almin [2]);
78     almax [3] = new exprClone (almin [3]);
79 
80     lb = new exprLBMul (almin, 4);
81     ub = new exprUBMul (almax, 4);
82   }
83 }
84 
85 
86 /// get lower/upper bounds of product f(x) g(x) in expression form
87 
getBounds(CouNumber & lb,CouNumber & ub)88 void exprMul::getBounds (CouNumber &lb, CouNumber &ub) {
89 
90   CouNumber lb1, ub1, lb2, ub2;
91 
92   arglist_ [0] -> getBounds (lb1, ub1);
93   arglist_ [1] -> getBounds (lb2, ub2);
94 
95   if (ub1 < 0) { // use lb1, dominant
96     if      (ub2 < 0) {lb = safeProd(ub1,ub2); ub = safeProd(lb1,lb2);}
97     else if (lb2 > 0) {lb = safeProd(lb1,ub2); ub = safeProd(ub1,lb2);}
98     else              {lb = safeProd(lb1,ub2); ub = safeProd(lb1,lb2);}
99   } else if (lb1 > 0) { // use ub1, dominant
100     if      (ub2 < 0) {lb = safeProd(ub1,lb2); ub = safeProd(lb1,ub2);}
101     else if (lb2 > 0) {lb = safeProd(lb1,lb2); ub = safeProd(ub1,ub2);}
102     else              {lb = safeProd(ub1,lb2); ub = safeProd(ub1,ub2);}
103   } else { // there is a zero to consider
104     if      (ub2 < 0) {lb = safeProd(ub1,lb2); ub = safeProd(lb1,lb2);}
105     else if (lb2 > 0) {lb = safeProd(lb1,ub2); ub = safeProd(ub1,ub2);}
106     else              {lb = CoinMin (safeProd(lb1,ub2), safeProd(lb2,ub1));
107                        ub = CoinMax (safeProd(lb1,lb2), safeProd(ub1,ub2));}
108   }
109 }
110