exprBQuad.cpp
Go to the documentation of this file.
1 /* $Id: exprBQuad.cpp 490 2011-01-14 16:07:12Z pbelotti $ */
2 /*
3  * Name: exprBQuad.cpp
4  * Author: Pietro Belotti
5  * Purpose: method to compute value of an expr?BQuad
6  *
7  * (C) Carnegie-Mellon University, 2006.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 #include "CouenneExprBQuad.hpp"
13 
14 using namespace Couenne;
15 
16 //#define DEBUG
17 
19 
20  // 1) loose: disaggregated bound
21  // 2) tighter: aggregate coefficient per variable
22  // 3) tightest: solve (convex) QP on available alpha-convexification
23 
24  // 1) loose bound
25  //
26  // w = a0 + a'x + x'Qx means that its lower bound is
27  //
28  // w_l = a0 + a'_+ x_l + a'_- x_u + \sum_
29 
30 
31  // 2) tighter bound -- TODO
32  //
33  // Compute lower (if sign == -1) or upper (sign == +1) bound of an
34  // exprQuad based on the information obtained through
35  // alpha-convexification, if any, or as follows:
36  //
37  // w = a0 + a'x + x'Qx =
38  // = a0 + sum{i} [(a_i + sum {j>=i} q_ij * x_j) * x_i] =
39  // = a0 + sum{i} [ z_i * x_i]
40  //
41  // Thus, some bound on z_i can be computed and a bound on the whole
42  // expression should be better than what can be obtained by summing
43  // all bounds separately.
44  //
45  // Notice that the above computation is fast and may be better than
46  // the convexification after some updates in the variable bounds
47  // without updating the convexification. Notice also that the
48  // direction can also be vertical, not only horizontal.
49 
50  CouNumber bound = c0_, term;
51 
52  // derive linear part (obtain constant)
53  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
54 
55  CouNumber
56  coe = el -> second, term = 0.,
57  lb = el -> first -> lb (),
58  ub = el -> first -> ub ();
59 
60  if (((coe < 0.) && (sign < 0)) ||
61  ((coe > 0.) && (sign > 0)))
62  {if ((term=ub) > COUENNE_INFINITY) return (sign < 0)? -COUENNE_INFINITY : COUENNE_INFINITY;}
63  else {if ((term=lb) < -COUENNE_INFINITY) return (sign < 0)? -COUENNE_INFINITY : COUENNE_INFINITY;}
64 
65  bound += coe * term;
66  }
67 
68 #ifdef DEBUG
69  printf ("quadBound --- linear, %cb = %g\n", (sign < 0) ? 'l' : 'u', bound);
70 #endif
71 
72  // derive quadratic part (obtain linear part)
73  for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
74 
75  int xind = row -> first -> Index ();
76 
77  CouNumber
78  lbi = row -> first -> lb (),
79  ubi = row -> first -> ub ();
80 
81  for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
82 
83  int yind = col -> first -> Index ();
84 
85  CouNumber coe = col -> second;
86 
87  if (xind == yind) { // term of the form q_ii x_i^2
88 
89  if (((coe > 0.) && (sign < 0)) ||
90  ((coe < 0.) && (sign > 0)))
91  term = (ubi < 0) ? (ubi * ubi) : (lbi > 0) ? (lbi * lbi) : 0.; //min{xi^2: xi in [lbi,ubi]
92  else
93  if ((term = CoinMax (lbi*lbi, ubi*ubi)) > COUENNE_INFINITY)
94  return (sign < 0) ? -COUENNE_INFINITY : COUENNE_INFINITY;
95 
96  term *= coe;
97 
98 #ifdef DEBUG
99  printf ("Qii %d %g %g -> %g\n", xind, coe, term, bound + term);
100 #endif
101  } else {
102 
103  coe *= 2;
104 
105  CouNumber
106  lbj = col -> first -> lb (),
107  ubj = col -> first -> ub (),
108  b1 = coe * lbi * lbj,
109  b2 = coe * lbi * ubj,
110  b3 = coe * ubi * lbj,
111  b4 = coe * ubi * ubj;
112 
113  if (fabs (lbi) == 0) b1 = b2 = 0;
114  if (fabs (lbj) == 0) b1 = b3 = 0;
115  if (fabs (ubi) == 0) b3 = b4 = 0;
116  if (fabs (ubj) == 0) b2 = b4 = 0;
117 
118  if (sign < 0) {
119  if ((term = CoinMin (CoinMin (b1, b2), CoinMin (b3, b4))) < -COUENNE_INFINITY)
120  return -COUENNE_INFINITY;
121  } else
122  if ((term = CoinMax (CoinMax (b1, b2), CoinMax (b3, b4))) > COUENNE_INFINITY)
123  return COUENNE_INFINITY;
124 
125 #ifdef DEBUG
126  printf ("Qij %d %d %g %g -> %g\n", xind, yind, coe, term, bound + term);
127 #endif
128  }
129 
130  // if ((i!=j) || (lbi >= 0) || (ubi <= 0))
131  bound += term;
132  }
133  }
134 
135  return bound;
136 }
CouNumber c0_
constant term
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
Bigint * b1
Definition: OSdtoa.cpp:1708
lincoeff lcoeff_
coefficients and indices of the linear term
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
CouNumber computeQBound(int sign)
method to compute the bound based on sign: -1 for lower, +1 for upper
Definition: exprBQuad.cpp:18