Eigen  5.0.1-dev+60122df6
 
Loading...
Searching...
No Matches
CompleteOrthogonalDecomposition.h
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// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19template <typename MatrixType_, typename PermutationIndex_>
20struct traits<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> : traits<MatrixType_> {
21 typedef MatrixXpr XprKind;
22 typedef SolverStorage StorageKind;
23 typedef PermutationIndex_ PermutationIndex;
24 enum { Flags = 0 };
25};
26
27} // end namespace internal
28
52template <typename MatrixType_, typename PermutationIndex_>
54 : public SolverBase<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> {
55 public:
56 typedef MatrixType_ MatrixType;
58
59 template <typename Derived>
60 friend struct internal::solve_assertion;
61 typedef PermutationIndex_ PermutationIndex;
62 EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecomposition)
63 enum {
64 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
65 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
66 };
67 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
69 typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
70 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
71 typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
73 HouseholderSequenceType;
74 typedef typename MatrixType::PlainObject PlainObject;
75
76 public:
84 CompleteOrthogonalDecomposition() : m_cpqr(), m_zCoeffs(), m_temp() {}
85
93 : m_cpqr(rows, cols), m_zCoeffs((std::min)(rows, cols)), m_temp(cols) {}
94
111 template <typename InputType>
113 : m_cpqr(matrix.rows(), matrix.cols()),
114 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
115 m_temp(matrix.cols()) {
116 compute(matrix.derived());
117 }
118
126 template <typename InputType>
128 : m_cpqr(matrix.derived()), m_zCoeffs((std::min)(matrix.rows(), matrix.cols())), m_temp(matrix.cols()) {
130 }
131
132#ifdef EIGEN_PARSED_BY_DOXYGEN
142 template <typename Rhs>
144#endif
145
146 HouseholderSequenceType householderQ(void) const;
147 HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); }
148
151 MatrixType matrixZ() const {
152 MatrixType Z = MatrixType::Identity(m_cpqr.cols(), m_cpqr.cols());
154 return Z;
155 }
156
160 const MatrixType& matrixQTZ() const { return m_cpqr.matrixQR(); }
161
173 const MatrixType& matrixT() const { return m_cpqr.matrixQR(); }
174
175 template <typename InputType>
177 // Compute the column pivoted QR factorization A P = Q R.
178 m_cpqr.compute(matrix);
180 return *this;
181 }
182
184 const PermutationType& colsPermutation() const { return m_cpqr.colsPermutation(); }
185
199 typename MatrixType::Scalar determinant() const;
200
214 typename MatrixType::RealScalar absDeterminant() const;
215
229 typename MatrixType::RealScalar logAbsDeterminant() const;
230
244 typename MatrixType::Scalar signDeterminant() const;
245
253 inline Index rank() const { return m_cpqr.rank(); }
254
262 inline Index dimensionOfKernel() const { return m_cpqr.dimensionOfKernel(); }
263
271 inline bool isInjective() const { return m_cpqr.isInjective(); }
272
280 inline bool isSurjective() const { return m_cpqr.isSurjective(); }
281
289 inline bool isInvertible() const { return m_cpqr.isInvertible(); }
290
297 eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
299 }
300
301 inline Index rows() const { return m_cpqr.rows(); }
302 inline Index cols() const { return m_cpqr.cols(); }
303
309 inline const HCoeffsType& hCoeffs() const { return m_cpqr.hCoeffs(); }
310
316 const HCoeffsType& zCoeffs() const { return m_zCoeffs; }
317
338 m_cpqr.setThreshold(threshold);
339 return *this;
340 }
341
351 m_cpqr.setThreshold(Default);
352 return *this;
353 }
354
359 RealScalar threshold() const { return m_cpqr.threshold(); }
360
368 inline Index nonzeroPivots() const { return m_cpqr.nonzeroPivots(); }
369
373 inline RealScalar maxPivot() const { return m_cpqr.maxPivot(); }
374
384 eigen_assert(m_cpqr.m_isInitialized && "Decomposition is not initialized.");
385 return Success;
386 }
387
388#ifndef EIGEN_PARSED_BY_DOXYGEN
389 template <typename RhsType, typename DstType>
390 void _solve_impl(const RhsType& rhs, DstType& dst) const;
391
392 template <bool Conjugate, typename RhsType, typename DstType>
393 void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
394#endif
395
396 protected:
397 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
398
399 template <bool Transpose_, typename Rhs>
400 void _check_solve_assertion(const Rhs& b) const {
401 EIGEN_ONLY_USED_FOR_DEBUG(b);
402 eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
403 eigen_assert((Transpose_ ? derived().cols() : derived().rows()) == b.rows() &&
404 "CompleteOrthogonalDecomposition::solve(): invalid number of rows of the right hand side matrix b");
405 }
406
408
413 template <bool Conjugate, typename Rhs>
414 void applyZOnTheLeftInPlace(Rhs& rhs) const;
415
418 template <typename Rhs>
419 void applyZAdjointOnTheLeftInPlace(Rhs& rhs) const;
420
422 HCoeffsType m_zCoeffs;
423 RowVectorType m_temp;
424};
425
426template <typename MatrixType, typename PermutationIndex>
428 return m_cpqr.determinant();
429}
430
431template <typename MatrixType, typename PermutationIndex>
433 return m_cpqr.absDeterminant();
434}
435
436template <typename MatrixType, typename PermutationIndex>
438 const {
439 return m_cpqr.logAbsDeterminant();
440}
441
442template <typename MatrixType, typename PermutationIndex>
444 return m_cpqr.signDeterminant();
445}
446
454template <typename MatrixType, typename PermutationIndex>
456 eigen_assert(m_cpqr.cols() <= NumTraits<PermutationIndex>::highest());
457
458 const Index rank = m_cpqr.rank();
459 const Index cols = m_cpqr.cols();
460 const Index rows = m_cpqr.rows();
461 m_zCoeffs.resize((std::min)(rows, cols));
462 m_temp.resize(cols);
463
464 if (rank < cols) {
465 // We have reduced the (permuted) matrix to the form
466 // [R11 R12]
467 // [ 0 R22]
468 // where R11 is r-by-r (r = rank) upper triangular, R12 is
469 // r-by-(n-r), and R22 is empty or the norm of R22 is negligible.
470 // We now compute the complete orthogonal decomposition by applying
471 // Householder transformations from the right to the upper trapezoidal
472 // matrix X = [R11 R12] to zero out R12 and obtain the factorization
473 // [R11 R12] = [T11 0] * Z, where T11 is r-by-r upper triangular and
474 // Z = Z(0) * Z(1) ... Z(r-1) is an n-by-n orthogonal matrix.
475 // We store the data representing Z in R12 and m_zCoeffs.
476 for (Index k = rank - 1; k >= 0; --k) {
477 if (k != rank - 1) {
478 // Given the API for Householder reflectors, it is more convenient if
479 // we swap the leading parts of columns k and r-1 (zero-based) to form
480 // the matrix X_k = [X(0:k, k), X(0:k, r:n)]
481 m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
482 }
483 // Construct Householder reflector Z(k) to zero out the last row of X_k,
484 // i.e. choose Z(k) such that
485 // [X(k, k), X(k, r:n)] * Z(k) = [beta, 0, .., 0].
486 RealScalar beta;
487 m_cpqr.m_qr.row(k).tail(cols - rank + 1).makeHouseholderInPlace(m_zCoeffs(k), beta);
488 m_cpqr.m_qr(k, rank - 1) = beta;
489 if (k > 0) {
490 // Apply Z(k) to the first k rows of X_k
491 m_cpqr.m_qr.topRightCorner(k, cols - rank + 1)
492 .applyHouseholderOnTheRight(m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k), &m_temp(0));
493 }
494 if (k != rank - 1) {
495 // Swap X(0:k,k) back to its proper location.
496 m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
497 }
498 }
499 }
500}
501
502template <typename MatrixType, typename PermutationIndex>
503template <bool Conjugate, typename Rhs>
505 const Index cols = this->cols();
506 const Index nrhs = rhs.cols();
507 const Index rank = this->rank();
508 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
509 for (Index k = rank - 1; k >= 0; --k) {
510 if (k != rank - 1) {
511 rhs.row(k).swap(rhs.row(rank - 1));
512 }
513 rhs.middleRows(rank - 1, cols - rank + 1)
514 .applyHouseholderOnTheLeft(matrixQTZ().row(k).tail(cols - rank).transpose().template conjugateIf<!Conjugate>(),
515 zCoeffs().template conjugateIf<Conjugate>()(k), &temp(0));
516 if (k != rank - 1) {
517 rhs.row(k).swap(rhs.row(rank - 1));
518 }
519 }
520}
521
522template <typename MatrixType, typename PermutationIndex>
523template <typename Rhs>
525 const Index cols = this->cols();
526 const Index nrhs = rhs.cols();
527 const Index rank = this->rank();
528 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
529 for (Index k = 0; k < rank; ++k) {
530 if (k != rank - 1) {
531 rhs.row(k).swap(rhs.row(rank - 1));
532 }
533 rhs.middleRows(rank - 1, cols - rank + 1)
534 .applyHouseholderOnTheLeft(matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k), &temp(0));
535 if (k != rank - 1) {
536 rhs.row(k).swap(rhs.row(rank - 1));
537 }
538 }
539}
540
541#ifndef EIGEN_PARSED_BY_DOXYGEN
542template <typename MatrixType_, typename PermutationIndex_>
543template <typename RhsType, typename DstType>
545 DstType& dst) const {
546 const Index rank = this->rank();
547 if (rank == 0) {
548 dst.setZero();
549 return;
550 }
551
552 // Compute c = Q^* * rhs
553 typename RhsType::PlainObject c(rhs);
554 c.applyOnTheLeft(matrixQ().setLength(rank).adjoint());
555
556 // Solve T z = c(1:rank, :)
557 dst.topRows(rank) = matrixT().topLeftCorner(rank, rank).template triangularView<Upper>().solve(c.topRows(rank));
558
559 const Index cols = this->cols();
560 if (rank < cols) {
561 // Compute y = Z^* * [ z ]
562 // [ 0 ]
563 dst.bottomRows(cols - rank).setZero();
564 applyZAdjointOnTheLeftInPlace(dst);
565 }
566
567 // Undo permutation to get x = P^{-1} * y.
568 dst = colsPermutation() * dst;
569}
570
571template <typename MatrixType_, typename PermutationIndex_>
572template <bool Conjugate, typename RhsType, typename DstType>
574 DstType& dst) const {
575 const Index rank = this->rank();
576
577 if (rank == 0) {
578 dst.setZero();
579 return;
580 }
581
582 typename RhsType::PlainObject c(colsPermutation().transpose() * rhs);
583
584 if (rank < cols()) {
585 applyZOnTheLeftInPlace<!Conjugate>(c);
586 }
587
588 matrixT()
589 .topLeftCorner(rank, rank)
590 .template triangularView<Upper>()
591 .transpose()
592 .template conjugateIf<Conjugate>()
593 .solveInPlace(c.topRows(rank));
594
595 dst.topRows(rank) = c.topRows(rank);
596 dst.bottomRows(rows() - rank).setZero();
597
598 dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>());
599}
600#endif
601
602namespace internal {
603
604template <typename MatrixType, typename PermutationIndex>
605struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>>
606 : traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject> {
607 enum { Flags = 0 };
608};
609
610template <typename DstXprType, typename MatrixType, typename PermutationIndex>
611struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>,
612 internal::assign_op<typename DstXprType::Scalar,
613 typename CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::Scalar>,
614 Dense2Dense> {
615 typedef CompleteOrthogonalDecomposition<MatrixType, PermutationIndex> CodType;
616 typedef Inverse<CodType> SrcXprType;
617 static void run(DstXprType& dst, const SrcXprType& src,
618 const internal::assign_op<typename DstXprType::Scalar, typename CodType::Scalar>&) {
619 typedef Matrix<typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime, 0,
620 CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime>
621 IdentityMatrixType;
622 dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
623 }
624};
625
626} // end namespace internal
627
629template <typename MatrixType, typename PermutationIndex>
630typename CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::HouseholderSequenceType
634
639template <typename Derived>
640template <typename PermutationIndex>
642MatrixBase<Derived>::completeOrthogonalDecomposition() const {
644}
645
646} // end namespace Eigen
647
648#endif // EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
Definition ColPivHouseholderQR.h:54
MatrixType::Scalar determinant() const
Definition ColPivHouseholderQR.h:440
Complete orthogonal decomposition (COD) of a matrix.
Definition CompleteOrthogonalDecomposition.h:54
const HCoeffsType & zCoeffs() const
Definition CompleteOrthogonalDecomposition.h:316
MatrixType matrixZ() const
Definition CompleteOrthogonalDecomposition.h:151
void applyZAdjointOnTheLeftInPlace(Rhs &rhs) const
Definition CompleteOrthogonalDecomposition.h:524
CompleteOrthogonalDecomposition()
Default Constructor.
Definition CompleteOrthogonalDecomposition.h:84
bool isSurjective() const
Definition CompleteOrthogonalDecomposition.h:280
MatrixType::Scalar signDeterminant() const
Definition CompleteOrthogonalDecomposition.h:443
Index dimensionOfKernel() const
Definition CompleteOrthogonalDecomposition.h:262
CompleteOrthogonalDecomposition(const EigenBase< InputType > &matrix)
Constructs a complete orthogonal decomposition from a given matrix.
Definition CompleteOrthogonalDecomposition.h:112
CompleteOrthogonalDecomposition(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition CompleteOrthogonalDecomposition.h:92
const Solve< CompleteOrthogonalDecomposition, Rhs > solve(const MatrixBase< Rhs > &b) const
MatrixType::RealScalar absDeterminant() const
Definition CompleteOrthogonalDecomposition.h:432
HouseholderSequenceType householderQ(void) const
Definition CompleteOrthogonalDecomposition.h:631
const Inverse< CompleteOrthogonalDecomposition > pseudoInverse() const
Definition CompleteOrthogonalDecomposition.h:296
MatrixType::RealScalar logAbsDeterminant() const
Definition CompleteOrthogonalDecomposition.h:437
CompleteOrthogonalDecomposition & setThreshold(const RealScalar &threshold)
Definition CompleteOrthogonalDecomposition.h:337
RealScalar threshold() const
Definition CompleteOrthogonalDecomposition.h:359
ComputationInfo info() const
Reports whether the complete orthogonal decomposition was successful.
Definition CompleteOrthogonalDecomposition.h:383
bool isInvertible() const
Definition CompleteOrthogonalDecomposition.h:289
const HCoeffsType & hCoeffs() const
Definition CompleteOrthogonalDecomposition.h:309
const PermutationType & colsPermutation() const
Definition CompleteOrthogonalDecomposition.h:184
const MatrixType & matrixQTZ() const
Definition CompleteOrthogonalDecomposition.h:160
bool isInjective() const
Definition CompleteOrthogonalDecomposition.h:271
void applyZOnTheLeftInPlace(Rhs &rhs) const
Definition CompleteOrthogonalDecomposition.h:504
void computeInPlace()
Definition CompleteOrthogonalDecomposition.h:455
Index nonzeroPivots() const
Definition CompleteOrthogonalDecomposition.h:368
CompleteOrthogonalDecomposition & setThreshold(Default_t)
Definition CompleteOrthogonalDecomposition.h:350
MatrixType::Scalar determinant() const
Definition CompleteOrthogonalDecomposition.h:427
Index rank() const
Definition CompleteOrthogonalDecomposition.h:253
const MatrixType & matrixT() const
Definition CompleteOrthogonalDecomposition.h:173
RealScalar maxPivot() const
Definition CompleteOrthogonalDecomposition.h:373
CompleteOrthogonalDecomposition(EigenBase< InputType > &matrix)
Constructs a complete orthogonal decomposition from a given matrix.
Definition CompleteOrthogonalDecomposition.h:127
EvalReturnType eval() const
Definition DenseBase.h:386
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition HouseholderSequence.h:117
Expression of the inverse of another expression.
Definition Inverse.h:43
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
Permutation matrix.
Definition PermutationMatrix.h:283
Pseudo expression representing a solving operation.
Definition Solve.h:62
constexpr Derived & derived()
Definition EigenBase.h:49
const ConstTransposeReturnType transpose() const
Definition SolverBase.h:128
const AdjointReturnType adjoint() const
Definition SolverBase.h:144
ComputationInfo
Definition Constants.h:438
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82
Definition EigenBase.h:33
constexpr Derived & derived()
Definition EigenBase.h:49
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:43