11 #ifndef EIGEN_SPARSE_QR_H 12 #define EIGEN_SPARSE_QR_H 16 template<
typename MatrixType,
typename OrderingType>
class SparseQR;
23 typedef typename SparseQRType::MatrixType ReturnType;
24 typedef typename ReturnType::StorageIndex StorageIndex;
25 typedef typename ReturnType::StorageKind StorageKind;
33 typedef typename SparseQRType::MatrixType ReturnType;
37 typedef typename Derived::PlainObject ReturnType;
70 template<
typename _MatrixType,
typename _OrderingType>
75 using Base::m_isInitialized;
77 using Base::_solve_impl;
78 typedef _MatrixType MatrixType;
79 typedef _OrderingType OrderingType;
80 typedef typename MatrixType::Scalar Scalar;
81 typedef typename MatrixType::RealScalar RealScalar;
82 typedef typename MatrixType::StorageIndex StorageIndex;
89 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
90 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
94 SparseQR () : m_analysisIsok(
false), m_lastError(
""), m_useDefaultThreshold(
true),m_isQSorted(
false),m_isEtreeOk(
false)
103 explicit SparseQR(
const MatrixType& mat) : m_analysisIsok(false), m_lastError(
""), m_useDefaultThreshold(true),m_isQSorted(false),m_isEtreeOk(false)
119 void analyzePattern(
const MatrixType& mat);
120 void factorize(
const MatrixType& mat);
143 const QRMatrixType&
matrixR()
const {
return m_R; }
151 eigen_assert(m_isInitialized &&
"The factorization should be called first, use compute()");
152 return m_nonzeropivots;
181 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
182 return m_outputPerm_c;
191 template<
typename Rhs,
typename Dest>
194 eigen_assert(m_isInitialized &&
"The factorization should be called first, use compute()");
195 eigen_assert(this->rows() == B.rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
197 Index rank = this->rank();
200 typename Dest::PlainObject y, b;
201 y = this->matrixQ().transpose() * B;
205 y.
resize((std::max<Index>)(cols(),y.rows()),y.cols());
206 y.topRows(rank) = this->matrixR().topLeftCorner(rank, rank).template triangularView<Upper>().solve(b.topRows(rank));
207 y.bottomRows(y.rows()-rank).setZero();
210 if (m_perm_c.size()) dest = colsPermutation() * y.
topRows(cols());
224 m_useDefaultThreshold =
false;
225 m_threshold = threshold;
232 template<
typename Rhs>
235 eigen_assert(m_isInitialized &&
"The factorization should be called first, use compute()");
236 eigen_assert(this->rows() == B.rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
239 template<
typename Rhs>
242 eigen_assert(m_isInitialized &&
"The factorization should be called first, use compute()");
243 eigen_assert(this->rows() == B.
rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
257 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
263 inline void _sort_matrix_Q()
265 if(this->m_isQSorted)
return;
269 this->m_isQSorted =
true;
275 bool m_factorizationIsok;
277 std::string m_lastError;
281 ScalarVector m_hcoeffs;
282 PermutationType m_perm_c;
283 PermutationType m_pivotperm;
284 PermutationType m_outputPerm_c;
285 RealScalar m_threshold;
286 bool m_useDefaultThreshold;
287 Index m_nonzeropivots;
289 IndexVector m_firstRowElt;
306 template <
typename MatrixType,
typename OrderingType>
309 eigen_assert(mat.isCompressed() &&
"SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
314 ord(matCpy, m_perm_c);
315 Index n = mat.cols();
316 Index m = mat.rows();
317 Index diagSize = (std::min)(m,n);
319 if (!m_perm_c.size())
322 m_perm_c.indices().setLinSpaced(n, 0,StorageIndex(n-1));
326 m_outputPerm_c = m_perm_c.inverse();
331 m_Q.resize(m, diagSize);
334 m_R.reserve(2*mat.nonZeros());
335 m_Q.reserve(2*mat.nonZeros());
336 m_hcoeffs.resize(diagSize);
337 m_analysisIsok =
true;
347 template <
typename MatrixType,
typename OrderingType>
352 eigen_assert(m_analysisIsok &&
"analyzePattern() should be called before this step");
353 StorageIndex m = StorageIndex(mat.rows());
354 StorageIndex n = StorageIndex(mat.cols());
355 StorageIndex diagSize = (std::min)(m,n);
358 Index nzcolR, nzcolQ;
360 RealScalar pivotThreshold = m_threshold;
367 m_outputPerm_c = m_perm_c.inverse();
380 const StorageIndex *originalOuterIndices = mat.outerIndexPtr();
381 if(MatrixType::IsRowMajor)
383 originalOuterIndicesCpy = IndexVector::Map(m_pmat.outerIndexPtr(),n+1);
384 originalOuterIndices = originalOuterIndicesCpy.
data();
387 for (
int i = 0; i < n; i++)
389 Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
390 m_pmat.outerIndexPtr()[p] = originalOuterIndices[i];
391 m_pmat.innerNonZeroPtr()[p] = originalOuterIndices[i+1] - originalOuterIndices[i];
399 if(m_useDefaultThreshold)
401 RealScalar max2Norm = 0.0;
402 for (
int j = 0; j < n; j++) max2Norm = numext::maxi(max2Norm, m_pmat.col(j).norm());
403 if(max2Norm==RealScalar(0))
404 max2Norm = RealScalar(1);
409 m_pivotperm.setIdentity(n);
411 StorageIndex nonzeroCol = 0;
415 for (StorageIndex col = 0; col < n; ++col)
419 mark(nonzeroCol) = col;
420 Qidx(0) = nonzeroCol;
421 nzcolR = 0; nzcolQ = 1;
422 bool found_diag = nonzeroCol>=m;
429 for (
typename QRMatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
431 StorageIndex curIdx = nonzeroCol;
432 if(itp) curIdx = StorageIndex(itp.row());
433 if(curIdx == nonzeroCol) found_diag =
true;
436 StorageIndex st = m_firstRowElt(curIdx);
439 m_lastError =
"Empty row found during numerical factorization";
446 for (; mark(st) != col; st = m_etree(st))
454 Index nt = nzcolR-bi;
455 for(
Index i = 0; i < nt/2; i++) std::swap(Ridx(bi+i), Ridx(nzcolR-i-1));
458 if(itp) tval(curIdx) = itp.value();
459 else tval(curIdx) = Scalar(0);
462 if(curIdx > nonzeroCol && mark(curIdx) != col )
464 Qidx(nzcolQ) = curIdx;
471 for (
Index i = nzcolR-1; i >= 0; i--)
473 Index curIdx = Ridx(i);
479 tdot = m_Q.col(curIdx).dot(tval);
481 tdot *= m_hcoeffs(curIdx);
485 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
486 tval(itq.row()) -= itq.value() * tdot;
489 if(m_etree(Ridx(i)) == nonzeroCol)
491 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
493 StorageIndex iQ = StorageIndex(itq.row());
503 Scalar tau = RealScalar(0);
506 if(nonzeroCol < diagSize)
510 Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
513 RealScalar sqrNorm = 0.;
514 for (
Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
515 if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
517 beta = numext::real(c0);
523 beta = sqrt(numext::abs2(c0) + sqrNorm);
524 if(numext::real(c0) >= RealScalar(0))
527 for (
Index itq = 1; itq < nzcolQ; ++itq)
528 tval(Qidx(itq)) /= (c0 - beta);
529 tau = numext::conj((beta-c0) / beta);
535 for (
Index i = nzcolR-1; i >= 0; i--)
537 Index curIdx = Ridx(i);
538 if(curIdx < nonzeroCol)
540 m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
541 tval(curIdx) = Scalar(0.);
545 if(nonzeroCol < diagSize && abs(beta) >= pivotThreshold)
547 m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
549 m_hcoeffs(nonzeroCol) = tau;
551 for (
Index itq = 0; itq < nzcolQ; ++itq)
553 Index iQ = Qidx(itq);
554 m_Q.insertBackByOuterInnerUnordered(nonzeroCol,iQ) = tval(iQ);
555 tval(iQ) = Scalar(0.);
558 if(nonzeroCol<diagSize)
559 m_Q.startVec(nonzeroCol);
564 for (
Index j = nonzeroCol; j < n-1; j++)
565 std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
573 m_hcoeffs.tail(diagSize-nonzeroCol).setZero();
577 m_Q.makeCompressed();
579 m_R.makeCompressed();
582 m_nonzeropivots = nonzeroCol;
588 m_R = tempR * m_pivotperm;
591 m_outputPerm_c = m_outputPerm_c * m_pivotperm;
594 m_isInitialized =
true;
595 m_factorizationIsok =
true;
599 template <
typename SparseQRType,
typename Derived>
602 typedef typename SparseQRType::QRMatrixType MatrixType;
603 typedef typename SparseQRType::Scalar Scalar;
605 SparseQR_QProduct(
const SparseQRType& qr,
const Derived& other,
bool transpose) :
606 m_qr(qr),m_other(other),m_transpose(transpose) {}
607 inline Index rows()
const {
return m_transpose ? m_qr.rows() : m_qr.cols(); }
608 inline Index cols()
const {
return m_other.cols(); }
611 template<
typename DesType>
612 void evalTo(DesType& res)
const 614 Index m = m_qr.rows();
615 Index n = m_qr.cols();
616 Index diagSize = (std::min)(m,n);
620 eigen_assert(m_qr.m_Q.rows() == m_other.rows() &&
"Non conforming object sizes");
622 for(
Index j = 0; j < res.cols(); j++){
623 for (
Index k = 0; k < diagSize; k++)
625 Scalar tau = Scalar(0);
626 tau = m_qr.m_Q.col(k).dot(res.col(j));
627 if(tau==Scalar(0))
continue;
628 tau = tau * m_qr.m_hcoeffs(k);
629 res.col(j) -= tau * m_qr.m_Q.col(k);
635 eigen_assert(m_qr.m_Q.rows() == m_other.rows() &&
"Non conforming object sizes");
637 for(
Index j = 0; j < res.cols(); j++)
639 for (
Index k = diagSize-1; k >=0; k--)
641 Scalar tau = Scalar(0);
642 tau = m_qr.m_Q.col(k).dot(res.col(j));
643 if(tau==Scalar(0))
continue;
644 tau = tau * m_qr.m_hcoeffs(k);
645 res.col(j) -= tau * m_qr.m_Q.col(k);
651 const SparseQRType& m_qr;
652 const Derived& m_other;
656 template<
typename SparseQRType>
659 typedef typename SparseQRType::Scalar Scalar;
666 template<
typename Derived>
675 inline Index rows()
const {
return m_qr.rows(); }
676 inline Index cols()
const {
return (std::min)(m_qr.rows(),m_qr.cols()); }
682 const SparseQRType& m_qr;
685 template<
typename SparseQRType>
689 template<
typename Derived>
694 const SparseQRType& m_qr;
699 template<
typename SparseQRType>
702 typedef typename SparseQRType::MatrixType MatrixType;
707 template<
typename DstXprType,
typename SparseQRType>
711 typedef typename DstXprType::Scalar Scalar;
712 typedef typename DstXprType::StorageIndex StorageIndex;
715 typename DstXprType::PlainObject idMat(src.m_qr.rows(), src.m_qr.rows());
718 const_cast<SparseQRType *
>(&src.m_qr)->_sort_matrix_Q();
723 template<
typename DstXprType,
typename SparseQRType>
727 typedef typename DstXprType::Scalar Scalar;
728 typedef typename DstXprType::StorageIndex StorageIndex;
731 dst = src.m_qr.matrixQ() * DstXprType::Identity(src.m_qr.rows(), src.m_qr.rows());
Index cols() const
Definition: SparseQR.h:128
Definition: Constants.h:526
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::StorageIndex *perm=0)
Compute the column elimination tree of a sparse matrix.
Definition: SparseColEtree.h:61
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
Definition: SparseQR.h:173
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar * data() const
Definition: PlainObjectBase.h:249
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SparseQR.h:255
A base class for sparse solvers.
Definition: SparseSolverBase.h:67
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:85
Definition: Constants.h:521
Holds information about the various numeric (i.e.
Definition: NumTraits.h:150
EIGEN_DEVICE_FUNC void resize(Index newSize)
Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods...
Definition: DenseBase.h:241
EIGEN_DEVICE_FUNC RowsBlockXpr topRows(Index n)
Definition: DenseBase.h:433
Index rows() const
Definition: SparseQR.h:124
const QRMatrixType & matrixR() const
Definition: SparseQR.h:143
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
Definition: SparseQR.h:348
Definition: AssignmentFunctors.h:21
Definition: AssignEvaluator.h:753
Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor Matrix...
Definition: EigenBase.h:28
Definition: SparseQR.h:19
Definition: ReturnByValue.h:50
Sparse left-looking rank-revealing QR factorization.
Definition: SparseQR.h:16
Index rows() const
Definition: SparseMatrixBase.h:167
Base class of any sparse matrices or sparse expressions.
Definition: ForwardDeclarations.h:281
Definition: SparseQR.h:17
Definition: SparseQR.h:18
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
Definition: SparseAssign.h:62
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Resizes to the given size, and sets all coefficients in this expression to zero.
Definition: CwiseNullaryOp.h:515
The inputs are invalid, or the algorithm has been improperly called.
Definition: Constants.h:439
Computation was successful.
Definition: Constants.h:432
EIGEN_DEVICE_FUNC Derived & setConstant(Index size, const Scalar &val)
Resizes to the given size, and sets all coefficients in this expression to the given value val...
Definition: CwiseNullaryOp.h:341
void analyzePattern(const MatrixType &mat)
Preprocessing step of a QR factorization.
Definition: SparseQR.h:307
Definition: BandTriangularSolver.h:13
Definition: CoreEvaluators.h:79
Index rank() const
Definition: SparseQR.h:149
const int Dynamic
This value means that a positive quantity (e.g., a size) is not known at compile-time, and that instead the value is stored in some runtime variable.
Definition: Constants.h:21
Pseudo expression representing a solving operation.
Definition: Solve.h:62
const PermutationType & colsPermutation() const
Definition: SparseQR.h:179
Generic expression where a coefficient-wise unary operator is applied to an expression.
Definition: CwiseUnaryOp.h:55
std::string lastErrorMessage() const
Definition: SparseQR.h:188
ComputationInfo
Enum for reporting the status of a computation.
Definition: Constants.h:430
SparseQR(const MatrixType &mat)
Construct a QR factorization of the matrix mat.
Definition: SparseQR.h:103
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
Definition: ForwardDeclarations.h:17
Definition: SparseAssign.h:61
void setPivotThreshold(const RealScalar &threshold)
Sets the threshold that is used to determine linearly dependent columns during the factorization...
Definition: SparseQR.h:222
const Solve< SparseQR, Rhs > solve(const MatrixBase< Rhs > &B) const
Definition: SparseQR.h:233
void compute(const MatrixType &mat)
Computes the QR factorization of the sparse matrix mat.
Definition: SparseQR.h:114