mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-08 09:49:03 +08:00
Fix the computation of the default pivot threshold for sparse QR
This commit is contained in:
parent
5a0c5c0393
commit
ced8dfc0d9
@ -100,7 +100,6 @@ class SparseQR
|
|||||||
const QRMatrixType& matrixR() const { return m_R; }
|
const QRMatrixType& matrixR() const { return m_R; }
|
||||||
|
|
||||||
/** \returns the number of non linearly dependent columns as determined by the pivoting threshold.
|
/** \returns the number of non linearly dependent columns as determined by the pivoting threshold.
|
||||||
* \warning This is not the true rank of the matrix. It is provided here only for compatibility.
|
|
||||||
*
|
*
|
||||||
* \sa setPivotThreshold()
|
* \sa setPivotThreshold()
|
||||||
*/
|
*/
|
||||||
@ -129,7 +128,7 @@ class SparseQR
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \returns A string describing the type of error.
|
/** \returns A string describing the type of error.
|
||||||
* This method to ease debugging, not to handle errors.
|
* This method is provided to ease debugging, not to handle errors.
|
||||||
*/
|
*/
|
||||||
std::string lastErrorMessage() const { return m_lastError; }
|
std::string lastErrorMessage() const { return m_lastError; }
|
||||||
|
|
||||||
@ -290,21 +289,15 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
// Compute the default threshold.
|
// Compute the default threshold.
|
||||||
if(m_useDefaultThreshold)
|
if(m_useDefaultThreshold)
|
||||||
{
|
{
|
||||||
RealScalar infNorm = 0.0;
|
RealScalar max2Norm = 0.0;
|
||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++) max2Norm = (max)(max2Norm, m_pmat.col(j).norm());
|
||||||
{
|
m_threshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
|
||||||
// FIXME No support for mat.col(i).maxCoeff())
|
|
||||||
for(typename MatrixType::InnerIterator it(m_pmat, j); it; ++it)
|
|
||||||
infNorm = (max)(infNorm, abs(it.value()));
|
|
||||||
}
|
|
||||||
// FIXME: 20 ??
|
|
||||||
m_threshold = 20 * (m + n) * infNorm * NumTraits<RealScalar>::epsilon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the numerical permutation
|
// Initialize the numerical permutation
|
||||||
m_pivotperm.setIdentity(n);
|
m_pivotperm.setIdentity(n);
|
||||||
|
|
||||||
Index rank = 0; // Record the number of valid pivots
|
Index nonzeroCol = 0; // Record the number of valid pivots
|
||||||
|
|
||||||
// Left looking rank-revealing QR factorization: compute a column of R and Q at a time
|
// Left looking rank-revealing QR factorization: compute a column of R and Q at a time
|
||||||
for (Index col = 0; col < n; ++col)
|
for (Index col = 0; col < n; ++col)
|
||||||
@ -312,8 +305,8 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
mark.setConstant(-1);
|
mark.setConstant(-1);
|
||||||
m_R.startVec(col);
|
m_R.startVec(col);
|
||||||
m_Q.startVec(col);
|
m_Q.startVec(col);
|
||||||
mark(rank) = col;
|
mark(nonzeroCol) = col;
|
||||||
Qidx(0) = rank;
|
Qidx(0) = nonzeroCol;
|
||||||
nzcolR = 0; nzcolQ = 1;
|
nzcolR = 0; nzcolQ = 1;
|
||||||
found_diag = false;
|
found_diag = false;
|
||||||
tval.setZero();
|
tval.setZero();
|
||||||
@ -324,17 +317,16 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
// thus the trick with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
|
// thus the trick with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
|
||||||
for (typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
|
for (typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
|
||||||
{
|
{
|
||||||
Index curIdx = rank ;
|
Index curIdx = nonzeroCol ;
|
||||||
if(itp) curIdx = itp.row();
|
if(itp) curIdx = itp.row();
|
||||||
if(curIdx == rank) found_diag = true;
|
if(curIdx == nonzeroCol) found_diag = true;
|
||||||
|
|
||||||
// Get the nonzeros indexes of the current column of R
|
// Get the nonzeros indexes of the current column of R
|
||||||
Index st = m_firstRowElt(curIdx); // The traversal of the etree starts here
|
Index st = m_firstRowElt(curIdx); // The traversal of the etree starts here
|
||||||
if (st < 0 )
|
if (st < 0 )
|
||||||
{
|
{
|
||||||
m_lastError = "Empty row found during numerical factorization";
|
m_lastError = "Empty row found during numerical factorization";
|
||||||
// FIXME numerical issue or ivalid input ??
|
m_info = InvalidInput;
|
||||||
m_info = NumericalIssue;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +348,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
else tval(curIdx) = Scalar(0);
|
else tval(curIdx) = Scalar(0);
|
||||||
|
|
||||||
// Compute the pattern of Q(:,k)
|
// Compute the pattern of Q(:,k)
|
||||||
if(curIdx > rank && mark(curIdx) != col )
|
if(curIdx > nonzeroCol && mark(curIdx) != col )
|
||||||
{
|
{
|
||||||
Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
|
Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
|
||||||
mark(curIdx) = col; // and mark it as visited
|
mark(curIdx) = col; // and mark it as visited
|
||||||
@ -373,9 +365,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
Scalar tdot(0);
|
Scalar tdot(0);
|
||||||
|
|
||||||
// First compute q' * tval
|
// First compute q' * tval
|
||||||
// FIXME: m_Q.col(curIdx).dot(tval) should amount to the same
|
tdot = m_Q.col(curIdx).dot(tval);
|
||||||
for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
|
|
||||||
tdot += internal::conj(itq.value()) * tval(itq.row());
|
|
||||||
|
|
||||||
tdot *= m_hcoeffs(curIdx);
|
tdot *= m_hcoeffs(curIdx);
|
||||||
|
|
||||||
@ -385,7 +375,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
tval(itq.row()) -= itq.value() * tdot;
|
tval(itq.row()) -= itq.value() * tdot;
|
||||||
|
|
||||||
// Detect fill-in for the current column of Q
|
// Detect fill-in for the current column of Q
|
||||||
if(m_etree(Ridx(i)) == rank)
|
if(m_etree(Ridx(i)) == nonzeroCol)
|
||||||
{
|
{
|
||||||
for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
|
for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
|
||||||
{
|
{
|
||||||
@ -431,7 +421,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
for (Index i = nzcolR-1; i >= 0; i--)
|
for (Index i = nzcolR-1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Index curIdx = Ridx(i);
|
Index curIdx = Ridx(i);
|
||||||
if(curIdx < rank)
|
if(curIdx < nonzeroCol)
|
||||||
{
|
{
|
||||||
m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
|
m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
|
||||||
tval(curIdx) = Scalar(0.);
|
tval(curIdx) = Scalar(0.);
|
||||||
@ -440,8 +430,8 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
|
|
||||||
if(abs(beta) >= m_threshold)
|
if(abs(beta) >= m_threshold)
|
||||||
{
|
{
|
||||||
m_R.insertBackByOuterInner(col, rank) = beta;
|
m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
|
||||||
rank++;
|
nonzeroCol++;
|
||||||
// The householder coefficient
|
// The householder coefficient
|
||||||
m_hcoeffs(col) = tau;
|
m_hcoeffs(col) = tau;
|
||||||
// Record the householder reflections
|
// Record the householder reflections
|
||||||
@ -456,7 +446,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
{
|
{
|
||||||
// Zero pivot found: move implicitly this column to the end
|
// Zero pivot found: move implicitly this column to the end
|
||||||
m_hcoeffs(col) = Scalar(0);
|
m_hcoeffs(col) = Scalar(0);
|
||||||
for (Index j = rank; j < n-1; j++)
|
for (Index j = nonzeroCol; j < n-1; j++)
|
||||||
std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
|
std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
|
||||||
|
|
||||||
// Recompute the column elimination tree
|
// Recompute the column elimination tree
|
||||||
@ -470,9 +460,9 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
|
|||||||
m_R.finalize();
|
m_R.finalize();
|
||||||
m_R.makeCompressed();
|
m_R.makeCompressed();
|
||||||
|
|
||||||
m_nonzeropivots = rank;
|
m_nonzeropivots = nonzeroCol;
|
||||||
|
|
||||||
if(rank<n)
|
if(nonzeroCol<n)
|
||||||
{
|
{
|
||||||
// Permute the triangular factor to put the 'dead' columns to the end
|
// Permute the triangular factor to put the 'dead' columns to the end
|
||||||
MatrixType tempR(m_R);
|
MatrixType tempR(m_R);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user