00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _SINGULAR_DECOMPOSITION_H
00020 #define _SINGULAR_DECOMPOSITION_H
00021
00022 #include <lsp/bidiagonal_transform.h>
00023 #include <lsp/qr_decomposition.h>
00024 #include <lsp/utils.h>
00025
00026 #include <boost/numeric/ublas/vector.hpp>
00027 #include <boost/numeric/ublas/matrix.hpp>
00028 #include <boost/numeric/ublas/matrix_proxy.hpp>
00029 #include <boost/numeric/ublas/banded.hpp>
00030
00031 using namespace boost::numeric::ublas;
00032
00033 namespace lsp{
00034
00053 template<class T> class singular_decomposition {
00054 public:
00055 typedef T matrix_type;
00056 typedef typename matrix_type::value_type value_type;
00057 typedef typename matrix_type::size_type size_type;
00058 typedef banded_adaptor< matrix_type > banded_adaptor_type;
00059 typedef bidiagonal_transform< matrix_type > bidiagonal_transform_type;
00060 typedef qr_decomposition< banded_adaptor_type > qr_decomposition_type;
00061 private:
00062 matrix_type& m_matrix;
00063 mutable bidiagonal_transform_type m_bd_trans;
00064 mutable banded_adaptor_type m_banded;
00065 mutable qr_decomposition_type m_qr_decomp;
00066 public:
00074 singular_decomposition( matrix_type& matrix ):
00075 m_matrix( matrix ),
00076 m_bd_trans( matrix ),
00077 m_banded(matrix, 0, 1),
00078 m_qr_decomp( m_banded )
00079 {
00080
00081 }
00082
00098 template<class M1, class M2> void apply( M1& left, M2& right ) const {
00099 typedef matrix_vector_slice< matrix_type > diagonal_type;
00100 typedef vector< size_type > permutation_type;
00101
00102 m_bd_trans.apply( left, right );
00103
00104 value_type lim = norm_frobenius( m_banded ) * m_bd_trans.matrix_error();
00105 for( typename banded_adaptor_type::iterator1 it1 = m_banded.begin1(); it1 != m_banded.end1(); ++it1){
00106 for( typename banded_adaptor_type::iterator2 it2 = it1.begin(); it2 != it1.end(); ++it2){
00107 if( std::abs(*it2) < lim )
00108 *it2 = 0;
00109 }
00110 }
00111
00112 m_qr_decomp.apply( left, right );
00113
00114 diagonal_type singular( m_matrix,
00115 slice(0, 1, std::min( m_banded.size1(), m_banded.size2() )),
00116 slice(0, 1, std::min( m_banded.size1(), m_banded.size2() )) );
00117 for( typename diagonal_type::iterator it = singular.begin(); it != singular.end(); ++it ){
00118 if( *it < 0 ){
00119 *it = -(*it);
00120 column( right, it.index() ) = -column( right, it.index() );
00121 }
00122 }
00123
00124 permutation_type pm( singular.size() );
00125 for( typename permutation_type::iterator it = pm.begin(); it != pm.end(); ++it ){
00126 *it = it.index();
00127 }
00128
00129 std::sort( pm.begin(), pm.end(), vector_less< diagonal_type, std::greater< typename diagonal_type::value_type > >( singular ) );
00130
00131 for( typename permutation_type::size_type it = 0; it != pm.size(); ++it ){
00132 if( it < pm(it) ) {
00133 row(m_matrix, pm(it)).swap( row(m_matrix, it) );
00134 row(left, pm(it)).swap( row(left, it) );
00135
00136 column(m_matrix, pm(it)).swap( column(m_matrix, it) );
00137 column(right, pm(it)).swap( column(right, it) );
00138 }
00139 }
00140
00141 }
00142 };
00143
00144 };
00145
00146 #endif // _SINGULAR_DECOMPOSITION_H