last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * Copyright (C) 2008 00005 * Pablo Alvarado 00006 * 00007 * This file is part of the Computer Vision and Robotics Library (CVR-Lib ) 00008 * 00009 * The CVR-Lib is free software; you can redistribute it and/or 00010 * modify it under the terms of the BSD License. 00011 * 00012 * All rights reserved. 00013 * 00014 * Redistribution and use in source and binary forms, with or without 00015 * modification, are permitted provided that the following conditions are met: 00016 * 00017 * 1. Redistributions of source code must retain the above copyright notice, 00018 * this list of conditions and the following disclaimer. 00019 * 00020 * 2. Redistributions in binary form must reproduce the above copyright notice, 00021 * this list of conditions and the following disclaimer in the documentation 00022 * and/or other materials provided with the distribution. 00023 * 00024 * 3. Neither the name of the authors nor the names of its contributors may be 00025 * used to endorse or promote products derived from this software without 00026 * specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00029 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00030 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00031 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00032 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00033 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00034 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00035 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00036 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00037 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 */ 00040 00041 /** 00042 * \file cvrSVD.h 00043 * Singular Value Decomposition 00044 * \author Xin Gu 00045 * \author Pablo Alvarado 00046 * \date 11.01.2001 00047 * 00048 * revisions ..: $Id: cvrSVD.h,v 1.1 2008/05/07 15:18:36 alvarado Exp $ 00049 */ 00050 00051 00052 #ifndef _CVR_S_V_D_H__ 00053 #define _CVR_S_V_D_H__ 00054 00055 #include "cvrMath.h" 00056 #include "cvrMatrix.h" 00057 #include "cvrLinearAlgebraFunctor.h" 00058 00059 #ifdef HAVE_LAPACK 00060 #include "cvrLapackInterface.h" 00061 #endif 00062 00063 namespace cvr { 00064 00065 /** 00066 * Singular Value Decomposition (SVD). 00067 * 00068 * The functor will take a \f$m\times n\f$ matrix A and compute its singular 00069 * value decomposition, consisting of three matrices U, W, and V, with 00070 * 00071 * \f[ 00072 * A = U \cdot W \cdot V^* 00073 * \f] 00074 * 00075 * where \f$V^*\f$ denotes the conjugate transpose of V. U is a 00076 * column-orthonormal \f$m\times m\f$ matrix, W is a diagonal \f$m\times n\f$ 00077 * matrix with the singular values on the diagonal, and V is a orthonormal 00078 * \f$n\times n\f$ matrix. Those columns of V whose corresponding entries in 00079 * W are zero are the basis of A's null space. 00080 * 00081 * You can find more theoretical information about a similar algorithm in 00082 * W. H. Press, S. A. Teukolsky, W. T. Vetterling, and B. P. Flannery: 00083 * Numerical Recipes in C, 2nd edition, Cambridge University Press, 1992. 00084 * For a quick review check the Wikipedia at 00085 * http://en.wikipedia.org/wiki/Singular_value_decomposition. 00086 * 00087 * This class is usually employed in the computation of linear mean squared 00088 * error. For a quick theory review check 00089 * http://en.wikipedia.org/wiki/Linear_least_squares 00090 * 00091 * Only instantiations of floating point types makes sense (i.e. for 00092 * T double or float). If you want the singular values and 00093 * corresponding singular vectors to be sorted, you have to set 00094 * parameters::sort to true. 00095 * 00096 * This class uses LAPACK if it is available. 00097 * 00098 * @see singularValueDecomposition::parameters 00099 * 00100 * @ingroup glinearAlgebra 00101 00102 */ 00103 class svd: public linearAlgebraFunctor { 00104 public: 00105 00106 /** 00107 * The parameters for the class 00108 */ 00109 class parameters : public linearAlgebraFunctor::parameters { 00110 public: 00111 /** 00112 * Default constructor 00113 */ 00114 parameters(); 00115 00116 /** 00117 * Copy constructor. 00118 * 00119 * @param other the parameters object to be copied 00120 */ 00121 parameters(const parameters& other); 00122 00123 /** 00124 * destructor 00125 */ 00126 ~parameters(); 00127 00128 /** 00129 * returns name of this type 00130 */ 00131 const std::string& name() const; 00132 00133 /** 00134 * copy the contents of a parameters object 00135 * @param other the parameters object to be copied 00136 * @return a reference to this parameters object 00137 */ 00138 parameters& copy(const parameters& other); 00139 00140 /** 00141 * Assigns the contents of the other object to this object 00142 */ 00143 inline parameters& operator=(const parameters& other); 00144 00145 /** 00146 * Returns a pointer to a clone of the parameters. 00147 */ 00148 virtual parameters* clone() const; 00149 00150 /** 00151 * Returns a pointer to a clone of the parameters. 00152 */ 00153 virtual parameters* newInstance() const; 00154 00155 /** 00156 * Read the parameters from the given ioHandler. 00157 * 00158 * @param handler the ioHandler to be used 00159 * @param complete if true (the default) the enclosing begin/end will 00160 * be also read, otherwise only the data block will be read. 00161 * @return true if write was successful 00162 */ 00163 virtual bool read(ioHandler &handler, const bool complete=true); 00164 00165 /** 00166 * Write the parameters in the given ioHandler. 00167 * 00168 * @param handler the ioHandler to be used 00169 * @param complete if true (the default) the enclosing begin/end will 00170 * be also written, otherwise only the data block will be 00171 * written. 00172 * @return true if write was successful 00173 */ 00174 virtual bool write(ioHandler& handler,const bool complete=true) const; 00175 00176 // --------------------------------------------------- 00177 // the parameters 00178 // --------------------------------------------------- 00179 00180 /** 00181 * If true, singular values and corresponding singular vectors 00182 * are rearranged so that singular values have descending 00183 * order. 00184 * 00185 * Default is false. 00186 */ 00187 bool sort; 00188 00189 /** 00190 * Specifies whether U (false) or Ut (true) is returned. It is 00191 * faster to return Ut. 00192 * 00193 * Default is false, ie U. 00194 */ 00195 bool transposeU; 00196 00197 /** 00198 * Specifies whether V (false) or Vt (true) is returned. It is 00199 * faster to return V. 00200 * 00201 * Default is false, ie V. 00202 */ 00203 bool transposeV; 00204 00205 /** 00206 * @name LAPACK options 00207 * 00208 * The following attributes are considered if the LAPACK library is 00209 * detected, and otherwise just ignored. 00210 */ 00211 //@{ 00212 /** 00213 * If \c true the divide-and-conquer method for calculating the SVD is 00214 * used. This is generally faster, especially on large matrices. However, 00215 * it uses more temporary memory than the simple method. Thus, if the 00216 * computation fails due to memory problems setting this parameter to \c 00217 * false might solve the problem. 00218 * 00219 * Default value: \c true 00220 */ 00221 bool useDivideAndConquer; 00222 00223 /** 00224 * Let the data matrix have M rows and N columns. Then, usually, U will 00225 * be an MxM orthogonal matrix and V an NxN orthogonal matrix. However, 00226 * there are only min(M,N) singular values. For most applications it 00227 * suffices to calculate only min(M,N) left and right singular vectors, 00228 * which is done when \c useMinDimensions is true (default). All singular 00229 * values are calculated when false. 00230 * 00231 * Default value: \c true 00232 */ 00233 bool useMinDimensions; 00234 //@} 00235 }; 00236 00237 /** 00238 * Default constructor 00239 */ 00240 svd(); 00241 00242 /** 00243 * Default constructor with parameters 00244 */ 00245 svd(const parameters& params); 00246 00247 /** 00248 * Constructor. 00249 * 00250 * Sets parameters::sort to the given value. 00251 */ 00252 svd(bool sort); 00253 00254 /** 00255 * Copy constructor 00256 */ 00257 svd(const svd& other); 00258 00259 /** 00260 * Destructor 00261 */ 00262 virtual ~svd(); 00263 00264 /** 00265 * Returns the name of this type ("svd") 00266 */ 00267 virtual const std::string& name() const; 00268 00269 /** 00270 * Copy data of "other" functor. 00271 * 00272 * @param other the functor to be copied 00273 * @return a reference to this functor object 00274 */ 00275 svd& copy(const svd& other); 00276 00277 /** 00278 * Returns a pointer to a clone of this functor. 00279 */ 00280 virtual svd* clone() const; 00281 00282 /** 00283 * Returns a pointer to a clone of this functor. 00284 */ 00285 virtual svd* newInstance() const; 00286 00287 /** 00288 * Returns used parameters 00289 */ 00290 const parameters& getParameters() const; 00291 00292 /** 00293 * OnPlace version of Singular Value Decomposition. 00294 * 00295 * Singular Value Decomposition means that a m*n-matrix A is 00296 * decomposed into three matrices U,W,V, such that A = U*W*V'. U 00297 * is m*n, W is a diagonal matrix with n elements (which is 00298 * implemented as vector), V is a n*n-matrix. 00299 * 00300 * Note that the function returns V, not V'. 00301 * 00302 * @param src matrix<T> with the source matrix, will also contain 00303 * the U matrix after the function has returned. If src is a m*n 00304 * matrix, U will also be of size m*n 00305 * @param w vector<T> with the singular values, sorted 00306 * descendingly The elements of this vector constitute the 00307 * diagonal of the W matrix. 00308 * @param v the V matrix 00309 * 00310 * @return \c true is the decomposition was successfull, 00311 * \c false if an error occured 00312 */ 00313 bool decomposition(fmatrix& src, fvector& w, fmatrix& v) const; 00314 00315 /** 00316 * OnPlace version of Singular Value Decomposition. 00317 * 00318 * Singular Value Decomposition means that a m*n-matrix A is 00319 * decomposed into three matrices U,W,V, such that A = U*W*V'. U 00320 * is m*n, W is a diagonal matrix with n elements (which is 00321 * implemented as vector), V is a n*n-matrix. 00322 * 00323 * Note that the function returns V, not V'. 00324 * 00325 * @param src matrix<T> with the source matrix, will also contain 00326 * the U matrix after the function has returned. If src is a m*n 00327 * matrix, U will also be of size m*n 00328 * @param w vector<T> with the singular values, sorted 00329 * descendingly The elements of this vector constitute the 00330 * diagonal of the W matrix. 00331 * @param v the V matrix 00332 * 00333 * @return \c true is the decomposition was successfull, 00334 * \c false if an error occured 00335 */ 00336 bool decomposition(dmatrix& src, dvector& w, dmatrix& v) const; 00337 00338 /** 00339 * OnPlace version of Singular Value Decomposition. 00340 * 00341 * @param src matrix<T> with the source matrix, will also contain 00342 * the U matrix after the function has returned. 00343 * @param w vector<T> with the singular values, sorted descendingly if 00344 * parameters::sort is true. 00345 * The elements of this vector constitute the diagonal 00346 * of the W matrix. 00347 * @param v the V matrix 00348 * @return true is the decomposition was successfull, false if an 00349 * error occured 00350 */ 00351 virtual bool apply(fmatrix& src, fvector& w, fmatrix& v) const; 00352 00353 /** 00354 * OnPlace version of Singular Value Decomposition. 00355 * 00356 * @param src matrix<T> with the source matrix, will also contain 00357 * the U matrix after the function has returned. 00358 * @param w vector<T> with the singular values, sorted descendingly if 00359 * parameters::sort is true. 00360 * The elements of this vector constitute the diagonal 00361 * of the W matrix. 00362 * @param v the V matrix 00363 * @return true is the decomposition was successfull, false if an 00364 * error occured 00365 */ 00366 virtual bool apply(dmatrix& src, dvector& w, dmatrix& v) const; 00367 00368 /** 00369 * OnCopy version of Singular Value Decomposition. 00370 * 00371 * @param src matrix<T> with the source matrix 00372 * @param u the U matrix 00373 * @param w vector<T> with the singular values, sorted descendingly if 00374 * parameters::sort is true. 00375 * The elements of this vector constitute the diagonal 00376 * of the W matrix. 00377 * @param v the V matrix 00378 * @return true is the decomposition was successfull, false if an 00379 * error occured 00380 */ 00381 virtual bool apply(const fmatrix& src, fmatrix& u, 00382 fvector& w, fmatrix& v) const; 00383 00384 /** 00385 * OnCopy version of Singular Value Decomposition. 00386 * 00387 * @param src matrix<T> with the source matrix 00388 * @param u the U matrix 00389 * @param w vector<T> with the singular values, sorted descendingly if 00390 * parameters::sort is true. 00391 * The elements of this vector constitute the diagonal 00392 * of the W matrix. 00393 * @param v the V matrix 00394 * @return true is the decomposition was successfull, false if an 00395 * error occured 00396 */ 00397 virtual bool apply(const dmatrix& src, dmatrix& u, 00398 dvector& w, dmatrix& v) const; 00399 00400 protected: 00401 00402 /** 00403 * Helper class 00404 */ 00405 template<typename T> 00406 class helper 00407 #ifdef HAVE_LAPACK 00408 : public lapackInterface 00409 #endif 00410 { 00411 public: 00412 /** 00413 * The only constructor expects a parameter object 00414 */ 00415 helper(const parameters& par); 00416 00417 /** 00418 * On-Copy version of Singular Value Decomposition. Singular Value 00419 * 00420 * Decomposition means that a m*n-matrix A is decomposed into three 00421 * matrices U,W,V, such that A = U*W*V'. U is m*n, W is a diagonal 00422 * matrix with n elements (which is implemented as vector), V is a 00423 * n*n-matrix. Note that the function returns V, not V'. 00424 * 00425 * @param src matrix<T> with the source matrix, will also contain 00426 * the U matrix after the function has returned. If 00427 * src is a m*n matrix, U will also be of size m*n 00428 * @param w vector<T> with the singular values, sorted descendingly 00429 * The elements of this vector constitute the diagonal 00430 * of the W matrix. 00431 * @param v the V matrix 00432 * @return true is the decomposition was successfull, false if an 00433 * error occured 00434 */ 00435 bool decomposition(const matrix<T>& src, 00436 matrix<T>& u, 00437 vector<T>& w, 00438 matrix<T>& v) const; 00439 00440 /** 00441 * On-Place version of Singular Value Decomposition. Singular Value 00442 * 00443 * Decomposition means that a m*n-matrix A is decomposed into three 00444 * matrices U,W,V, such that A = U*W*V'. U is m*n, W is a diagonal 00445 * matrix with n elements (which is implemented as vector), V is a 00446 * n*n-matrix. Note that the function returns V, not V'. 00447 * 00448 * @param src matrix<T> with the source matrix, will also contain 00449 * the U matrix after the function has returned. If 00450 * src is a m*n matrix, U will also be of size m*n 00451 * @param w vector<T> with the singular values, sorted descendingly 00452 * The elements of this vector constitute the diagonal 00453 * of the W matrix. 00454 * @param v the V matrix 00455 * @return true is the decomposition was successfull, false if an 00456 * error occured 00457 */ 00458 bool decomposition(matrix<T>& src, vector<T>& w, matrix<T>& v) const; 00459 00460 private: 00461 /** 00462 * Reference to the parameters 00463 */ 00464 const parameters& params_; 00465 00466 /** 00467 * help method:(a^2+b^2)^0.5 without destructive underflow or overflow 00468 */ 00469 inline T pythag(const T a,const T b) const; 00470 00471 /** 00472 * sign 00473 */ 00474 inline T sign(const T a,const T b) const; 00475 00476 /** 00477 * check if the given number is zero 00478 */ 00479 inline bool isZero(const T x) const; 00480 00481 /** 00482 * check if the given number is not zero 00483 */ 00484 inline bool notZero(const T x) const; 00485 00486 /** 00487 * Compute the dot product of a part of two matrix rows 00488 */ 00489 inline T dotOfRows(const matrix<T>& data, 00490 const int row1, 00491 const int row2, 00492 int lowCol=0, 00493 const int highCol=container::MaxIndex) const; 00494 00495 /** 00496 * Compute the dot product of a part of two matrix columns 00497 */ 00498 inline T dotOfColumns(const matrix<T>& data, 00499 const int col1, 00500 const int col2, 00501 int lowRow=0, 00502 const int highRow=container::MaxIndex) const; 00503 00504 /** 00505 * Compute the sum of a part of a matrix row 00506 */ 00507 inline T sumOfRowPart(const matrix<T>& data, 00508 const int row, 00509 int lowCol=0, 00510 const int highCol=container::MaxIndex) const; 00511 00512 /** 00513 * Compute the sum of a part of a matrix column 00514 */ 00515 inline T sumOfColumnPart(const matrix<T>& data, 00516 const int col, 00517 int lowRow=0, 00518 const int highRow=container::MaxIndex) const; 00519 00520 00521 /** 00522 * Compute the sum of the absolute value of a part of a matrix row 00523 */ 00524 inline T sumOfAbsRowPart(const matrix<T>& data, 00525 const int row, 00526 int lowCol=0, 00527 const int highCol=container::MaxIndex) const; 00528 00529 /** 00530 * Compute the sum of the absolute values of a part of a matrix column 00531 */ 00532 inline T sumOfAbsColumnPart(const matrix<T>& data, 00533 const int col, 00534 int lowRow=0, 00535 const int highRow=container::MaxIndex) const; 00536 00537 inline void multiplyColumn(matrix<T>& data, 00538 const int col, 00539 const T factor, 00540 int lowRow=0, 00541 const int highRow=container::MaxIndex) const; 00542 00543 inline void multiplyRow(matrix<T>& data, 00544 const int row, 00545 const T factor, 00546 int lowCol=0, 00547 const int highCol=container::MaxIndex) const; 00548 00549 inline void fillColumn(matrix<T>& data, 00550 const int col, 00551 const T value, 00552 int lowRow=0, 00553 const int highRow=container::MaxIndex) const; 00554 00555 inline void fillRow(matrix<T>& data, 00556 const int row, 00557 const T value, 00558 int lowCol=0, 00559 const int highCol=container::MaxIndex) const; 00560 00561 /** 00562 * OnPlace version of Singular Value Decomposition. Singular Value 00563 * 00564 * Decomposition means that a m*n-matrix A is decomposed into three 00565 * matrices U,W,V, such that A = U*W*V'. U is m*n, W is a diagonal 00566 * matrix with n elements (which is implemented as vector), V is a 00567 * n*n-matrix. Note that the function returns V, not V'. 00568 * 00569 * @param src matrix<T> with the source matrix, will also contain 00570 * the U matrix after the function has returned. If 00571 * src is a m*n matrix, U will also be of size m*n 00572 * @param w vector<T> with the singular values, sorted descendingly 00573 * The elements of this vector constitute the diagonal 00574 * of the W matrix. 00575 * @param v the V matrix 00576 * @return true is the decomposition was successfull, false if an 00577 * error occured 00578 */ 00579 bool decompositionLocal(matrix<T>& src, 00580 vector<T>& w, 00581 matrix<T>& v) const; 00582 00583 00584 #ifdef HAVE_LAPACK 00585 00586 // lapack routine in template form 00587 00588 int svd(char* jobu, char* jobvt, 00589 integer* m, integer* n, T* a, integer* lda, 00590 T* s, T* u, integer* ldu, T* vt, integer* ldvt, 00591 T* work, integer* lwork, 00592 integer* info) const; 00593 00594 int sdd(char* jobz, integer* m, integer* n, T* a, integer* lda, 00595 T* s, T* u, integer* ldu, T* vt, integer* ldvt, 00596 T* work, integer* lwork, integer* iwork, 00597 integer* info) const; 00598 00599 bool lapackApply(const matrix<T>& theMatrix, 00600 matrix<T>& leftSV, 00601 vector<T>& singularValues, 00602 matrix<T>& rightSVtrans) const; 00603 00604 bool lapackApply(matrix<T>& theMatrix, 00605 vector<T>& singularValues, 00606 matrix<T>& rightSVtrans) const; 00607 #endif 00608 00609 }; 00610 00611 }; 00612 } 00613 00614 #include "cvrSVD_inline.h" 00615 00616 #endif