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 |
---|