latest version v1.9 - last update 10 Apr 2010 |
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 .......: ltiUnifiedGeneralizedEigenSystem.h 00027 * authors ....: Peter Doerfler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 21.11.2003 00030 * revisions ..: $Id: ltiUnifiedGeneralizedEigenSystem.h,v 1.8 2006/02/08 12:50:16 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_UNIFIED_GENERALIZED_EIGEN_SYSTEM_H_ 00034 #define _LTI_UNIFIED_GENERALIZED_EIGEN_SYSTEM_H_ 00035 00036 #include "ltiGeneralizedEigenSystem.h" 00037 #include "ltiLinearAlgebraFunctor.h" 00038 00039 00040 namespace lti { 00041 /** 00042 * This functor is meant to be used for solving any generalized 00043 * Eigenvalue problem without need to think about the most efficient 00044 * usage of the available methods. If the LAPACK is available it 00045 * will automatically be used since it is much faster. 00046 * 00047 * This functor only handles generalized Eigenvalue problems. For 00048 * non-generalized EV problems use there is only a LAPACK functor: 00049 * genEigenSystem. For the generalized eigenvalue problem either 00050 * generalizedEigenSystem or fastGeneralizedEigenSystem can be used. 00051 * 00052 * It is preferred to use this class instead of the generalized 00053 * eigenSystem functors available. 00054 */ 00055 template<class T> 00056 class unifiedGeneralizedEigenSystem : public linearAlgebraFunctor { 00057 public: 00058 /** 00059 * the parameters for the class unifiedGeneralizedEigenSystem. 00060 * 00061 * Note that the parameter problemType of 00062 * fastGeneralizedEigenSystem is statically set to Type1 in this 00063 * functor, which results in the same functionality as that of 00064 * generalizedEigenSystem. If you need other types use the LAPACK 00065 * method directly. 00066 */ 00067 class parameters : public linearAlgebraFunctor::parameters { 00068 public: 00069 00070 /** 00071 * The Eigensystem solution method to use. Note that functors 00072 * starting with Fast___ are only available if LAPACK is 00073 * used. The default is set according to your installation. 00074 */ 00075 enum eEigenSystemType { 00076 GeneralizedEigenSystem, /*!< use generalizedEigenSystem */ 00077 FastGeneralizedEigenSystem = 10 /*!< use fastGeneralizedEigenSystem */ 00078 }; 00079 00080 /** 00081 * default constructor 00082 */ 00083 parameters() : linearAlgebraFunctor::parameters() { 00084 00085 sort = true; 00086 dimensions = 0; 00087 useDC = true; 00088 #ifdef HAVE_LAPACK 00089 esType = FastGeneralizedEigenSystem; 00090 #else 00091 esType = GeneralizedEigenSystem; 00092 #endif 00093 }; 00094 00095 /** 00096 * copy constructor 00097 * @param other the parameters object to be copied 00098 */ 00099 parameters(const parameters& other) : linearAlgebraFunctor::parameters() { 00100 copy(other); 00101 } 00102 00103 /** 00104 * destructor 00105 */ 00106 ~parameters() { 00107 }; 00108 00109 /** 00110 * returns name of this type 00111 */ 00112 const char* getTypeName() const { 00113 return "unifiedGeneralizedEigenSystem::parameters"; 00114 }; 00115 00116 /** 00117 * copy the contents of a parameters object 00118 * @param other the parameters object to be copied 00119 * @return a reference to this parameters object 00120 */ 00121 parameters& copy(const parameters& other) { 00122 # ifndef _LTI_MSC_6 00123 // MS Visual C++ 6 is not able to compile this... 00124 linearAlgebraFunctor::parameters::copy(other); 00125 # else 00126 // ...so we have to use this workaround. 00127 // Conditional on that, copy may not be virtual. 00128 linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy) 00129 (const linearAlgebraFunctor::parameters&) = 00130 linearAlgebraFunctor::parameters::copy; 00131 (this->*p_copy)(other); 00132 # endif 00133 00134 00135 sort = other.sort; 00136 dimensions = other.dimensions; 00137 esType = other.esType; 00138 00139 return *this; 00140 }; 00141 00142 /** 00143 * copy the contents of a parameters object 00144 * @param other the parameters object to be copied 00145 * @return a reference to this parameters object 00146 */ 00147 parameters& operator=(const parameters& other) { 00148 return copy(other); 00149 }; 00150 00151 /** 00152 * returns a pointer to a clone of the parameters 00153 */ 00154 virtual functor::parameters* clone() const { 00155 return new parameters(*this); 00156 }; 00157 00158 # ifndef _LTI_MSC_6 00159 /** 00160 * write the parameters in the given ioHandler 00161 * @param handler the ioHandler to be used 00162 * @param complete if true (the default) the enclosing begin/end will 00163 * be also written, otherwise only the data block will be written. 00164 * @return true if write was successful 00165 */ 00166 virtual bool write(ioHandler& handler,const bool complete=true) const 00167 # else 00168 /** 00169 * this function is required by MSVC only, as a workaround for a 00170 * very awful bug, which exists since MSVC V.4.0, and still by 00171 * V.6.0 with all bugfixes (so called "service packs") remains 00172 * there... This method is also public due to another bug, so please 00173 * NEVER EVER call this method directly: use write() instead 00174 */ 00175 bool writeMS(ioHandler& handler,const bool complete=true) const 00176 # endif 00177 { 00178 bool b = true; 00179 if (complete) { 00180 b = handler.writeBegin(); 00181 } 00182 00183 if (b) { 00184 00185 lti::write(handler,"sort",sort); 00186 lti::write(handler,"dimensions",dimensions); 00187 00188 switch (esType) { 00189 case GeneralizedEigenSystem: 00190 lti::write(handler,"esType","GeneralizedEigenSystem"); 00191 break; 00192 case FastGeneralizedEigenSystem: 00193 lti::write(handler,"esType","FastGeneralizedEigenSystem"); 00194 break; 00195 default: 00196 #ifdef HAVE_LAPACK 00197 lti::write(handler,"esType","FastGeneralizedEigenSystem"); 00198 #else 00199 lti::write(handler,"esType","GeneralizedEigenSystem"); 00200 #endif 00201 break; 00202 } 00203 00204 } 00205 00206 # ifndef _LTI_MSC_6 00207 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00208 // compile... 00209 b = b && linearAlgebraFunctor::parameters::write(handler,false); 00210 # else 00211 bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&, 00212 const bool) const = 00213 linearAlgebraFunctor::parameters::writeMS; 00214 b = b && (this->*p_writeMS)(handler,false); 00215 # endif 00216 00217 if (complete) { 00218 b = b && handler.writeEnd(); 00219 } 00220 00221 return b; 00222 } 00223 00224 # ifdef _LTI_MSC_6 00225 /** 00226 * write the parameters in the given ioHandler 00227 * @param handler the ioHandler to be used 00228 * @param complete if true (the default) the enclosing begin/end will 00229 * be also written, otherwise only the data block will be written. 00230 * @return true if write was successful 00231 */ 00232 bool write(ioHandler& handler, 00233 const bool complete=true) const { 00234 // ...we need this workaround to cope with another really 00235 // awful MSVC bug. 00236 return writeMS(handler,complete); 00237 } 00238 # endif 00239 00240 00241 # ifndef _LTI_MSC_6 00242 /** 00243 * read the parameters from the given ioHandler 00244 * @param handler the ioHandler to be used 00245 * @param complete if true (the default) the enclosing begin/end will 00246 * be also written, otherwise only the data block will be written. 00247 * @return true if write was successful 00248 */ 00249 virtual bool read(ioHandler& handler,const bool complete=true) 00250 # else 00251 /** 00252 * this function is required by MSVC only, as a workaround for a 00253 * very awful bug, which exists since MSVC V.4.0, and still by 00254 * V.6.0 with all bugfixes (so called "service packs") remains 00255 * there... This method is also public due to another bug, so please 00256 * NEVER EVER call this method directly: use read() instead 00257 */ 00258 bool readMS(ioHandler& handler,const bool complete=true) 00259 # endif 00260 { 00261 bool b = true; 00262 if (complete) { 00263 b = handler.readBegin(); 00264 } 00265 00266 if (b) { 00267 00268 lti::read(handler,"sort",sort); 00269 lti::read(handler,"dimensions",dimensions); 00270 00271 std::string tmp; 00272 lti::read(handler,"esType",tmp); 00273 if (tmp=="GeneralizedEigenSystem") { 00274 esType = GeneralizedEigenSystem; 00275 } else if (tmp=="FastGeneralizedEigenSystem") { 00276 esType = FastGeneralizedEigenSystem; 00277 } else { 00278 #ifdef HAVE_LAPACK 00279 esType = FastGeneralizedEigenSystem; 00280 #else 00281 esType = GeneralizedEigenSystem; 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 write 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 eigenSystem<T>::parameters::sort. 00330 */ 00331 bool sort; 00332 00333 /** 00334 * The number of eigenvalues/-vectors to be calculated. If zero 00335 * all EV are calculated. Default 0. 00336 * 00337 * See also: 00338 * - generalizedEigenSystem<T>::parameters::dimensions 00339 * - fastGeneralizedEigenSystem<T>::parameters::dimensions 00340 */ 00341 int dimensions; 00342 00343 /** 00344 * The eigenSystem given is used. Note that you cannot use 00345 * fastGeneralizedEigenSystem if LAPACK is not installed. The 00346 * default is dependent on the the system configuration: If 00347 * LAPACK is available, fastGeneralizedEigenSystem is used, 00348 * otherwise generalizedEigenSystem. 00349 */ 00350 eEigenSystemType esType; 00351 00352 /** 00353 * This parameters is used only if 00354 * esType==FastGeneralizedEigenSystem. It determines whether the 00355 * divide and conquer strategy is used or not. Default true. 00356 * 00357 * See fastGeneralizedEigenSystem<T>::parameters::useDC 00358 */ 00359 bool useDC; 00360 00361 }; 00362 00363 /** 00364 * default constructor 00365 */ 00366 unifiedGeneralizedEigenSystem(); 00367 00368 /** 00369 * Construct a functor using the given parameters 00370 */ 00371 unifiedGeneralizedEigenSystem(const parameters& par); 00372 00373 /** 00374 * copy constructor 00375 * @param other the object to be copied 00376 */ 00377 unifiedGeneralizedEigenSystem(const unifiedGeneralizedEigenSystem& other); 00378 00379 /** 00380 * destructor 00381 */ 00382 virtual ~unifiedGeneralizedEigenSystem(); 00383 00384 /** 00385 * returns the name of this type ("unifiedGeneralizedEigenSystem") 00386 */ 00387 virtual const char* getTypeName() const; 00388 00389 /** 00390 * copy data of "other" functor. 00391 * @param other the functor to be copied 00392 * @return a reference to this functor object 00393 */ 00394 unifiedGeneralizedEigenSystem& 00395 copy(const unifiedGeneralizedEigenSystem& other); 00396 00397 /** 00398 * alias for copy member 00399 * @param other the functor to be copied 00400 * @return a reference to this functor object 00401 */ 00402 unifiedGeneralizedEigenSystem& 00403 operator=(const unifiedGeneralizedEigenSystem& other); 00404 00405 /** 00406 * returns a pointer to a clone of this functor. 00407 */ 00408 virtual functor* clone() const; 00409 00410 /** 00411 * Update functor's parameters. 00412 * 00413 * Update some internal data according to the parameters. 00414 * 00415 * @return true if successful, false otherwise 00416 */ 00417 virtual bool updateParameters(); 00418 00419 /** 00420 * returns used parameters 00421 */ 00422 const parameters& getParameters() const; 00423 00424 /** 00425 * Read the functor from the given ioHandler. 00426 * 00427 * This method automatically sets the correct eigensystem solver 00428 * that is given in the parameters and transfers the relevant 00429 * parameters to that functor. 00430 * 00431 * @param handler the ioHandler to be used 00432 * @param complete if true (the default) the enclosing begin/end will 00433 * be also written, otherwise only the data block will be written. 00434 * @return true if write was successful 00435 */ 00436 virtual bool read(ioHandler& handler,const bool complete=true); 00437 00438 /** 00439 * Computes eigenvalues and eigenvectors of the given matrix. The 00440 * functor can efficiently calculate only a few dimensions of the 00441 * eigenspace, taking those with the largest eigenvalues. The 00442 * number of dimensions is set with parameters::dimensions. 00443 * 00444 * @param a the symmetric matrix A 00445 * @param b the symmetric, positive definite matrix B 00446 * @param eigenvalues elements will contain the eigenvalues 00447 * @param eigenvectors columns will contain the eigenvectors 00448 * corresponding to the eigenvalues 00449 */ 00450 inline bool apply(const matrix<T>& a, 00451 const matrix<T>& b, 00452 vector<T>& eigenvalues, 00453 matrix<T>& eigenvectors) const { 00454 return eigen->apply(a,b,eigenvalues,eigenvectors); 00455 } 00456 00457 /** 00458 * Computes eigenvalues and eigenvectors of the given matrix. The 00459 * functor can efficiently calculate only a few dimensions of the 00460 * eigenspace, taking those with the largest eigenvalues. The 00461 * number of dimensions is set with parameters::dimensions. 00462 * 00463 * @param a the symmetric matrix A 00464 * @param b the symmetric, positive definite matrix B 00465 * @param eigenvalues elements will contain the eigenvalues 00466 */ 00467 inline bool apply(const matrix<T>& a, 00468 const matrix<T>& b, 00469 vector<T>& eigenvalues) const { 00470 return eigen->apply(a,b,eigenvalues); 00471 } 00472 00473 protected: 00474 00475 /** 00476 * The actual eigenSystem. 00477 */ 00478 generalizedEigenSystem<T>* eigen; 00479 00480 }; 00481 } 00482 00483 #endif