![]() |
|
|||
Warning, file /include/eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // This file is part of Eigen, a lightweight C++ template library 0002 // for linear algebra. 0003 // 0004 // Copyright (C) 2009 Claire Maurice 0005 // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> 0006 // Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk> 0007 // 0008 // This Source Code Form is subject to the terms of the Mozilla 0009 // Public License v. 2.0. If a copy of the MPL was not distributed 0010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 0011 0012 #ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H 0013 #define EIGEN_COMPLEX_EIGEN_SOLVER_H 0014 0015 #include "./ComplexSchur.h" 0016 0017 namespace Eigen { 0018 0019 /** \eigenvalues_module \ingroup Eigenvalues_Module 0020 * 0021 * 0022 * \class ComplexEigenSolver 0023 * 0024 * \brief Computes eigenvalues and eigenvectors of general complex matrices 0025 * 0026 * \tparam _MatrixType the type of the matrix of which we are 0027 * computing the eigendecomposition; this is expected to be an 0028 * instantiation of the Matrix class template. 0029 * 0030 * The eigenvalues and eigenvectors of a matrix \f$ A \f$ are scalars 0031 * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda v 0032 * \f$. If \f$ D \f$ is a diagonal matrix with the eigenvalues on 0033 * the diagonal, and \f$ V \f$ is a matrix with the eigenvectors as 0034 * its columns, then \f$ A V = V D \f$. The matrix \f$ V \f$ is 0035 * almost always invertible, in which case we have \f$ A = V D V^{-1} 0036 * \f$. This is called the eigendecomposition. 0037 * 0038 * The main function in this class is compute(), which computes the 0039 * eigenvalues and eigenvectors of a given function. The 0040 * documentation for that function contains an example showing the 0041 * main features of the class. 0042 * 0043 * \sa class EigenSolver, class SelfAdjointEigenSolver 0044 */ 0045 template<typename _MatrixType> class ComplexEigenSolver 0046 { 0047 public: 0048 0049 /** \brief Synonym for the template parameter \p _MatrixType. */ 0050 typedef _MatrixType MatrixType; 0051 0052 enum { 0053 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 0054 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 0055 Options = MatrixType::Options, 0056 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 0057 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 0058 }; 0059 0060 /** \brief Scalar type for matrices of type #MatrixType. */ 0061 typedef typename MatrixType::Scalar Scalar; 0062 typedef typename NumTraits<Scalar>::Real RealScalar; 0063 typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 0064 0065 /** \brief Complex scalar type for #MatrixType. 0066 * 0067 * This is \c std::complex<Scalar> if #Scalar is real (e.g., 0068 * \c float or \c double) and just \c Scalar if #Scalar is 0069 * complex. 0070 */ 0071 typedef std::complex<RealScalar> ComplexScalar; 0072 0073 /** \brief Type for vector of eigenvalues as returned by eigenvalues(). 0074 * 0075 * This is a column vector with entries of type #ComplexScalar. 0076 * The length of the vector is the size of #MatrixType. 0077 */ 0078 typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options&(~RowMajor), MaxColsAtCompileTime, 1> EigenvalueType; 0079 0080 /** \brief Type for matrix of eigenvectors as returned by eigenvectors(). 0081 * 0082 * This is a square matrix with entries of type #ComplexScalar. 0083 * The size is the same as the size of #MatrixType. 0084 */ 0085 typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorType; 0086 0087 /** \brief Default constructor. 0088 * 0089 * The default constructor is useful in cases in which the user intends to 0090 * perform decompositions via compute(). 0091 */ 0092 ComplexEigenSolver() 0093 : m_eivec(), 0094 m_eivalues(), 0095 m_schur(), 0096 m_isInitialized(false), 0097 m_eigenvectorsOk(false), 0098 m_matX() 0099 {} 0100 0101 /** \brief Default Constructor with memory preallocation 0102 * 0103 * Like the default constructor but with preallocation of the internal data 0104 * according to the specified problem \a size. 0105 * \sa ComplexEigenSolver() 0106 */ 0107 explicit ComplexEigenSolver(Index size) 0108 : m_eivec(size, size), 0109 m_eivalues(size), 0110 m_schur(size), 0111 m_isInitialized(false), 0112 m_eigenvectorsOk(false), 0113 m_matX(size, size) 0114 {} 0115 0116 /** \brief Constructor; computes eigendecomposition of given matrix. 0117 * 0118 * \param[in] matrix Square matrix whose eigendecomposition is to be computed. 0119 * \param[in] computeEigenvectors If true, both the eigenvectors and the 0120 * eigenvalues are computed; if false, only the eigenvalues are 0121 * computed. 0122 * 0123 * This constructor calls compute() to compute the eigendecomposition. 0124 */ 0125 template<typename InputType> 0126 explicit ComplexEigenSolver(const EigenBase<InputType>& matrix, bool computeEigenvectors = true) 0127 : m_eivec(matrix.rows(),matrix.cols()), 0128 m_eivalues(matrix.cols()), 0129 m_schur(matrix.rows()), 0130 m_isInitialized(false), 0131 m_eigenvectorsOk(false), 0132 m_matX(matrix.rows(),matrix.cols()) 0133 { 0134 compute(matrix.derived(), computeEigenvectors); 0135 } 0136 0137 /** \brief Returns the eigenvectors of given matrix. 0138 * 0139 * \returns A const reference to the matrix whose columns are the eigenvectors. 0140 * 0141 * \pre Either the constructor 0142 * ComplexEigenSolver(const MatrixType& matrix, bool) or the member 0143 * function compute(const MatrixType& matrix, bool) has been called before 0144 * to compute the eigendecomposition of a matrix, and 0145 * \p computeEigenvectors was set to true (the default). 0146 * 0147 * This function returns a matrix whose columns are the eigenvectors. Column 0148 * \f$ k \f$ is an eigenvector corresponding to eigenvalue number \f$ k 0149 * \f$ as returned by eigenvalues(). The eigenvectors are normalized to 0150 * have (Euclidean) norm equal to one. The matrix returned by this 0151 * function is the matrix \f$ V \f$ in the eigendecomposition \f$ A = V D 0152 * V^{-1} \f$, if it exists. 0153 * 0154 * Example: \include ComplexEigenSolver_eigenvectors.cpp 0155 * Output: \verbinclude ComplexEigenSolver_eigenvectors.out 0156 */ 0157 const EigenvectorType& eigenvectors() const 0158 { 0159 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized."); 0160 eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); 0161 return m_eivec; 0162 } 0163 0164 /** \brief Returns the eigenvalues of given matrix. 0165 * 0166 * \returns A const reference to the column vector containing the eigenvalues. 0167 * 0168 * \pre Either the constructor 0169 * ComplexEigenSolver(const MatrixType& matrix, bool) or the member 0170 * function compute(const MatrixType& matrix, bool) has been called before 0171 * to compute the eigendecomposition of a matrix. 0172 * 0173 * This function returns a column vector containing the 0174 * eigenvalues. Eigenvalues are repeated according to their 0175 * algebraic multiplicity, so there are as many eigenvalues as 0176 * rows in the matrix. The eigenvalues are not sorted in any particular 0177 * order. 0178 * 0179 * Example: \include ComplexEigenSolver_eigenvalues.cpp 0180 * Output: \verbinclude ComplexEigenSolver_eigenvalues.out 0181 */ 0182 const EigenvalueType& eigenvalues() const 0183 { 0184 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized."); 0185 return m_eivalues; 0186 } 0187 0188 /** \brief Computes eigendecomposition of given matrix. 0189 * 0190 * \param[in] matrix Square matrix whose eigendecomposition is to be computed. 0191 * \param[in] computeEigenvectors If true, both the eigenvectors and the 0192 * eigenvalues are computed; if false, only the eigenvalues are 0193 * computed. 0194 * \returns Reference to \c *this 0195 * 0196 * This function computes the eigenvalues of the complex matrix \p matrix. 0197 * The eigenvalues() function can be used to retrieve them. If 0198 * \p computeEigenvectors is true, then the eigenvectors are also computed 0199 * and can be retrieved by calling eigenvectors(). 0200 * 0201 * The matrix is first reduced to Schur form using the 0202 * ComplexSchur class. The Schur decomposition is then used to 0203 * compute the eigenvalues and eigenvectors. 0204 * 0205 * The cost of the computation is dominated by the cost of the 0206 * Schur decomposition, which is \f$ O(n^3) \f$ where \f$ n \f$ 0207 * is the size of the matrix. 0208 * 0209 * Example: \include ComplexEigenSolver_compute.cpp 0210 * Output: \verbinclude ComplexEigenSolver_compute.out 0211 */ 0212 template<typename InputType> 0213 ComplexEigenSolver& compute(const EigenBase<InputType>& matrix, bool computeEigenvectors = true); 0214 0215 /** \brief Reports whether previous computation was successful. 0216 * 0217 * \returns \c Success if computation was successful, \c NoConvergence otherwise. 0218 */ 0219 ComputationInfo info() const 0220 { 0221 eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized."); 0222 return m_schur.info(); 0223 } 0224 0225 /** \brief Sets the maximum number of iterations allowed. */ 0226 ComplexEigenSolver& setMaxIterations(Index maxIters) 0227 { 0228 m_schur.setMaxIterations(maxIters); 0229 return *this; 0230 } 0231 0232 /** \brief Returns the maximum number of iterations. */ 0233 Index getMaxIterations() 0234 { 0235 return m_schur.getMaxIterations(); 0236 } 0237 0238 protected: 0239 0240 static void check_template_parameters() 0241 { 0242 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 0243 } 0244 0245 EigenvectorType m_eivec; 0246 EigenvalueType m_eivalues; 0247 ComplexSchur<MatrixType> m_schur; 0248 bool m_isInitialized; 0249 bool m_eigenvectorsOk; 0250 EigenvectorType m_matX; 0251 0252 private: 0253 void doComputeEigenvectors(RealScalar matrixnorm); 0254 void sortEigenvalues(bool computeEigenvectors); 0255 }; 0256 0257 0258 template<typename MatrixType> 0259 template<typename InputType> 0260 ComplexEigenSolver<MatrixType>& 0261 ComplexEigenSolver<MatrixType>::compute(const EigenBase<InputType>& matrix, bool computeEigenvectors) 0262 { 0263 check_template_parameters(); 0264 0265 // this code is inspired from Jampack 0266 eigen_assert(matrix.cols() == matrix.rows()); 0267 0268 // Do a complex Schur decomposition, A = U T U^* 0269 // The eigenvalues are on the diagonal of T. 0270 m_schur.compute(matrix.derived(), computeEigenvectors); 0271 0272 if(m_schur.info() == Success) 0273 { 0274 m_eivalues = m_schur.matrixT().diagonal(); 0275 if(computeEigenvectors) 0276 doComputeEigenvectors(m_schur.matrixT().norm()); 0277 sortEigenvalues(computeEigenvectors); 0278 } 0279 0280 m_isInitialized = true; 0281 m_eigenvectorsOk = computeEigenvectors; 0282 return *this; 0283 } 0284 0285 0286 template<typename MatrixType> 0287 void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm) 0288 { 0289 const Index n = m_eivalues.size(); 0290 0291 matrixnorm = numext::maxi(matrixnorm,(std::numeric_limits<RealScalar>::min)()); 0292 0293 // Compute X such that T = X D X^(-1), where D is the diagonal of T. 0294 // The matrix X is unit triangular. 0295 m_matX = EigenvectorType::Zero(n, n); 0296 for(Index k=n-1 ; k>=0 ; k--) 0297 { 0298 m_matX.coeffRef(k,k) = ComplexScalar(1.0,0.0); 0299 // Compute X(i,k) using the (i,k) entry of the equation X T = D X 0300 for(Index i=k-1 ; i>=0 ; i--) 0301 { 0302 m_matX.coeffRef(i,k) = -m_schur.matrixT().coeff(i,k); 0303 if(k-i-1>0) 0304 m_matX.coeffRef(i,k) -= (m_schur.matrixT().row(i).segment(i+1,k-i-1) * m_matX.col(k).segment(i+1,k-i-1)).value(); 0305 ComplexScalar z = m_schur.matrixT().coeff(i,i) - m_schur.matrixT().coeff(k,k); 0306 if(z==ComplexScalar(0)) 0307 { 0308 // If the i-th and k-th eigenvalue are equal, then z equals 0. 0309 // Use a small value instead, to prevent division by zero. 0310 numext::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm; 0311 } 0312 m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z; 0313 } 0314 } 0315 0316 // Compute V as V = U X; now A = U T U^* = U X D X^(-1) U^* = V D V^(-1) 0317 m_eivec.noalias() = m_schur.matrixU() * m_matX; 0318 // .. and normalize the eigenvectors 0319 for(Index k=0 ; k<n ; k++) 0320 { 0321 m_eivec.col(k).normalize(); 0322 } 0323 } 0324 0325 0326 template<typename MatrixType> 0327 void ComplexEigenSolver<MatrixType>::sortEigenvalues(bool computeEigenvectors) 0328 { 0329 const Index n = m_eivalues.size(); 0330 for (Index i=0; i<n; i++) 0331 { 0332 Index k; 0333 m_eivalues.cwiseAbs().tail(n-i).minCoeff(&k); 0334 if (k != 0) 0335 { 0336 k += i; 0337 std::swap(m_eivalues[k],m_eivalues[i]); 0338 if(computeEigenvectors) 0339 m_eivec.col(i).swap(m_eivec.col(k)); 0340 } 0341 } 0342 } 0343 0344 } // end namespace Eigen 0345 0346 #endif // EIGEN_COMPLEX_EIGEN_SOLVER_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |