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