BayesOpt
ublas_cholesky.hpp
Go to the documentation of this file.
1 
2 /*
3  - begin : 2005-08-24
4  - copyright : (C) 2005 by Gunter Winkler, Konstantin Kutzkow
5  2011-2013 by Ruben Martinez-Cantin <rmcantin@unizar.es>
6  - email : guwi17@gmx.de
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 */
23 
24 #ifndef _H_CHOLESKY_HPP_
25 #define _H_CHOLESKY_HPP_
26 
27 
28 #include <cassert>
29 
30 #include <boost/numeric/ublas/vector.hpp>
31 #include <boost/numeric/ublas/vector_proxy.hpp>
32 
33 #include <boost/numeric/ublas/matrix.hpp>
34 #include <boost/numeric/ublas/matrix_proxy.hpp>
35 
36 #include <boost/numeric/ublas/vector_expression.hpp>
37 #include <boost/numeric/ublas/matrix_expression.hpp>
38 
39 #include <boost/numeric/ublas/triangular.hpp>
40 
41 namespace bayesopt
42 {
43  namespace utils
44  {
45  namespace ublas = boost::numeric::ublas;
46 
47 
56  template < class MATRIX, class TRIA >
57  size_t cholesky_decompose(const MATRIX& A, TRIA& L)
58  {
59  using namespace ublas;
60 
61  typedef typename MATRIX::value_type T;
62 
63  assert( A.size1() == A.size2() );
64  assert( A.size1() == L.size1() );
65  assert( A.size2() == L.size2() );
66 
67  const size_t n = A.size1();
68 
69  for (size_t k=0 ; k < n; k++) {
70 
71  double qL_kk = A(k,k) - inner_prod( project( row(L, k), range(0, k) ),
72  project( row(L, k), range(0, k) ) );
73 
74  if (qL_kk <= 0) {
75  return 1 + k;
76  } else {
77  double L_kk = sqrt( qL_kk );
78  L(k,k) = L_kk;
79 
80  matrix_column<TRIA> cLk(L, k);
81  project( cLk, range(k+1, n) )
82  = ( project( column(A, k), range(k+1, n) )
83  - prod( project(L, range(k+1, n), range(0, k)),
84  project(row(L, k), range(0, k) ) ) ) / L_kk;
85  }
86  }
87  return 0;
88  }
89 
90 
98  template < class MATRIX >
99  size_t cholesky_decompose(MATRIX& A)
100  {
101  using namespace ublas;
102  typedef typename MATRIX::value_type T;
103 
104  const MATRIX& A_c(A);
105 
106  const size_t n = A.size1();
107 
108  for (size_t k=0 ; k < n; k++) {
109 
110  double qL_kk = A_c(k,k) - inner_prod( project( row(A_c, k), range(0, k) ),
111  project( row(A_c, k), range(0, k) ) );
112 
113  if (qL_kk <= 0) {
114  return 1 + k;
115  } else {
116  double L_kk = sqrt( qL_kk );
117 
118  matrix_column<MATRIX> cLk(A, k);
119  project( cLk, range(k+1, n) )
120  = ( project( column(A_c, k), range(k+1, n) )
121  - prod( project(A_c, range(k+1, n), range(0, k)),
122  project(row(A_c, k), range(0, k) ) ) ) / L_kk;
123  A(k,k) = L_kk;
124  }
125  }
126  return 0;
127  }
128 
129 #if 0
130  using namespace ublas;
131 
132  // Operations:
133  // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
134  // n * (n - 1) / 2 additions
135 
136  // Dense (proxy) case
137  template<class E1, class E2>
138  void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
139  lower_tag, column_major_tag) {
140  std::cout << " is_lc ";
141  typedef typename E2::size_type size_type;
142  typedef typename E2::difference_type difference_type;
143  typedef typename E2::value_type value_type;
144 
145  BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
146  BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
147  size_type size = e2 ().size ();
148  for (size_type n = 0; n < size; ++ n) {
149 #ifndef BOOST_UBLAS_SINGULAR_CHECK
150  BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
151 #else
152  if (e1 () (n, n) == value_type/*zero*/())
153  singular ().raise ();
154 #endif
155  value_type t = e2 () (n) / e1 () (n, n);
156  e2 () (n) = t;
157  if (t != value_type/*zero*/()) {
158  project( e2 (), range(n+1, size) )
159  .minus_assign( t * project( column( e1 (), n), range(n+1, size) ) );
160  }
161  }
162  }
163 #endif
164 
165 
166 
174  template < class MATRIX >
176  {
177  using namespace ublas;
178 
179  typedef typename MATRIX::value_type T;
180 
181  // read access to a const matrix is faster
182  const MATRIX& A_c(A);
183 
184  const size_t n = A.size1();
185 
186  for (size_t k=0 ; k < n; k++) {
187 
188  double qL_kk = A_c(k,k) - inner_prod( project( row( A_c, k ), range(0, k) ),
189  project( row( A_c, k ), range(0, k) ) );
190 
191  if (qL_kk <= 0) {
192  return 1 + k;
193  } else {
194  double L_kk = sqrt( qL_kk );
195 
196  // aktualisieren
197  for (size_t i = k+1; i < A.size1(); ++i) {
198  T* Aik = A.find_element(i, k);
199 
200  if (Aik != 0) {
201  *Aik = ( *Aik - inner_prod( project( row( A_c, k ), range(0, k) ),
202  project( row( A_c, i ), range(0, k) ) ) ) / L_kk;
203  }
204  }
205 
206  A(k,k) = L_kk;
207  }
208  }
209 
210  return 0;
211  }
212 
213 
214 
220  template < class TRIA, class MATRIX >
221  void
222  cholesky_solve(const TRIA& L, MATRIX& x, ublas::lower)
223  {
224  using namespace ublas;
225  // ::inplace_solve(L, x, lower_tag(), typename TRIA::orientation_category () );
226  inplace_solve(L, x, lower_tag() );
227  inplace_solve(trans(L), x, upper_tag());
228  }
229 
230  /****** Added by Ruben Martinez-Cantin. 2011 ***********/
231 
238  template < class Min, class Mout >
239  size_t
240  inverse_cholesky(const Min& M, Mout& inverse)
241  {
242  typedef typename Mout::value_type value_type;
243 
244  size_t size = M.size1();
245  Min L(size,size);
246  size_t res = cholesky_decompose(M, L);
247 
248  if (res != 0) return res;
249 
250  inverse.assign(ublas::identity_matrix<value_type>(size));
251  cholesky_solve(L,inverse,ublas::lower());
252 
253  return 0;
254  }
255 
263  template < class TRIA, class VECTOR >
264  void cholesky_add_row(TRIA& L, const VECTOR& v)
265  {
266  using namespace ublas;
267  typedef typename TRIA::value_type T;
268 
269  assert( L.size1() == L.size2() );
270  assert( L.size1()+1 == v.size() );
271 
272  const size_t n = v.size();
273 
274  L.resize(n,n);
275  double L_j;
276 
277  for (size_t j = 0; j < n-1; ++j)
278  {
279  L_j = v(j) - inner_prod(project (row(L, j), range(0,j)),
280  project (row(L,n-1), range(0,j)));
281  L(n-1,j) = (L_j) / L(j,j);
282  }
283  L_j = v(n-1) - inner_prod(project (row(L, n-1), range(0,n-1)),
284  project (row(L,n-1), range(0,n-1)));
285  L(n-1,n-1) = sqrt(L_j);
286  return;
287  }
288 
289  } //namespace utils
290 
291 } // namespace bayesopt
292 
293 #endif
void cholesky_add_row(TRIA &L, const VECTOR &v)
decompose the symmetric positive definit matrix A into product L L^T.
Namespace of the library interface.
Definition: using.dox:1
size_t cholesky_decompose(const MATRIX &A, TRIA &L)
decompose the symmetric positive definit matrix A into product L L^T.
void cholesky_solve(const TRIA &L, MATRIX &x, ublas::lower)
solve system L L^T x = b inplace
size_t incomplete_cholesky_decompose(MATRIX &A)
decompose the symmetric positive definit matrix A into product L L^T.
size_t inverse_cholesky(const Min &M, Mout &inverse)
Computes the inverse matrix of a symmetric positive definite matrix.