Eigen::SparseQR< MatrixType_, OrderingType_ > Class Template Reference

Sparse left-looking QR factorization with numerical column pivoting. More...

#include <SparseQR.h>

+ Inheritance diagram for Eigen::SparseQR< MatrixType_, OrderingType_ >:

Public Types

enum  { ColsAtCompileTime = MatrixType::ColsAtCompileTime , MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime }
 
typedef MatrixType_ MatrixType
 
typedef OrderingType_ OrderingType
 
typedef MatrixType::Scalar Scalar
 
typedef MatrixType::RealScalar RealScalar
 
typedef MatrixType::StorageIndex StorageIndex
 
typedef SparseMatrix< Scalar, ColMajor, StorageIndexQRMatrixType
 
typedef Matrix< StorageIndex, Dynamic, 1 > IndexVector
 
typedef Matrix< Scalar, Dynamic, 1 > ScalarVector
 
typedef PermutationMatrix< Dynamic, Dynamic, StorageIndexPermutationType
 

Public Member Functions

 SparseQR ()
 
 SparseQR (const MatrixType &mat)
 
void compute (const MatrixType &mat)
 
void analyzePattern (const MatrixType &mat)
 Preprocessing step of a QR factorization. More...
 
void factorize (const MatrixType &mat)
 Performs the numerical QR factorization of the input matrix. More...
 
Index rows () const
 
Index cols () const
 
const QRMatrixTypematrixR () const
 
Index rank () const
 
SparseQRMatrixQReturnType< SparseQRmatrixQ () const
 
const PermutationTypecolsPermutation () const
 
std::string lastErrorMessage () const
 
template<typename Rhs , typename Dest >
bool _solve_impl (const MatrixBase< Rhs > &B, MatrixBase< Dest > &dest) const
 
void setPivotThreshold (const RealScalar &threshold)
 
template<typename Rhs >
const Solve< SparseQR, Rhs > solve (const MatrixBase< Rhs > &B) const
 
template<typename Rhs >
const Solve< SparseQR, Rhs > solve (const SparseMatrixBase< Rhs > &B) const
 
ComputationInfo info () const
 Reports whether previous computation was successful. More...
 
void _sort_matrix_Q ()
 
- Public Member Functions inherited from Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >
 SparseSolverBase ()
 
 SparseSolverBase (SparseSolverBase &&other)
 
 ~SparseSolverBase ()
 
SparseQR< MatrixType_, OrderingType_ > & derived ()
 
const SparseQR< MatrixType_, OrderingType_ > & derived () const
 
const Solve< SparseQR< MatrixType_, OrderingType_ >, Rhs > solve (const MatrixBase< Rhs > &b) const
 
const Solve< SparseQR< MatrixType_, OrderingType_ >, Rhs > solve (const SparseMatrixBase< Rhs > &b) const
 
void _solve_impl (const SparseMatrixBase< Rhs > &b, SparseMatrixBase< Dest > &dest) const
 

Protected Types

typedef SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > > Base
 

Protected Attributes

bool m_analysisIsok
 
bool m_factorizationIsok
 
ComputationInfo m_info
 
std::string m_lastError
 
QRMatrixType m_pmat
 
QRMatrixType m_R
 
QRMatrixType m_Q
 
ScalarVector m_hcoeffs
 
PermutationType m_perm_c
 
PermutationType m_pivotperm
 
PermutationType m_outputPerm_c
 
RealScalar m_threshold
 
bool m_useDefaultThreshold
 
Index m_nonzeropivots
 
IndexVector m_etree
 
IndexVector m_firstRowElt
 
bool m_isQSorted
 
bool m_isEtreeOk
 
- Protected Attributes inherited from Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >
bool m_isInitialized
 

Friends

template<typename , typename >
struct SparseQR_QProduct
 

Detailed Description

template<typename MatrixType_, typename OrderingType_>
class Eigen::SparseQR< MatrixType_, OrderingType_ >

Sparse left-looking QR factorization with numerical column pivoting.

This class implements a left-looking QR decomposition of sparse matrices with numerical column pivoting. When a column has a norm less than a given tolerance it is implicitly permuted to the end. The QR factorization thus obtained is given by A*P = Q*R where R is upper triangular or trapezoidal.

P is the column permutation which is the product of the fill-reducing and the numerical permutations. Use colsPermutation() to get it.

Q is the orthogonal matrix represented as products of Householder reflectors. Use matrixQ() to get an expression and matrixQ().adjoint() to get the adjoint. You can then apply it to a vector.

R is the sparse triangular or trapezoidal matrix. The later occurs when A is rank-deficient. matrixR().topLeftCorner(rank(), rank()) always returns a triangular factor of full rank.

Template Parameters
MatrixType_The type of the sparse matrix A, must be a column-major SparseMatrix<>
OrderingType_The fill-reducing ordering method. See the OrderingMethods module for the list of built-in and external ordering methods.

\implsparsesolverconcept

The numerical pivoting strategy and default threshold are the same as in SuiteSparse QR, and detailed in the following paper: Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011. Even though it is qualified as "rank-revealing", this strategy might fail for some rank deficient problems. When this class is used to solve linear or least-square problems it is thus strongly recommended to check the accuracy of the computed solution. If it failed, it usually helps to increase the threshold with setPivotThreshold.

Warning
The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()).
For complex matrices matrixQ().transpose() will actually return the adjoint matrix.

Member Typedef Documentation

◆ Base

template<typename MatrixType_ , typename OrderingType_ >
typedef SparseSolverBase<SparseQR<MatrixType_, OrderingType_> > Eigen::SparseQR< MatrixType_, OrderingType_ >::Base
protected

◆ IndexVector

template<typename MatrixType_ , typename OrderingType_ >
typedef Matrix<StorageIndex, Dynamic, 1> Eigen::SparseQR< MatrixType_, OrderingType_ >::IndexVector

◆ MatrixType

template<typename MatrixType_ , typename OrderingType_ >
typedef MatrixType_ Eigen::SparseQR< MatrixType_, OrderingType_ >::MatrixType

◆ OrderingType

template<typename MatrixType_ , typename OrderingType_ >
typedef OrderingType_ Eigen::SparseQR< MatrixType_, OrderingType_ >::OrderingType

◆ PermutationType

template<typename MatrixType_ , typename OrderingType_ >
typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> Eigen::SparseQR< MatrixType_, OrderingType_ >::PermutationType

◆ QRMatrixType

template<typename MatrixType_ , typename OrderingType_ >
typedef SparseMatrix<Scalar, ColMajor, StorageIndex> Eigen::SparseQR< MatrixType_, OrderingType_ >::QRMatrixType

◆ RealScalar

template<typename MatrixType_ , typename OrderingType_ >
typedef MatrixType::RealScalar Eigen::SparseQR< MatrixType_, OrderingType_ >::RealScalar

◆ Scalar

template<typename MatrixType_ , typename OrderingType_ >
typedef MatrixType::Scalar Eigen::SparseQR< MatrixType_, OrderingType_ >::Scalar

◆ ScalarVector

template<typename MatrixType_ , typename OrderingType_ >
typedef Matrix<Scalar, Dynamic, 1> Eigen::SparseQR< MatrixType_, OrderingType_ >::ScalarVector

◆ StorageIndex

template<typename MatrixType_ , typename OrderingType_ >
typedef MatrixType::StorageIndex Eigen::SparseQR< MatrixType_, OrderingType_ >::StorageIndex

Member Enumeration Documentation

◆ anonymous enum

template<typename MatrixType_ , typename OrderingType_ >
anonymous enum
Enumerator
ColsAtCompileTime 
MaxColsAtCompileTime 
105 { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };
@ ColsAtCompileTime
Definition: SparseQR.h:105
@ MaxColsAtCompileTime
Definition: SparseQR.h:105

Constructor & Destructor Documentation

◆ SparseQR() [1/2]

template<typename MatrixType_ , typename OrderingType_ >
Eigen::SparseQR< MatrixType_, OrderingType_ >::SparseQR ( )
inline
109  : m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true), m_isQSorted(false), m_isEtreeOk(false) {}
bool m_isQSorted
Definition: SparseQR.h:297
bool m_isEtreeOk
Definition: SparseQR.h:298
std::string m_lastError
Definition: SparseQR.h:284
bool m_useDefaultThreshold
Definition: SparseQR.h:293
bool m_analysisIsok
Definition: SparseQR.h:281

◆ SparseQR() [2/2]

template<typename MatrixType_ , typename OrderingType_ >
Eigen::SparseQR< MatrixType_, OrderingType_ >::SparseQR ( const MatrixType mat)
inlineexplicit

Construct a QR factorization of the matrix mat.

Warning
The matrix mat must be in compressed mode (see SparseMatrix::makeCompressed()).
See also
compute()
118  : m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true), m_isQSorted(false), m_isEtreeOk(false) {
119  compute(mat);
120  }
void compute(const MatrixType &mat)
Definition: SparseQR.h:128

References Eigen::SparseQR< MatrixType_, OrderingType_ >::compute().

Member Function Documentation

◆ _solve_impl()

template<typename MatrixType_ , typename OrderingType_ >
template<typename Rhs , typename Dest >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::_solve_impl ( const MatrixBase< Rhs > &  B,
MatrixBase< Dest > &  dest 
) const
inline
202  {
203  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
204  eigen_assert(this->rows() == B.rows() &&
205  "SparseQR::solve() : invalid number of rows in the right hand side matrix");
206 
207  Index rank = this->rank();
208 
209  // Compute Q^* * b;
210  typename Dest::PlainObject y, b;
211  y = this->matrixQ().adjoint() * B;
212  b = y;
213 
214  // Solve with the triangular matrix R
215  y.resize((std::max<Index>)(cols(), y.rows()), y.cols());
216  y.topRows(rank) = this->matrixR().topLeftCorner(rank, rank).template triangularView<Upper>().solve(b.topRows(rank));
217  y.bottomRows(y.rows() - rank).setZero();
218 
219  // Apply the column permutation
220  if (m_perm_c.size())
221  dest = colsPermutation() * y.topRows(cols());
222  else
223  dest = y.topRows(cols());
224 
225  m_info = Success;
226  return true;
227  }
#define eigen_assert(x)
Definition: Macros.h:910
Scalar * b
Definition: benchVecAdd.cpp:17
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:48
EIGEN_DEVICE_FUNC Index size() const
Definition: PermutationMatrix.h:96
PermutationType m_perm_c
Definition: SparseQR.h:289
Index cols() const
Definition: SparseQR.h:141
const QRMatrixType & matrixR() const
Definition: SparseQR.h:156
ComputationInfo m_info
Definition: SparseQR.h:283
Index rows() const
Definition: SparseQR.h:137
const PermutationType & colsPermutation() const
Definition: SparseQR.h:190
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
Definition: SparseQR.h:185
Index rank() const
Definition: SparseQR.h:162
Definition: matrices.h:74
@ Success
Definition: Constants.h:440
Scalar * y
Definition: level1_cplx_impl.h:128
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83

References b, Eigen::SparseQR< MatrixType_, OrderingType_ >::cols(), Eigen::SparseQR< MatrixType_, OrderingType_ >::colsPermutation(), eigen_assert, Eigen::SparseQR< MatrixType_, OrderingType_ >::m_info, Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized, Eigen::SparseQR< MatrixType_, OrderingType_ >::m_perm_c, Eigen::SparseQR< MatrixType_, OrderingType_ >::matrixQ(), Eigen::SparseQR< MatrixType_, OrderingType_ >::matrixR(), Eigen::SparseQR< MatrixType_, OrderingType_ >::rank(), Eigen::SparseQR< MatrixType_, OrderingType_ >::rows(), Eigen::PermutationBase< Derived >::size(), Eigen::Success, and y.

◆ _sort_matrix_Q()

template<typename MatrixType_ , typename OrderingType_ >
void Eigen::SparseQR< MatrixType_, OrderingType_ >::_sort_matrix_Q ( )
inline
272  {
273  if (this->m_isQSorted) return;
274  // The matrix Q is sorted during the transposition
275  SparseMatrix<Scalar, RowMajor, Index> mQrm(this->m_Q);
276  this->m_Q = mQrm;
277  this->m_isQSorted = true;
278  }
QRMatrixType m_Q
Definition: SparseQR.h:287

References Eigen::SparseQR< MatrixType_, OrderingType_ >::m_isQSorted, and Eigen::SparseQR< MatrixType_, OrderingType_ >::m_Q.

◆ analyzePattern()

template<typename MatrixType , typename OrderingType >
void Eigen::SparseQR< MatrixType, OrderingType >::analyzePattern ( const MatrixType mat)

Preprocessing step of a QR factorization.

Warning
The matrix mat must be in compressed mode (see SparseMatrix::makeCompressed()).

In this step, the fill-reducing permutation is computed and applied to the columns of A and the column elimination tree is computed as well. Only the sparsity pattern of mat is exploited.

Note
In this step it is assumed that there is no empty row in the matrix mat.
314  {
315  eigen_assert(
316  mat.isCompressed() &&
317  "SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
318  // Copy to a column major matrix if the input is rowmajor
319  std::conditional_t<MatrixType::IsRowMajor, QRMatrixType, const MatrixType&> matCpy(mat);
320  // Compute the column fill reducing ordering
321  OrderingType ord;
322  ord(matCpy, m_perm_c);
323  Index n = mat.cols();
324  Index m = mat.rows();
325  Index diagSize = (std::min)(m, n);
326 
327  if (!m_perm_c.size()) {
328  m_perm_c.resize(n);
329  m_perm_c.indices().setLinSpaced(n, 0, StorageIndex(n - 1));
330  }
331 
332  // Compute the column elimination tree of the permuted matrix
335  m_isEtreeOk = true;
336 
337  m_R.resize(m, n);
338  m_Q.resize(m, diagSize);
339 
340  // Allocate space for nonzero elements: rough estimation
341  m_R.reserve(2 * mat.nonZeros()); // FIXME Get a more accurate estimation through symbolic factorization with the
342  // etree
343  m_Q.reserve(2 * mat.nonZeros());
344  m_hcoeffs.resize(diagSize);
345  m_analysisIsok = true;
346 }
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
void resize(Index newSize)
Definition: PermutationMatrix.h:119
InverseReturnType inverse() const
Definition: PermutationMatrix.h:172
const IndicesType & indices() const
Definition: PermutationMatrix.h:334
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
Index nonZeros() const
Definition: SparseCompressedBase.h:64
Index cols() const
Definition: SparseMatrix.h:161
void resize(Index rows, Index cols)
Definition: SparseMatrix.h:734
bool isCompressed() const
Definition: SparseCompressedBase.h:114
Index rows() const
Definition: SparseMatrix.h:159
void reserve(Index reserveSize)
Definition: SparseMatrix.h:315
PermutationType m_outputPerm_c
Definition: SparseQR.h:291
IndexVector m_firstRowElt
Definition: SparseQR.h:296
ScalarVector m_hcoeffs
Definition: SparseQR.h:288
OrderingType_ OrderingType
Definition: SparseQR.h:96
QRMatrixType m_R
Definition: SparseQR.h:286
IndexVector m_etree
Definition: SparseQR.h:295
MatrixType::StorageIndex StorageIndex
Definition: SparseQR.h:99
#define min(a, b)
Definition: datatypes.h:22
int * m
Definition: level2_cplx_impl.h:294
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::StorageIndex *perm=0)
Definition: SparseColEtree.h:61

References Eigen::internal::coletree(), Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::cols(), eigen_assert, Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::isCompressed(), m, min, n, Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::nonZeros(), and Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::rows().

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::compute().

◆ cols()

◆ colsPermutation()

template<typename MatrixType_ , typename OrderingType_ >
const PermutationType& Eigen::SparseQR< MatrixType_, OrderingType_ >::colsPermutation ( ) const
inline
Returns
a const reference to the column permutation P that was applied to A such that A*P = Q*R It is the combination of the fill-in reducing permutation and numerical column pivoting.
190  {
191  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
192  return m_outputPerm_c;
193  }

References eigen_assert, Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized, and Eigen::SparseQR< MatrixType_, OrderingType_ >::m_outputPerm_c.

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::_solve_impl().

◆ compute()

template<typename MatrixType_ , typename OrderingType_ >
void Eigen::SparseQR< MatrixType_, OrderingType_ >::compute ( const MatrixType mat)
inline

Computes the QR factorization of the sparse matrix mat.

Warning
The matrix mat must be in compressed mode (see SparseMatrix::makeCompressed()).
See also
analyzePattern(), factorize()
128  {
130  factorize(mat);
131  }
void analyzePattern(const MatrixType &mat)
Preprocessing step of a QR factorization.
Definition: SparseQR.h:314
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
Definition: SparseQR.h:356

References Eigen::SparseQR< MatrixType_, OrderingType_ >::analyzePattern(), and Eigen::SparseQR< MatrixType_, OrderingType_ >::factorize().

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::SparseQR().

◆ factorize()

template<typename MatrixType , typename OrderingType >
void Eigen::SparseQR< MatrixType, OrderingType >::factorize ( const MatrixType mat)

Performs the numerical QR factorization of the input matrix.

The function SparseQR::analyzePattern(const MatrixType&) must have been called beforehand with a matrix having the same sparsity pattern than mat.

