Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
cholesky.hpp
Go to the documentation of this file.
00001 
00002 /*
00003  -   begin                : 2005-08-24
00004  -   copyright            : (C) 2005 by Gunter Winkler, Konstantin Kutzkow
00005  -   email                : guwi17@gmx.de
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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     // Operations:
00129     //  n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
00130     //  n * (n - 1) / 2 additions
00131 
00132     // Dense (proxy) case
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/*zero*/(), singular ());
00147 #else
00148             if (e1 () (n, n) == value_type/*zero*/())
00149                 singular ().raise ();
00150 #endif
00151             value_type t = e2 () (n) / e1 () (n, n);
00152             e2 () (n) = t;
00153             if (t != value_type/*zero*/()) {
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   // read access to a const matrix is faster
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       // refresh
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 //   ::inplace_solve(L, x, lower_tag(), typename TRIA::orientation_category () );
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   // determine the inverse of the lower traingular matrix
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   // multiply the upper and lower inverses together
00253   M = prod(trans(triangular_adaptor<MATRIX,lower>(M)), triangular_adaptor<MATRIX,lower>(M));
00254 } 
00255 
00256 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:21 for Jafar by doxygen 1.7.6.1
LAAS-CNRS