Changeset 227
- Timestamp:
- Feb 1, 2005, 1:52:27 AM (18 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/PCA.cc
r189 r227 35 35 // Single value decompose the data matrix 36 36 std::auto_ptr<cpptools::SVD> pSVD( new cpptools::SVD( A_center ) ); 37 pSVD-> process();38 gslapi::matrix U = pSVD-> get_u();39 gslapi::matrix V = pSVD-> get_v();37 pSVD->decompose(); 38 gslapi::matrix U = pSVD->U(); 39 gslapi::matrix V = pSVD->V(); 40 40 41 41 // Read the eigenvectors and eigenvalues 42 42 eigenvectors_ = U.transpose(); 43 eigenvalues_ = pSVD-> get_s_vec();43 eigenvalues_ = pSVD->s(); 44 44 45 45 // T … … 83 83 // Single value decompose the data matrix 84 84 std::auto_ptr<cpptools::SVD> pSVD( new cpptools::SVD( A_center ) ); 85 pSVD-> process();86 gslapi::matrix U = pSVD-> get_u();87 gslapi::matrix V = pSVD-> get_v();85 pSVD->decompose(); 86 gslapi::matrix U = pSVD->U(); 87 gslapi::matrix V = pSVD->V(); 88 88 89 89 // Read the eigenvectors and eigenvalues 90 90 eigenvectors_ = V.transpose();//U.transpose(); 91 eigenvalues_ = pSVD-> get_s_vec();91 eigenvalues_ = pSVD->s(); 92 92 93 93 // Transform back when done with SVD! -
trunk/src/SVD.cc
r42 r227 1 1 // $Id$ 2 3 #include <cstdlib>4 #include <cmath>5 #include <iostream>6 7 #include <gsl/gsl_linalg.h>8 2 9 3 #include "SVD.h" … … 11 5 12 6 namespace theplu { 13 namespace cpptools { 14 15 //Constructor that can only be used for test-method 16 SVD::SVD() : loaded_( false ), solver_( false ) 17 {} 18 19 //Constructor initializing the svd object with matrix A to be decomposed 20 SVD::SVD( const gslapi::matrix& Ain ) : A_( Ain ) 21 { 22 //Get dimensions 23 //////////////// 24 size_t n = Ain.columns(); 25 26 //Instantiate matrix with correct dimenstions 27 //and assign all elements the value zero 28 ///////////////////////////////////////////// 29 V_ = gslapi::matrix( n, n, true ); 30 31 //Assign vector s_ with correct dimenstion 32 ///////////////////////////////////////////////// 33 s_ = gslapi::vector( n ); 34 35 loaded_ = true; 36 solver_ = false; 37 } 7 namespace cpptools { 38 8 39 9 40 //Constructor initializing the svd object for Solver 41 //Solver requires an extra-vector b: 42 //Ax = b 43 //The x vector will be reached using the get_x() function. 44 SVD::SVD( const gslapi::matrix& Ain, const gslapi::vector& b ) : A_( Ain ), b_( b ) 45 { 46 //Get dimensions 47 //////////////// 48 size_t n = Ain.columns(); 49 50 //Instantiate matrix with correct dimenstions 51 //and assign all elements the value zero 52 ///////////////////////////////////////////// 53 V_ = gslapi::matrix( n, n, true ); 54 55 56 //Assign vector s_ with correct dimenstion 57 ///////////////////////////////////////////////// 58 s_ = gslapi::vector( n ); 59 60 61 //An extra vector holding the answer to equation Ax = b is required 62 /////////////////////////////////////////////////////////////////// 63 x_ = gslapi::vector( n ); 64 65 66 //Also set solver to true 67 ///////////////////////// 68 solver_ = true; 69 loaded_ = true; 70 } 71 72 73 //Destructor 74 SVD::~SVD() 75 { 76 } 10 SVD::SVD(const gslapi::matrix& Ain) 11 : U_(Ain), V_(Ain.columns(),Ain.columns()), s_(Ain.columns()) 12 { 13 } 77 14 78 15 79 16 80 double SVD::norm(gslapi::matrix& A) const 81 { 82 double sum=0.0; 83 for (size_t i=0; i<A.rows(); ++i) 84 for (size_t j=0; j<A.columns(); ++j) 85 sum += A(i,j)*A(i,j); 86 return sqrt(sum); 87 } 17 SVD::~SVD(void) 18 { 19 } 88 20 89 21 90 22 91 //Method to process calculation 92 bool SVD::process( SVDtypes stype ) 93 { 94 if( !loaded_ ) 95 { 96 std::cerr << "Use proper constructor, matrix A not loaded!\n"; 97 return false; 23 int SVD::decompose(SVDalgorithm algo) 24 { 25 switch (algo) { 26 case GolubReinsch: 27 return golub_reinsch(); 28 case ModifiedGolubReinsch: 29 return modified_golub_reinsch(); 30 case Jacobi: 31 return jacobi(); 98 32 } 99 100 switch( stype ) 101 { 102 103 case Unmodified: 104 if( !process_default() ) exit( -1 ); 105 break; 106 107 case Modified: 108 if( !process_modified() ) exit( -1 ); 109 break; 110 111 case Jacobi: 112 if( !process_jacobi() ) exit( -1 ); 113 break; 114 115 case Solver: 116 if( !process_solver() ) exit( -1 ); 117 break; 118 119 default: 120 std::cerr << "Programmer try to use method not implemented!\n"; 121 return false; 122 break; 123 124 } 125 return true; 126 } 127 128 129 //Default-method for SVD 130 bool SVD::process_default() 131 { 132 //Perform SVD using GSL library 133 //An additional workvector is 134 //required here 135 /////////////////////////////// 136 gslapi::vector w( A_.columns() ); 137 if( gsl_linalg_SV_decomp( A_.gsl_matrix_pointer(), V_.gsl_matrix_pointer(), 138 s_.gsl_vector_pointer(), w.gsl_vector_pointer() 139 ) != 0 ) 140 { 141 std::cerr << "failed to run gsl_linalg_SV_decomp!\n"; 142 return false; 143 } 144 145 return true; 146 } 147 148 149 //Modified SVD method 150 //This method is faster when M>>N 151 bool SVD::process_modified() 152 { 153 //Perform SVD using GSL library 154 //An additional workmatrix X is 155 //required here 156 /////////////////////////////// 157 size_t n = A_.rows(); 158 gslapi::vector w( n ); 159 gslapi::matrix X( n, n, true ); 160 161 if( gsl_linalg_SV_decomp_mod( A_.gsl_matrix_pointer(), X.gsl_matrix_pointer(), 162 V_.gsl_matrix_pointer(), s_.gsl_vector_pointer(), 163 w.gsl_vector_pointer() 164 ) != 0 ) 165 { 166 std::cerr << "failed to run gsl_linalg_SV_decomp_mod!\n"; 167 return false; 168 } 169 170 return true; 171 } 172 173 174 //Default-method for SVD 175 //Computes singular values to higer 176 //accuracy 177 bool SVD::process_jacobi() 178 { 179 //Perform SVD using GSL library 180 /////////////////////////////// 181 if( gsl_linalg_SV_decomp_jacobi( A_.gsl_matrix_pointer(), V_.gsl_matrix_pointer(), 182 s_.gsl_vector_pointer() 183 ) != 0 ) 184 { 185 std::cerr << "failed to run gsl_linalg_SV_decomp_jacobi!\n"; 186 return false; 187 } 188 189 return true; 190 } 191 192 193 //Solver solves the system Ax=b 194 //using SVD (process_default). 195 bool SVD::process_solver() 196 { 197 //Perform SVD using GSL library 198 /////////////////////////////// 199 this->process_default(); 200 201 //Solve ... 202 if( gsl_linalg_SV_solve( A_.gsl_matrix_pointer(), V_.gsl_matrix_pointer(), 203 s_.gsl_vector_pointer(), b_.gsl_vector_pointer(), 204 x_.gsl_vector_pointer() 205 ) != 0 ) 206 { 207 std::cerr << "failed to run gsl_linalg_SV_solve!\n"; 208 return false; 209 } 210 211 212 return true; 213 } 33 // the program should never end up here, return values should be 34 // something different from normal GSL return values, or maybe 35 // throw an exception. 36 return 0; 37 } 214 38 215 39 216 40 217 //This method will create a diagonal matrix of vector s_ 218 gslapi::matrix SVD::get_s() const 219 { 220 size_t n = A_.rows(); 221 222 gslapi::matrix S( n, n, true ); 223 224 for( size_t i = 0; i < n; ++i ) 225 S(i,i)= s_(i); 226 227 return S; 228 } 229 230 //This function will run the SVD function and print 231 //matrices in matlab format so that you can verify 232 //the answer. 233 bool SVD::test() 234 { 235 using namespace std; 41 int SVD::golub_reinsch(void) 42 { 43 gslapi::vector w(U_.columns()); 44 return gsl_linalg_SV_decomp(U_.gsl_matrix_pointer(), 45 V_.gsl_matrix_pointer(), 46 s_.TEMP_gsl_vector_pointer(), 47 w.TEMP_gsl_vector_pointer()); 48 } 236 49 237 50 238 //Initialize GNU random stuff239 ///////////////////////////////////240 srand( time( 0 ) );241 51 242 243 //Initialise random test-matrix 244 /////////////////////////////// 245 const size_t DIM = 3; 246 gslapi::matrix A( DIM, DIM ); 247 for( size_t i = 0; i < DIM; ++i ) 248 { 249 for( size_t j = 0; j < DIM; ++j ) 250 { 251 // Jari, change below random numbers to proper RNG 252 A(i,j)= 10 * (double) rand() / RAND_MAX; //Use random numbers between 0 and 10 253 } 254 } 52 int SVD::modified_golub_reinsch(void) 53 { 54 gslapi::vector w(U_.columns()); 55 gslapi::matrix X(U_.columns(),U_.columns()); 56 return gsl_linalg_SV_decomp_mod(U_.gsl_matrix_pointer(), 57 X.gsl_matrix_pointer(), 58 V_.gsl_matrix_pointer(), 59 s_.TEMP_gsl_vector_pointer(), 60 w.TEMP_gsl_vector_pointer()); 61 } 255 62 256 63 257 //Set data258 //////////259 A_ = A;260 size_t n = A_.rows();261 size_t m = A_.columns();262 n = m = DIM;263 loaded_ = true;264 265 266 //Set work matrices267 ///////////////////268 V_ = gslapi::matrix( n, n, true );269 270 //Assign vector s_ with correct dimensions271 /////////////////////////////////////////////////272 s_ = gslapi::vector( n );273 274 double error = 1;275 gslapi::matrix E, S;276 277 278 //Print matrix to screen279 ////////////////////////280 cout << "A = " << endl;281 cout << A << endl;282 283 cout.setf( ios::scientific );284 285 286 //Run test 1: Unmodified method287 ///////////////////////////////288 this->process();289 S = this->get_s();290 291 E = A - A_*S*V_.transpose();292 293 294 error = sqrt(norm(E));295 cout << "error(Unmodified method) = " << error << endl;296 cout << "to compare with " << MAXTOL << endl;297 if( error < MAXTOL ) { cout << "test ok!!!\n"; }298 else { cout << "test failed!\n"; return false; }299 300 301 //Run test 2: Modified method302 ///////////////////////////////303 A_ = A;304 this->process( Modified );305 S = this->get_s();306 E = A - A_*S*V_.transpose();307 error = sqrt(norm(E));308 cout << "error(Modified method) = " << error << endl;309 cout << "to compare with " << MAXTOL << endl;310 if( error < MAXTOL ) { cout << "test ok!!!\n"; }311 else { cout << "test failed!\n"; return false; }312 313 314 //Run test 2: Modified method315 ///////////////////////////////316 A_ = A;317 this->process( Jacobi );318 S = this->get_s();319 E = A - A_*S*V_.transpose();320 error = sqrt(norm(E));321 cout << "error(Jacobi method) = " << error << endl;322 cout << "to compare with " << MAXTOL << endl;323 if( error < MAXTOL ) { cout << "test ok!!!\n"; }324 else { cout << "test failed!\n"; return false; }325 326 return true; //Test with good outcome!327 }328 329 64 }} // of namespace cpptools and namespace theplu -
trunk/src/SVD.h
r43 r227 1 1 // $Id$ 2 2 3 #ifndef _theplu_cpptools_svd_ 4 #define _theplu_cpptools_svd_ 3 #ifndef _theplu_cpptools_svd_ 4 #define _theplu_cpptools_svd_ 5 5 6 6 #include "matrix.h" 7 7 #include "vector.h" 8 9 #include <gsl/gsl_linalg.h> 8 10 9 11 namespace theplu { … … 13 15 /// namespace. 14 16 /// 15 namespace cpptools { 17 namespace cpptools { 16 18 17 /** 18 Class encapsulating methods for Singular Value Decomposition. 19 \n\n 19 // Jari check that interface is complete 20 21 /** 22 Class encapsulating GSL methods for singular value decomposition, 23 SVD. 24 25 A = U S V' = (MxN)(NxN)(NxN) = (MxN)\n 26 20 27 A = Matrix to be decomposed, size MxN\n 21 28 U = Orthogonal matrix, size MxN\n 22 29 S = Diagonal matrix of singular values, size NxN\n 23 30 V = Orthogonal matrix, size NxN\n 24 A = U S V' = (MxN)(NxN)(NxN) = (MxN)\n25 26 Shouldn't there be a reference to the algortithm here?27 28 @version 1.0 $Revision$ $Date$29 31 */ 30 32 31 33 class SVD 32 34 { 33 static const double MAXTOL = 1E-6; 35 public: 34 36 35 enum SVDtypes { 36 Unmodified, 37 Modified, 38 Jacobi, 39 Solver 37 /// 38 /// A number of SVD algorithms are implemented in GSL. They have 39 /// their strengths and weaknesses, check the GSL documentation. 40 /// 41 /// There are restrictions on the matrix dimensions depending on 42 /// which SVD algorithm is used. From the GSL's SVD source code 43 /// one finds that the Golub-Reinsch algorithm implementation will 44 /// not work on matrices with fewer rows than columns, the same is 45 /// also true for the modified Golub-Reinsch algorithm. 46 /// 47 /// @see GSL's SVD documentation. 48 /// 49 enum SVDalgorithm { 50 GolubReinsch, 51 ModifiedGolubReinsch, 52 Jacobi 40 53 }; 41 54 42 public: 43 /** 44 The default constructor should only be used for testing!!! 45 */46 SVD( void);55 /// 56 /// Constructs an SVD object using the matrix A as only input. The 57 /// input matrix is copied for further use in the object. 58 /// 59 SVD(const gslapi::matrix& ); 47 60 48 49 /** 50 Constructs an SVD object using the matrix A as only 51 input. The input matrix is copied for further use in the 52 object. 53 */ 54 SVD( const gslapi::matrix& ); 55 56 /** 57 Constructor initializing the SVD object for Solver. 58 Solver requires an extra-vector paramter \a b: \f$Ax = b\f$ 59 The \f$x\f$ vector will be reached using the get_x() 60 function. 61 @see get_x() function. 62 */ 61 ~SVD(void); 63 62 64 SVD( const gslapi::matrix&, const gslapi::vector& b); 65 ~SVD(); 63 /// 64 /// This function will perform SVD with the method specified by \a 65 /// algo. 66 /// 67 /// @return Whatever GSL returns. 68 /// 69 int decompose(SVDalgorithm algo=GolubReinsch); 66 70 67 /** 68 This function will run the method specified by the SVDtypes. Precently 69 there are 3 SVD methods implemented and one solver. These are: \n\n 70 Unmodified: (see GSL documentation about gsl_linalg_SV_decomp function)\n 71 Modified: This method is faster when M>>N. (see GSL documentation 72 about gsl_linalg_SV_decomp_mod function)\n 73 Jacobi: Computes singular values to higer accuracy than default method 74 (see GSL documentation about gsl_linalg_SV_decomp_jacobi.\n 75 Solver: Using Unmodified to perform SVD and then solves the system \f$Ax=b\f$ 76 */ 77 bool process( SVDtypes stype = Unmodified ); 71 /// 72 /// Access to the s vector. 73 /// 74 /// @return A copy of the s vector. 75 /// 76 /// @note If decompose() has not been run the outcome of the call 77 /// is undefined. 78 /// 79 gslapi::vector s(void) const { return s_; } 78 80 79 /** 80 Function will return the matrix U. Require that process() has been 81 executed. 82 */ 83 gslapi::matrix get_u() const { return A_; } 81 /// 82 /// Solve the system \f$Ax=b\f$ using the decomposition of A. 83 /// 84 /// @note If decompose() has not been run the outcome of the call 85 /// is undefined. 86 /// 87 /// @return Whatever GSL returns. 88 /// 89 inline int solve(gslapi::vector b, gslapi::vector x) 90 { return gsl_linalg_SV_solve(U_.gsl_matrix_pointer(), 91 V_.gsl_matrix_pointer(), 92 s_.gsl_vector_pointer(), 93 b.gsl_vector_pointer(), 94 x.TEMP_gsl_vector_pointer()); 95 } 84 96 85 /** 86 Function will return the matrix V. Require that process() has been 87 executed. 88 */ 89 gslapi::matrix get_v() const { return V_; } 97 /// 98 /// Access to the U matrix. 99 /// 100 /// @return A copy of the U matrix. 101 /// 102 /// @note If decompose() has not been run the outcome of the call 103 /// is undefined. 104 /// 105 gslapi::matrix U(void) const { return U_; } 90 106 107 /// 108 /// Access to the V matrix. 109 /// 110 /// @return A copy of the V matrix. 111 /// 112 /// @note If decompose() has not been run the outcome of the call 113 /// is undefined. 114 /// 115 gslapi::matrix V(void) const { return V_; } 91 116 92 /** 93 Function will return the vector x containing the solution 94 \f$ x=A^{-1}b \f$. Require that process( Solver ) has been 95 executed. 96 @see Read about Solver in the bool process() function. 97 */ 117 private: 118 inline int jacobi(void) 119 { return gsl_linalg_SV_decomp_jacobi(U_.gsl_matrix_pointer(), 120 V_.gsl_matrix_pointer(), 121 s_.TEMP_gsl_vector_pointer()); 122 } 123 int golub_reinsch(void); 124 int modified_golub_reinsch(void); 98 125 99 gslapi::vector get_x() const { return x_; } 100 101 /** 102 Function returning diagonal matrix S. Require that process() has been 103 executed. 104 */ 105 gslapi::matrix get_s() const; 106 107 108 /** 109 Function returning diagonal matrix S in vector form. 110 */ 111 gslapi::vector get_s_vec() const { return s_; } 112 113 114 /** 115 This method will execute Default, Unmodified and Jacobi methods one at a time 116 and calculate the error, \f$ e = \left\Vert A - USV^{T} \right\Vert_{2} \f$. 117 The method will return "true" if \f$e < 10^{-6}\f$ else false. A test program 118 is available that executes this method, c++_tools/test/svd_test. No test is 119 performed for solver but the aim is to add one in the future. 120 */ 121 bool test(); 122 123 private: 124 125 gslapi::matrix A_, V_; 126 gslapi::vector s_, b_, x_; 127 bool loaded_, solver_; 128 129 //SVD methods 130 bool process_default(); 131 bool process_modified(); 132 bool process_jacobi(); 133 bool process_solver(); 134 135 double norm(gslapi::matrix& A) const; // move into class gslapi::matrix? 126 gslapi::matrix U_, V_; 127 gslapi::vector s_; 136 128 }; 137 129 -
trunk/src/SVM.cc
r197 r227 119 119 } 120 120 121 gslapi::vector E = ( kernel_train*target_train.mul _elements(alpha_train)121 gslapi::vector E = ( kernel_train*target_train.mul(alpha_train) 122 122 - target_train ) ; 123 123 … … 184 184 alpha_train[index.second] = alpha_new2; 185 185 186 E = kernel_train*target_train.mul _elements(alpha_train) - target_train;186 E = kernel_train*target_train.mul(alpha_train) - target_train; 187 187 gslapi::vector ones(alpha_train.size(),1); 188 188 -
trunk/src/SVM.h
r188 r227 62 62 /// 63 63 inline theplu::gslapi::vector output(void) 64 {return kernel_.get() * alpha_.mul _elements(target_)+64 {return kernel_.get() * alpha_.mul(target_)+ 65 65 theplu::gslapi::vector(alpha_.size(),bias_);} 66 66 -
trunk/src/vector.cc
r132 r227 20 20 21 21 vector::vector(void) 22 : v_(NULL) 23 { 24 } 25 26 27 28 vector::vector(const size_t n, const double init_value) 22 : v_(NULL), view_(NULL) 23 { 24 } 25 26 27 28 vector::vector(const size_t n,const double init_value) 29 : view_(NULL) 29 30 { 30 31 v_ = gsl_vector_alloc(n); … … 34 35 35 36 36 vector::vector(const vector& other, const std::vector<size_t>& index) 37 { 38 if (index.size()){ 39 v_ = gsl_vector_alloc(index.size()); 40 for (size_t i=0; i<index.size(); i++) 41 gsl_vector_set(v_, i, other(index[i])); 42 } 43 else 44 v_ = other.gsl_vector_copy(); 37 vector::vector(const vector& other) 38 : view_(NULL) 39 { 40 v_ = other.TEMP_gsl_vector_copy(); 45 41 } 46 42 … … 48 44 49 45 vector::vector(gsl_vector* vec) 50 : v_(vec) 46 : v_(vec), view_(NULL) 51 47 { 52 48 } … … 55 51 56 52 vector::vector(std::istream& is) 53 : view_(NULL) 57 54 { 58 55 using namespace std; … … 132 129 v_=NULL; 133 130 } 134 } 135 136 137 138 gsl_vector* vector::gsl_vector_copy(void) const 131 delete view_; 132 } 133 134 135 136 gsl_vector* vector::TEMP_gsl_vector_copy(void) const 139 137 { 140 138 gsl_vector* vec = gsl_vector_alloc(size()); … … 145 143 146 144 145 std::pair<double,double> vector::minmax(void) const 146 { 147 double min, max; 148 gsl_vector_minmax(v_,&min,&max); 149 return std::pair<double,double>(min,max); 150 } 151 147 152 148 153 149 154 std::pair<size_t,size_t> vector::minmax_index(void) const 150 155 { 151 size_t min_index=0; 152 size_t max_index=0; 153 void gsl_vector_minmax_index (const gsl_vector * v_, size_t * 154 min_index, size_t * max_index); 155 return std::pair<size_t,size_t>(min_index, max_index); 156 } 157 158 159 160 156 size_t min_index, max_index; 157 gsl_vector_minmax_index(v_,&min_index,&max_index); 158 return std::pair<size_t,size_t>(min_index,max_index); 159 } 160 161 162 163 /* Jari, remove this section 161 164 std::pair<size_t,size_t> vector::minmax_index(const std::vector<size_t>& subset ) const 162 165 { … … 171 174 return std::pair<size_t,size_t>(min_index, max_index); 172 175 } 173 174 175 176 vector vector::mul_elements( const vector& other ) const 177 { 178 vector res( *this ); 179 gsl_vector_mul( res.v_, other.v_ ); 180 return res; 181 } 176 */ 182 177 183 178 void vector::shuffle(void) const … … 196 191 { 197 192 double sum = 0; 198 for ( u_int i=0; i<size(); i++)193 for (size_t i=0; i<size(); i++) 199 194 sum += gsl_vector_get( v_, i ); 200 195 return( sum ); … … 246 241 if ( v_ ) 247 242 gsl_vector_free( v_ ); 248 v_ = other. gsl_vector_copy();243 v_ = other.TEMP_gsl_vector_copy(); 249 244 } 250 245 return *this; -
trunk/src/vector.h
r142 r227 28 28 29 29 /// 30 /// This is the C++ tools interface to GSL vector. 31 /// 32 30 /// This is the C++ tools interface to GSL vector. 'double' is the 31 /// only type supported, maybe we should add a 'complex' type as 32 /// well in the future. 33 /// 34 /// \par[File streams] Reading and writing vectors to file streams 35 /// are of course supported. These are implemented without using GSL 36 /// functionality, and thus binary read and write to streams are not 37 /// supported. 38 /// 39 /// \par[Vector views] GSL vector views are supported and these are 40 /// disguised as ordinary gslapi::vectors. A support function is 41 /// added, gslapi::vector::is_view(), that can be used to check if 42 /// the vector object is a view. Note that view vectors do not own 43 /// the undelying data, and is not valid if the original vector is 44 /// deallocated. 45 /// 33 46 class vector 34 47 { … … 47 60 48 61 /// 49 /// The copy constructor, creating a new sub-vector defined by \a 50 /// index (default is to copy the whole vector). 51 /// 52 vector(const vector&, 53 const std::vector<size_t>& index = std::vector<size_t>()); 62 /// The copy constructor. 63 /// 64 /// @note If the object to be copied is a vector view, the values 65 /// of the view will be copied, i.e. the view is not copied. 66 /// 67 vector(const vector&); 54 68 55 69 /// … … 73 87 74 88 /// 75 /// Create a new copy of the internal GSL vector. 76 /// 77 /// Necessary memory for the new GSL vector is allocated and the 78 /// caller is responsible for freeing the allocated memory. 79 /// 80 /// @return A pointer to a copy of the internal GSL vector. 81 /// 82 gsl_vector* gsl_vector_copy(void) const; 89 /// Vector addition, \f$this_i = this_i + other_i \; \forall i\f$. 90 /// 91 /// @return .GSL_SUCCESS on normal exit. 92 /// 93 // Jari, doxygen group as Vector operators 94 inline int add(const vector& other) { return gsl_vector_add(v_,other.v_); } 95 96 /// 97 /// Add a constant to a vector, \f$this_i = this_i + term \; 98 /// \forall i\f$. 99 /// 100 /// @return .GSL_SUCCESS on normal exit. 101 /// 102 // Jari, doxygen group as Vector operators 103 inline int 104 add_constant(double term) { return gsl_vector_add_constant(v_,term); } 105 106 /// 107 /// This function performs element-wise division, \f$this_i = 108 /// this_i/other_i \; \forall i\f$. 109 /// 110 /// @return .GSL_SUCCESS on normal exit. 111 /// 112 // Jari, doxygen group as Vector operators 113 inline int div(const vector& other) { return gsl_vector_div(v_,other.v_); } 114 115 /// 116 /// @return True if all elements in the vector is zero, false 117 /// othwerwise; 118 /// 119 inline bool isnull(void) const { return gsl_vector_isnull(v_); } 120 121 /// 122 /// Check if the vector object is a view (sub vector) to another 123 /// vector. 124 /// 125 /// @return True if the object is a view, false othwerwise; 126 /// 127 inline bool isview(void) const { return view_; } 83 128 84 129 /// … … 90 135 /// @return A pointer to the internal GSL vector, 91 136 /// 92 inline gsl_vector* gsl_vector_pointer(void) { return v_; } 93 94 ///This function returns the indices of the minimum and maximum values in 95 ///the vector, storing them in imin and imax. When 96 ///there are several equal minimum or maximum elements then the lowest 97 ///indices are returned. @return Index corresponding to the smallest 98 /// and largest value. 99 /// 137 inline gsl_vector* TEMP_gsl_vector_pointer(void) { return v_; } 138 139 /// 140 /// @return The maximum value of the vector. 141 /// 142 // Jari, doxygen group as Finding maximum and minimum elements 143 inline double max(void) const { return gsl_vector_max(v_); } 144 145 /// 146 /// @return The element index to the maximum value of the 147 /// vector. The lowest index has precedence. 148 /// 149 // Jari, doxygen group as Finding maximum and minimum elements 150 inline size_t max_index(void) const { return gsl_vector_max_index(v_); } 151 152 /// 153 /// @return The minimum value of the vector. 154 /// 155 // Jari, doxygen group as Finding maximum and minimum elements 156 inline double min(void) const { return gsl_vector_min(v_); } 157 158 /// 159 /// @return The element index to the minimum value of the 160 /// vector. The lowest index has precedence. 161 /// 162 // Jari, doxygen group as Finding maximum and minimum elements 163 inline size_t min_index(void) const { return gsl_vector_min_index(v_); } 164 165 /// 166 /// @return The minimum and maximum values of the vector, as the 167 /// \a first and \a second member of the returned \a pair, 168 /// respectively. 169 /// 170 // Jari, doxygen group as Finding maximum and minimum elements 171 std::pair<double,double> vector::minmax(void) const; 172 173 /// 174 /// @return The indecies to the minimum and maximum values of the 175 /// vector, as the \a first and \a second member of the returned 176 /// \a pair, respectively. The lowest index has precedence. 177 /// 178 // Jari, doxygen group as Finding maximum and minimum elements 100 179 std::pair<size_t,size_t> vector::minmax_index(void) const; 101 180 … … 110 189 /// 111 190 std::pair<size_t,size_t> 112 vector::minmax_index(const std::vector<size_t>& subset ) const; 113 114 /// 115 /// This function multiplies all elements between two vectors and 116 /// returns a third vector containing the result, \f$a_i = b_i * 117 /// c_i \; \forall i\f$. 118 /// 119 /// @return The result vector. 120 /// 121 vector vector::mul_elements( const vector& other ) const; 191 vector::TEMP_minmax_index(const std::vector<size_t>& subset ) const; 192 193 /// 194 /// This function performs element-wise multiplication, \f$this_i = 195 /// this_i * other_i \; \forall i\f$. 196 /// 197 /// @return .GSL_SUCCESS on normal exit. 198 /// 199 // Jari, doxygen group as Vector operators 200 inline int mul(const vector& other) { return gsl_vector_mul(v_,other.v_); } 201 202 /// 203 /// Reverse the order of elements in the vector. 204 /// 205 /// @return .GSL_SUCCESS on normal exit. 206 /// 207 // Jari, doxygen group as Exchanging elements 208 inline int reverse(void) { return gsl_vector_reverse(v_);} 209 210 /// 211 /// Rescale vector, \f$this_i = this_i * factor \; \forall i\f$. 212 /// 213 /// @return .GSL_SUCCESS on normal exit. 214 /// 215 // Jari, doxygen group as Vector operators 216 inline int scale(double factor) { return gsl_vector_scale(v_,factor); } 122 217 123 218 /// 124 219 /// Set all elements to \a value. 125 220 /// 221 // Jari, doxygen group as Initializing vector elements 126 222 inline void set_all(const double& value) { gsl_vector_set_all(v_,value); } 127 223 … … 131 227 /// one. 132 228 /// 229 // Jari, doxygen group as Initializing vector elements 133 230 inline void set_basis(const size_t i) { gsl_vector_set_basis(v_,i); } 134 231 … … 136 233 /// Set all elements to zero. 137 234 /// 235 // Jari, doxygen group as Initializing vector elements 138 236 inline void set_zero(void) { gsl_vector_set_zero(v_); } 139 237 … … 150 248 151 249 /// 250 /// Vector subtraction, \f$this_i = this_i - other_i \; \forall i\f$. 251 /// 252 /// @return .GSL_SUCCESS on normal exit. 253 /// 254 // Jari, doxygen group as Vector operators 255 inline int sub(const vector& other) { return gsl_vector_sub(v_,other.v_); } 256 257 /// 152 258 /// Calculate the sum of all vector elements. 153 259 /// 154 260 /// @return The sum. 155 261 /// 262 // Jari, doxygen group as "Extends GSL". 156 263 double vector::sum(void) const; 157 264 158 265 /// 266 /// Swap vector elements by copying. The two vectors must have the 267 /// same length. 268 /// 269 /// @return .GSL_SUCCESS on normal exit. 270 /// 271 inline int swap(vector& other) { return gsl_vector_swap(v_,other.v_); } 272 273 /// 274 /// Exchange elements \a i and \a j. 275 /// 276 /// @return .GSL_SUCCESS on normal exit. 277 /// 278 // Jari, doxygen group as Exchanging elements 279 inline int 280 swap_elements(size_t i,size_t j) { return gsl_vector_swap_elements(v_,i,j);} 281 282 /// 159 283 /// Element access operator. 160 284 /// 161 285 /// @return Reference to element \a i. 162 286 /// 287 // Jari, doxygen group as Accessing vector elements 163 288 inline double& operator()(size_t i) { return *gsl_vector_ptr(v_,i); } 164 289 … … 168 293 /// @return The value of element \a i. 169 294 /// 295 // Jari, doxygen group as Accessing vector elements 170 296 inline const double& operator()(size_t i) const 171 297 { return *gsl_vector_const_ptr(v_,i); } … … 176 302 /// @return Reference to element \a i. 177 303 /// 304 // Jari, doxygen group as Accessing vector elements 178 305 inline double& operator[](size_t i) { return *gsl_vector_ptr(v_,i); } 179 306 … … 183 310 /// @return The value of element \a i. 184 311 /// 312 // Jari, doxygen group as Accessing vector elements 185 313 inline const double& operator[](size_t i) const 186 314 { return *gsl_vector_const_ptr(v_,i); } … … 217 345 218 346 /// 219 /// Multiply and assign operator.347 /// Multiply with scalar and assign operator. 220 348 /// 221 349 vector& operator*=(const double d) { gsl_vector_scale(v_,d); return *this; } 222 350 223 351 /// 224 /// Multiply operator. 225 /// 226 vector& operator*(const double d) { gsl_vector_scale(v_,d); return *this; } 352 /// Vector with scalar multiplication. 353 /// 354 /// \note This operator is not implemented! 355 /// 356 vector operator*(const double d) const; 227 357 228 358 229 359 private: 230 360 361 /// 362 /// Create a new copy of the internal GSL vector. 363 /// 364 /// Necessary memory for the new GSL vector is allocated and the 365 /// caller is responsible for freeing the allocated memory. 366 /// 367 /// @return A pointer to a copy of the internal GSL vector. 368 /// 369 gsl_vector* TEMP_gsl_vector_copy(void) const; 370 231 371 gsl_vector* v_; 232 372 gsl_vector_view* view_; 233 373 }; 234 374 -
trunk/test/test_svd.cc
r42 r227 1 1 // $Id$ 2 // 3 // Testing for a succesful reconstruction of a decomposed random 4 // matrix, aswell that U and V are orthogonal. 2 5 3 //Test program for SVD class.4 6 5 7 #include "SVD.h" 8 #include "matrix.h" 9 #include "random_singleton.h" 10 #include "vector.h" 6 11 7 int main() 12 using namespace std; 13 using namespace theplu::cpptools; 14 using namespace theplu::gslapi; 15 16 17 18 double this_norm(const matrix& A) 8 19 { 9 theplu::cpptools::SVD* mysvd = new theplu::cpptools::SVD; 10 if( mysvd->test() ) { delete mysvd; return 0; } 11 else { delete mysvd; return -1; } 20 double sum=0.0; 21 for (size_t i=0; i<A.rows(); ++i) 22 for (size_t j=0; j<A.columns(); ++j) 23 sum += A(i,j)*A(i,j); 24 return sum; 12 25 } 26 27 28 29 bool test(size_t m, size_t n, SVD::SVDalgorithm algo) { 30 31 // accepted error, Jari: should be picked up from GSL 32 double MAXTOL=1e-13; 33 random_singleton* rng=random_singleton::get_instance(-1); 34 35 // initialise a random test-matrix 36 matrix A(m,n); 37 for (size_t i=0; i<m; ++i) 38 for(size_t j=0; j<n; ++j) 39 A(i,j)=1000*rng->get_uniform_double(); 40 41 SVD svd(A); 42 svd.decompose(algo); 43 theplu::gslapi::vector s(svd.s()); 44 matrix S(s.size(),s.size()); 45 for (size_t i=0; i<s.size(); ++i) 46 S(i,i)=s[i]; 47 matrix V=svd.V(); 48 matrix U=svd.U(); 49 double error = this_norm(A-U*S*V.transpose()); 50 bool testerror=false; 51 if (error>MAXTOL) { 52 cerr << "test_svd: FAILED, algorithm " << algo << " recontruction error (" 53 << error << ") > tolerance (" << MAXTOL << "), matrix dimension (" 54 << m << ',' << n << ')' << endl; 55 testerror=true; 56 } 57 58 error=this_norm(V.transpose()*V)-n; 59 if (error>MAXTOL) { 60 cerr << "test_svd: FAILED, algorithm " << algo << " V orthogonality error (" 61 << error << ") > tolerance (" << MAXTOL << ')' << endl; 62 testerror=true; 63 } 64 65 error=this_norm(U.transpose()*U)-n; 66 if (error>MAXTOL) { 67 cerr << "test_svd: FAILED, algorithm " << algo << " U orthogonality error (" 68 << error << ") > tolerance (" << MAXTOL << ')' << endl; 69 testerror=true; 70 } 71 return testerror; 72 } 73 74 75 76 int main(const int argc,const char* argv[]) 77 { 78 bool testfail=false; 79 80 // The GSL Jacobi, Golub-Reinsch, and modified Golub-Reinsch 81 // implementations supports rows>=columns matrix dimensions only 82 testfail|=test(12,12,SVD::GolubReinsch); 83 testfail|=test(12,4,SVD::GolubReinsch); 84 testfail|=test(12,12,SVD::ModifiedGolubReinsch); 85 testfail|=test(12,4,SVD::ModifiedGolubReinsch); 86 testfail|=test(12,12,SVD::Jacobi); 87 testfail|=test(12,4,SVD::Jacobi); 88 89 return (testfail ? -1 : 0); 90 }
Note: See TracChangeset
for help on using the changeset viewer.