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
00162
00163
00164
00172 template < class MATRIX >
00173 size_t incomplete_cholesky_decompose(MATRIX& A)
00174 {
00175 using namespace ublas;
00176
00177 typedef typename MATRIX::value_type T;
00178
00179
00180 const MATRIX& A_c(A);
00181
00182 const size_t n = A.size1();
00183
00184 for (size_t k=0 ; k < n; k++) {
00185
00186 double qL_kk = A_c(k,k) - inner_prod( project( row( A_c, k ), range(0, k) ),
00187 project( row( A_c, k ), range(0, k) ) );
00188
00189 if (qL_kk <= 0) {
00190 return 1 + k;
00191 } else {
00192 double L_kk = sqrt( qL_kk );
00193
00194
00195 for (size_t i = k+1; i < A.size1(); ++i) {
00196 T* Aik = A.find_element(i, k);
00197
00198 if (Aik != 0) {
00199 *Aik = ( *Aik - inner_prod( project( row( A_c, k ), range(0, k) ),
00200 project( row( A_c, i ), range(0, k) ) ) ) / L_kk;
00201 }
00202 }
00203
00204 A(k,k) = L_kk;
00205 }
00206 }
00207
00208 return 0;
00209 }
00210
00211
00212
00213
00219 template < class TRIA, class VEC >
00220 void
00221 cholesky_solve(const TRIA& L, VEC& x, ublas::lower)
00222 {
00223 using namespace ublas;
00224
00225 inplace_solve(L, x, lower_tag() );
00226 inplace_solve(trans(L), x, upper_tag());
00227 }
00228
00229
00230 #endif