Parameters
matThe sparse column-major matrix
356  {
357  using std::abs;
358 
359  eigen_assert(m_analysisIsok && "analyzePattern() should be called before this step");
362  StorageIndex diagSize = (std::min)(m, n);
363  IndexVector mark((std::max)(m, n));
364  mark.setConstant(-1); // Record the visited nodes
365  IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
366  Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
367  ScalarVector tval(m); // The dense vector used to compute the current column
368 
369  m_R.setZero();
370  m_Q.setZero();
371  m_pmat = mat;
372  if (!m_isEtreeOk) {
375  m_isEtreeOk = true;
376  }
377 
378  m_pmat.uncompress(); // To have the innerNonZeroPtr allocated
379 
380  // Apply the fill-in reducing permutation lazily:
381  {
382  // If the input is row major, copy the original column indices,
383  // otherwise directly use the input matrix
384  //
385  IndexVector originalOuterIndicesCpy;
386  const StorageIndex* originalOuterIndices = mat.outerIndexPtr();
387  if (MatrixType::IsRowMajor) {
388  originalOuterIndicesCpy = IndexVector::Map(m_pmat.outerIndexPtr(), n + 1);
389  originalOuterIndices = originalOuterIndicesCpy.data();
390  }
391 
392  for (int i = 0; i < n; i++) {
393  Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
394  m_pmat.outerIndexPtr()[p] = originalOuterIndices[i];
395  m_pmat.innerNonZeroPtr()[p] = originalOuterIndices[i + 1] - originalOuterIndices[i];
396  }
397  }
398 
399  /* Compute the default threshold as in MatLab, see:
400  * Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
401  * Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
402  */
403  RealScalar pivotThreshold;
404  if (m_useDefaultThreshold) {
405  RealScalar max2Norm = 0.0;
406  for (int j = 0; j < n; j++) max2Norm = numext::maxi(max2Norm, m_pmat.col(j).norm());
407  if (max2Norm == RealScalar(0)) max2Norm = RealScalar(1);
408  pivotThreshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
409  } else {
410  pivotThreshold = m_threshold;
411  }
412 
413  // Initialize the numerical permutation
415 
416  StorageIndex nonzeroCol = 0; // Record the number of valid pivots
417  m_Q.startVec(0);
418 
419  // Left looking rank-revealing QR factorization: compute a column of R and Q at a time
420  for (StorageIndex col = 0; col < n; ++col) {
421  mark.setConstant(-1);
422  m_R.startVec(col);
423  mark(nonzeroCol) = col;
424  Qidx(0) = nonzeroCol;
425  nzcolR = 0;
426  nzcolQ = 1;
427  bool found_diag = nonzeroCol >= m;
428  tval.setZero();
429 
430  // Symbolic factorization: find the nonzero locations of the column k of the factors R and Q, i.e.,
431  // all the nodes (with indexes lower than rank) reachable through the column elimination tree (etree) rooted at node
432  // k. Note: if the diagonal entry does not exist, then its contribution must be explicitly added, thus the trick
433  // with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
434  for (typename QRMatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp) {
435  StorageIndex curIdx = nonzeroCol;
436  if (itp) curIdx = StorageIndex(itp.row());
437  if (curIdx == nonzeroCol) found_diag = true;
438 
439  // Get the nonzeros indexes of the current column of R
440  StorageIndex st = m_firstRowElt(curIdx); // The traversal of the etree starts here
441  if (st < 0) {
442  m_lastError = "Empty row found during numerical factorization";
444  return;
445  }
446 
447  // Traverse the etree
448  Index bi = nzcolR;
449  for (; mark(st) != col; st = m_etree(st)) {
450  Ridx(nzcolR) = st; // Add this row to the list,
451  mark(st) = col; // and mark this row as visited
452  nzcolR++;
453  }
454 
455  // Reverse the list to get the topological ordering
456  Index nt = nzcolR - bi;
457  for (Index i = 0; i < nt / 2; i++) std::swap(Ridx(bi + i), Ridx(nzcolR - i - 1));
458 
459  // Copy the current (curIdx,pcol) value of the input matrix
460  if (itp)
461  tval(curIdx) = itp.value();
462  else
463  tval(curIdx) = Scalar(0);
464 
465  // Compute the pattern of Q(:,k)
466  if (curIdx > nonzeroCol && mark(curIdx) != col) {
467  Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
468  mark(curIdx) = col; // and mark it as visited
469  nzcolQ++;
470  }
471  }
472 
473  // Browse all the indexes of R(:,col) in reverse order
474  for (Index i = nzcolR - 1; i >= 0; i--) {
475  Index curIdx = Ridx(i);
476 
477  // Apply the curIdx-th householder vector to the current column (temporarily stored into tval)
478  Scalar tdot(0);
479 
480  // First compute q' * tval
481  tdot = m_Q.col(curIdx).dot(tval);
482 
483  tdot *= m_hcoeffs(curIdx);
484 
485  // Then update tval = tval - q * tau
486  tval -= tdot * m_Q.col(curIdx);
487 
488  // Detect fill-in for the current column of Q
489  if (m_etree(Ridx(i)) == nonzeroCol) {
490  for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq) {
491  StorageIndex iQ = StorageIndex(itq.row());
492  if (mark(iQ) != col) {
493  Qidx(nzcolQ++) = iQ; // Add this row to the pattern of Q,
494  mark(iQ) = col; // and mark it as visited
495  }
496  }
497  }
498  } // End update current column
499 
500  Scalar tau = RealScalar(0);
501  RealScalar beta = 0;
502 
503  if (nonzeroCol < diagSize) {
504  // Compute the Householder reflection that eliminate the current column
505  // FIXME this step should call the Householder module.
506  Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
507 
508  // First, the squared norm of Q((col+1):m, col)
509  RealScalar sqrNorm = 0.;
510  for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
511  if (sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0)) {
512  beta = numext::real(c0);
513  tval(Qidx(0)) = 1;
514  } else {
515  using std::sqrt;
516  beta = sqrt(numext::abs2(c0) + sqrNorm);
517  if (numext::real(c0) >= RealScalar(0)) beta = -beta;
518  tval(Qidx(0)) = 1;
519  for (Index itq = 1; itq < nzcolQ; ++itq) tval(Qidx(itq)) /= (c0 - beta);
520  tau = numext::conj((beta - c0) / beta);
521  }
522  }
523 
524  // Insert values in R
525  for (Index i = nzcolR - 1; i >= 0; i--) {
526  Index curIdx = Ridx(i);
527  if (curIdx < nonzeroCol) {
528  m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
529  tval(curIdx) = Scalar(0.);
530  }
531  }
532 
533  if (nonzeroCol < diagSize && abs(beta) >= pivotThreshold) {
534  m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
535  // The householder coefficient
536  m_hcoeffs(nonzeroCol) = tau;
537  // Record the householder reflections
538  for (Index itq = 0; itq < nzcolQ; ++itq) {
539  Index iQ = Qidx(itq);
540  m_Q.insertBackByOuterInnerUnordered(nonzeroCol, iQ) = tval(iQ);
541  tval(iQ) = Scalar(0.);
542  }
543  nonzeroCol++;
544  if (nonzeroCol < diagSize) m_Q.startVec(nonzeroCol);
545  } else {
546  // Zero pivot found: move implicitly this column to the end
547  for (Index j = nonzeroCol; j < n - 1; j++) std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j + 1]);
548 
549  // Recompute the column elimination tree
551  m_isEtreeOk = false;
552  }
553  }
554 
555  m_hcoeffs.tail(diagSize - nonzeroCol).setZero();
556 
557  // Finalize the column pointers of the sparse matrices R and Q
558  m_Q.finalize();
560  m_R.finalize();
562  m_isQSorted = false;
563 
564  m_nonzeropivots = nonzeroCol;
565 
566  if (nonzeroCol < n) {
567  // Permute the triangular factor to put the 'dead' columns to the end
568  QRMatrixType tempR(m_R);
569  m_R = tempR * m_pivotperm;
570 
571  // Update the column permutation
573  }
574 
575  m_isInitialized = true;
576  m_factorizationIsok = true;
577  m_info = Success;
578 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Eigen::SparseMatrix< double > mat
Definition: EigenUnitTest.cpp:10
m col(1)
float * p
Definition: Tutorial_Map_using.cpp:9
SCALAR Scalar
Definition: bench_gemm.cpp:45
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
void setIdentity()
Definition: PermutationMatrix.h:122
static ConstMapType Map(const Scalar *data)
Definition: PlainObjectBase.h:595
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition: CwiseNullaryOp.h:569
Scalar dot(const MatrixBase< OtherDerived > &other) const
RealScalar norm() const
Definition: SparseDot.h:88
void setZero()
Definition: SparseMatrix.h:303
void startVec(Index outer)
Definition: SparseMatrix.h:451
Scalar & insertBackByOuterInner(Index outer, Index inner)
Definition: SparseMatrix.h:430
void uncompress()
Definition: SparseMatrix.h:622
void finalize()
Definition: SparseMatrix.h:461
const StorageIndex * innerNonZeroPtr() const
Definition: SparseMatrix.h:198
void makeCompressed()
Definition: SparseMatrix.h:589
Base::InnerIterator InnerIterator
Definition: SparseMatrix.h:138
const StorageIndex * outerIndexPtr() const
Definition: SparseMatrix.h:189
Scalar & insertBackByOuterInnerUnordered(Index outer, Index inner)
Definition: SparseMatrix.h:442
SparseMatrix< Scalar, ColMajor, StorageIndex > QRMatrixType
Definition: SparseQR.h:100
MatrixType::Scalar Scalar
Definition: SparseQR.h:97
RealScalar m_threshold
Definition: SparseQR.h:292
bool m_factorizationIsok
Definition: SparseQR.h:282
Matrix< StorageIndex, Dynamic, 1 > IndexVector
Definition: SparseQR.h:101
Matrix< Scalar, Dynamic, 1 > ScalarVector
Definition: SparseQR.h:102
PermutationType m_pivotperm
Definition: SparseQR.h:290
MatrixType::RealScalar RealScalar
Definition: SparseQR.h:98
Index m_nonzeropivots
Definition: SparseQR.h:294
float real
Definition: datatypes.h:10
#define max(a, b)
Definition: datatypes.h:23
@ InvalidInput
Definition: Constants.h:447
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
Scalar beta
Definition: level2_cplx_impl.h:36
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T maxi(const T &x, const T &y)
Definition: MathFunctions.h:926
EIGEN_DEVICE_FUNC bool abs2(bool x)
Definition: MathFunctions.h:1102
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References abs(), Eigen::numext::abs2(), beta, col(), Eigen::internal::coletree(), Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::cols(), conj(), Eigen::PlainObjectBase< Derived >::data(), eigen_assert, i, imag(), Eigen::InvalidInput, j, m, max, Eigen::numext::maxi(), min, n, Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::outerIndexPtr(), p, Eigen::SparseMatrix< Scalar_, Options_, StorageIndex_ >::rows(), Eigen::PlainObjectBase< Derived >::setConstant(), Eigen::PlainObjectBase< Derived >::setZero(), sqrt(), Eigen::Success, and swap().

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::compute().

