HessenbergDecomposition.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. // Copyright (C) 2010 Jitse Niesen <jitse@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. #ifndef EIGEN_HESSENBERGDECOMPOSITION_H
  11. #define EIGEN_HESSENBERGDECOMPOSITION_H
  12. namespace Eigen {
  13. namespace internal {
  14. template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType;
  15. template<typename MatrixType>
  16. struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType> >
  17. {
  18. typedef MatrixType ReturnType;
  19. };
  20. }
  21. /** \eigenvalues_module \ingroup Eigenvalues_Module
  22. *
  23. *
  24. * \class HessenbergDecomposition
  25. *
  26. * \brief Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation
  27. *
  28. * \tparam _MatrixType the type of the matrix of which we are computing the Hessenberg decomposition
  29. *
  30. * This class performs an Hessenberg decomposition of a matrix \f$ A \f$. In
  31. * the real case, the Hessenberg decomposition consists of an orthogonal
  32. * matrix \f$ Q \f$ and a Hessenberg matrix \f$ H \f$ such that \f$ A = Q H
  33. * Q^T \f$. An orthogonal matrix is a matrix whose inverse equals its
  34. * transpose (\f$ Q^{-1} = Q^T \f$). A Hessenberg matrix has zeros below the
  35. * subdiagonal, so it is almost upper triangular. The Hessenberg decomposition
  36. * of a complex matrix is \f$ A = Q H Q^* \f$ with \f$ Q \f$ unitary (that is,
  37. * \f$ Q^{-1} = Q^* \f$).
  38. *
  39. * Call the function compute() to compute the Hessenberg decomposition of a
  40. * given matrix. Alternatively, you can use the
  41. * HessenbergDecomposition(const MatrixType&) constructor which computes the
  42. * Hessenberg decomposition at construction time. Once the decomposition is
  43. * computed, you can use the matrixH() and matrixQ() functions to construct
  44. * the matrices H and Q in the decomposition.
  45. *
  46. * The documentation for matrixH() contains an example of the typical use of
  47. * this class.
  48. *
  49. * \sa class ComplexSchur, class Tridiagonalization, \ref QR_Module "QR Module"
  50. */
  51. template<typename _MatrixType> class HessenbergDecomposition
  52. {
  53. public:
  54. /** \brief Synonym for the template parameter \p _MatrixType. */
  55. typedef _MatrixType MatrixType;
  56. enum {
  57. Size = MatrixType::RowsAtCompileTime,
  58. SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1,
  59. Options = MatrixType::Options,
  60. MaxSize = MatrixType::MaxRowsAtCompileTime,
  61. MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1
  62. };
  63. /** \brief Scalar type for matrices of type #MatrixType. */
  64. typedef typename MatrixType::Scalar Scalar;
  65. typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
  66. /** \brief Type for vector of Householder coefficients.
  67. *
  68. * This is column vector with entries of type #Scalar. The length of the
  69. * vector is one less than the size of #MatrixType, if it is a fixed-side
  70. * type.
  71. */
  72. typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
  73. /** \brief Return type of matrixQ() */
  74. typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
  75. typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;
  76. /** \brief Default constructor; the decomposition will be computed later.
  77. *
  78. * \param [in] size The size of the matrix whose Hessenberg decomposition will be computed.
  79. *
  80. * The default constructor is useful in cases in which the user intends to
  81. * perform decompositions via compute(). The \p size parameter is only
  82. * used as a hint. It is not an error to give a wrong \p size, but it may
  83. * impair performance.
  84. *
  85. * \sa compute() for an example.
  86. */
  87. explicit HessenbergDecomposition(Index size = Size==Dynamic ? 2 : Size)
  88. : m_matrix(size,size),
  89. m_temp(size),
  90. m_isInitialized(false)
  91. {
  92. if(size>1)
  93. m_hCoeffs.resize(size-1);
  94. }
  95. /** \brief Constructor; computes Hessenberg decomposition of given matrix.
  96. *
  97. * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed.
  98. *
  99. * This constructor calls compute() to compute the Hessenberg
  100. * decomposition.
  101. *
  102. * \sa matrixH() for an example.
  103. */
  104. template<typename InputType>
  105. explicit HessenbergDecomposition(const EigenBase<InputType>& matrix)
  106. : m_matrix(matrix.derived()),
  107. m_temp(matrix.rows()),
  108. m_isInitialized(false)
  109. {
  110. if(matrix.rows()<2)
  111. {
  112. m_isInitialized = true;
  113. return;
  114. }
  115. m_hCoeffs.resize(matrix.rows()-1,1);
  116. _compute(m_matrix, m_hCoeffs, m_temp);
  117. m_isInitialized = true;
  118. }
  119. /** \brief Computes Hessenberg decomposition of given matrix.
  120. *
  121. * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed.
  122. * \returns Reference to \c *this
  123. *
  124. * The Hessenberg decomposition is computed by bringing the columns of the
  125. * matrix successively in the required form using Householder reflections
  126. * (see, e.g., Algorithm 7.4.2 in Golub \& Van Loan, <i>%Matrix
  127. * Computations</i>). The cost is \f$ 10n^3/3 \f$ flops, where \f$ n \f$
  128. * denotes the size of the given matrix.
  129. *
  130. * This method reuses of the allocated data in the HessenbergDecomposition
  131. * object.
  132. *
  133. * Example: \include HessenbergDecomposition_compute.cpp
  134. * Output: \verbinclude HessenbergDecomposition_compute.out
  135. */
  136. template<typename InputType>
  137. HessenbergDecomposition& compute(const EigenBase<InputType>& matrix)
  138. {
  139. m_matrix = matrix.derived();
  140. if(matrix.rows()<2)
  141. {
  142. m_isInitialized = true;
  143. return *this;
  144. }
  145. m_hCoeffs.resize(matrix.rows()-1,1);
  146. _compute(m_matrix, m_hCoeffs, m_temp);
  147. m_isInitialized = true;
  148. return *this;
  149. }
  150. /** \brief Returns the Householder coefficients.
  151. *
  152. * \returns a const reference to the vector of Householder coefficients
  153. *
  154. * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
  155. * or the member function compute(const MatrixType&) has been called
  156. * before to compute the Hessenberg decomposition of a matrix.
  157. *
  158. * The Householder coefficients allow the reconstruction of the matrix
  159. * \f$ Q \f$ in the Hessenberg decomposition from the packed data.
  160. *
  161. * \sa packedMatrix(), \ref Householder_Module "Householder module"
  162. */
  163. const CoeffVectorType& householderCoefficients() const
  164. {
  165. eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
  166. return m_hCoeffs;
  167. }
  168. /** \brief Returns the internal representation of the decomposition
  169. *
  170. * \returns a const reference to a matrix with the internal representation
  171. * of the decomposition.
  172. *
  173. * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
  174. * or the member function compute(const MatrixType&) has been called
  175. * before to compute the Hessenberg decomposition of a matrix.
  176. *
  177. * The returned matrix contains the following information:
  178. * - the upper part and lower sub-diagonal represent the Hessenberg matrix H
  179. * - the rest of the lower part contains the Householder vectors that, combined with
  180. * Householder coefficients returned by householderCoefficients(),
  181. * allows to reconstruct the matrix Q as
  182. * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
  183. * Here, the matrices \f$ H_i \f$ are the Householder transformations
  184. * \f$ H_i = (I - h_i v_i v_i^T) \f$
  185. * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and
  186. * \f$ v_i \f$ is the Householder vector defined by
  187. * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$
  188. * with M the matrix returned by this function.
  189. *
  190. * See LAPACK for further details on this packed storage.
  191. *
  192. * Example: \include HessenbergDecomposition_packedMatrix.cpp
  193. * Output: \verbinclude HessenbergDecomposition_packedMatrix.out
  194. *
  195. * \sa householderCoefficients()
  196. */
  197. const MatrixType& packedMatrix() const
  198. {
  199. eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
  200. return m_matrix;
  201. }
  202. /** \brief Reconstructs the orthogonal matrix Q in the decomposition
  203. *
  204. * \returns object representing the matrix Q
  205. *
  206. * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
  207. * or the member function compute(const MatrixType&) has been called
  208. * before to compute the Hessenberg decomposition of a matrix.
  209. *
  210. * This function returns a light-weight object of template class
  211. * HouseholderSequence. You can either apply it directly to a matrix or
  212. * you can convert it to a matrix of type #MatrixType.
  213. *
  214. * \sa matrixH() for an example, class HouseholderSequence
  215. */
  216. HouseholderSequenceType matrixQ() const
  217. {
  218. eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
  219. return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
  220. .setLength(m_matrix.rows() - 1)
  221. .setShift(1);
  222. }
  223. /** \brief Constructs the Hessenberg matrix H in the decomposition
  224. *
  225. * \returns expression object representing the matrix H
  226. *
  227. * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
  228. * or the member function compute(const MatrixType&) has been called
  229. * before to compute the Hessenberg decomposition of a matrix.
  230. *
  231. * The object returned by this function constructs the Hessenberg matrix H
  232. * when it is assigned to a matrix or otherwise evaluated. The matrix H is
  233. * constructed from the packed matrix as returned by packedMatrix(): The
  234. * upper part (including the subdiagonal) of the packed matrix contains
  235. * the matrix H. It may sometimes be better to directly use the packed
  236. * matrix instead of constructing the matrix H.
  237. *
  238. * Example: \include HessenbergDecomposition_matrixH.cpp
  239. * Output: \verbinclude HessenbergDecomposition_matrixH.out
  240. *
  241. * \sa matrixQ(), packedMatrix()
  242. */
  243. MatrixHReturnType matrixH() const
  244. {
  245. eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
  246. return MatrixHReturnType(*this);
  247. }
  248. private:
  249. typedef Matrix<Scalar, 1, Size, Options | RowMajor, 1, MaxSize> VectorType;
  250. typedef typename NumTraits<Scalar>::Real RealScalar;
  251. static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp);
  252. protected:
  253. MatrixType m_matrix;
  254. CoeffVectorType m_hCoeffs;
  255. VectorType m_temp;
  256. bool m_isInitialized;
  257. };
  258. /** \internal
  259. * Performs a tridiagonal decomposition of \a matA in place.
  260. *
  261. * \param matA the input selfadjoint matrix
  262. * \param hCoeffs returned Householder coefficients
  263. *
  264. * The result is written in the lower triangular part of \a matA.
  265. *
  266. * Implemented from Golub's "%Matrix Computations", algorithm 8.3.1.
  267. *
  268. * \sa packedMatrix()
  269. */
  270. template<typename MatrixType>
  271. void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp)
  272. {
  273. eigen_assert(matA.rows()==matA.cols());
  274. Index n = matA.rows();
  275. temp.resize(n);
  276. for (Index i = 0; i<n-1; ++i)
  277. {
  278. // let's consider the vector v = i-th column starting at position i+1
  279. Index remainingSize = n-i-1;
  280. RealScalar beta;
  281. Scalar h;
  282. matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
  283. matA.col(i).coeffRef(i+1) = beta;
  284. hCoeffs.coeffRef(i) = h;
  285. // Apply similarity transformation to remaining columns,
  286. // i.e., compute A = H A H'
  287. // A = H A
  288. matA.bottomRightCorner(remainingSize, remainingSize)
  289. .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0));
  290. // A = A H'
  291. matA.rightCols(remainingSize)
  292. .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), numext::conj(h), &temp.coeffRef(0));
  293. }
  294. }
  295. namespace internal {
  296. /** \eigenvalues_module \ingroup Eigenvalues_Module
  297. *
  298. *
  299. * \brief Expression type for return value of HessenbergDecomposition::matrixH()
  300. *
  301. * \tparam MatrixType type of matrix in the Hessenberg decomposition
  302. *
  303. * Objects of this type represent the Hessenberg matrix in the Hessenberg
  304. * decomposition of some matrix. The object holds a reference to the
  305. * HessenbergDecomposition class until the it is assigned or evaluated for
  306. * some other reason (the reference should remain valid during the life time
  307. * of this object). This class is the return type of
  308. * HessenbergDecomposition::matrixH(); there is probably no other use for this
  309. * class.
  310. */
  311. template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType
  312. : public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType> >
  313. {
  314. public:
  315. /** \brief Constructor.
  316. *
  317. * \param[in] hess Hessenberg decomposition
  318. */
  319. HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition<MatrixType>& hess) : m_hess(hess) { }
  320. /** \brief Hessenberg matrix in decomposition.
  321. *
  322. * \param[out] result Hessenberg matrix in decomposition \p hess which
  323. * was passed to the constructor
  324. */
  325. template <typename ResultType>
  326. inline void evalTo(ResultType& result) const
  327. {
  328. result = m_hess.packedMatrix();
  329. Index n = result.rows();
  330. if (n>2)
  331. result.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero();
  332. }
  333. Index rows() const { return m_hess.packedMatrix().rows(); }
  334. Index cols() const { return m_hess.packedMatrix().cols(); }
  335. protected:
  336. const HessenbergDecomposition<MatrixType>& m_hess;
  337. };
  338. } // end namespace internal
  339. } // end namespace Eigen
  340. #endif // EIGEN_HESSENBERGDECOMPOSITION_H