CVR-Lib last update 20 Sep 2009

cvrSVD.h

Go to the documentation of this file.
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

Generated on Sun Sep 20 22:08:00 2009 for CVR-Lib by Doxygen 1.5.8