vrcore  0.45
visuReal Messkern
 All Classes Files Functions Variables
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  - email : guwi17@gmx.de
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 */
22 
23 #ifndef _H_CHOLESKY_HPP_
24 #define _H_CHOLESKY_HPP_
25 
26 #include <cassert>
27 
28 #include <boost/numeric/ublas/vector.hpp>
29 #include <boost/numeric/ublas/vector_proxy.hpp>
30 
31 #include <boost/numeric/ublas/matrix.hpp>
32 #include <boost/numeric/ublas/matrix_proxy.hpp>
33 
34 #include <boost/numeric/ublas/vector_expression.hpp>
35 #include <boost/numeric/ublas/matrix_expression.hpp>
36 
37 #include <boost/numeric/ublas/triangular.hpp>
38 
39 namespace ublas = boost::numeric::ublas;
40 
41 
50 template < class MATRIX, class TRIA >
51 size_t cholesky_decompose(const MATRIX& A, TRIA& L)
52 {
53  using namespace ublas;
54 
55  typedef typename MATRIX::value_type T;
56 
57  assert( A.size1() == A.size2() );
58  assert( A.size1() == L.size1() );
59  assert( A.size2() == L.size2() );
60 
61  const size_t n = A.size1();
62 
63  for (size_t k=0 ; k < n; k++) {
64 
65  double qL_kk = A(k,k) - inner_prod( project( row(L, k), range(0, k) ),
66  project( row(L, k), range(0, k) ) );
67 
68  if (qL_kk <= 0) {
69  return 1 + k;
70  } else {
71  double L_kk = sqrt( qL_kk );
72  L(k,k) = L_kk;
73 
74  matrix_column<TRIA> cLk(L, k);
75  project( cLk, range(k+1, n) )
76  = ( project( column(A, k), range(k+1, n) )
77  - prod( project(L, range(k+1, n), range(0, k)),
78  project(row(L, k), range(0, k) ) ) ) / L_kk;
79  }
80  }
81  return 0;
82 }
83 
84 
92 template < class MATRIX >
93 size_t cholesky_decompose(MATRIX& A)
94 {
95  using namespace ublas;
96 
97  typedef typename MATRIX::value_type T;
98 
99  const MATRIX& A_c(A);
100 
101  const size_t n = A.size1();
102 
103  for (size_t k=0 ; k < n; k++) {
104 
105  double qL_kk = A_c(k,k) - inner_prod( project( row(A_c, k), range(0, k) ),
106  project( row(A_c, k), range(0, k) ) );
107 
108  if (qL_kk <= 0) {
109  return 1 + k;
110  } else {
111  double L_kk = sqrt( qL_kk );
112 
113  matrix_column<MATRIX> cLk(A, k);
114  project( cLk, range(k+1, n) )
115  = ( project( column(A_c, k), range(k+1, n) )
116  - prod( project(A_c, range(k+1, n), range(0, k)),
117  project(row(A_c, k), range(0, k) ) ) ) / L_kk;
118  A(k,k) = L_kk;
119  }
120  }
121  return 0;
122 }
123 
124 #if 0
125  using namespace ublas;
126 
127  // Operations:
128  // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
129  // n * (n - 1) / 2 additions
130 
131  // Dense (proxy) case
132  template<class E1, class E2>
133  void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
134  lower_tag, column_major_tag) {
135  std::cout << " is_lc ";
136  typedef typename E2::size_type size_type;
137  typedef typename E2::difference_type difference_type;
138  typedef typename E2::value_type value_type;
139 
140  BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
141  BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
142  size_type size = e2 ().size ();
143  for (size_type n = 0; n < size; ++ n) {
144 #ifndef BOOST_UBLAS_SINGULAR_CHECK
145  BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
146 #else
147  if (e1 () (n, n) == value_type/*zero*/())
148  singular ().raise ();
149 #endif
150  value_type t = e2 () (n) / e1 () (n, n);
151  e2 () (n) = t;
152  if (t != value_type/*zero*/()) {
153  project( e2 (), range(n+1, size) )
154  .minus_assign( t * project( column( e1 (), n), range(n+1, size) ) );
155  }
156  }
157  }
158 #endif
159 
160 
161 
162 
163 
171 template < class MATRIX >
173 {
174  using namespace ublas;
175 
176  typedef typename MATRIX::value_type T;
177 
178  // read access to a const matrix is faster
179  const MATRIX& A_c(A);
180 
181  const size_t n = A.size1();
182 
183  for (size_t k=0 ; k < n; k++) {
184 
185  double qL_kk = A_c(k,k) - inner_prod( project( row( A_c, k ), range(0, k) ),
186  project( row( A_c, k ), range(0, k) ) );
187 
188  if (qL_kk <= 0) {
189  return 1 + k;
190  } else {
191  double L_kk = sqrt( qL_kk );
192 
193  // aktualisieren
194  for (size_t i = k+1; i < A.size1(); ++i) {
195  T* Aik = A.find_element(i, k);
196 
197  if (Aik != 0) {
198  *Aik = ( *Aik - inner_prod( project( row( A_c, k ), range(0, k) ),
199  project( row( A_c, i ), range(0, k) ) ) ) / L_kk;
200  }
201  }
202 
203  A(k,k) = L_kk;
204  }
205  }
206 
207  return 0;
208 }
209 
210 
211 
212 
218 template < class TRIA, class VEC >
219 void
220 cholesky_solve(const TRIA& L, VEC& x, ublas::lower)
221 {
222  using namespace ublas;
223 // ::inplace_solve(L, x, lower_tag(), typename TRIA::orientation_category () );
224  inplace_solve(L, x, lower_tag() );
225  inplace_solve(trans(L), x, upper_tag());
226 }
227 
228 
229 #endif
size_t cholesky_decompose(const MATRIX &A, TRIA &L)
decompose the symmetric positive definit matrix A into product L L^T.
Definition: cholesky.hpp:51
void cholesky_solve(const TRIA &L, VEC &x, ublas::lower)
solve system L L^T x = b inplace
Definition: cholesky.hpp:220
size_t incomplete_cholesky_decompose(MATRIX &A)
decompose the symmetric positive definit matrix A into product L L^T.
Definition: cholesky.hpp:172