1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2016 Rasmus Munk Larsen <rmlarsen@google.com> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H 11 #define EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H 12 13 namespace Eigen { 14 15 namespace internal { 16 template <typename _MatrixType> 17 struct traits<CompleteOrthogonalDecomposition<_MatrixType> > 18 : traits<_MatrixType> { 19 enum { Flags = 0 }; 20 }; 21 22 } // end namespace internal 23 24 /** \ingroup QR_Module 25 * 26 * \class CompleteOrthogonalDecomposition 27 * 28 * \brief Complete orthogonal decomposition (COD) of a matrix. 29 * 30 * \param MatrixType the type of the matrix of which we are computing the COD. 31 * 32 * This class performs a rank-revealing complete orthogonal decomposition of a 33 * matrix \b A into matrices \b P, \b Q, \b T, and \b Z such that 34 * \f[ 35 * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, 36 * \begin{bmatrix} \mathbf{T} & \mathbf{0} \\ 37 * \mathbf{0} & \mathbf{0} \end{bmatrix} \, \mathbf{Z} 38 * \f] 39 * by using Householder transformations. Here, \b P is a permutation matrix, 40 * \b Q and \b Z are unitary matrices and \b T an upper triangular matrix of 41 * size rank-by-rank. \b A may be rank deficient. 42 * 43 * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. 44 * 45 * \sa MatrixBase::completeOrthogonalDecomposition() 46 */ 47 template <typename _MatrixType> 48 class CompleteOrthogonalDecomposition { 49 public: 50 typedef _MatrixType MatrixType; 51 enum { 52 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 53 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 54 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 55 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 56 }; 57 typedef typename MatrixType::Scalar Scalar; 58 typedef typename MatrixType::RealScalar RealScalar; 59 typedef typename MatrixType::StorageIndex StorageIndex; 60 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType; 61 typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> 62 PermutationType; 63 typedef typename internal::plain_row_type<MatrixType, Index>::type 64 IntRowVectorType; 65 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType; 66 typedef typename internal::plain_row_type<MatrixType, RealScalar>::type 67 RealRowVectorType; 68 typedef HouseholderSequence< 69 MatrixType, typename internal::remove_all< 70 typename HCoeffsType::ConjugateReturnType>::type> 71 HouseholderSequenceType; 72 typedef typename MatrixType::PlainObject PlainObject; 73 74 private: 75 typedef typename PermutationType::Index PermIndexType; 76 77 public: 78 /** 79 * \brief Default Constructor. 80 * 81 * The default constructor is useful in cases in which the user intends to 82 * perform decompositions via 83 * \c CompleteOrthogonalDecomposition::compute(const* MatrixType&). 84 */ 85 CompleteOrthogonalDecomposition() : m_cpqr(), m_zCoeffs(), m_temp() {} 86 87 /** \brief Default Constructor with memory preallocation 88 * 89 * Like the default constructor but with preallocation of the internal data 90 * according to the specified problem \a size. 91 * \sa CompleteOrthogonalDecomposition() 92 */ 93 CompleteOrthogonalDecomposition(Index rows, Index cols) 94 : m_cpqr(rows, cols), m_zCoeffs((std::min)(rows, cols)), m_temp(cols) {} 95 96 /** \brief Constructs a complete orthogonal decomposition from a given 97 * matrix. 98 * 99 * This constructor computes the complete orthogonal decomposition of the 100 * matrix \a matrix by calling the method compute(). The default 101 * threshold for rank determination will be used. It is a short cut for: 102 * 103 * \code 104 * CompleteOrthogonalDecomposition<MatrixType> cod(matrix.rows(), 105 * matrix.cols()); 106 * cod.setThreshold(Default); 107 * cod.compute(matrix); 108 * \endcode 109 * 110 * \sa compute() 111 */ 112 template <typename InputType> 113 explicit CompleteOrthogonalDecomposition(const EigenBase<InputType>& matrix) 114 : m_cpqr(matrix.rows(), matrix.cols()), 115 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())), 116 m_temp(matrix.cols()) 117 { 118 compute(matrix.derived()); 119 } 120 121 /** \brief Constructs a complete orthogonal decomposition from a given matrix 122 * 123 * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref. 124 * 125 * \sa CompleteOrthogonalDecomposition(const EigenBase&) 126 */ 127 template<typename InputType> 128 explicit CompleteOrthogonalDecomposition(EigenBase<InputType>& matrix) 129 : m_cpqr(matrix.derived()), 130 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())), 131 m_temp(matrix.cols()) 132 { 133 computeInPlace(); 134 } 135 136 137 /** This method computes the minimum-norm solution X to a least squares 138 * problem \f[\mathrm{minimize} \|A X - B\|, \f] where \b A is the matrix of 139 * which \c *this is the complete orthogonal decomposition. 140 * 141 * \param b the right-hand sides of the problem to solve. 142 * 143 * \returns a solution. 144 * 145 */ 146 template <typename Rhs> 147 inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve( 148 const MatrixBase<Rhs>& b) const { 149 eigen_assert(m_cpqr.m_isInitialized && 150 "CompleteOrthogonalDecomposition is not initialized."); 151 return Solve<CompleteOrthogonalDecomposition, Rhs>(*this, b.derived()); 152 } 153 154 HouseholderSequenceType householderQ(void) const; 155 HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); } 156 157 /** \returns the matrix \b Z. 158 */ 159 MatrixType matrixZ() const { 160 MatrixType Z = MatrixType::Identity(m_cpqr.cols(), m_cpqr.cols()); 161 applyZAdjointOnTheLeftInPlace(Z); 162 return Z.adjoint(); 163 } 164 165 /** \returns a reference to the matrix where the complete orthogonal 166 * decomposition is stored 167 */ 168 const MatrixType& matrixQTZ() const { return m_cpqr.matrixQR(); } 169 170 /** \returns a reference to the matrix where the complete orthogonal 171 * decomposition is stored. 172 * \warning The strict lower part and \code cols() - rank() \endcode right 173 * columns of this matrix contains internal values. 174 * Only the upper triangular part should be referenced. To get it, use 175 * \code matrixT().template triangularView<Upper>() \endcode 176 * For rank-deficient matrices, use 177 * \code 178 * matrixR().topLeftCorner(rank(), rank()).template triangularView<Upper>() 179 * \endcode 180 */ 181 const MatrixType& matrixT() const { return m_cpqr.matrixQR(); } 182 183 template <typename InputType> 184 CompleteOrthogonalDecomposition& compute(const EigenBase<InputType>& matrix) { 185 // Compute the column pivoted QR factorization A P = Q R. 186 m_cpqr.compute(matrix); 187 computeInPlace(); 188 return *this; 189 } 190 191 /** \returns a const reference to the column permutation matrix */ 192 const PermutationType& colsPermutation() const { 193 return m_cpqr.colsPermutation(); 194 } 195 196 /** \returns the absolute value of the determinant of the matrix of which 197 * *this is the complete orthogonal decomposition. It has only linear 198 * complexity (that is, O(n) where n is the dimension of the square matrix) 199 * as the complete orthogonal decomposition has already been computed. 200 * 201 * \note This is only for square matrices. 202 * 203 * \warning a determinant can be very big or small, so for matrices 204 * of large enough dimension, there is a risk of overflow/underflow. 205 * One way to work around that is to use logAbsDeterminant() instead. 206 * 207 * \sa logAbsDeterminant(), MatrixBase::determinant() 208 */ 209 typename MatrixType::RealScalar absDeterminant() const; 210 211 /** \returns the natural log of the absolute value of the determinant of the 212 * matrix of which *this is the complete orthogonal decomposition. It has 213 * only linear complexity (that is, O(n) where n is the dimension of the 214 * square matrix) as the complete orthogonal decomposition has already been 215 * computed. 216 * 217 * \note This is only for square matrices. 218 * 219 * \note This method is useful to work around the risk of overflow/underflow 220 * that's inherent to determinant computation. 221 * 222 * \sa absDeterminant(), MatrixBase::determinant() 223 */ 224 typename MatrixType::RealScalar logAbsDeterminant() const; 225 226 /** \returns the rank of the matrix of which *this is the complete orthogonal 227 * decomposition. 228 * 229 * \note This method has to determine which pivots should be considered 230 * nonzero. For that, it uses the threshold value that you can control by 231 * calling setThreshold(const RealScalar&). 232 */ 233 inline Index rank() const { return m_cpqr.rank(); } 234 235 /** \returns the dimension of the kernel of the matrix of which *this is the 236 * complete orthogonal decomposition. 237 * 238 * \note This method has to determine which pivots should be considered 239 * nonzero. For that, it uses the threshold value that you can control by 240 * calling setThreshold(const RealScalar&). 241 */ 242 inline Index dimensionOfKernel() const { return m_cpqr.dimensionOfKernel(); } 243 244 /** \returns true if the matrix of which *this is the decomposition represents 245 * an injective linear map, i.e. has trivial kernel; false otherwise. 246 * 247 * \note This method has to determine which pivots should be considered 248 * nonzero. For that, it uses the threshold value that you can control by 249 * calling setThreshold(const RealScalar&). 250 */ 251 inline bool isInjective() const { return m_cpqr.isInjective(); } 252 253 /** \returns true if the matrix of which *this is the decomposition represents 254 * a surjective linear map; false otherwise. 255 * 256 * \note This method has to determine which pivots should be considered 257 * nonzero. For that, it uses the threshold value that you can control by 258 * calling setThreshold(const RealScalar&). 259 */ 260 inline bool isSurjective() const { return m_cpqr.isSurjective(); } 261 262 /** \returns true if the matrix of which *this is the complete orthogonal 263 * decomposition is invertible. 264 * 265 * \note This method has to determine which pivots should be considered 266 * nonzero. For that, it uses the threshold value that you can control by 267 * calling setThreshold(const RealScalar&). 268 */ 269 inline bool isInvertible() const { return m_cpqr.isInvertible(); } 270 271 /** \returns the pseudo-inverse of the matrix of which *this is the complete 272 * orthogonal decomposition. 273 * \warning: Do not compute \c this->pseudoInverse()*rhs to solve a linear systems. 274 * It is more efficient and numerically stable to call \c this->solve(rhs). 275 */ 276 inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const 277 { 278 return Inverse<CompleteOrthogonalDecomposition>(*this); 279 } 280 281 inline Index rows() const { return m_cpqr.rows(); } 282 inline Index cols() const { return m_cpqr.cols(); } 283 284 /** \returns a const reference to the vector of Householder coefficients used 285 * to represent the factor \c Q. 286 * 287 * For advanced uses only. 288 */ 289 inline const HCoeffsType& hCoeffs() const { return m_cpqr.hCoeffs(); } 290 291 /** \returns a const reference to the vector of Householder coefficients 292 * used to represent the factor \c Z. 293 * 294 * For advanced uses only. 295 */ 296 const HCoeffsType& zCoeffs() const { return m_zCoeffs; } 297 298 /** Allows to prescribe a threshold to be used by certain methods, such as 299 * rank(), who need to determine when pivots are to be considered nonzero. 300 * Most be called before calling compute(). 301 * 302 * When it needs to get the threshold value, Eigen calls threshold(). By 303 * default, this uses a formula to automatically determine a reasonable 304 * threshold. Once you have called the present method 305 * setThreshold(const RealScalar&), your value is used instead. 306 * 307 * \param threshold The new value to use as the threshold. 308 * 309 * A pivot will be considered nonzero if its absolute value is strictly 310 * greater than 311 * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$ 312 * where maxpivot is the biggest pivot. 313 * 314 * If you want to come back to the default behavior, call 315 * setThreshold(Default_t) 316 */ 317 CompleteOrthogonalDecomposition& setThreshold(const RealScalar& threshold) { 318 m_cpqr.setThreshold(threshold); 319 return *this; 320 } 321 322 /** Allows to come back to the default behavior, letting Eigen use its default 323 * formula for determining the threshold. 324 * 325 * You should pass the special object Eigen::Default as parameter here. 326 * \code qr.setThreshold(Eigen::Default); \endcode 327 * 328 * See the documentation of setThreshold(const RealScalar&). 329 */ 330 CompleteOrthogonalDecomposition& setThreshold(Default_t) { 331 m_cpqr.setThreshold(Default); 332 return *this; 333 } 334 335 /** Returns the threshold that will be used by certain methods such as rank(). 336 * 337 * See the documentation of setThreshold(const RealScalar&). 338 */ 339 RealScalar threshold() const { return m_cpqr.threshold(); } 340 341 /** \returns the number of nonzero pivots in the complete orthogonal 342 * decomposition. Here nonzero is meant in the exact sense, not in a 343 * fuzzy sense. So that notion isn't really intrinsically interesting, 344 * but it is still useful when implementing algorithms. 345 * 346 * \sa rank() 347 */ 348 inline Index nonzeroPivots() const { return m_cpqr.nonzeroPivots(); } 349 350 /** \returns the absolute value of the biggest pivot, i.e. the biggest 351 * diagonal coefficient of R. 352 */ 353 inline RealScalar maxPivot() const { return m_cpqr.maxPivot(); } 354 355 /** \brief Reports whether the complete orthogonal decomposition was 356 * succesful. 357 * 358 * \note This function always returns \c Success. It is provided for 359 * compatibility 360 * with other factorization routines. 361 * \returns \c Success 362 */ 363 ComputationInfo info() const { 364 eigen_assert(m_cpqr.m_isInitialized && "Decomposition is not initialized."); 365 return Success; 366 } 367 368 #ifndef EIGEN_PARSED_BY_DOXYGEN 369 template <typename RhsType, typename DstType> 370 EIGEN_DEVICE_FUNC void _solve_impl(const RhsType& rhs, DstType& dst) const; 371 #endif 372 373 protected: 374 static void check_template_parameters() { 375 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 376 } 377 378 void computeInPlace(); 379 380 /** Overwrites \b rhs with \f$ \mathbf{Z}^* * \mathbf{rhs} \f$. 381 */ 382 template <typename Rhs> 383 void applyZAdjointOnTheLeftInPlace(Rhs& rhs) const; 384 385 ColPivHouseholderQR<MatrixType> m_cpqr; 386 HCoeffsType m_zCoeffs; 387 RowVectorType m_temp; 388 }; 389 390 template <typename MatrixType> 391 typename MatrixType::RealScalar 392 CompleteOrthogonalDecomposition<MatrixType>::absDeterminant() const { 393 return m_cpqr.absDeterminant(); 394 } 395 396 template <typename MatrixType> 397 typename MatrixType::RealScalar 398 CompleteOrthogonalDecomposition<MatrixType>::logAbsDeterminant() const { 399 return m_cpqr.logAbsDeterminant(); 400 } 401 402 /** Performs the complete orthogonal decomposition of the given matrix \a 403 * matrix. The result of the factorization is stored into \c *this, and a 404 * reference to \c *this is returned. 405 * 406 * \sa class CompleteOrthogonalDecomposition, 407 * CompleteOrthogonalDecomposition(const MatrixType&) 408 */ 409 template <typename MatrixType> 410 void CompleteOrthogonalDecomposition<MatrixType>::computeInPlace() 411 { 412 check_template_parameters(); 413 414 // the column permutation is stored as int indices, so just to be sure: 415 eigen_assert(m_cpqr.cols() <= NumTraits<int>::highest()); 416 417 const Index rank = m_cpqr.rank(); 418 const Index cols = m_cpqr.cols(); 419 const Index rows = m_cpqr.rows(); 420 m_zCoeffs.resize((std::min)(rows, cols)); 421 m_temp.resize(cols); 422 423 if (rank < cols) { 424 // We have reduced the (permuted) matrix to the form 425 // [R11 R12] 426 // [ 0 R22] 427 // where R11 is r-by-r (r = rank) upper triangular, R12 is 428 // r-by-(n-r), and R22 is empty or the norm of R22 is negligible. 429 // We now compute the complete orthogonal decomposition by applying 430 // Householder transformations from the right to the upper trapezoidal 431 // matrix X = [R11 R12] to zero out R12 and obtain the factorization 432 // [R11 R12] = [T11 0] * Z, where T11 is r-by-r upper triangular and 433 // Z = Z(0) * Z(1) ... Z(r-1) is an n-by-n orthogonal matrix. 434 // We store the data representing Z in R12 and m_zCoeffs. 435 for (Index k = rank - 1; k >= 0; --k) { 436 if (k != rank - 1) { 437 // Given the API for Householder reflectors, it is more convenient if 438 // we swap the leading parts of columns k and r-1 (zero-based) to form 439 // the matrix X_k = [X(0:k, k), X(0:k, r:n)] 440 m_cpqr.m_qr.col(k).head(k + 1).swap( 441 m_cpqr.m_qr.col(rank - 1).head(k + 1)); 442 } 443 // Construct Householder reflector Z(k) to zero out the last row of X_k, 444 // i.e. choose Z(k) such that 445 // [X(k, k), X(k, r:n)] * Z(k) = [beta, 0, .., 0]. 446 RealScalar beta; 447 m_cpqr.m_qr.row(k) 448 .tail(cols - rank + 1) 449 .makeHouseholderInPlace(m_zCoeffs(k), beta); 450 m_cpqr.m_qr(k, rank - 1) = beta; 451 if (k > 0) { 452 // Apply Z(k) to the first k rows of X_k 453 m_cpqr.m_qr.topRightCorner(k, cols - rank + 1) 454 .applyHouseholderOnTheRight( 455 m_cpqr.m_qr.row(k).tail(cols - rank).transpose(), m_zCoeffs(k), 456 &m_temp(0)); 457 } 458 if (k != rank - 1) { 459 // Swap X(0:k,k) back to its proper location. 460 m_cpqr.m_qr.col(k).head(k + 1).swap( 461 m_cpqr.m_qr.col(rank - 1).head(k + 1)); 462 } 463 } 464 } 465 } 466 467 template <typename MatrixType> 468 template <typename Rhs> 469 void CompleteOrthogonalDecomposition<MatrixType>::applyZAdjointOnTheLeftInPlace( 470 Rhs& rhs) const { 471 const Index cols = this->cols(); 472 const Index nrhs = rhs.cols(); 473 const Index rank = this->rank(); 474 Matrix<typename MatrixType::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs)); 475 for (Index k = 0; k < rank; ++k) { 476 if (k != rank - 1) { 477 rhs.row(k).swap(rhs.row(rank - 1)); 478 } 479 rhs.middleRows(rank - 1, cols - rank + 1) 480 .applyHouseholderOnTheLeft( 481 matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k), 482 &temp(0)); 483 if (k != rank - 1) { 484 rhs.row(k).swap(rhs.row(rank - 1)); 485 } 486 } 487 } 488 489 #ifndef EIGEN_PARSED_BY_DOXYGEN 490 template <typename _MatrixType> 491 template <typename RhsType, typename DstType> 492 void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl( 493 const RhsType& rhs, DstType& dst) const { 494 eigen_assert(rhs.rows() == this->rows()); 495 496 const Index rank = this->rank(); 497 if (rank == 0) { 498 dst.setZero(); 499 return; 500 } 501 502 // Compute c = Q^* * rhs 503 // Note that the matrix Q = H_0^* H_1^*... so its inverse is 504 // Q^* = (H_0 H_1 ...)^T 505 typename RhsType::PlainObject c(rhs); 506 c.applyOnTheLeft( 507 householderSequence(matrixQTZ(), hCoeffs()).setLength(rank).transpose()); 508 509 // Solve T z = c(1:rank, :) 510 dst.topRows(rank) = matrixT() 511 .topLeftCorner(rank, rank) 512 .template triangularView<Upper>() 513 .solve(c.topRows(rank)); 514 515 const Index cols = this->cols(); 516 if (rank < cols) { 517 // Compute y = Z^* * [ z ] 518 // [ 0 ] 519 dst.bottomRows(cols - rank).setZero(); 520 applyZAdjointOnTheLeftInPlace(dst); 521 } 522 523 // Undo permutation to get x = P^{-1} * y. 524 dst = colsPermutation() * dst; 525 } 526 #endif 527 528 namespace internal { 529 530 template<typename DstXprType, typename MatrixType> 531 struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType> >, internal::assign_op<typename DstXprType::Scalar,typename CompleteOrthogonalDecomposition<MatrixType>::Scalar>, Dense2Dense> 532 { 533 typedef CompleteOrthogonalDecomposition<MatrixType> CodType; 534 typedef Inverse<CodType> SrcXprType; 535 static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename CodType::Scalar> &) 536 { 537 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.rows())); 538 } 539 }; 540 541 } // end namespace internal 542 543 /** \returns the matrix Q as a sequence of householder transformations */ 544 template <typename MatrixType> 545 typename CompleteOrthogonalDecomposition<MatrixType>::HouseholderSequenceType 546 CompleteOrthogonalDecomposition<MatrixType>::householderQ() const { 547 return m_cpqr.householderQ(); 548 } 549 550 /** \return the complete orthogonal decomposition of \c *this. 551 * 552 * \sa class CompleteOrthogonalDecomposition 553 */ 554 template <typename Derived> 555 const CompleteOrthogonalDecomposition<typename MatrixBase<Derived>::PlainObject> 556 MatrixBase<Derived>::completeOrthogonalDecomposition() const { 557 return CompleteOrthogonalDecomposition<PlainObject>(eval()); 558 } 559 560 } // end namespace Eigen 561 562 #endif // EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H 563