Warning, file /include/eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef EIGEN_GENERALIZEDEIGENSOLVER_H
0013 #define EIGEN_GENERALIZEDEIGENSOLVER_H
0014
0015 #include "./RealQZ.h"
0016
0017 namespace Eigen {
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template<typename _MatrixType> class GeneralizedEigenSolver
0059 {
0060 public:
0061
0062
0063 typedef _MatrixType MatrixType;
0064
0065 enum {
0066 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
0067 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0068 Options = MatrixType::Options,
0069 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0070 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0071 };
0072
0073
0074 typedef typename MatrixType::Scalar Scalar;
0075 typedef typename NumTraits<Scalar>::Real RealScalar;
0076 typedef Eigen::Index Index;
0077
0078
0079
0080
0081
0082
0083
0084 typedef std::complex<RealScalar> ComplexScalar;
0085
0086
0087
0088
0089
0090
0091 typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> VectorType;
0092
0093
0094
0095
0096
0097
0098 typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ComplexVectorType;
0099
0100
0101
0102 typedef CwiseBinaryOp<internal::scalar_quotient_op<ComplexScalar,Scalar>,ComplexVectorType,VectorType> EigenvalueType;
0103
0104
0105
0106
0107
0108
0109 typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorsType;
0110
0111
0112
0113
0114
0115
0116
0117
0118 GeneralizedEigenSolver()
0119 : m_eivec(),
0120 m_alphas(),
0121 m_betas(),
0122 m_valuesOkay(false),
0123 m_vectorsOkay(false),
0124 m_realQZ()
0125 {}
0126
0127
0128
0129
0130
0131
0132
0133 explicit GeneralizedEigenSolver(Index size)
0134 : m_eivec(size, size),
0135 m_alphas(size),
0136 m_betas(size),
0137 m_valuesOkay(false),
0138 m_vectorsOkay(false),
0139 m_realQZ(size),
0140 m_tmp(size)
0141 {}
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 GeneralizedEigenSolver(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true)
0156 : m_eivec(A.rows(), A.cols()),
0157 m_alphas(A.cols()),
0158 m_betas(A.cols()),
0159 m_valuesOkay(false),
0160 m_vectorsOkay(false),
0161 m_realQZ(A.cols()),
0162 m_tmp(A.cols())
0163 {
0164 compute(A, B, computeEigenvectors);
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 EigenvectorsType eigenvectors() const {
0180 eigen_assert(m_vectorsOkay && "Eigenvectors for GeneralizedEigenSolver were not calculated.");
0181 return m_eivec;
0182 }
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 EigenvalueType eigenvalues() const
0203 {
0204 eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
0205 return EigenvalueType(m_alphas,m_betas);
0206 }
0207
0208
0209
0210
0211
0212
0213 ComplexVectorType alphas() const
0214 {
0215 eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
0216 return m_alphas;
0217 }
0218
0219
0220
0221
0222
0223
0224 VectorType betas() const
0225 {
0226 eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
0227 return m_betas;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 GeneralizedEigenSolver& compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true);
0254
0255 ComputationInfo info() const
0256 {
0257 eigen_assert(m_valuesOkay && "EigenSolver is not initialized.");
0258 return m_realQZ.info();
0259 }
0260
0261
0262
0263 GeneralizedEigenSolver& setMaxIterations(Index maxIters)
0264 {
0265 m_realQZ.setMaxIterations(maxIters);
0266 return *this;
0267 }
0268
0269 protected:
0270
0271 static void check_template_parameters()
0272 {
0273 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
0274 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
0275 }
0276
0277 EigenvectorsType m_eivec;
0278 ComplexVectorType m_alphas;
0279 VectorType m_betas;
0280 bool m_valuesOkay, m_vectorsOkay;
0281 RealQZ<MatrixType> m_realQZ;
0282 ComplexVectorType m_tmp;
0283 };
0284
0285 template<typename MatrixType>
0286 GeneralizedEigenSolver<MatrixType>&
0287 GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
0288 {
0289 check_template_parameters();
0290
0291 using std::sqrt;
0292 using std::abs;
0293 eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
0294 Index size = A.cols();
0295 m_valuesOkay = false;
0296 m_vectorsOkay = false;
0297
0298
0299 m_realQZ.compute(A, B, computeEigenvectors);
0300 if (m_realQZ.info() == Success)
0301 {
0302
0303 m_alphas.resize(size);
0304 m_betas.resize(size);
0305 if (computeEigenvectors)
0306 {
0307 m_eivec.resize(size,size);
0308 m_tmp.resize(size);
0309 }
0310
0311
0312 Map<VectorType> v(reinterpret_cast<Scalar*>(m_tmp.data()), size);
0313 ComplexVectorType &cv = m_tmp;
0314 const MatrixType &mS = m_realQZ.matrixS();
0315 const MatrixType &mT = m_realQZ.matrixT();
0316
0317 Index i = 0;
0318 while (i < size)
0319 {
0320 if (i == size - 1 || mS.coeff(i+1, i) == Scalar(0))
0321 {
0322
0323 m_alphas.coeffRef(i) = mS.diagonal().coeff(i);
0324 m_betas.coeffRef(i) = mT.diagonal().coeff(i);
0325 if (computeEigenvectors)
0326 {
0327 v.setConstant(Scalar(0.0));
0328 v.coeffRef(i) = Scalar(1.0);
0329
0330 if(abs(m_betas.coeffRef(i)) >= (std::numeric_limits<RealScalar>::min)())
0331 {
0332
0333 const Scalar alpha = real(m_alphas.coeffRef(i));
0334 const Scalar beta = m_betas.coeffRef(i);
0335 for (Index j = i-1; j >= 0; j--)
0336 {
0337 const Index st = j+1;
0338 const Index sz = i-j;
0339 if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
0340 {
0341
0342 Matrix<Scalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( v.segment(st,sz) );
0343 Matrix<Scalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
0344 v.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
0345 j--;
0346 }
0347 else
0348 {
0349 v.coeffRef(j) = -v.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum() / (beta*mS.coeffRef(j,j) - alpha*mT.coeffRef(j,j));
0350 }
0351 }
0352 }
0353 m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v;
0354 m_eivec.col(i).real().normalize();
0355 m_eivec.col(i).imag().setConstant(0);
0356 }
0357 ++i;
0358 }
0359 else
0360 {
0361
0362
0363
0364
0365
0366 RealScalar a = mT.diagonal().coeff(i),
0367 b = mT.diagonal().coeff(i+1);
0368 const RealScalar beta = m_betas.coeffRef(i) = m_betas.coeffRef(i+1) = a*b;
0369
0370
0371 Matrix<RealScalar,2,2> S2 = mS.template block<2,2>(i,i) * Matrix<Scalar,2,1>(b,a).asDiagonal();
0372
0373 Scalar p = Scalar(0.5) * (S2.coeff(0,0) - S2.coeff(1,1));
0374 Scalar z = sqrt(abs(p * p + S2.coeff(1,0) * S2.coeff(0,1)));
0375 const ComplexScalar alpha = ComplexScalar(S2.coeff(1,1) + p, (beta > 0) ? z : -z);
0376 m_alphas.coeffRef(i) = conj(alpha);
0377 m_alphas.coeffRef(i+1) = alpha;
0378
0379 if (computeEigenvectors) {
0380
0381 cv.setZero();
0382 cv.coeffRef(i+1) = Scalar(1.0);
0383
0384 cv.coeffRef(i) = -(static_cast<Scalar>(beta*mS.coeffRef(i,i+1)) - alpha*mT.coeffRef(i,i+1))
0385 / (static_cast<Scalar>(beta*mS.coeffRef(i,i)) - alpha*mT.coeffRef(i,i));
0386 for (Index j = i-1; j >= 0; j--)
0387 {
0388 const Index st = j+1;
0389 const Index sz = i+1-j;
0390 if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
0391 {
0392
0393 Matrix<ComplexScalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( cv.segment(st,sz) );
0394 Matrix<ComplexScalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
0395 cv.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
0396 j--;
0397 } else {
0398 cv.coeffRef(j) = cv.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum()
0399 / (alpha*mT.coeffRef(j,j) - static_cast<Scalar>(beta*mS.coeffRef(j,j)));
0400 }
0401 }
0402 m_eivec.col(i+1).noalias() = (m_realQZ.matrixZ().transpose() * cv);
0403 m_eivec.col(i+1).normalize();
0404 m_eivec.col(i) = m_eivec.col(i+1).conjugate();
0405 }
0406 i += 2;
0407 }
0408 }
0409
0410 m_valuesOkay = true;
0411 m_vectorsOkay = computeEigenvectors;
0412 }
0413 return *this;
0414 }
0415
0416 }
0417
0418 #endif