alphaConvexify.cpp
Go to the documentation of this file.
1 /* $Id: alphaConvexify.cpp 490 2011-01-14 16:07:12Z pbelotti $
2  *
3  * Name: alphaConvexify.cpp
4  * Author: Stefan Vigerske
5  * Purpose: create alpha-convexification of a quadratic expression
6  *
7  * (C) Carnegie-Mellon University, 2007-09.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 
12 #include "CoinHelperFunctions.hpp"
13 #include "OsiSolverInterface.hpp"
14 #include "IpLapack.hpp"
15 
16 #include "CouenneExprQuad.hpp"
17 #include "CouenneProblem.hpp"
18 
19 using namespace Couenne;
20 
21 //#define DEBUG
22 
44  //const OsiSolverInterface &si) {
45 
46  if (matrix_.size () == 0)
47  return false;
48 
49  // inverse of dIndex_ mapping: for each variable tell me the index
50  // that it will have in dIndex_, or -1 if not there
51 
52  int k=0,
53  nDiag = bounds_.size (),
54  *indexmap = new int [p -> nVars ()],
55  *indices = new int [nDiag];
56 
57  //CoinFillN (indexmap, si.getNumCols (), -1);
58  CoinFillN (indexmap, p -> nVars (), -1);
59 
60  // box diameter
61  double *diam = new double [nDiag];
62 
63  bool changed_bounds = false;
64 
65  for (std::map <exprVar *, std::pair <CouNumber, CouNumber> >::iterator i = bounds_.begin ();
66  i != bounds_.end (); ++i, k++) {
67 
68 #ifdef DEBUG
69  printf ("b%04d. [%20g, %20g]\n", i->first->Index(), i->second.first, i->second.second);
70 #endif
71 
72  int index = i -> first -> Index ();
73  indexmap [index] = k;
74  indices [k] = index;
75 
76  CouNumber
77  lb = i -> first -> lb (),
78  ub = i -> first -> ub ();
79 
80  // if one variable unbounded, bail out
81  if ((lb < -COUENNE_INFINITY) ||
82  (ub > COUENNE_INFINITY)) {
83 
84  delete [] diam;
85  delete [] indexmap;
86  delete [] indices;
87 
88 #ifdef DEBUG
89  printf ("unbounded, bailing out\n");
90 #endif
91 
92  return false;
93  }
94 
95  // if no variable has changed bounds, no need to convexify
96  if (fabs (lb - i->second.first) > COUENNE_EPS) {i -> second.first = lb; changed_bounds = true;}
97  if (fabs (ub - i->second.second) > COUENNE_EPS) {i -> second.second = ub; changed_bounds = true;}
98 
99  diam [k] = ub - lb;
100 #ifdef DEBUG
101  printf ("diam %4d - %4d = %g - %g = %g\n", index, k, ub, lb, diam [k]);
102 #endif
103  }
104 
105  if (!changed_bounds) {
106 
107  delete [] diam;
108  delete [] indexmap;
109  delete [] indices;
110 
111  return true;
112  }
113 
114  // lower triangular of quadratic term matrix, scaled by box diameter
115 
116  double *matrix = new double [nDiag * nDiag];
117 
118  CoinFillN (matrix, nDiag * nDiag, 0.);
119 
120  for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
121 
122  int
123  xind = row -> first -> Index (),
124  irow = indexmap [xind];
125 
126  for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
127 
128  int
129  yind = col -> first -> Index (),
130  icol = indexmap [yind];
131 
132  double cell = col -> second * diam [irow] * diam [icol];
133 
134  matrix [icol * nDiag + irow] = cell;
135  if (irow != icol)
136  matrix [irow * nDiag + icol] = cell;
137  }
138  }
139 
140  // compute value of matrix entry = q_ij * (u_i-l_i) * (u_j-l_j)
141  // I (Stefan) do not understand the Lapack docu; it says it needs
142  // only the lower triangular but it seem to need both parts to
143  // work correct
144 
145  delete [] indexmap;
146 
147  // compute minimum and maximum eigenvalue of matrix
148  double* eigval = new double [nDiag];
149  int info;
150 
151 #ifdef DEBUG
152  printf ("nDiag = %d\n", nDiag);
153  for (int i=0; i<nDiag; i++) {
154  for (int j=0; j<nDiag; j++)
155  printf ("%6.2f ", matrix [i*nDiag + j]);
156  printf ("\n");
157  }
158 #endif
159 
160  Ipopt::IpLapackDsyev (true, // compute eigenvector
161  nDiag, // dimension
162  matrix, // matrix
163  nDiag, // "leading dimension" (number of columns, I think)
164  eigval, // output vector to store eigenvalues
165  info); // output status variable
166 
167  if (info != 0) {
168  printf ("exprQuad::alphaConvexify, warning: problem computing eigenvalue, info=%d\n", info);
169  return false;
170  //TODO error handling
171  }
172 
173  // clean eigenvector structure
174  eigen_.erase (eigen_.begin (), eigen_.end ());
175 
176  for (int i=0; i<nDiag; i++) {
177 
178  std::pair <CouNumber, std::vector <std::pair <exprVar *, CouNumber> > > eigenCoord;
179 
180  eigenCoord. first = eigval [i];
181 
182  for (int j=0; j<nDiag; j++) {
183 
184  CouNumber elem = matrix [i * nDiag + j];
185 
186  if (fabs (elem) > COUENNE_EPS)
187  eigenCoord. second. push_back (std::pair <exprVar *, CouNumber>
188  (p -> Var (indices [j]), elem));
189  }
190 
191  eigen_.push_back (eigenCoord);
192  }
193 
194 #ifdef DEBUG
195  for (std::vector <std::pair <CouNumber,
196  std::vector <std::pair <exprVar *, CouNumber> > > >::iterator i = eigen_.begin ();
197  i != eigen_.end (); ++i) {
198  printf (" [%g] -- ", i -> first);
199  for (std::vector <std::pair <exprVar *, CouNumber> >::iterator j = i -> second. begin();
200  j != i -> second. end (); ++j)
201  printf ("(%d,%g) ", j -> first -> Index (), j -> second);
202  printf ("\n");
203  }
204 #endif
205 
206  delete [] indices;
207  delete [] matrix;
208  delete [] diam;
209  delete [] eigval;
210 
211  return true;
212 }
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
fint irow
static char * j
Definition: OSdtoa.cpp:3622
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
fint end
Class for MINLP problems with symbolic information.
void fint fint * k
std::vector< std::pair< CouNumber, std::vector< std::pair< exprVar *, CouNumber > > > > eigen_
eigenvalues and eigenvectors
#define COUENNE_EPS
std::map< exprVar *, std::pair< CouNumber, CouNumber > > bounds_
current bounds (checked before re-computing eigenvalues/vectors)
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
variable-type operator
virtual bool alphaConvexify(const CouenneProblem *)
Compute data for -convexification of a quadratic form (fills in dCoeff_ and dIndex_ for the convex un...