Home | History | Annotate | Download | only in Eigenvalues
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2012 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 // Copyright (C) 2010,2012 Jitse Niesen <jitse (at) maths.leeds.ac.uk>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_GENERALIZEDEIGENSOLVER_H
     12 #define EIGEN_GENERALIZEDEIGENSOLVER_H
     13 
     14 #include "./RealQZ.h"
     15 
     16 namespace Eigen {
     17 
     18 /** \eigenvalues_module \ingroup Eigenvalues_Module
     19   *
     20   *
     21   * \class GeneralizedEigenSolver
     22   *
     23   * \brief Computes the generalized eigenvalues and eigenvectors of a pair of general matrices
     24   *
     25   * \tparam _MatrixType the type of the matrices of which we are computing the
     26   * eigen-decomposition; this is expected to be an instantiation of the Matrix
     27   * class template. Currently, only real matrices are supported.
     28   *
     29   * The generalized eigenvalues and eigenvectors of a matrix pair \f$ A \f$ and \f$ B \f$ are scalars
     30   * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda Bv \f$.  If
     31   * \f$ D \f$ is a diagonal matrix with the eigenvalues on the diagonal, and
     32   * \f$ V \f$ is a matrix with the eigenvectors as its columns, then \f$ A V =
     33   * B V D \f$. The matrix \f$ V \f$ is almost always invertible, in which case we
     34   * have \f$ A = B V D V^{-1} \f$. This is called the generalized eigen-decomposition.
     35   *
     36   * The generalized eigenvalues and eigenvectors of a matrix pair may be complex, even when the
     37   * matrices are real. Moreover, the generalized eigenvalue might be infinite if the matrix B is
     38   * singular. To workaround this difficulty, the eigenvalues are provided as a pair of complex \f$ \alpha \f$
     39   * and real \f$ \beta \f$ such that: \f$ \lambda_i = \alpha_i / \beta_i \f$. If \f$ \beta_i \f$ is (nearly) zero,
     40   * then one can consider the well defined left eigenvalue \f$ \mu = \beta_i / \alpha_i\f$ such that:
     41   * \f$ \mu_i A v_i = B v_i \f$, or even \f$ \mu_i u_i^T A  = u_i^T B \f$ where \f$ u_i \f$ is
     42   * called the left eigenvector.
     43   *
     44   * Call the function compute() to compute the generalized eigenvalues and eigenvectors of
     45   * a given matrix pair. Alternatively, you can use the
     46   * GeneralizedEigenSolver(const MatrixType&, const MatrixType&, bool) constructor which computes the
     47   * eigenvalues and eigenvectors at construction time. Once the eigenvalue and
     48   * eigenvectors are computed, they can be retrieved with the eigenvalues() and
     49   * eigenvectors() functions.
     50   *
     51   * Here is an usage example of this class:
     52   * Example: \include GeneralizedEigenSolver.cpp
     53   * Output: \verbinclude GeneralizedEigenSolver.out
     54   *
     55   * \sa MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver
     56   */
     57 template<typename _MatrixType> class GeneralizedEigenSolver
     58 {
     59   public:
     60 
     61     /** \brief Synonym for the template parameter \p _MatrixType. */
     62     typedef _MatrixType MatrixType;
     63 
     64     enum {
     65       RowsAtCompileTime = MatrixType::RowsAtCompileTime,
     66       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
     67       Options = MatrixType::Options,
     68       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
     69       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
     70     };
     71 
     72     /** \brief Scalar type for matrices of type #MatrixType. */
     73     typedef typename MatrixType::Scalar Scalar;
     74     typedef typename NumTraits<Scalar>::Real RealScalar;
     75     typedef typename MatrixType::Index Index;
     76 
     77     /** \brief Complex scalar type for #MatrixType.
     78       *
     79       * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
     80       * \c float or \c double) and just \c Scalar if #Scalar is
     81       * complex.
     82       */
     83     typedef std::complex<RealScalar> ComplexScalar;
     84 
     85     /** \brief Type for vector of real scalar values eigenvalues as returned by betas().
     86       *
     87       * This is a column vector with entries of type #Scalar.
     88       * The length of the vector is the size of #MatrixType.
     89       */
     90     typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> VectorType;
     91 
     92     /** \brief Type for vector of complex scalar values eigenvalues as returned by betas().
     93       *
     94       * This is a column vector with entries of type #ComplexScalar.
     95       * The length of the vector is the size of #MatrixType.
     96       */
     97     typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ComplexVectorType;
     98 
     99     /** \brief Expression type for the eigenvalues as returned by eigenvalues().
    100       */
    101     typedef CwiseBinaryOp<internal::scalar_quotient_op<ComplexScalar,Scalar>,ComplexVectorType,VectorType> EigenvalueType;
    102 
    103     /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
    104       *
    105       * This is a square matrix with entries of type #ComplexScalar.
    106       * The size is the same as the size of #MatrixType.
    107       */
    108     typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorsType;
    109 
    110     /** \brief Default constructor.
    111       *
    112       * The default constructor is useful in cases in which the user intends to
    113       * perform decompositions via EigenSolver::compute(const MatrixType&, bool).
    114       *
    115       * \sa compute() for an example.
    116       */
    117     GeneralizedEigenSolver() : m_eivec(), m_alphas(), m_betas(), m_isInitialized(false), m_realQZ(), m_matS(), m_tmp() {}
    118 
    119     /** \brief Default constructor with memory preallocation
    120       *
    121       * Like the default constructor but with preallocation of the internal data
    122       * according to the specified problem \a size.
    123       * \sa GeneralizedEigenSolver()
    124       */
    125     GeneralizedEigenSolver(Index size)
    126       : m_eivec(size, size),
    127         m_alphas(size),
    128         m_betas(size),
    129         m_isInitialized(false),
    130         m_eigenvectorsOk(false),
    131         m_realQZ(size),
    132         m_matS(size, size),
    133         m_tmp(size)
    134     {}
    135 
    136     /** \brief Constructor; computes the generalized eigendecomposition of given matrix pair.
    137       *
    138       * \param[in]  A  Square matrix whose eigendecomposition is to be computed.
    139       * \param[in]  B  Square matrix whose eigendecomposition is to be computed.
    140       * \param[in]  computeEigenvectors  If true, both the eigenvectors and the
    141       *    eigenvalues are computed; if false, only the eigenvalues are computed.
    142       *
    143       * This constructor calls compute() to compute the generalized eigenvalues
    144       * and eigenvectors.
    145       *
    146       * \sa compute()
    147       */
    148     GeneralizedEigenSolver(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true)
    149       : m_eivec(A.rows(), A.cols()),
    150         m_alphas(A.cols()),
    151         m_betas(A.cols()),
    152         m_isInitialized(false),
    153         m_eigenvectorsOk(false),
    154         m_realQZ(A.cols()),
    155         m_matS(A.rows(), A.cols()),
    156         m_tmp(A.cols())
    157     {
    158       compute(A, B, computeEigenvectors);
    159     }
    160 
    161     /* \brief Returns the computed generalized eigenvectors.
    162       *
    163       * \returns  %Matrix whose columns are the (possibly complex) eigenvectors.
    164       *
    165       * \pre Either the constructor
    166       * GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
    167       * compute(const MatrixType&, const MatrixType& bool) has been called before, and
    168       * \p computeEigenvectors was set to true (the default).
    169       *
    170       * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
    171       * to eigenvalue number \f$ k \f$ as returned by eigenvalues().  The
    172       * eigenvectors are normalized to have (Euclidean) norm equal to one. The
    173       * matrix returned by this function is the matrix \f$ V \f$ in the
    174       * generalized eigendecomposition \f$ A = B V D V^{-1} \f$, if it exists.
    175       *
    176       * \sa eigenvalues()
    177       */
    178 //    EigenvectorsType eigenvectors() const;
    179 
    180     /** \brief Returns an expression of the computed generalized eigenvalues.
    181       *
    182       * \returns An expression of the column vector containing the eigenvalues.
    183       *
    184       * It is a shortcut for \code this->alphas().cwiseQuotient(this->betas()); \endcode
    185       * Not that betas might contain zeros. It is therefore not recommended to use this function,
    186       * but rather directly deal with the alphas and betas vectors.
    187       *
    188       * \pre Either the constructor
    189       * GeneralizedEigenSolver(const MatrixType&,const MatrixType&,bool) or the member function
    190       * compute(const MatrixType&,const MatrixType&,bool) has been called before.
    191       *
    192       * The eigenvalues are repeated according to their algebraic multiplicity,
    193       * so there are as many eigenvalues as rows in the matrix. The eigenvalues
    194       * are not sorted in any particular order.
    195       *
    196       * \sa alphas(), betas(), eigenvectors()
    197       */
    198     EigenvalueType eigenvalues() const
    199     {
    200       eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
    201       return EigenvalueType(m_alphas,m_betas);
    202     }
    203 
    204     /** \returns A const reference to the vectors containing the alpha values
    205       *
    206       * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
    207       *
    208       * \sa betas(), eigenvalues() */
    209     ComplexVectorType alphas() const
    210     {
    211       eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
    212       return m_alphas;
    213     }
    214 
    215     /** \returns A const reference to the vectors containing the beta values
    216       *
    217       * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
    218       *
    219       * \sa alphas(), eigenvalues() */
    220     VectorType betas() const
    221     {
    222       eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
    223       return m_betas;
    224     }
    225 
    226     /** \brief Computes generalized eigendecomposition of given matrix.
    227       *
    228       * \param[in]  A  Square matrix whose eigendecomposition is to be computed.
    229       * \param[in]  B  Square matrix whose eigendecomposition is to be computed.
    230       * \param[in]  computeEigenvectors  If true, both the eigenvectors and the
    231       *    eigenvalues are computed; if false, only the eigenvalues are
    232       *    computed.
    233       * \returns    Reference to \c *this
    234       *
    235       * This function computes the eigenvalues of the real matrix \p matrix.
    236       * The eigenvalues() function can be used to retrieve them.  If
    237       * \p computeEigenvectors is true, then the eigenvectors are also computed
    238       * and can be retrieved by calling eigenvectors().
    239       *
    240       * The matrix is first reduced to real generalized Schur form using the RealQZ
    241       * class. The generalized Schur decomposition is then used to compute the eigenvalues
    242       * and eigenvectors.
    243       *
    244       * The cost of the computation is dominated by the cost of the
    245       * generalized Schur decomposition.
    246       *
    247       * This method reuses of the allocated data in the GeneralizedEigenSolver object.
    248       */
    249     GeneralizedEigenSolver& compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true);
    250 
    251     ComputationInfo info() const
    252     {
    253       eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
    254       return m_realQZ.info();
    255     }
    256 
    257     /** Sets the maximal number of iterations allowed.
    258     */
    259     GeneralizedEigenSolver& setMaxIterations(Index maxIters)
    260     {
    261       m_realQZ.setMaxIterations(maxIters);
    262       return *this;
    263     }
    264 
    265   protected:
    266     MatrixType m_eivec;
    267     ComplexVectorType m_alphas;
    268     VectorType m_betas;
    269     bool m_isInitialized;
    270     bool m_eigenvectorsOk;
    271     RealQZ<MatrixType> m_realQZ;
    272     MatrixType m_matS;
    273 
    274     typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
    275     ColumnVectorType m_tmp;
    276 };
    277 
    278 //template<typename MatrixType>
    279 //typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType GeneralizedEigenSolver<MatrixType>::eigenvectors() const
    280 //{
    281 //  eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
    282 //  eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
    283 //  Index n = m_eivec.cols();
    284 //  EigenvectorsType matV(n,n);
    285 //  // TODO
    286 //  return matV;
    287 //}
    288 
    289 template<typename MatrixType>
    290 GeneralizedEigenSolver<MatrixType>&
    291 GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
    292 {
    293   using std::sqrt;
    294   using std::abs;
    295   eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
    296 
    297   // Reduce to generalized real Schur form:
    298   // A = Q S Z and B = Q T Z
    299   m_realQZ.compute(A, B, computeEigenvectors);
    300 
    301   if (m_realQZ.info() == Success)
    302   {
    303     m_matS = m_realQZ.matrixS();
    304     if (computeEigenvectors)
    305       m_eivec = m_realQZ.matrixZ().transpose();
    306 
    307     // Compute eigenvalues from matS
    308     m_alphas.resize(A.cols());
    309     m_betas.resize(A.cols());
    310     Index i = 0;
    311     while (i < A.cols())
    312     {
    313       if (i == A.cols() - 1 || m_matS.coeff(i+1, i) == Scalar(0))
    314       {
    315         m_alphas.coeffRef(i) = m_matS.coeff(i, i);
    316         m_betas.coeffRef(i)  = m_realQZ.matrixT().coeff(i,i);
    317         ++i;
    318       }
    319       else
    320       {
    321         Scalar p = Scalar(0.5) * (m_matS.coeff(i, i) - m_matS.coeff(i+1, i+1));
    322         Scalar z = sqrt(abs(p * p + m_matS.coeff(i+1, i) * m_matS.coeff(i, i+1)));
    323         m_alphas.coeffRef(i)   = ComplexScalar(m_matS.coeff(i+1, i+1) + p, z);
    324         m_alphas.coeffRef(i+1) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, -z);
    325 
    326         m_betas.coeffRef(i)   = m_realQZ.matrixT().coeff(i,i);
    327         m_betas.coeffRef(i+1) = m_realQZ.matrixT().coeff(i,i);
    328         i += 2;
    329       }
    330     }
    331   }
    332 
    333   m_isInitialized = true;
    334   m_eigenvectorsOk = false;//computeEigenvectors;
    335 
    336   return *this;
    337 }
    338 
    339 } // end namespace Eigen
    340 
    341 #endif // EIGEN_GENERALIZEDEIGENSOLVER_H
    342