ComplexEigenSolver.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2009 Claire Maurice
  5. // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
  6. // Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
  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. #ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H
  12. #define EIGEN_COMPLEX_EIGEN_SOLVER_H
  13. #include "./ComplexSchur.h"
  14. namespace Eigen {
  15. /** \eigenvalues_module \ingroup Eigenvalues_Module
  16. *
  17. *
  18. * \class ComplexEigenSolver
  19. *
  20. * \brief Computes eigenvalues and eigenvectors of general complex matrices
  21. *
  22. * \tparam _MatrixType the type of the matrix of which we are
  23. * computing the eigendecomposition; this is expected to be an
  24. * instantiation of the Matrix class template.
  25. *
  26. * The eigenvalues and eigenvectors of a matrix \f$ A \f$ are scalars
  27. * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda v
  28. * \f$. If \f$ D \f$ is a diagonal matrix with the eigenvalues on
  29. * the diagonal, and \f$ V \f$ is a matrix with the eigenvectors as
  30. * its columns, then \f$ A V = V D \f$. The matrix \f$ V \f$ is
  31. * almost always invertible, in which case we have \f$ A = V D V^{-1}
  32. * \f$. This is called the eigendecomposition.
  33. *
  34. * The main function in this class is compute(), which computes the
  35. * eigenvalues and eigenvectors of a given function. The
  36. * documentation for that function contains an example showing the
  37. * main features of the class.
  38. *
  39. * \sa class EigenSolver, class SelfAdjointEigenSolver
  40. */
  41. template<typename _MatrixType> class ComplexEigenSolver
  42. {
  43. public:
  44. /** \brief Synonym for the template parameter \p _MatrixType. */
  45. typedef _MatrixType MatrixType;
  46. enum {
  47. RowsAtCompileTime = MatrixType::RowsAtCompileTime,
  48. ColsAtCompileTime = MatrixType::ColsAtCompileTime,
  49. Options = MatrixType::Options,
  50. MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
  51. MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
  52. };
  53. /** \brief Scalar type for matrices of type #MatrixType. */
  54. typedef typename MatrixType::Scalar Scalar;
  55. typedef typename NumTraits<Scalar>::Real RealScalar;
  56. typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
  57. /** \brief Complex scalar type for #MatrixType.
  58. *
  59. * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
  60. * \c float or \c double) and just \c Scalar if #Scalar is
  61. * complex.
  62. */
  63. typedef std::complex<RealScalar> ComplexScalar;
  64. /** \brief Type for vector of eigenvalues as returned by eigenvalues().
  65. *
  66. * This is a column vector with entries of type #ComplexScalar.
  67. * The length of the vector is the size of #MatrixType.
  68. */
  69. typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options&(~RowMajor), MaxColsAtCompileTime, 1> EigenvalueType;
  70. /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
  71. *
  72. * This is a square matrix with entries of type #ComplexScalar.
  73. * The size is the same as the size of #MatrixType.
  74. */
  75. typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorType;
  76. /** \brief Default constructor.
  77. *
  78. * The default constructor is useful in cases in which the user intends to
  79. * perform decompositions via compute().
  80. */
  81. ComplexEigenSolver()
  82. : m_eivec(),
  83. m_eivalues(),
  84. m_schur(),
  85. m_isInitialized(false),
  86. m_eigenvectorsOk(false),
  87. m_matX()
  88. {}
  89. /** \brief Default Constructor with memory preallocation
  90. *
  91. * Like the default constructor but with preallocation of the internal data
  92. * according to the specified problem \a size.
  93. * \sa ComplexEigenSolver()
  94. */
  95. explicit ComplexEigenSolver(Index size)
  96. : m_eivec(size, size),
  97. m_eivalues(size),
  98. m_schur(size),
  99. m_isInitialized(false),
  100. m_eigenvectorsOk(false),
  101. m_matX(size, size)
  102. {}
  103. /** \brief Constructor; computes eigendecomposition of given matrix.
  104. *
  105. * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
  106. * \param[in] computeEigenvectors If true, both the eigenvectors and the
  107. * eigenvalues are computed; if false, only the eigenvalues are
  108. * computed.
  109. *
  110. * This constructor calls compute() to compute the eigendecomposition.
  111. */
  112. template<typename InputType>
  113. explicit ComplexEigenSolver(const EigenBase<InputType>& matrix, bool computeEigenvectors = true)
  114. : m_eivec(matrix.rows(),matrix.cols()),
  115. m_eivalues(matrix.cols()),
  116. m_schur(matrix.rows()),
  117. m_isInitialized(false),
  118. m_eigenvectorsOk(false),
  119. m_matX(matrix.rows(),matrix.cols())
  120. {
  121. compute(matrix.derived(), computeEigenvectors);
  122. }
  123. /** \brief Returns the eigenvectors of given matrix.
  124. *
  125. * \returns A const reference to the matrix whose columns are the eigenvectors.
  126. *
  127. * \pre Either the constructor
  128. * ComplexEigenSolver(const MatrixType& matrix, bool) or the member
  129. * function compute(const MatrixType& matrix, bool) has been called before
  130. * to compute the eigendecomposition of a matrix, and
  131. * \p computeEigenvectors was set to true (the default).
  132. *
  133. * This function returns a matrix whose columns are the eigenvectors. Column
  134. * \f$ k \f$ is an eigenvector corresponding to eigenvalue number \f$ k
  135. * \f$ as returned by eigenvalues(). The eigenvectors are normalized to
  136. * have (Euclidean) norm equal to one. The matrix returned by this
  137. * function is the matrix \f$ V \f$ in the eigendecomposition \f$ A = V D
  138. * V^{-1} \f$, if it exists.
  139. *
  140. * Example: \include ComplexEigenSolver_eigenvectors.cpp
  141. * Output: \verbinclude ComplexEigenSolver_eigenvectors.out
  142. */
  143. const EigenvectorType& eigenvectors() const
  144. {
  145. eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
  146. eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
  147. return m_eivec;
  148. }
  149. /** \brief Returns the eigenvalues of given matrix.
  150. *
  151. * \returns A const reference to the column vector containing the eigenvalues.
  152. *
  153. * \pre Either the constructor
  154. * ComplexEigenSolver(const MatrixType& matrix, bool) or the member
  155. * function compute(const MatrixType& matrix, bool) has been called before
  156. * to compute the eigendecomposition of a matrix.
  157. *
  158. * This function returns a column vector containing the
  159. * eigenvalues. Eigenvalues are repeated according to their
  160. * algebraic multiplicity, so there are as many eigenvalues as
  161. * rows in the matrix. The eigenvalues are not sorted in any particular
  162. * order.
  163. *
  164. * Example: \include ComplexEigenSolver_eigenvalues.cpp
  165. * Output: \verbinclude ComplexEigenSolver_eigenvalues.out
  166. */
  167. const EigenvalueType& eigenvalues() const
  168. {
  169. eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
  170. return m_eivalues;
  171. }
  172. /** \brief Computes eigendecomposition of given matrix.
  173. *
  174. * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
  175. * \param[in] computeEigenvectors If true, both the eigenvectors and the
  176. * eigenvalues are computed; if false, only the eigenvalues are
  177. * computed.
  178. * \returns Reference to \c *this
  179. *
  180. * This function computes the eigenvalues of the complex matrix \p matrix.
  181. * The eigenvalues() function can be used to retrieve them. If
  182. * \p computeEigenvectors is true, then the eigenvectors are also computed
  183. * and can be retrieved by calling eigenvectors().
  184. *
  185. * The matrix is first reduced to Schur form using the
  186. * ComplexSchur class. The Schur decomposition is then used to
  187. * compute the eigenvalues and eigenvectors.
  188. *
  189. * The cost of the computation is dominated by the cost of the
  190. * Schur decomposition, which is \f$ O(n^3) \f$ where \f$ n \f$
  191. * is the size of the matrix.
  192. *
  193. * Example: \include ComplexEigenSolver_compute.cpp
  194. * Output: \verbinclude ComplexEigenSolver_compute.out
  195. */
  196. template<typename InputType>
  197. ComplexEigenSolver& compute(const EigenBase<InputType>& matrix, bool computeEigenvectors = true);
  198. /** \brief Reports whether previous computation was successful.
  199. *
  200. * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
  201. */
  202. ComputationInfo info() const
  203. {
  204. eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
  205. return m_schur.info();
  206. }
  207. /** \brief Sets the maximum number of iterations allowed. */
  208. ComplexEigenSolver& setMaxIterations(Index maxIters)
  209. {
  210. m_schur.setMaxIterations(maxIters);
  211. return *this;
  212. }
  213. /** \brief Returns the maximum number of iterations. */
  214. Index getMaxIterations()
  215. {
  216. return m_schur.getMaxIterations();
  217. }
  218. protected:
  219. static void check_template_parameters()
  220. {
  221. EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
  222. }
  223. EigenvectorType m_eivec;
  224. EigenvalueType m_eivalues;
  225. ComplexSchur<MatrixType> m_schur;
  226. bool m_isInitialized;
  227. bool m_eigenvectorsOk;
  228. EigenvectorType m_matX;
  229. private:
  230. void doComputeEigenvectors(RealScalar matrixnorm);
  231. void sortEigenvalues(bool computeEigenvectors);
  232. };
  233. template<typename MatrixType>
  234. template<typename InputType>
  235. ComplexEigenSolver<MatrixType>&
  236. ComplexEigenSolver<MatrixType>::compute(const EigenBase<InputType>& matrix, bool computeEigenvectors)
  237. {
  238. check_template_parameters();
  239. // this code is inspired from Jampack
  240. eigen_assert(matrix.cols() == matrix.rows());
  241. // Do a complex Schur decomposition, A = U T U^*
  242. // The eigenvalues are on the diagonal of T.
  243. m_schur.compute(matrix.derived(), computeEigenvectors);
  244. if(m_schur.info() == Success)
  245. {
  246. m_eivalues = m_schur.matrixT().diagonal();
  247. if(computeEigenvectors)
  248. doComputeEigenvectors(m_schur.matrixT().norm());
  249. sortEigenvalues(computeEigenvectors);
  250. }
  251. m_isInitialized = true;
  252. m_eigenvectorsOk = computeEigenvectors;
  253. return *this;
  254. }
  255. template<typename MatrixType>
  256. void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm)
  257. {
  258. const Index n = m_eivalues.size();
  259. matrixnorm = numext::maxi(matrixnorm,(std::numeric_limits<RealScalar>::min)());
  260. // Compute X such that T = X D X^(-1), where D is the diagonal of T.
  261. // The matrix X is unit triangular.
  262. m_matX = EigenvectorType::Zero(n, n);
  263. for(Index k=n-1 ; k>=0 ; k--)
  264. {
  265. m_matX.coeffRef(k,k) = ComplexScalar(1.0,0.0);
  266. // Compute X(i,k) using the (i,k) entry of the equation X T = D X
  267. for(Index i=k-1 ; i>=0 ; i--)
  268. {
  269. m_matX.coeffRef(i,k) = -m_schur.matrixT().coeff(i,k);
  270. if(k-i-1>0)
  271. 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();
  272. ComplexScalar z = m_schur.matrixT().coeff(i,i) - m_schur.matrixT().coeff(k,k);
  273. if(z==ComplexScalar(0))
  274. {
  275. // If the i-th and k-th eigenvalue are equal, then z equals 0.
  276. // Use a small value instead, to prevent division by zero.
  277. numext::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
  278. }
  279. m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z;
  280. }
  281. }
  282. // Compute V as V = U X; now A = U T U^* = U X D X^(-1) U^* = V D V^(-1)
  283. m_eivec.noalias() = m_schur.matrixU() * m_matX;
  284. // .. and normalize the eigenvectors
  285. for(Index k=0 ; k<n ; k++)
  286. {
  287. m_eivec.col(k).normalize();
  288. }
  289. }
  290. template<typename MatrixType>
  291. void ComplexEigenSolver<MatrixType>::sortEigenvalues(bool computeEigenvectors)
  292. {
  293. const Index n = m_eivalues.size();
  294. for (Index i=0; i<n; i++)
  295. {
  296. Index k;
  297. m_eivalues.cwiseAbs().tail(n-i).minCoeff(&k);
  298. if (k != 0)
  299. {
  300. k += i;
  301. std::swap(m_eivalues[k],m_eivalues[i]);
  302. if(computeEigenvectors)
  303. m_eivec.col(i).swap(m_eivec.col(k));
  304. }
  305. }
  306. }
  307. } // end namespace Eigen
  308. #endif // EIGEN_COMPLEX_EIGEN_SOLVER_H