◆ info()

template<typename MatrixType_ , typename OrderingType_ >
ComputationInfo Eigen::SparseQR< MatrixType_, OrderingType_ >::info ( ) const
inline

Reports whether previous computation was successful.

Returns
Success if computation was successful, NumericalIssue if the QR factorization reports a numerical problem InvalidInput if the input matrix is invalid
See also
iparm()
266  {
267  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
268  return m_info;
269  }

References eigen_assert, Eigen::SparseQR< MatrixType_, OrderingType_ >::m_info, and Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized.

◆ lastErrorMessage()

template<typename MatrixType_ , typename OrderingType_ >
std::string Eigen::SparseQR< MatrixType_, OrderingType_ >::lastErrorMessage ( ) const
inline
Returns
A string describing the type of error. This method is provided to ease debugging, not to handle errors.
198 { return m_lastError; }

References Eigen::SparseQR< MatrixType_, OrderingType_ >::m_lastError.

◆ matrixQ()

template<typename MatrixType_ , typename OrderingType_ >
SparseQRMatrixQReturnType<SparseQR> Eigen::SparseQR< MatrixType_, OrderingType_ >::matrixQ ( void  ) const
inline
Returns
an expression of the matrix Q as products of sparse Householder reflectors. The common usage of this function is to apply it to a dense matrix or vector
VectorXd B1, B2;
// Initialize B1
B2 = matrixQ() * B1;

