00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _LEAST_SQUARES_H
00020 #define _LEAST_SQUARES_H
00021
00022 #include <lsp/singular_decomposition.h>
00023 #include <lsp/utils.h>
00024
00025 #include <boost/numeric/ublas/vector.hpp>
00026 #include <boost/numeric/ublas/matrix.hpp>
00027
00028 using namespace boost::numeric::ublas;
00029
00030 namespace lsp {
00031
00041 template<class M, class V> class least_squares {
00042 public:
00043 typedef M matrix_type;
00044 typedef V vector_type;
00045 typedef typename matrix_type::value_type matrix_value_type;
00046 typedef typename matrix_type::size_type matrix_size_type;
00047 typedef typename vector_type::value_type vector_value_type;
00048 typedef typename vector_type::size_type vector_size_type;
00049 typedef matrix_value_type value_type;
00050 typedef matrix_size_type size_type;
00051 typedef singular_decomposition< matrix_type > singular_decomposition_type;
00052
00053 private:
00054 matrix_type& m_matrix;
00055 vector_type& m_vector;
00056 singular_decomposition_type m_svd;
00057 public:
00069 least_squares( matrix_type& matrix, vector_type& vector ):
00070 m_matrix( matrix ),
00071 m_vector( vector ),
00072 m_svd( m_matrix ) {
00073
00074 assert( vector.size() == matrix.size1() );
00075 }
00082 template<class sV, class sM> void solve( sV& ret, sM& cov ) const {
00083 typedef sV result_vector_type;
00084 typedef sM covariation_matrix_type;
00085 typedef banded_adaptor< covariation_matrix_type > diagonal_covariation_type;
00086 typedef matrix_vector_slice< matrix_type > diagonal_type;
00087 typedef matrix< value_type > unitary_marix_type;
00088
00089 unitary_marix_type left( identity_matrix< value_type > (m_matrix.size1()) );
00090 unitary_marix_type right( identity_matrix< value_type > (m_matrix.size2()) );
00091
00092 m_svd.apply(left, right);
00093
00094 m_vector = prod( left, m_vector );
00095
00096 diagonal_type singular( m_matrix,
00097 slice(0, 1, std::min( m_matrix.size1(), m_matrix.size2() )),
00098 slice(0, 1, std::min( m_matrix.size1(), m_matrix.size2() )) );
00099
00100 ret.resize( m_matrix.size2() );
00101
00102 diagonal_covariation_type dcov(cov,0,0);
00103 for( typename diagonal_type::iterator it = singular.begin(); it != singular.end(); ++it ){
00104 if( *it != 0 ) {
00105 ret( it.index() ) = m_vector( it.index() ) / (*it);
00106 dcov( it.index(), it.index() ) = value_type( 1 ) / ( (*it) * (*it) );
00107 } else {
00108 ret( it.index() ) = value_type( 0 );
00109 dcov( it.index(), it.index() ) = value_type( 0 );
00110 }
00111 }
00112
00113 cov = prod( dcov, trans(right) );
00114 cov = prod( right, cov );
00115
00116 ret = prod( right, ret );
00117 }
00118 template<class sV> void solve( sV& ret ) const {
00119 solve( ret, null_type::s_null );
00120 }
00121
00122 };
00123
00124 };
00125
00149 #endif // _LEAST_SQUARES_H