LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiUnifiedSVD.h

00001 /*
00002  * Copyright (C) 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*--------------------------------------------------------------------
00025  * project ....: LTI-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiUnifiedSVD.h
00027  * authors ....: Peter Doerfler
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 20.11.2003
00030  * revisions ..: $Id: ltiUnifiedSVD.h,v 1.9 2007/01/10 02:26:26 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_UNIFIED_SVD_H_
00034 #define _LTI_UNIFIED_SVD_H_
00035 
00036 #include "ltiSVD.h"
00037 #include "ltiLinearAlgebraFunctor.h"
00038 
00039 namespace lti {
00040   /**
00041    * This functor is meant to be used for calculating the Singular
00042    * Vector Decomposition without need to think about the most
00043    * efficient usage of the available methods. If the LAPACK is
00044    * available it will automatically be used since it is much faster.
00045    *
00046    * It is preferred to use this class instead of the SVD functors
00047    * available.
00048    */
00049   template<class T>
00050   class unifiedSVD : public linearAlgebraFunctor {
00051   public:
00052     /**
00053      * the parameters for the class unifiedSVD
00054      */
00055     class parameters : public linearAlgebraFunctor::parameters {
00056     public:
00057 
00058       /**
00059        * The SVD method to use. Note that functors
00060        * starting with Fast___ are only available if LAPACK is
00061        * used. The default is set according to your installation.
00062        */
00063       enum eSVDType {
00064         SVD,            /*!< use singularValueDecomp */
00065         FastSVD = 10    /*!< use fastSVD */
00066       };
00067 
00068       /**
00069        * default constructor
00070        */
00071       parameters() : linearAlgebraFunctor::parameters() {
00072         
00073         sort = true;
00074         transposeU = false;
00075         transposeV = false;
00076         useDC = true;
00077         useMinDimensions = true;
00078 #ifdef HAVE_LAPACK
00079         svdType = FastSVD;
00080 #else
00081         svdType = SVD;
00082 #endif
00083       };
00084 
00085       /**
00086        * copy constructor
00087        * @param other the parameters object to be copied
00088        */
00089       parameters(const parameters& other) : linearAlgebraFunctor::parameters() {
00090         copy(other);
00091       }
00092       
00093       /**
00094        * destructor
00095        */
00096       ~parameters() {
00097       };
00098 
00099       /**
00100        * returns name of this type
00101        */
00102       const char* getTypeName() const {
00103         return "unifiedSVD::parameters";
00104       };
00105 
00106       /**
00107        * copy the contents of a parameters object
00108        * @param other the parameters object to be copied
00109        * @return a reference to this parameters object
00110        */
00111       parameters& copy(const parameters& other) {
00112 #     ifndef _LTI_MSC_6
00113         // MS Visual C++ 6 is not able to compile this...
00114         linearAlgebraFunctor::parameters::copy(other);
00115 #     else
00116         // ...so we have to use this workaround.
00117         // Conditional on that, copy may not be virtual.
00118         linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy)
00119                             (const linearAlgebraFunctor::parameters&) =
00120                             linearAlgebraFunctor::parameters::copy;
00121         (this->*p_copy)(other);
00122 #     endif
00123 
00124         
00125         sort = other.sort;
00126         transposeU = other.transposeU;
00127         transposeV = other.transposeV;
00128         useDC = other.useDC;
00129         useMinDimensions = other.useMinDimensions;
00130         svdType = other.svdType;
00131         
00132         
00133         return *this;
00134       };
00135 
00136       /**
00137        * copy the contents of a parameters object
00138        * @param other the parameters object to be copied
00139        * @return a reference to this parameters object
00140        */
00141       parameters& operator=(const parameters& other) {
00142         return copy(other);
00143       };
00144 
00145       /**
00146        * returns a pointer to a clone of the parameters
00147        */
00148       virtual functor::parameters* clone() const {
00149         return new parameters(*this);
00150       };
00151 
00152 #     ifndef _LTI_MSC_6
00153       /**
00154        * write the parameters in the given ioHandler
00155        * @param handler the ioHandler to be used
00156        * @param complete if true (the default) the enclosing begin/end will
00157        *        be also written, otherwise only the data block will be written.
00158        * @return true if write was successful
00159        */
00160       virtual bool write(ioHandler& handler,const bool complete=true) const
00161 #     else
00162       /**
00163        * this function is required by MSVC only, as a workaround for a
00164        * very awful bug, which exists since MSVC V.4.0, and still by
00165        * V.6.0 with all bugfixes (so called "service packs") remains
00166        * there...  This method is also public due to another bug, so please
00167        * NEVER EVER call this method directly: use write() instead
00168        */
00169       bool writeMS(ioHandler& handler,const bool complete=true) const
00170 #     endif
00171       {
00172         bool b = true;
00173         if (complete) {
00174           b = handler.writeBegin();
00175         }
00176         
00177         if (b) {
00178           
00179           lti::write(handler,"sort",sort);
00180           lti::write(handler,"transposeU",transposeU);
00181           lti::write(handler,"transposeV",transposeV);
00182           lti::write(handler,"useDC",useDC);
00183           lti::write(handler,"useMinDimensions",useMinDimensions);
00184           
00185           switch (svdType) {
00186             case SVD:
00187               lti::write(handler,"svdType","SVD");
00188               break;
00189             case FastSVD:
00190               lti::write(handler,"svdType","FastSVD");
00191               break;
00192             default:
00193 #ifdef HAVE_LAPACK
00194               lti::write(handler,"svdType","FastSVD");
00195 #else              
00196               lti::write(handler,"svdType","SVD");
00197 #endif
00198               break;
00199           }
00200 
00201         }
00202 
00203 #     ifndef _LTI_MSC_6
00204         // This is the standard C++ code, which MS Visual C++ 6 is not able to
00205         // compile...
00206         b = b && linearAlgebraFunctor::parameters::write(handler,false);
00207 #     else
00208         bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&,
00209                                                          const bool) const =
00210           linearAlgebraFunctor::parameters::writeMS;
00211         b = b && (this->*p_writeMS)(handler,false);
00212 #     endif
00213 
00214         if (complete) {
00215           b = b && handler.writeEnd();
00216         }
00217 
00218         return b;
00219       }
00220 
00221 #     ifdef _LTI_MSC_6
00222       /**
00223        * write the parameters in the given ioHandler
00224        * @param handler the ioHandler to be used
00225        * @param complete if true (the default) the enclosing begin/end will
00226        *        be also written, otherwise only the data block will be written.
00227        * @return true if write was successful
00228        */
00229       bool write(ioHandler& handler,
00230                  const bool complete=true) const {
00231         // ...we need this workaround to cope with another really
00232         // awful MSVC bug.
00233         return writeMS(handler,complete);
00234       }
00235 #     endif
00236 
00237 
00238 #     ifndef _LTI_MSC_6
00239       /**
00240        * read the parameters from the given ioHandler
00241        * @param handler the ioHandler to be used
00242        * @param complete if true (the default) the enclosing begin/end will
00243        *        be also written, otherwise only the data block will be written.
00244        * @return true if read was successful
00245        */
00246       virtual bool read(ioHandler& handler,const bool complete=true)
00247 #     else
00248       /**
00249        * this function is required by MSVC only, as a workaround for a
00250        * very awful bug, which exists since MSVC V.4.0, and still by
00251        * V.6.0 with all bugfixes (so called "service packs") remains
00252        * there...  This method is also public due to another bug, so please
00253        * NEVER EVER call this method directly: use read() instead
00254        */
00255       bool readMS(ioHandler& handler,const bool complete=true)
00256 #     endif
00257       {
00258         bool b = true;
00259         if (complete) {
00260           b = handler.readBegin();
00261         }
00262         
00263         if (b) {
00264           
00265           lti::read(handler,"sort",sort);
00266           lti::read(handler,"transposeU",transposeU);
00267           lti::read(handler,"transposeV",transposeV);
00268           lti::read(handler,"useDC",useDC);
00269           lti::read(handler,"useMinDimensions",useMinDimensions);
00270 
00271           std::string tmp;
00272           lti::read(handler,"svdType",tmp);
00273           if (tmp=="SVD") {
00274             svdType = SVD;
00275           } else if (tmp=="FastSVD") {
00276             svdType = FastSVD;
00277           } else {
00278 #ifdef HAVE_LAPACK
00279             svdType = FastSVD;
00280 #else
00281             svdType = SVD;
00282 #endif
00283           }
00284 
00285         }
00286 
00287 #       ifndef _LTI_MSC_6
00288         // This is the standard C++ code, which MS Visual C++ 6 is not
00289         // able to compile...
00290         b = b && linearAlgebraFunctor::parameters::read(handler,false);
00291 #       else
00292         bool (linearAlgebraFunctor::parameters::* p_readMS)(ioHandler&,
00293                                                         const bool) =
00294           linearAlgebraFunctor::parameters::readMS;
00295         b = b && (this->*p_readMS)(handler,false);
00296 #       endif
00297 
00298         if (complete) {
00299           b = b && handler.readEnd();
00300         }
00301         
00302         return b;
00303       }
00304 
00305 #     ifdef _LTI_MSC_6
00306       /**
00307        * read the parameters from the given ioHandler
00308        * @param handler the ioHandler to be used
00309        * @param complete if true (the default) the enclosing begin/end will
00310        *        be also written, otherwise only the data block will be written.
00311        * @return true if read was successful
00312        */
00313       bool read(ioHandler& handler,const bool complete=true) {
00314         // ...we need this workaround to cope with another really awful MSVC
00315         // bug.
00316         return readMS(handler,complete);
00317       }
00318 #     endif
00319 
00320       // ------------------------------------------------
00321       // the parameters
00322       // ------------------------------------------------
00323 
00324 
00325       /**
00326        * If true the eigenvalues and eigenvectors are sorted in
00327        * descending order. Default true.
00328        *
00329        * See singularValueDecomp<T>::parameters::sort.
00330        */
00331       bool sort;
00332 
00333       /**
00334        * If true the transpose of matrix U is returned instead of
00335        * U. Default false.
00336        *
00337        * See singularValueDecomp<T>::parameters::transposeU
00338        */
00339       bool transposeU;
00340 
00341       /**
00342        * If true the transpose of matrix V is returned instead of
00343        * V. Default false.
00344        *
00345        * See singularValueDecomp<T>::parameters::transposeV
00346        */
00347       bool transposeV;
00348 
00349       /**
00350        * This parameters is used only if svdType=FastSVD. It
00351        * determines whether the divide and conquer strategy is used or
00352        * not. Default true.
00353        *
00354        * See fastSVD<T>::parameters::useDC
00355        */
00356       bool useDC;
00357 
00358       /**
00359        * This parameters is used only if svdType=FastSVD. If true only
00360        * min(rows,columns) of the data matrix singular vectors are calculated.
00361        *
00362        * Default value: \c true.
00363        *
00364        * See fastSVD<T>::parameters::useMinDimensions
00365        */
00366       bool useMinDimensions;
00367 
00368       /**
00369        * The SVD type given is used. Note that you cannot use
00370        * fastSVD if LAPACK is not installed. The default is
00371        * dependent on the the system configuration: If LAPACK is
00372        * available, fastSVD is used, otherwise singularValueDecomp.
00373        */
00374       eSVDType svdType;
00375 
00376 
00377     };
00378 
00379     /**
00380      * default constructor
00381      */
00382     unifiedSVD();
00383 
00384     /**
00385      * Construct a functor using the given parameters
00386      */
00387     unifiedSVD(const parameters& par);
00388 
00389     /**
00390      * copy constructor
00391      * @param other the object to be copied
00392      */
00393     unifiedSVD(const unifiedSVD& other);
00394 
00395     /**
00396      * destructor
00397      */
00398     virtual ~unifiedSVD();
00399 
00400     /**
00401      * returns the name of this type ("unifiedSVD")
00402      */
00403     virtual const char* getTypeName() const;
00404 
00405     /**
00406      * copy data of "other" functor.
00407      * @param other the functor to be copied
00408      * @return a reference to this functor object
00409      */
00410     unifiedSVD& copy(const unifiedSVD& other);
00411 
00412     /**
00413      * alias for copy member
00414      * @param other the functor to be copied
00415      * @return a reference to this functor object
00416      */
00417     unifiedSVD& operator=(const unifiedSVD& other);
00418 
00419     /**
00420      * returns a pointer to a clone of this functor.
00421      */
00422     virtual functor* clone() const;
00423 
00424     /**
00425      * set functor's parameters.
00426      * This member makes a copy of <em>theParam</em>: the functor
00427      * will keep its own copy of the parameters!
00428      * @return true if successful, false otherwise
00429      */
00430     virtual bool updateParameters();
00431 
00432     /**
00433      * returns used parameters
00434      */
00435     const parameters& getParameters() const;
00436 
00437     /**
00438      * Read the functor from the given ioHandler. 
00439      *
00440      * This method automatically sets the correct SVD solver
00441      * that is given in the parameters and transfers the relevant
00442      * parameters to that functor.
00443      *
00444      * @param handler the ioHandler to be used
00445      * @param complete if true (the default) the enclosing begin/end will
00446      *        be also written, otherwise only the data block will be written.
00447      * @return true if write was successful
00448      */
00449     virtual bool read(ioHandler& handler,const bool complete=true);
00450 
00451     /**
00452      * OnPlace version of Singular Value Decomposition. Singular Value
00453      * Decomposition means that a m*n-matrix A is decomposed into three
00454      * matrices U,W,V, such that  A = U*W*V'. U is m*n, W is a diagonal
00455      * matrix with n elements (which is implemented as vector), V is a
00456      * n*n-matrix. Note that the function returns V, not V'.
00457      * @param src matrix<T> with the source matrix, will also contain
00458      *            the U matrix after the function has returned. If
00459      *            src is a m*n matrix, U will also be of size m*n
00460      * @param w vector<T> with the singular values, sorted descendingly
00461      *                    The elements of this vector constitute the diagonal
00462      *                    of the W matrix.
00463      * @param v the V matrix
00464      * @return true is the decomposition was successfull, false if an
00465      *         error occured
00466      */
00467     inline bool decomposition(matrix<T>& src, 
00468                               vector<T>& w, 
00469                               matrix<T>& v) const {
00470       return svd->decomposition(src,w,v);
00471     }
00472 
00473     /**
00474      * OnPlace version of Singular Value Decomposition.
00475      * @param src matrix<T> with the source matrix, will also contain
00476      *            the U matrix after the function has returned.
00477      * @param w vector<T> with the singular values, sorted descendingly if
00478      *                    parameters::sort is true.
00479      *                    The elements of this vector constitute the diagonal
00480      *                    of the W matrix.
00481      * @param v the V matrix
00482      * @return true is the decomposition was successfull, false if an
00483      *         error occured
00484      */
00485     inline bool apply(matrix<T>& src, vector<T>& w, matrix<T>& v) const {
00486       return svd->apply(src,w,v);
00487     }
00488 
00489     /**
00490      * OnCopy version of Singular Value Decomposition.
00491      * @param src matrix<T> with the source matrix
00492      * @param u the U matrix
00493      * @param w vector<T> with the singular values, sorted descendingly if
00494      *                    parameters::sort is true.
00495      *                    The elements of this vector constitute the diagonal
00496      *                    of the W matrix.
00497      * @param v the V matrix
00498      * @return true is the decomposition was successfull, false if an
00499      *         error occured
00500      */
00501     inline bool apply(const matrix<T>& src, matrix<T>& u,
00502                       vector<T>& w, matrix<T>& v) const {
00503       return svd->apply(src,u,w,v);
00504     }
00505 
00506     
00507   protected:
00508     
00509     /**
00510      * The actual eigenSystem.
00511      */
00512     singularValueDecomp<T>* svd;
00513     
00514   };
00515 }
00516 
00517 #endif

Generated on Sat Apr 10 15:26:20 2010 for LTI-Lib by Doxygen 1.6.1