SimplicialCholesky: avoid multiple twisting of the same matrix when calling compute()

This commit is contained in:
Gael Guennebaud 2012-06-01 15:51:03 +02:00
parent 97cdf6ce9e
commit 7f63169f09

View File

@ -104,7 +104,7 @@ class SimplicialCholeskyBase
SimplicialCholeskyBase(const MatrixType& matrix) SimplicialCholeskyBase(const MatrixType& matrix)
: m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1) : m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1)
{ {
compute(matrix); derived().compute(matrix);
} }
~SimplicialCholeskyBase() ~SimplicialCholeskyBase()
@ -128,14 +128,6 @@ class SimplicialCholeskyBase
return m_info; return m_info;
} }
/** Computes the sparse Cholesky decomposition of \a matrix */
Derived& compute(const MatrixType& matrix)
{
derived().analyzePattern(matrix);
derived().factorize(matrix);
return derived();
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
* *
* \sa compute() * \sa compute()
@ -258,10 +250,42 @@ class SimplicialCholeskyBase
protected: protected:
/** Computes the sparse Cholesky decomposition of \a matrix */
template<bool DoLDLT> template<bool DoLDLT>
void factorize(const MatrixType& a); void compute(const MatrixType& matrix)
{
eigen_assert(matrix.rows()==matrix.cols());
Index size = matrix.cols();
CholMatrixType ap(size,size);
ordering(matrix, ap);
analyzePattern_preordered(ap, DoLDLT);
factorize_preordered<DoLDLT>(ap);
}
void analyzePattern(const MatrixType& a, bool doLDLT); template<bool DoLDLT>
void factorize(const MatrixType& a)
{
eigen_assert(a.rows()==a.cols());
int size = a.cols();
CholMatrixType ap(size,size);
ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_Pinv);
factorize_preordered<DoLDLT>(ap);
}
template<bool DoLDLT>
void factorize_preordered(const CholMatrixType& a);
void analyzePattern(const MatrixType& a, bool doLDLT)
{
eigen_assert(a.rows()==a.cols());
int size = a.cols();
CholMatrixType ap(size,size);
ordering(a, ap);
analyzePattern_preordered(ap,doLDLT);
}
void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
void ordering(const MatrixType& a, CholMatrixType& ap);
/** keeps off-diagonal entries; drops diagonal entries */ /** keeps off-diagonal entries; drops diagonal entries */
struct keep_diag { struct keep_diag {
@ -375,6 +399,13 @@ public:
return Traits::getU(Base::m_matrix); return Traits::getU(Base::m_matrix);
} }
/** Computes the sparse Cholesky decomposition of \a matrix */
SimplicialLLT compute(const MatrixType& matrix)
{
Base::template compute<false>(matrix);
return *this;
}
/** Performs a symbolic decomposition on the sparcity of \a matrix. /** Performs a symbolic decomposition on the sparcity of \a matrix.
* *
* This function is particularly useful when solving for several problems having the same structure. * This function is particularly useful when solving for several problems having the same structure.
@ -459,6 +490,13 @@ public:
return Traits::getU(Base::m_matrix); return Traits::getU(Base::m_matrix);
} }
/** Computes the sparse Cholesky decomposition of \a matrix */
SimplicialLDLT compute(const MatrixType& matrix)
{
Base::template compute<true>(matrix);
return *this;
}
/** Performs a symbolic decomposition on the sparcity of \a matrix. /** Performs a symbolic decomposition on the sparcity of \a matrix.
* *
* This function is particularly useful when solving for several problems having the same structure. * This function is particularly useful when solving for several problems having the same structure.
@ -515,7 +553,7 @@ public:
SimplicialCholesky(const MatrixType& matrix) SimplicialCholesky(const MatrixType& matrix)
: Base(), m_LDLT(true) : Base(), m_LDLT(true)
{ {
Base::compute(matrix); compute(matrix);
} }
SimplicialCholesky& setMode(SimplicialCholeskyMode mode) SimplicialCholesky& setMode(SimplicialCholeskyMode mode)
@ -544,6 +582,16 @@ public:
return Base::m_matrix; return Base::m_matrix;
} }
/** Computes the sparse Cholesky decomposition of \a matrix */
SimplicialCholesky compute(const MatrixType& matrix)
{
if(m_LDLT)
Base::template compute<true>(matrix);
else
Base::template compute<false>(matrix);
return *this;
}
/** Performs a symbolic decomposition on the sparcity of \a matrix. /** Performs a symbolic decomposition on the sparcity of \a matrix.
* *
* This function is particularly useful when solving for several problems having the same structure. * This function is particularly useful when solving for several problems having the same structure.
@ -625,22 +673,17 @@ public:
}; };
template<typename Derived> template<typename Derived>
void SimplicialCholeskyBase<Derived>::analyzePattern(const MatrixType& a, bool doLDLT) void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, CholMatrixType& ap)
{ {
eigen_assert(a.rows()==a.cols()); eigen_assert(a.rows()==a.cols());
const Index size = a.rows(); const Index size = a.rows();
m_matrix.resize(size, size);
m_parent.resize(size);
m_nonZerosPerCol.resize(size);
ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
// TODO allows to configure the permutation // TODO allows to configure the permutation
{ {
CholMatrixType C; CholMatrixType C;
C = a.template selfadjointView<UpLo>(); C = a.template selfadjointView<UpLo>();
// remove diagonal entries: // remove diagonal entries:
C.prune(keep_diag()); // seems not to be needed
// C.prune(keep_diag());
internal::minimum_degree_ordering(C, m_P); internal::minimum_degree_ordering(C, m_P);
} }
@ -649,8 +692,19 @@ void SimplicialCholeskyBase<Derived>::analyzePattern(const MatrixType& a, bool d
else else
m_Pinv.resize(0); m_Pinv.resize(0);
SparseMatrix<Scalar,ColMajor,Index> ap(size,size); ap.resize(size,size);
ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_Pinv); ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_Pinv);
}
template<typename Derived>
void SimplicialCholeskyBase<Derived>::analyzePattern_preordered(const CholMatrixType& ap, bool doLDLT)
{
const Index size = ap.rows();
m_matrix.resize(size, size);
m_parent.resize(size);
m_nonZerosPerCol.resize(size);
ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
for(Index k = 0; k < size; ++k) for(Index k = 0; k < size; ++k)
{ {
@ -693,11 +747,11 @@ void SimplicialCholeskyBase<Derived>::analyzePattern(const MatrixType& a, bool d
template<typename Derived> template<typename Derived>
template<bool DoLDLT> template<bool DoLDLT>
void SimplicialCholeskyBase<Derived>::factorize(const MatrixType& a) void SimplicialCholeskyBase<Derived>::factorize_preordered(const CholMatrixType& ap)
{ {
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
eigen_assert(a.rows()==a.cols()); eigen_assert(ap.rows()==ap.cols());
const Index size = a.rows(); const Index size = ap.rows();
eigen_assert(m_parent.size()==size); eigen_assert(m_parent.size()==size);
eigen_assert(m_nonZerosPerCol.size()==size); eigen_assert(m_nonZerosPerCol.size()==size);
@ -709,9 +763,6 @@ void SimplicialCholeskyBase<Derived>::factorize(const MatrixType& a)
ei_declare_aligned_stack_constructed_variable(Index, pattern, size, 0); ei_declare_aligned_stack_constructed_variable(Index, pattern, size, 0);
ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0); ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
SparseMatrix<Scalar,ColMajor,Index> ap(size,size);
ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_Pinv);
bool ok = true; bool ok = true;
m_diag.resize(DoLDLT ? size : 0); m_diag.resize(DoLDLT ? size : 0);