[136] | 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@inria.fr>
|
---|
| 5 | // Copyright (C) 2010 Jitse Niesen <jitse@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
|
---|