00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _H_CHOLESKY_HPP_
00024 #define _H_CHOLESKY_HPP_
00025
00026
00027 #include <cassert>
00028
00029 #include <boost/numeric/ublas/vector.hpp>
00030 #include <boost/numeric/ublas/vector_proxy.hpp>
00031
00032 #include <boost/numeric/ublas/matrix.hpp>
00033 #include <boost/numeric/ublas/matrix_proxy.hpp>
00034
00035 #include <boost/numeric/ublas/vector_expression.hpp>
00036 #include <boost/numeric/ublas/matrix_expression.hpp>
00037
00038 #include <boost/numeric/ublas/triangular.hpp>
00039
00040 namespace ublas = boost::numeric::ublas;
00041
00042
00051 template < class MATRIX, class TRIA >
00052 size_t cholesky_decompose(const MATRIX& A, TRIA& L)
00053 {
00054 using namespace ublas;
00055
00056 typedef typename MATRIX::value_type T;
00057
00058 assert( A.size1() == A.size2() );
00059 assert( A.size1() == L.size1() );
00060 assert( A.size2() == L.size2() );
00061
00062 const size_t n = A.size1();
00063
00064 for (size_t k=0 ; k < n; k++) {
00065
00066 double qL_kk = A(k,k) - inner_prod( project( row(L, k), range(0, k) ),
00067 project( row(L, k), range(0, k) ) );
00068
00069 if (qL_kk <= 0) {
00070 return 1 + k;
00071 } else {
00072 double L_kk = sqrt( qL_kk );
00073 L(k,k) = L_kk;
00074
00075 matrix_column<TRIA> cLk(L, k);
00076 project( cLk, range(k+1, n) )
00077 = ( project( column(A, k), range(k+1, n) )
00078 - prod( project(L, range(k+1, n), range(0, k)),
00079 project(row(L, k), range(0, k) ) ) ) / L_kk;
00080 }
00081 }
00082 return 0;
00083 }
00084
00085
00093 template < class MATRIX >
00094 size_t cholesky_decompose(MATRIX& A)
00095 {
00096 using namespace ublas;
00097
00098 typedef typename MATRIX::value_type T;
00099
00100 const MATRIX& A_c(A);
00101
00102 const size_t n = A.size1();
00103
00104 for (size_t k=0 ; k < n; k++) {
00105
00106 double qL_kk = A_c(k,k) - inner_prod( project( row(A_c, k), range(0, k) ),
00107 project( row(A_c, k), range(0, k) ) );
00108
00109 if (qL_kk <= 0) {
00110 return 1 + k;
00111 } else {
00112 double L_kk = sqrt( qL_kk );
00113
00114 matrix_column<MATRIX> cLk(A, k);
00115 project( cLk, range(k+1, n) )
00116 = ( project( column(A_c, k), range(k+1, n) )
00117 - prod( project(A_c, range(k+1, n), range(0, k)),
00118 project(row(A_c, k), range(0, k) ) ) ) / L_kk;
00119 A(k,k) = L_kk;
00120 }
00121 }
00122 return 0;
00123 }
00124
00125 #if 0
00126 using namespace ublas;
00127
00128
00129
00130
00131
00132
00133 template<class E1, class E2>
00134 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
00135 lower_tag, column_major_tag) {
00136 std::cout << " is_lc ";
00137 typedef typename E2::size_type size_type;
00138 typedef typename E2::difference_type difference_type;
00139 typedef typename E2::value_type value_type;
00140
00141 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
00142 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
00143 size_type size = e2 ().size ();
00144 for (size_type n = 0; n < size; ++ n) {
00145 #ifndef BOOST_UBLAS_SINGULAR_CHECK
00146 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type(), singular ());
00147 #else
00148 if (e1 () (n, n) == value_type())
00149 singular ().raise ();
00150 #endif
00151 value_type t = e2 () (n) / e1 () (n, n);
00152 e2 () (n) = t;
00153 if (t != value_type()) {
00154 project( e2 (), range(n+1, size) )
00155 .minus_assign( t * project( column( e1 (), n), range(n+1, size) ) );
00156 }
00157 }
00158 }
00159 #endif
00160
00161
00169 template < class MATRIX >
00170 size_t incomplete_cholesky_decompose(MATRIX& A)
00171 {
00172 using namespace ublas;
00173
00174 typedef typename MATRIX::value_type T;
00175
00176
00177 const MATRIX& A_c(A);
00178
00179 const size_t n = A.size1();
00180
00181 for (size_t k=0 ; k < n; k++) {
00182
00183 double qL_kk = A_c(k,k) - inner_prod( project( row( A_c, k ), range(0, k) ),
00184 project( row( A_c, k ), range(0, k) ) );
00185
00186 if (qL_kk <= 0) {
00187 return 1 + k;
00188 } else {
00189 double L_kk = sqrt( qL_kk );
00190
00191
00192 for (size_t i = k+1; i < A.size1(); ++i) {
00193 T* Aik = A.find_element(i, k);
00194
00195 if (Aik != 0) {
00196 *Aik = ( *Aik - inner_prod( project( row( A_c, k ), range(0, k) ),
00197 project( row( A_c, i ), range(0, k) ) ) ) / L_kk;
00198 }
00199 }
00200
00201 A(k,k) = L_kk;
00202 }
00203 }
00204
00205 return 0;
00206 }
00207
00208
00214 template < class TRIA, class VEC >
00215 void cholesky_solve(const TRIA& L, VEC& x, ublas::lower)
00216 {
00217 using namespace ublas;
00218
00219 inplace_solve(L, x, lower_tag() );
00220 inplace_solve(trans(L), x, upper_tag());
00221 }
00222
00223
00229 template< class MATRIX >
00230 void cholesky_invert (MATRIX &M)
00231 {
00232 using namespace ublas;
00233 typedef typename MATRIX::size_type size_type;
00234 typedef typename MATRIX::value_type value_type;
00235
00236 size_type size = M.size1();
00237
00238
00239 for (size_type i = 0; i < size; ++ i) {
00240 M(i,i) = 1 / M(i,i);
00241
00242 for (size_type j = i+1; j < size; ++ j) {
00243 value_type elem(0);
00244
00245 for (size_type k = i; k < j; ++ k) {
00246 elem -= M(j,k)*M(k,i);
00247 }
00248 M(j,i) = elem / M(j,j);
00249 }
00250 }
00251
00252
00253 M = prod(trans(triangular_adaptor<MATRIX,lower>(M)), triangular_adaptor<MATRIX,lower>(M));
00254 }
00255
00256 #endif