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