To get a plain SparseMatrix representation of Q:

SparseMatrix<double> Q;
Q = SparseQR<SparseMatrix<double> >(A).matrixQ();
MatrixXf Q
Definition: HouseholderQR_householderQ.cpp:1
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47

Internally, this call simply performs a sparse product between the matrix Q and a sparse identity matrix. However, due to the fact that the sparse reflectors are stored unsorted, two transpositions are needed to sort them before performing the product.

185 { return SparseQRMatrixQReturnType<SparseQR>(*this); }

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::_solve_impl().

◆ matrixR()

template<typename MatrixType_ , typename OrderingType_ >
const QRMatrixType& Eigen::SparseQR< MatrixType_, OrderingType_ >::matrixR ( ) const
inline
Returns
a const reference to the sparse upper triangular matrix R of the QR factorization.
Warning
The entries of the returned matrix are not sorted. This means that using it in algorithms expecting sorted entries will fail. This include random coefficient accesses (SpaseMatrix::coeff()), and coefficient-wise operations. Matrix products and triangular solves are fine though.

To sort the entries, you can assign it to a row-major matrix, and if a column-major matrix is required, you can copy it again:

SparseMatrix<double> R = qr.matrixR(); // column-major, not sorted!
SparseMatrix<double,RowMajor> Rr = qr.matrixR(); // row-major, sorted
SparseMatrix<double> Rc = Rr; // column-major, sorted
HouseholderQR< MatrixXf > qr(A)
@ R
Definition: StatisticsVector.h:21
156 { return m_R; }

References Eigen::SparseQR< MatrixType_, OrderingType_ >::m_R.

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::_solve_impl().

◆ rank()

template<typename MatrixType_ , typename OrderingType_ >
Index Eigen::SparseQR< MatrixType_, OrderingType_ >::rank ( ) const
inline
Returns
the number of non linearly dependent columns as determined by the pivoting threshold.
See also
setPivotThreshold()
162  {
163  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
164  return m_nonzeropivots;
165  }

References eigen_assert, Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized, and Eigen::SparseQR< MatrixType_, OrderingType_ >::m_nonzeropivots.

Referenced by Eigen::SparseQR< MatrixType_, OrderingType_ >::_solve_impl().

◆ rows()

◆ setPivotThreshold()

template<typename MatrixType_ , typename OrderingType_ >
void Eigen::SparseQR< MatrixType_, OrderingType_ >::setPivotThreshold ( const RealScalar threshold)
inline

Sets the threshold that is used to determine linearly dependent columns during the factorization.

In practice, if during the factorization the norm of the column that has to be eliminated is below this threshold, then the entire column is treated as zero, and it is moved at the end.

234  {
235  m_useDefaultThreshold = false;
236  m_threshold = threshold;
237  }

