1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud (at) inria.fr> 5 // Copyright (C) 2010 Jitse Niesen <jitse (at) maths.leeds.ac.uk> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H 12 #define EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H 13 14 #include "./Tridiagonalization.h" 15 16 namespace Eigen { 17 18 /** \eigenvalues_module \ingroup Eigenvalues_Module 19 * 20 * 21 * \class GeneralizedSelfAdjointEigenSolver 22 * 23 * \brief Computes eigenvalues and eigenvectors of the generalized selfadjoint eigen problem 24 * 25 * \tparam _MatrixType the type of the matrix of which we are computing the 26 * eigendecomposition; this is expected to be an instantiation of the Matrix 27 * class template. 28 * 29 * This class solves the generalized eigenvalue problem 30 * \f$ Av = \lambda Bv \f$. In this case, the matrix \f$ A \f$ should be 31 * selfadjoint and the matrix \f$ B \f$ should be positive definite. 32 * 33 * Only the \b lower \b triangular \b part of the input matrix is referenced. 34 * 35 * Call the function compute() to compute the eigenvalues and eigenvectors of 36 * a given matrix. Alternatively, you can use the 37 * GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int) 38 * constructor which computes the eigenvalues and eigenvectors at construction time. 39 * Once the eigenvalue and eigenvectors are computed, they can be retrieved with the eigenvalues() 40 * and eigenvectors() functions. 41 * 42 * The documentation for GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int) 43 * contains an example of the typical use of this class. 44 * 45 * \sa class SelfAdjointEigenSolver, class EigenSolver, class ComplexEigenSolver 46 */ 47 template<typename _MatrixType> 48 class GeneralizedSelfAdjointEigenSolver : public SelfAdjointEigenSolver<_MatrixType> 49 { 50 typedef SelfAdjointEigenSolver<_MatrixType> Base; 51 public: 52 53 typedef typename Base::Index Index; 54 typedef _MatrixType MatrixType; 55 56 /** \brief Default constructor for fixed-size matrices. 57 * 58 * The default constructor is useful in cases in which the user intends to 59 * perform decompositions via compute(). This constructor 60 * can only be used if \p _MatrixType is a fixed-size matrix; use 61 * GeneralizedSelfAdjointEigenSolver(Index) for dynamic-size matrices. 62 */ 63 GeneralizedSelfAdjointEigenSolver() : Base() {} 64 65 /** \brief Constructor, pre-allocates memory for dynamic-size matrices. 66 * 67 * \param [in] size Positive integer, size of the matrix whose 68 * eigenvalues and eigenvectors will be computed. 69 * 70 * This constructor is useful for dynamic-size matrices, when the user 71 * intends to perform decompositions via compute(). The \p size 72 * parameter is only used as a hint. It is not an error to give a wrong 73 * \p size, but it may impair performance. 74 * 75 * \sa compute() for an example 76 */ 77 GeneralizedSelfAdjointEigenSolver(Index size) 78 : Base(size) 79 {} 80 81 /** \brief Constructor; computes generalized eigendecomposition of given matrix pencil. 82 * 83 * \param[in] matA Selfadjoint matrix in matrix pencil. 84 * Only the lower triangular part of the matrix is referenced. 85 * \param[in] matB Positive-definite matrix in matrix pencil. 86 * Only the lower triangular part of the matrix is referenced. 87 * \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}. 88 * Default is #ComputeEigenvectors|#Ax_lBx. 89 * 90 * This constructor calls compute(const MatrixType&, const MatrixType&, int) 91 * to compute the eigenvalues and (if requested) the eigenvectors of the 92 * generalized eigenproblem \f$ Ax = \lambda B x \f$ with \a matA the 93 * selfadjoint matrix \f$ A \f$ and \a matB the positive definite matrix 94 * \f$ B \f$. Each eigenvector \f$ x \f$ satisfies the property 95 * \f$ x^* B x = 1 \f$. The eigenvectors are computed if 96 * \a options contains ComputeEigenvectors. 97 * 98 * In addition, the two following variants can be solved via \p options: 99 * - \c ABx_lx: \f$ ABx = \lambda x \f$ 100 * - \c BAx_lx: \f$ BAx = \lambda x \f$ 101 * 102 * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType2.cpp 103 * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType2.out 104 * 105 * \sa compute(const MatrixType&, const MatrixType&, int) 106 */ 107 GeneralizedSelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB, 108 int options = ComputeEigenvectors|Ax_lBx) 109 : Base(matA.cols()) 110 { 111 compute(matA, matB, options); 112 } 113 114 /** \brief Computes generalized eigendecomposition of given matrix pencil. 115 * 116 * \param[in] matA Selfadjoint matrix in matrix pencil. 117 * Only the lower triangular part of the matrix is referenced. 118 * \param[in] matB Positive-definite matrix in matrix pencil. 119 * Only the lower triangular part of the matrix is referenced. 120 * \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}. 121 * Default is #ComputeEigenvectors|#Ax_lBx. 122 * 123 * \returns Reference to \c *this 124 * 125 * Accoring to \p options, this function computes eigenvalues and (if requested) 126 * the eigenvectors of one of the following three generalized eigenproblems: 127 * - \c Ax_lBx: \f$ Ax = \lambda B x \f$ 128 * - \c ABx_lx: \f$ ABx = \lambda x \f$ 129 * - \c BAx_lx: \f$ BAx = \lambda x \f$ 130 * with \a matA the selfadjoint matrix \f$ A \f$ and \a matB the positive definite 131 * matrix \f$ B \f$. 132 * In addition, each eigenvector \f$ x \f$ satisfies the property \f$ x^* B x = 1 \f$. 133 * 134 * The eigenvalues() function can be used to retrieve 135 * the eigenvalues. If \p options contains ComputeEigenvectors, then the 136 * eigenvectors are also computed and can be retrieved by calling 137 * eigenvectors(). 138 * 139 * The implementation uses LLT to compute the Cholesky decomposition 140 * \f$ B = LL^* \f$ and computes the classical eigendecomposition 141 * of the selfadjoint matrix \f$ L^{-1} A (L^*)^{-1} \f$ if \p options contains Ax_lBx 142 * and of \f$ L^{*} A L \f$ otherwise. This solves the 143 * generalized eigenproblem, because any solution of the generalized 144 * eigenproblem \f$ Ax = \lambda B x \f$ corresponds to a solution 145 * \f$ L^{-1} A (L^*)^{-1} (L^* x) = \lambda (L^* x) \f$ of the 146 * eigenproblem for \f$ L^{-1} A (L^*)^{-1} \f$. Similar statements 147 * can be made for the two other variants. 148 * 149 * Example: \include SelfAdjointEigenSolver_compute_MatrixType2.cpp 150 * Output: \verbinclude SelfAdjointEigenSolver_compute_MatrixType2.out 151 * 152 * \sa GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int) 153 */ 154 GeneralizedSelfAdjointEigenSolver& compute(const MatrixType& matA, const MatrixType& matB, 155 int options = ComputeEigenvectors|Ax_lBx); 156 157 protected: 158 159 }; 160 161 162 template<typename MatrixType> 163 GeneralizedSelfAdjointEigenSolver<MatrixType>& GeneralizedSelfAdjointEigenSolver<MatrixType>:: 164 compute(const MatrixType& matA, const MatrixType& matB, int options) 165 { 166 eigen_assert(matA.cols()==matA.rows() && matB.rows()==matA.rows() && matB.cols()==matB.rows()); 167 eigen_assert((options&~(EigVecMask|GenEigMask))==0 168 && (options&EigVecMask)!=EigVecMask 169 && ((options&GenEigMask)==0 || (options&GenEigMask)==Ax_lBx 170 || (options&GenEigMask)==ABx_lx || (options&GenEigMask)==BAx_lx) 171 && "invalid option parameter"); 172 173 bool computeEigVecs = ((options&EigVecMask)==0) || ((options&EigVecMask)==ComputeEigenvectors); 174 175 // Compute the cholesky decomposition of matB = L L' = U'U 176 LLT<MatrixType> cholB(matB); 177 178 int type = (options&GenEigMask); 179 if(type==0) 180 type = Ax_lBx; 181 182 if(type==Ax_lBx) 183 { 184 // compute C = inv(L) A inv(L') 185 MatrixType matC = matA.template selfadjointView<Lower>(); 186 cholB.matrixL().template solveInPlace<OnTheLeft>(matC); 187 cholB.matrixU().template solveInPlace<OnTheRight>(matC); 188 189 Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly ); 190 191 // transform back the eigen vectors: evecs = inv(U) * evecs 192 if(computeEigVecs) 193 cholB.matrixU().solveInPlace(Base::m_eivec); 194 } 195 else if(type==ABx_lx) 196 { 197 // compute C = L' A L 198 MatrixType matC = matA.template selfadjointView<Lower>(); 199 matC = matC * cholB.matrixL(); 200 matC = cholB.matrixU() * matC; 201 202 Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly); 203 204 // transform back the eigen vectors: evecs = inv(U) * evecs 205 if(computeEigVecs) 206 cholB.matrixU().solveInPlace(Base::m_eivec); 207 } 208 else if(type==BAx_lx) 209 { 210 // compute C = L' A L 211 MatrixType matC = matA.template selfadjointView<Lower>(); 212 matC = matC * cholB.matrixL(); 213 matC = cholB.matrixU() * matC; 214 215 Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly); 216 217 // transform back the eigen vectors: evecs = L * evecs 218 if(computeEigVecs) 219 Base::m_eivec = cholB.matrixL() * Base::m_eivec; 220 } 221 222 return *this; 223 } 224 225 } // end namespace Eigen 226 227 #endif // EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H 228