Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
GeneralizedEigenSolver.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2012-2016 Gael Guennebaud <[email protected]>
5// Copyright (C) 2010,2012 Jitse Niesen <[email protected]>
6// Copyright (C) 2016 Tobias Wood <[email protected]>
7//
8// This Source Code Form is subject to the terms of the Mozilla
9// Public License v. 2.0. If a copy of the MPL was not distributed
10// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11
12#ifndef EIGEN_GENERALIZEDEIGENSOLVER_H
13#define EIGEN_GENERALIZEDEIGENSOLVER_H
14
15#include "./RealQZ.h"
16
17// IWYU pragma: private
18#include "./InternalHeaderCheck.h"
19
20namespace Eigen {
21
61template <typename MatrixType_>
63 public:
65 typedef MatrixType_ MatrixType;
66
67 enum {
68 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
69 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
70 Options = internal::traits<MatrixType>::Options,
71 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
72 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
73 };
74
76 typedef typename MatrixType::Scalar Scalar;
77 typedef typename NumTraits<Scalar>::Real RealScalar;
79
86 typedef std::complex<RealScalar> ComplexScalar;
87
94
101
106
112 typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime,
113 MaxColsAtCompileTime>
115
124 : m_eivec(), m_alphas(), m_betas(), m_computeEigenvectors(false), m_isInitialized(false), m_realQZ() {}
125
133 : m_eivec(size, size),
134 m_alphas(size),
135 m_betas(size),
136 m_computeEigenvectors(false),
137 m_isInitialized(false),
138 m_realQZ(size),
139 m_tmp(size) {}
140
153 GeneralizedEigenSolver(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true)
154 : m_eivec(A.rows(), A.cols()),
155 m_alphas(A.cols()),
156 m_betas(A.cols()),
157 m_computeEigenvectors(false),
158 m_isInitialized(false),
159 m_realQZ(A.cols()),
160 m_tmp(A.cols()) {
161 compute(A, B, computeEigenvectors);
162 }
163
164 /* \brief Returns the computed generalized eigenvectors.
165 *
166 * \returns %Matrix whose columns are the (possibly complex) right eigenvectors.
167 * i.e. the eigenvectors that solve (A - l*B)x = 0. The ordering matches the eigenvalues.
168 *
169 * \pre Either the constructor
170 * GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
171 * compute(const MatrixType&, const MatrixType& bool) has been called before, and
172 * \p computeEigenvectors was set to true (the default).
173 *
174 * \sa eigenvalues()
175 */
176 EigenvectorsType eigenvectors() const {
177 eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvectors");
178 eigen_assert(m_computeEigenvectors && "Eigenvectors for GeneralizedEigenSolver were not calculated");
179 return m_eivec;
180 }
181
201 eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvalues.");
202 return EigenvalueType(m_alphas, m_betas);
203 }
204
210 const ComplexVectorType& alphas() const {
211 eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute alphas.");
212 return m_alphas;
213 }
214
220 const VectorType& betas() const {
221 eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute betas.");
222 return m_betas;
223 }
224
248 GeneralizedEigenSolver& compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true);
249
250 ComputationInfo info() const {
251 eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
252 return m_realQZ.info();
253 }
254
258 m_realQZ.setMaxIterations(maxIters);
259 return *this;
260 }
261
262 protected:
263 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
264 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
265
266 EigenvectorsType m_eivec;
267 ComplexVectorType m_alphas;
268 VectorType m_betas;
269 bool m_computeEigenvectors;
270 bool m_isInitialized;
271 RealQZ<MatrixType> m_realQZ;
272 ComplexVectorType m_tmp;
273};
274
275template <typename MatrixType>
277 const MatrixType& B,
278 bool computeEigenvectors) {
279 using std::abs;
280 using std::sqrt;
281 eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
282 Index size = A.cols();
283 // Reduce to generalized real Schur form:
284 // A = Q S Z and B = Q T Z
285 m_realQZ.compute(A, B, computeEigenvectors);
286 if (m_realQZ.info() == Success) {
287 // Resize storage
288 m_alphas.resize(size);
289 m_betas.resize(size);
290 if (computeEigenvectors) {
291 m_eivec.resize(size, size);
292 m_tmp.resize(size);
293 }
294
295 // Aliases:
296 Map<VectorType> v(reinterpret_cast<Scalar*>(m_tmp.data()), size);
297 ComplexVectorType& cv = m_tmp;
298 const MatrixType& mS = m_realQZ.matrixS();
299 const MatrixType& mT = m_realQZ.matrixT();
300
301 Index i = 0;
302 while (i < size) {
303 if (i == size - 1 || mS.coeff(i + 1, i) == Scalar(0)) {
304 // Real eigenvalue
305 m_alphas.coeffRef(i) = mS.diagonal().coeff(i);
306 m_betas.coeffRef(i) = mT.diagonal().coeff(i);
307 if (computeEigenvectors) {
308 v.setConstant(Scalar(0.0));
309 v.coeffRef(i) = Scalar(1.0);
310 // For singular eigenvalues do nothing more
311 if (abs(m_betas.coeffRef(i)) >= (std::numeric_limits<RealScalar>::min)()) {
312 // Non-singular eigenvalue
313 const Scalar alpha = real(m_alphas.coeffRef(i));
314 const Scalar beta = m_betas.coeffRef(i);
315 for (Index j = i - 1; j >= 0; j--) {
316 const Index st = j + 1;
317 const Index sz = i - j;
318 if (j > 0 && mS.coeff(j, j - 1) != Scalar(0)) {
319 // 2x2 block
320 Matrix<Scalar, 2, 1> rhs = (alpha * mT.template block<2, Dynamic>(j - 1, st, 2, sz) -
321 beta * mS.template block<2, Dynamic>(j - 1, st, 2, sz))
322 .lazyProduct(v.segment(st, sz));
324 beta * mS.template block<2, 2>(j - 1, j - 1) - alpha * mT.template block<2, 2>(j - 1, j - 1);
325 v.template segment<2>(j - 1) = lhs.partialPivLu().solve(rhs);
326 j--;
327 } else {
328 v.coeffRef(j) = -v.segment(st, sz)
329 .transpose()
330 .cwiseProduct(beta * mS.block(j, st, 1, sz) - alpha * mT.block(j, st, 1, sz))
331 .sum() /
332 (beta * mS.coeffRef(j, j) - alpha * mT.coeffRef(j, j));
333 }
334 }
335 }
336 m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v;
337 m_eivec.col(i).real().normalize();
338 m_eivec.col(i).imag().setConstant(0);
339 }
340 ++i;
341 } else {
342 // We need to extract the generalized eigenvalues of the pair of a general 2x2 block S and a positive diagonal
343 // 2x2 block T Then taking beta=T_00*T_11, we can avoid any division, and alpha is the eigenvalues of A = (U^-1
344 // * S * U) * diag(T_11,T_00):
345
346 // T = [a 0]
347 // [0 b]
348 RealScalar a = mT.diagonal().coeff(i), b = mT.diagonal().coeff(i + 1);
349 const RealScalar beta = m_betas.coeffRef(i) = m_betas.coeffRef(i + 1) = a * b;
350
351 // ^^ NOTE: using diagonal()(i) instead of coeff(i,i) workarounds a MSVC bug.
352 Matrix<RealScalar, 2, 2> S2 = mS.template block<2, 2>(i, i) * Matrix<Scalar, 2, 1>(b, a).asDiagonal();
353
354 Scalar p = Scalar(0.5) * (S2.coeff(0, 0) - S2.coeff(1, 1));
355 Scalar z = sqrt(abs(p * p + S2.coeff(1, 0) * S2.coeff(0, 1)));
356 const ComplexScalar alpha = ComplexScalar(S2.coeff(1, 1) + p, (beta > 0) ? z : -z);
357 m_alphas.coeffRef(i) = conj(alpha);
358 m_alphas.coeffRef(i + 1) = alpha;
359
360 if (computeEigenvectors) {
361 // Compute eigenvector in position (i+1) and then position (i) is just the conjugate
362 cv.setZero();
363 cv.coeffRef(i + 1) = Scalar(1.0);
364 // here, the "static_cast" workaound expression template issues.
365 cv.coeffRef(i) = -(static_cast<Scalar>(beta * mS.coeffRef(i, i + 1)) - alpha * mT.coeffRef(i, i + 1)) /
366 (static_cast<Scalar>(beta * mS.coeffRef(i, i)) - alpha * mT.coeffRef(i, i));
367 for (Index j = i - 1; j >= 0; j--) {
368 const Index st = j + 1;
369 const Index sz = i + 1 - j;
370 if (j > 0 && mS.coeff(j, j - 1) != Scalar(0)) {
371 // 2x2 block
372 Matrix<ComplexScalar, 2, 1> rhs = (alpha * mT.template block<2, Dynamic>(j - 1, st, 2, sz) -
373 beta * mS.template block<2, Dynamic>(j - 1, st, 2, sz))
374 .lazyProduct(cv.segment(st, sz));
376 beta * mS.template block<2, 2>(j - 1, j - 1) - alpha * mT.template block<2, 2>(j - 1, j - 1);
377 cv.template segment<2>(j - 1) = lhs.partialPivLu().solve(rhs);
378 j--;
379 } else {
380 cv.coeffRef(j) = cv.segment(st, sz)
381 .transpose()
382 .cwiseProduct(beta * mS.block(j, st, 1, sz) - alpha * mT.block(j, st, 1, sz))
383 .sum() /
384 (alpha * mT.coeffRef(j, j) - static_cast<Scalar>(beta * mS.coeffRef(j, j)));
385 }
386 }
387 m_eivec.col(i + 1).noalias() = (m_realQZ.matrixZ().transpose() * cv);
388 m_eivec.col(i + 1).normalize();
389 m_eivec.col(i) = m_eivec.col(i + 1).conjugate();
390 }
391 i += 2;
392 }
393 }
394 }
395 m_computeEigenvectors = computeEigenvectors;
396 m_isInitialized = true;
397 return *this;
398}
399
400} // end namespace Eigen
401
402#endif // EIGEN_GENERALIZEDEIGENSOLVER_H
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition CwiseBinaryOp.h:79
Computes the generalized eigenvalues and eigenvectors of a pair of general matrices.
Definition GeneralizedEigenSolver.h:62
CwiseBinaryOp< internal::scalar_quotient_op< ComplexScalar, Scalar >, ComplexVectorType, VectorType > EigenvalueType
Expression type for the eigenvalues as returned by eigenvalues().
Definition GeneralizedEigenSolver.h:105
GeneralizedEigenSolver & compute(const MatrixType &A, const MatrixType &B, bool computeEigenvectors=true)
Computes generalized eigendecomposition of given matrix.
Definition GeneralizedEigenSolver.h:276
const VectorType & betas() const
Definition GeneralizedEigenSolver.h:220
std::complex< RealScalar > ComplexScalar
Complex scalar type for MatrixType.
Definition GeneralizedEigenSolver.h:86
Matrix< ComplexScalar, ColsAtCompileTime, 1, Options &~RowMajor, MaxColsAtCompileTime, 1 > ComplexVectorType
Type for vector of complex scalar values eigenvalues as returned by alphas().
Definition GeneralizedEigenSolver.h:100
Matrix< Scalar, ColsAtCompileTime, 1, Options &~RowMajor, MaxColsAtCompileTime, 1 > VectorType
Type for vector of real scalar values eigenvalues as returned by betas().
Definition GeneralizedEigenSolver.h:93
MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType.
Definition GeneralizedEigenSolver.h:76
GeneralizedEigenSolver()
Default constructor.
Definition GeneralizedEigenSolver.h:123
const ComplexVectorType & alphas() const
Definition GeneralizedEigenSolver.h:210
Eigen::Index Index
Definition GeneralizedEigenSolver.h:78
GeneralizedEigenSolver(const MatrixType &A, const MatrixType &B, bool computeEigenvectors=true)
Constructor; computes the generalized eigendecomposition of given matrix pair.
Definition GeneralizedEigenSolver.h:153
EigenvalueType eigenvalues() const
Returns an expression of the computed generalized eigenvalues.
Definition GeneralizedEigenSolver.h:200
GeneralizedEigenSolver(Index size)
Default constructor with memory preallocation.
Definition GeneralizedEigenSolver.h:132
GeneralizedEigenSolver & setMaxIterations(Index maxIters)
Definition GeneralizedEigenSolver.h:257
Matrix< ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime > EigenvectorsType
Type for matrix of eigenvectors as returned by eigenvectors().
Definition GeneralizedEigenSolver.h:114
MatrixType_ MatrixType
Synonym for the template parameter MatrixType_.
Definition GeneralizedEigenSolver.h:65
A matrix or vector expression mapping an existing array of data.
Definition Map.h:96
const DiagonalWrapper< const Derived > asDiagonal() const
Definition DiagonalMatrix.h:344
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:217
constexpr const Scalar & coeff(Index rowId, Index colId) const
Definition PlainObjectBase.h:198
Derived & setZero(Index size)
Definition CwiseNullaryOp.h:563
Performs a real QZ decomposition of a pair of square matrices.
Definition RealQZ.h:61
ComputationInfo info() const
Reports whether previous computation was successful.
Definition RealQZ.h:170
RealQZ & setMaxIterations(Index maxIters)
Definition RealQZ.h:185
ComputationInfo
Definition Constants.h:438
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition Core:137
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition Meta.h:523