/src/Geometry_Eigen/Eigen/src/QR/ColPivHouseholderQR.h

http://github.com/Akranar/daguerreo · C Header · 532 lines · 266 code · 64 blank · 202 comment · 34 complexity · 9dab4b3b1e6a185c9de698171addbac7 MD5 · raw file

  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) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
  6. //
  7. // Eigen is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU Lesser General Public
  9. // License as published by the Free Software Foundation; either
  10. // version 3 of the License, or (at your option) any later version.
  11. //
  12. // Alternatively, you can redistribute it and/or
  13. // modify it under the terms of the GNU General Public License as
  14. // published by the Free Software Foundation; either version 2 of
  15. // the License, or (at your option) any later version.
  16. //
  17. // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
  18. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of the GNU Lesser General Public
  23. // License and a copy of the GNU General Public License along with
  24. // Eigen. If not, see <http://www.gnu.org/licenses/>.
  25. #ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
  26. #define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
  27. /** \ingroup QR_Module
  28. *
  29. * \class ColPivHouseholderQR
  30. *
  31. * \brief Householder rank-revealing QR decomposition of a matrix with column-pivoting
  32. *
  33. * \param MatrixType the type of the matrix of which we are computing the QR decomposition
  34. *
  35. * This class performs a rank-revealing QR decomposition of a matrix \b A into matrices \b P, \b Q and \b R
  36. * such that
  37. * \f[
  38. * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, \mathbf{R}
  39. * \f]
  40. * by using Householder transformations. Here, \b P is a permutation matrix, \b Q a unitary matrix and \b R an
  41. * upper triangular matrix.
  42. *
  43. * This decomposition performs column pivoting in order to be rank-revealing and improve
  44. * numerical stability. It is slower than HouseholderQR, and faster than FullPivHouseholderQR.
  45. *
  46. * \sa MatrixBase::colPivHouseholderQr()
  47. */
  48. template<typename _MatrixType> class ColPivHouseholderQR
  49. {
  50. public:
  51. typedef _MatrixType MatrixType;
  52. enum {
  53. RowsAtCompileTime = MatrixType::RowsAtCompileTime,
  54. ColsAtCompileTime = MatrixType::ColsAtCompileTime,
  55. Options = MatrixType::Options,
  56. MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
  57. MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
  58. };
  59. typedef typename MatrixType::Scalar Scalar;
  60. typedef typename MatrixType::RealScalar RealScalar;
  61. typedef typename MatrixType::Index Index;
  62. typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
  63. typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
  64. typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
  65. typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
  66. typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
  67. typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
  68. typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
  69. /**
  70. * \brief Default Constructor.
  71. *
  72. * The default constructor is useful in cases in which the user intends to
  73. * perform decompositions via ColPivHouseholderQR::compute(const MatrixType&).
  74. */
  75. ColPivHouseholderQR()
  76. : m_qr(),
  77. m_hCoeffs(),
  78. m_colsPermutation(),
  79. m_colsTranspositions(),
  80. m_temp(),
  81. m_colSqNorms(),
  82. m_isInitialized(false) {}
  83. /** \brief Default Constructor with memory preallocation
  84. *
  85. * Like the default constructor but with preallocation of the internal data
  86. * according to the specified problem \a size.
  87. * \sa ColPivHouseholderQR()
  88. */
  89. ColPivHouseholderQR(Index rows, Index cols)
  90. : m_qr(rows, cols),
  91. m_hCoeffs((std::min)(rows,cols)),
  92. m_colsPermutation(cols),
  93. m_colsTranspositions(cols),
  94. m_temp(cols),
  95. m_colSqNorms(cols),
  96. m_isInitialized(false),
  97. m_usePrescribedThreshold(false) {}
  98. ColPivHouseholderQR(const MatrixType& matrix)
  99. : m_qr(matrix.rows(), matrix.cols()),
  100. m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
  101. m_colsPermutation(matrix.cols()),
  102. m_colsTranspositions(matrix.cols()),
  103. m_temp(matrix.cols()),
  104. m_colSqNorms(matrix.cols()),
  105. m_isInitialized(false),
  106. m_usePrescribedThreshold(false)
  107. {
  108. compute(matrix);
  109. }
  110. /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
  111. * *this is the QR decomposition, if any exists.
  112. *
  113. * \param b the right-hand-side of the equation to solve.
  114. *
  115. * \returns a solution.
  116. *
  117. * \note The case where b is a matrix is not yet implemented. Also, this
  118. * code is space inefficient.
  119. *
  120. * \note_about_checking_solutions
  121. *
  122. * \note_about_arbitrary_choice_of_solution
  123. *
  124. * Example: \include ColPivHouseholderQR_solve.cpp
  125. * Output: \verbinclude ColPivHouseholderQR_solve.out
  126. */
  127. template<typename Rhs>
  128. inline const internal::solve_retval<ColPivHouseholderQR, Rhs>
  129. solve(const MatrixBase<Rhs>& b) const
  130. {
  131. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  132. return internal::solve_retval<ColPivHouseholderQR, Rhs>(*this, b.derived());
  133. }
  134. HouseholderSequenceType householderQ(void) const;
  135. /** \returns a reference to the matrix where the Householder QR decomposition is stored
  136. */
  137. const MatrixType& matrixQR() const
  138. {
  139. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  140. return m_qr;
  141. }
  142. ColPivHouseholderQR& compute(const MatrixType& matrix);
  143. const PermutationType& colsPermutation() const
  144. {
  145. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  146. return m_colsPermutation;
  147. }
  148. /** \returns the absolute value of the determinant of the matrix of which
  149. * *this is the QR decomposition. It has only linear complexity
  150. * (that is, O(n) where n is the dimension of the square matrix)
  151. * as the QR decomposition has already been computed.
  152. *
  153. * \note This is only for square matrices.
  154. *
  155. * \warning a determinant can be very big or small, so for matrices
  156. * of large enough dimension, there is a risk of overflow/underflow.
  157. * One way to work around that is to use logAbsDeterminant() instead.
  158. *
  159. * \sa logAbsDeterminant(), MatrixBase::determinant()
  160. */
  161. typename MatrixType::RealScalar absDeterminant() const;
  162. /** \returns the natural log of the absolute value of the determinant of the matrix of which
  163. * *this is the QR decomposition. It has only linear complexity
  164. * (that is, O(n) where n is the dimension of the square matrix)
  165. * as the QR decomposition has already been computed.
  166. *
  167. * \note This is only for square matrices.
  168. *
  169. * \note This method is useful to work around the risk of overflow/underflow that's inherent
  170. * to determinant computation.
  171. *
  172. * \sa absDeterminant(), MatrixBase::determinant()
  173. */
  174. typename MatrixType::RealScalar logAbsDeterminant() const;
  175. /** \returns the rank of the matrix of which *this is the QR decomposition.
  176. *
  177. * \note This method has to determine which pivots should be considered nonzero.
  178. * For that, it uses the threshold value that you can control by calling
  179. * setThreshold(const RealScalar&).
  180. */
  181. inline Index rank() const
  182. {
  183. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  184. RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
  185. Index result = 0;
  186. for(Index i = 0; i < m_nonzero_pivots; ++i)
  187. result += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);
  188. return result;
  189. }
  190. /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition.
  191. *
  192. * \note This method has to determine which pivots should be considered nonzero.
  193. * For that, it uses the threshold value that you can control by calling
  194. * setThreshold(const RealScalar&).
  195. */
  196. inline Index dimensionOfKernel() const
  197. {
  198. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  199. return cols() - rank();
  200. }
  201. /** \returns true if the matrix of which *this is the QR decomposition represents an injective
  202. * linear map, i.e. has trivial kernel; false otherwise.
  203. *
  204. * \note This method has to determine which pivots should be considered nonzero.
  205. * For that, it uses the threshold value that you can control by calling
  206. * setThreshold(const RealScalar&).
  207. */
  208. inline bool isInjective() const
  209. {
  210. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  211. return rank() == cols();
  212. }
  213. /** \returns true if the matrix of which *this is the QR decomposition represents a surjective
  214. * linear map; false otherwise.
  215. *
  216. * \note This method has to determine which pivots should be considered nonzero.
  217. * For that, it uses the threshold value that you can control by calling
  218. * setThreshold(const RealScalar&).
  219. */
  220. inline bool isSurjective() const
  221. {
  222. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  223. return rank() == rows();
  224. }
  225. /** \returns true if the matrix of which *this is the QR decomposition is invertible.
  226. *
  227. * \note This method has to determine which pivots should be considered nonzero.
  228. * For that, it uses the threshold value that you can control by calling
  229. * setThreshold(const RealScalar&).
  230. */
  231. inline bool isInvertible() const
  232. {
  233. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  234. return isInjective() && isSurjective();
  235. }
  236. /** \returns the inverse of the matrix of which *this is the QR decomposition.
  237. *
  238. * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
  239. * Use isInvertible() to first determine whether this matrix is invertible.
  240. */
  241. inline const
  242. internal::solve_retval<ColPivHouseholderQR, typename MatrixType::IdentityReturnType>
  243. inverse() const
  244. {
  245. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  246. return internal::solve_retval<ColPivHouseholderQR,typename MatrixType::IdentityReturnType>
  247. (*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
  248. }
  249. inline Index rows() const { return m_qr.rows(); }
  250. inline Index cols() const { return m_qr.cols(); }
  251. const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
  252. /** Allows to prescribe a threshold to be used by certain methods, such as rank(),
  253. * who need to determine when pivots are to be considered nonzero. This is not used for the
  254. * QR decomposition itself.
  255. *
  256. * When it needs to get the threshold value, Eigen calls threshold(). By default, this
  257. * uses a formula to automatically determine a reasonable threshold.
  258. * Once you have called the present method setThreshold(const RealScalar&),
  259. * your value is used instead.
  260. *
  261. * \param threshold The new value to use as the threshold.
  262. *
  263. * A pivot will be considered nonzero if its absolute value is strictly greater than
  264. * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
  265. * where maxpivot is the biggest pivot.
  266. *
  267. * If you want to come back to the default behavior, call setThreshold(Default_t)
  268. */
  269. ColPivHouseholderQR& setThreshold(const RealScalar& threshold)
  270. {
  271. m_usePrescribedThreshold = true;
  272. m_prescribedThreshold = threshold;
  273. return *this;
  274. }
  275. /** Allows to come back to the default behavior, letting Eigen use its default formula for
  276. * determining the threshold.
  277. *
  278. * You should pass the special object Eigen::Default as parameter here.
  279. * \code qr.setThreshold(Eigen::Default); \endcode
  280. *
  281. * See the documentation of setThreshold(const RealScalar&).
  282. */
  283. ColPivHouseholderQR& setThreshold(Default_t)
  284. {
  285. m_usePrescribedThreshold = false;
  286. return *this;
  287. }
  288. /** Returns the threshold that will be used by certain methods such as rank().
  289. *
  290. * See the documentation of setThreshold(const RealScalar&).
  291. */
  292. RealScalar threshold() const
  293. {
  294. eigen_assert(m_isInitialized || m_usePrescribedThreshold);
  295. return m_usePrescribedThreshold ? m_prescribedThreshold
  296. // this formula comes from experimenting (see "LU precision tuning" thread on the list)
  297. // and turns out to be identical to Higham's formula used already in LDLt.
  298. : NumTraits<Scalar>::epsilon() * m_qr.diagonalSize();
  299. }
  300. /** \returns the number of nonzero pivots in the QR decomposition.
  301. * Here nonzero is meant in the exact sense, not in a fuzzy sense.
  302. * So that notion isn't really intrinsically interesting, but it is
  303. * still useful when implementing algorithms.
  304. *
  305. * \sa rank()
  306. */
  307. inline Index nonzeroPivots() const
  308. {
  309. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  310. return m_nonzero_pivots;
  311. }
  312. /** \returns the absolute value of the biggest pivot, i.e. the biggest
  313. * diagonal coefficient of R.
  314. */
  315. RealScalar maxPivot() const { return m_maxpivot; }
  316. protected:
  317. MatrixType m_qr;
  318. HCoeffsType m_hCoeffs;
  319. PermutationType m_colsPermutation;
  320. IntRowVectorType m_colsTranspositions;
  321. RowVectorType m_temp;
  322. RealRowVectorType m_colSqNorms;
  323. bool m_isInitialized, m_usePrescribedThreshold;
  324. RealScalar m_prescribedThreshold, m_maxpivot;
  325. Index m_nonzero_pivots;
  326. Index m_det_pq;
  327. };
  328. template<typename MatrixType>
  329. typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::absDeterminant() const
  330. {
  331. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  332. eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
  333. return internal::abs(m_qr.diagonal().prod());
  334. }
  335. template<typename MatrixType>
  336. typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDeterminant() const
  337. {
  338. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  339. eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
  340. return m_qr.diagonal().cwiseAbs().array().log().sum();
  341. }
  342. template<typename MatrixType>
  343. ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
  344. {
  345. Index rows = matrix.rows();
  346. Index cols = matrix.cols();
  347. Index size = matrix.diagonalSize();
  348. m_qr = matrix;
  349. m_hCoeffs.resize(size);
  350. m_temp.resize(cols);
  351. m_colsTranspositions.resize(matrix.cols());
  352. Index number_of_transpositions = 0;
  353. m_colSqNorms.resize(cols);
  354. for(Index k = 0; k < cols; ++k)
  355. m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm();
  356. RealScalar threshold_helper = m_colSqNorms.maxCoeff() * internal::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows);
  357. m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
  358. m_maxpivot = RealScalar(0);
  359. for(Index k = 0; k < size; ++k)
  360. {
  361. // first, we look up in our table m_colSqNorms which column has the biggest squared norm
  362. Index biggest_col_index;
  363. RealScalar biggest_col_sq_norm = m_colSqNorms.tail(cols-k).maxCoeff(&biggest_col_index);
  364. biggest_col_index += k;
  365. // since our table m_colSqNorms accumulates imprecision at every step, we must now recompute
  366. // the actual squared norm of the selected column.
  367. // Note that not doing so does result in solve() sometimes returning inf/nan values
  368. // when running the unit test with 1000 repetitions.
  369. biggest_col_sq_norm = m_qr.col(biggest_col_index).tail(rows-k).squaredNorm();
  370. // we store that back into our table: it can't hurt to correct our table.
  371. m_colSqNorms.coeffRef(biggest_col_index) = biggest_col_sq_norm;
  372. // if the current biggest column is smaller than epsilon times the initial biggest column,
  373. // terminate to avoid generating nan/inf values.
  374. // Note that here, if we test instead for "biggest == 0", we get a failure every 1000 (or so)
  375. // repetitions of the unit test, with the result of solve() filled with large values of the order
  376. // of 1/(size*epsilon).
  377. if(biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
  378. {
  379. m_nonzero_pivots = k;
  380. m_hCoeffs.tail(size-k).setZero();
  381. m_qr.bottomRightCorner(rows-k,cols-k)
  382. .template triangularView<StrictlyLower>()
  383. .setZero();
  384. break;
  385. }
  386. // apply the transposition to the columns
  387. m_colsTranspositions.coeffRef(k) = biggest_col_index;
  388. if(k != biggest_col_index) {
  389. m_qr.col(k).swap(m_qr.col(biggest_col_index));
  390. std::swap(m_colSqNorms.coeffRef(k), m_colSqNorms.coeffRef(biggest_col_index));
  391. ++number_of_transpositions;
  392. }
  393. // generate the householder vector, store it below the diagonal
  394. RealScalar beta;
  395. m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta);
  396. // apply the householder transformation to the diagonal coefficient
  397. m_qr.coeffRef(k,k) = beta;
  398. // remember the maximum absolute value of diagonal coefficients
  399. if(internal::abs(beta) > m_maxpivot) m_maxpivot = internal::abs(beta);
  400. // apply the householder transformation
  401. m_qr.bottomRightCorner(rows-k, cols-k-1)
  402. .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1));
  403. // update our table of squared norms of the columns
  404. m_colSqNorms.tail(cols-k-1) -= m_qr.row(k).tail(cols-k-1).cwiseAbs2();
  405. }
  406. m_colsPermutation.setIdentity(cols);
  407. for(Index k = 0; k < m_nonzero_pivots; ++k)
  408. m_colsPermutation.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
  409. m_det_pq = (number_of_transpositions%2) ? -1 : 1;
  410. m_isInitialized = true;
  411. return *this;
  412. }
  413. namespace internal {
  414. template<typename _MatrixType, typename Rhs>
  415. struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
  416. : solve_retval_base<ColPivHouseholderQR<_MatrixType>, Rhs>
  417. {
  418. EIGEN_MAKE_SOLVE_HELPERS(ColPivHouseholderQR<_MatrixType>,Rhs)
  419. template<typename Dest> void evalTo(Dest& dst) const
  420. {
  421. eigen_assert(rhs().rows() == dec().rows());
  422. const int cols = dec().cols(),
  423. nonzero_pivots = dec().nonzeroPivots();
  424. if(nonzero_pivots == 0)
  425. {
  426. dst.setZero();
  427. return;
  428. }
  429. typename Rhs::PlainObject c(rhs());
  430. // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
  431. c.applyOnTheLeft(householderSequence(dec().matrixQR(), dec().hCoeffs())
  432. .setLength(dec().nonzeroPivots())
  433. .transpose()
  434. );
  435. dec().matrixQR()
  436. .topLeftCorner(nonzero_pivots, nonzero_pivots)
  437. .template triangularView<Upper>()
  438. .solveInPlace(c.topRows(nonzero_pivots));
  439. typename Rhs::PlainObject d(c);
  440. d.topRows(nonzero_pivots)
  441. = dec().matrixQR()
  442. .topLeftCorner(nonzero_pivots, nonzero_pivots)
  443. .template triangularView<Upper>()
  444. * c.topRows(nonzero_pivots);
  445. for(Index i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
  446. for(Index i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
  447. }
  448. };
  449. } // end namespace internal
  450. /** \returns the matrix Q as a sequence of householder transformations */
  451. template<typename MatrixType>
  452. typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType>
  453. ::householderQ() const
  454. {
  455. eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
  456. return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()).setLength(m_nonzero_pivots);
  457. }
  458. /** \return the column-pivoting Householder QR decomposition of \c *this.
  459. *
  460. * \sa class ColPivHouseholderQR
  461. */
  462. template<typename Derived>
  463. const ColPivHouseholderQR<typename MatrixBase<Derived>::PlainObject>
  464. MatrixBase<Derived>::colPivHouseholderQr() const
  465. {
  466. return ColPivHouseholderQR<PlainObject>(eval());
  467. }
  468. #endif // EIGEN_COLPIVOTINGHOUSEHOLDERQR_H