mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Add a sparse QR factorization and update the elimination tree in SparseLU
This commit is contained in:
@@ -170,7 +170,7 @@ class SparseLU
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
* \returns \c Success if computation was succesful,
|
||||
* \c NumericalIssue if the PaStiX reports a problem
|
||||
* \c NumericalIssue if the LU factorization reports a problem, zero diagonal for instance
|
||||
* \c InvalidInput if the input matrix is invalid
|
||||
*
|
||||
* \sa iparm()
|
||||
@@ -320,15 +320,14 @@ void SparseLU<MatrixType, OrderingType>::analyzePattern(const MatrixType& mat)
|
||||
}
|
||||
|
||||
// Compute the column elimination tree of the permuted matrix
|
||||
/*if (m_etree.size() == 0) */m_etree.resize(m_mat.cols());
|
||||
|
||||
SparseLUBase<Scalar,Index>::LU_sp_coletree(m_mat, m_etree);
|
||||
IndexVector firstRowElt;
|
||||
internal::coletree(m_mat, m_etree,firstRowElt);
|
||||
|
||||
// In symmetric mode, do not do postorder here
|
||||
if (!m_symmetricmode) {
|
||||
IndexVector post, iwork;
|
||||
// Post order etree
|
||||
SparseLUBase<Scalar,Index>::LU_TreePostorder(m_mat.cols(), m_etree, post);
|
||||
internal::treePostorder(m_mat.cols(), m_etree, post);
|
||||
|
||||
|
||||
// Renumber etree in postorder
|
||||
@@ -445,13 +444,12 @@ void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix)
|
||||
// Work on one 'panel' at a time. A panel is one of the following :
|
||||
// (a) a relaxed supernode at the bottom of the etree, or
|
||||
// (b) panel_size contiguous columns, <panel_size> defined by the user
|
||||
int jcol,kcol;
|
||||
int jcol;
|
||||
IndexVector panel_histo(n);
|
||||
Index nextu, nextlu, jsupno, fsupc, new_next;
|
||||
Index pivrow; // Pivotal row number in the original row matrix
|
||||
int nseg1; // Number of segments in U-column above panel row jcol
|
||||
int nseg; // Number of segments in each U-column
|
||||
int irep, icol;
|
||||
int irep;
|
||||
int i, k, jj;
|
||||
for (jcol = 0; jcol < n; )
|
||||
{
|
||||
|
||||
@@ -22,10 +22,6 @@ struct SparseLUBase
|
||||
typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
|
||||
typedef SparseMatrix<Scalar,ColMajor,Index> MatrixType;
|
||||
|
||||
static int etree_find (int i, IndexVector& pp);
|
||||
static int LU_sp_coletree(const MatrixType& mat, IndexVector& parent);
|
||||
static void LU_nr_etdfs (int n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, int postnum);
|
||||
static void LU_TreePostorder(int n, IndexVector& parent, IndexVector& post);
|
||||
template <typename VectorType>
|
||||
static int expand(VectorType& vec, int& length, int nbElts, int keep_prev, int& num_expansions);
|
||||
static int LUMemInit(int m, int n, int annz, int lwork, int fillratio, int panel_size, GlobalLU_t& glu);
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
*/
|
||||
#ifndef SPARSELU_COLETREE_H
|
||||
#define SPARSELU_COLETREE_H
|
||||
|
||||
namespace internal {
|
||||
/** Find the root of the tree/set containing the vertex i : Use Path halving */
|
||||
template< typename Scalar,typename Index>
|
||||
int SparseLUBase<Scalar,Index>::etree_find (int i, IndexVector& pp)
|
||||
template<typename IndexVector>
|
||||
int etree_find (int i, IndexVector& pp)
|
||||
{
|
||||
int p = pp(i); // Parent
|
||||
int gp = pp(p); // Grand parent
|
||||
@@ -50,45 +52,53 @@ int SparseLUBase<Scalar,Index>::etree_find (int i, IndexVector& pp)
|
||||
* NOTE : The matrix is supposed to be in column-major format.
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename Index>
|
||||
int SparseLUBase<Scalar,Index>::LU_sp_coletree(const MatrixType& mat, IndexVector& parent)
|
||||
template <typename MatrixType, typename IndexVector>
|
||||
int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt)
|
||||
{
|
||||
int nc = mat.cols(); // Number of columns
|
||||
int nr = mat.rows(); // Number of rows
|
||||
|
||||
typedef typename MatrixType::Index Index;
|
||||
Index nc = mat.cols(); // Number of columns
|
||||
Index m = mat.rows();
|
||||
IndexVector root(nc); // root of subtree of etree
|
||||
root.setZero();
|
||||
IndexVector pp(nc); // disjoint sets
|
||||
pp.setZero(); // Initialize disjoint sets
|
||||
IndexVector firstcol(nr); // First nonzero column in each row
|
||||
|
||||
parent.resize(mat.cols());
|
||||
//Compute first nonzero column in each row
|
||||
int row,col;
|
||||
firstcol.setConstant(nc); //for (row = 0; row < nr; firstcol(row++) = nc);
|
||||
firstRowElt.resize(m);
|
||||
firstRowElt.setConstant(nc);
|
||||
firstRowElt.segment(0, nc).setLinSpaced(nc, 0, nc-1);
|
||||
bool found_diag;
|
||||
for (col = 0; col < nc; col++)
|
||||
{
|
||||
for (typename MatrixType::InnerIterator it(mat, col); it; ++it)
|
||||
{ // Is it necessary to browse the whole matrix, the lower part should do the job ??
|
||||
{
|
||||
row = it.row();
|
||||
firstcol(row) = (std::min)(firstcol(row), col);
|
||||
firstRowElt(row) = (std::min)(firstRowElt(row), col);
|
||||
}
|
||||
}
|
||||
/* Compute etree by Liu's algorithm for symmetric matrices,
|
||||
except use (firstcol[r],c) in place of an edge (r,c) of A.
|
||||
except use (firstRowElt[r],c) in place of an edge (r,c) of A.
|
||||
Thus each row clique in A'*A is replaced by a star
|
||||
centered at its first vertex, which has the same fill. */
|
||||
int rset, cset, rroot;
|
||||
for (col = 0; col < nc; col++)
|
||||
{
|
||||
found_diag = false;
|
||||
pp(col) = col;
|
||||
cset = col;
|
||||
root(cset) = col;
|
||||
parent(col) = nc;
|
||||
for (typename MatrixType::InnerIterator it(mat, col); it; ++it)
|
||||
/* The diagonal element is treated here even if it does not exist in the matrix
|
||||
* hence the loop is executed once more */
|
||||
for (typename MatrixType::InnerIterator it(mat, col); it||!found_diag; ++it)
|
||||
{ // A sequence of interleaved find and union is performed
|
||||
row = firstcol(it.row());
|
||||
int i = col;
|
||||
if(it) i = it.index();
|
||||
if (i == col) found_diag = true;
|
||||
row = firstRowElt(i);
|
||||
if (row >= col) continue;
|
||||
rset = etree_find(row, pp); // Find the name of the set containing row
|
||||
rset = internal::etree_find(row, pp); // Find the name of the set containing row
|
||||
rroot = root(rset);
|
||||
if (rroot != col)
|
||||
{
|
||||
@@ -106,8 +116,8 @@ int SparseLUBase<Scalar,Index>::LU_sp_coletree(const MatrixType& mat, IndexVecto
|
||||
* Depth-first search from vertex n. No recursion.
|
||||
* This routine was contributed by Cédric Doucet, CEDRAT Group, Meylan, France.
|
||||
*/
|
||||
template <typename Scalar, typename Index>
|
||||
void SparseLUBase<Scalar,Index>::LU_nr_etdfs (int n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, int postnum)
|
||||
template <typename IndexVector>
|
||||
void nr_etdfs (int n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, int postnum)
|
||||
{
|
||||
int current = n, first, next;
|
||||
while (postnum != n)
|
||||
@@ -152,8 +162,8 @@ void SparseLUBase<Scalar,Index>::LU_nr_etdfs (int n, IndexVector& parent, IndexV
|
||||
* \param parent Input tree
|
||||
* \param post postordered tree
|
||||
*/
|
||||
template <typename Scalar, typename Index>
|
||||
void SparseLUBase<Scalar,Index>::LU_TreePostorder(int n, IndexVector& parent, IndexVector& post)
|
||||
template <typename IndexVector>
|
||||
void treePostorder(int n, IndexVector& parent, IndexVector& post)
|
||||
{
|
||||
IndexVector first_kid, next_kid; // Linked list of children
|
||||
int postnum;
|
||||
@@ -174,7 +184,8 @@ void SparseLUBase<Scalar,Index>::LU_TreePostorder(int n, IndexVector& parent, In
|
||||
|
||||
// Depth-first search from dummy root vertex #n
|
||||
postnum = 0;
|
||||
LU_nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
|
||||
internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
|
||||
}
|
||||
|
||||
} // internal
|
||||
#endif
|
||||
@@ -44,7 +44,7 @@ void SparseLUBase<Scalar,Index>::LU_heap_relax_snode (const int n, IndexVector&
|
||||
|
||||
// The etree may not be postordered, but its heap ordered
|
||||
IndexVector post;
|
||||
LU_TreePostorder(n, et, post); // Post order etree
|
||||
internal::treePostorder(n, et, post); // Post order etree
|
||||
IndexVector inv_post(n+1);
|
||||
int i;
|
||||
for (i = 0; i < n+1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
|
||||
|
||||
Reference in New Issue
Block a user