References Eigen::SparseQR< MatrixType_, OrderingType_ >::m_threshold, and Eigen::SparseQR< MatrixType_, OrderingType_ >::m_useDefaultThreshold.

◆ solve() [1/2]

template<typename MatrixType_ , typename OrderingType_ >
template<typename Rhs >
const Solve<SparseQR, Rhs> Eigen::SparseQR< MatrixType_, OrderingType_ >::solve ( const MatrixBase< Rhs > &  B) const
inline
Returns
the solution X of \( A X = B \) using the current decomposition of A.
See also
compute()
244  {
245  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
246  eigen_assert(this->rows() == B.rows() &&
247  "SparseQR::solve() : invalid number of rows in the right hand side matrix");
248  return Solve<SparseQR, Rhs>(*this, B.derived());
249  }

References eigen_assert, Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized, and Eigen::SparseQR< MatrixType_, OrderingType_ >::rows().

◆ solve() [2/2]

template<typename MatrixType_ , typename OrderingType_ >
template<typename Rhs >
const Solve<SparseQR, Rhs> Eigen::SparseQR< MatrixType_, OrderingType_ >::solve ( const SparseMatrixBase< Rhs > &  B) const
inline
251  {
252  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
253  eigen_assert(this->rows() == B.rows() &&
254  "SparseQR::solve() : invalid number of rows in the right hand side matrix");
255  return Solve<SparseQR, Rhs>(*this, B.derived());
256  }

References eigen_assert, Eigen::SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > >::m_isInitialized, Eigen::SparseMatrixBase< Derived >::rows(), and Eigen::SparseQR< MatrixType_, OrderingType_ >::rows().

Friends And Related Function Documentation

◆ SparseQR_QProduct

template<typename MatrixType_ , typename OrderingType_ >
template<typename , typename >
friend struct SparseQR_QProduct
friend

Member Data Documentation

◆ m_analysisIsok

template<typename MatrixType_ , typename OrderingType_ >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::m_analysisIsok
protected

◆ m_etree

template<typename MatrixType_ , typename OrderingType_ >
IndexVector Eigen::SparseQR< MatrixType_, OrderingType_ >::m_etree
protected

◆ m_factorizationIsok

template<typename MatrixType_ , typename OrderingType_ >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::m_factorizationIsok
protected

◆ m_firstRowElt

template<typename MatrixType_ , typename OrderingType_ >
IndexVector Eigen::SparseQR< MatrixType_, OrderingType_ >::m_firstRowElt
protected

◆ m_hcoeffs

template<typename MatrixType_ , typename OrderingType_ >
ScalarVector Eigen::SparseQR< MatrixType_, OrderingType_ >::m_hcoeffs
protected

◆ m_info

template<typename MatrixType_ , typename OrderingType_ >
ComputationInfo Eigen::SparseQR< MatrixType_, OrderingType_ >::m_info
mutableprotected

◆ m_isEtreeOk

template<typename MatrixType_ , typename OrderingType_ >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::m_isEtreeOk
protected

◆ m_isQSorted

template<typename MatrixType_ , typename OrderingType_ >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::m_isQSorted
protected

◆ m_lastError

template<typename MatrixType_ , typename OrderingType_ >
std::string Eigen::SparseQR< MatrixType_, OrderingType_ >::m_lastError
protected

◆ m_nonzeropivots

template<typename MatrixType_ , typename OrderingType_ >
Index Eigen::SparseQR< MatrixType_, OrderingType_ >::m_nonzeropivots
protected

◆ m_outputPerm_c

template<typename MatrixType_ , typename OrderingType_ >
PermutationType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_outputPerm_c
protected

◆ m_perm_c

template<typename MatrixType_ , typename OrderingType_ >
PermutationType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_perm_c
protected

◆ m_pivotperm

template<typename MatrixType_ , typename OrderingType_ >
PermutationType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_pivotperm
protected

◆ m_pmat

template<typename MatrixType_ , typename OrderingType_ >
QRMatrixType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_pmat
protected

◆ m_Q

template<typename MatrixType_ , typename OrderingType_ >
QRMatrixType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_Q
protected

◆ m_R

template<typename MatrixType_ , typename OrderingType_ >
QRMatrixType Eigen::SparseQR< MatrixType_, OrderingType_ >::m_R
protected

◆ m_threshold

template<typename MatrixType_ , typename OrderingType_ >
RealScalar Eigen::SparseQR< MatrixType_, OrderingType_ >::m_threshold
protected

◆ m_useDefaultThreshold

template<typename MatrixType_ , typename OrderingType_ >
bool Eigen::SparseQR< MatrixType_, OrderingType_ >::m_useDefaultThreshold
protected

The documentation for this class was generated from the following file: