From 1618df55dfc971113a974841b52e86391f445ff2 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 18 Nov 2010 10:28:39 +0100 Subject: [PATCH] Add support for sparse symmetric permutations --- Eigen/src/Sparse/SparseSelfAdjointView.h | 256 +++++++++++++++++------ 1 file changed, 195 insertions(+), 61 deletions(-) diff --git a/Eigen/src/Sparse/SparseSelfAdjointView.h b/Eigen/src/Sparse/SparseSelfAdjointView.h index b4ece8dd4..a6542d0ce 100644 --- a/Eigen/src/Sparse/SparseSelfAdjointView.h +++ b/Eigen/src/Sparse/SparseSelfAdjointView.h @@ -45,12 +45,21 @@ class SparseSelfAdjointTimeDenseProduct; template class DenseTimeSparseSelfAdjointProduct; +template +class SparseSymmetricPermutationProduct; + namespace internal { template struct traits > : traits { }; +template +void permute_symm_to_symm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm = 0); + +template +void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm = 0); + } template class SparseSelfAdjointView @@ -74,7 +83,8 @@ template class SparseSelfAdjointView inline Index cols() const { return m_matrix.cols(); } /** \internal \returns a reference to the nested matrix */ - const MatrixType& matrix() const { return m_matrix; } + const _MatrixTypeNested& matrix() const { return m_matrix; } + _MatrixTypeNested& matrix() { return m_matrix.const_cast_derived(); } /** Efficient sparse self-adjoint matrix times dense vector/matrix product */ template @@ -109,66 +119,22 @@ template class SparseSelfAdjointView /** \internal triggered by sparse_matrix = SparseSelfadjointView; */ template void evalTo(SparseMatrix& _dest) const { - typedef SparseMatrix Dest; - Dest& dest(_dest.derived()); - enum { - StorageOrderMatch = Dest::IsRowMajor == _MatrixTypeNested::IsRowMajor - }; - VectorI count = Dest::IsRowMajor ? m_countPerRow : m_countPerCol; - Index size = m_matrix.rows(); - count.resize(size); - count.setZero(); - dest.resize(size,size); - for(Index j = 0; jj) || (UpLo==Upper && ij) || (UpLo==Upper && i(m_matrix, _dest); + } + + /** \returns an expression of P^-1 H P */ + SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix& perm) const + { + return SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo>(m_matrix, perm); + } + + template + SparseSelfAdjointView& operator=(const SparseSymmetricPermutationProduct& permutedMatrix) + { + permutedMatrix.evalTo(*this); + return *this; } - // const SparseLLT llt() const; // const SparseLDLT ldlt() const; @@ -176,8 +142,8 @@ template class SparseSelfAdjointView protected: const typename MatrixType::Nested m_matrix; - VectorI m_countPerRow; - VectorI m_countPerCol; + mutable VectorI m_countPerRow; + mutable VectorI m_countPerCol; }; /*************************************************************************** @@ -305,4 +271,172 @@ class DenseTimeSparseSelfAdjointProduct private: DenseTimeSparseSelfAdjointProduct& operator=(const DenseTimeSparseSelfAdjointProduct&); }; + +/*************************************************************************** +* Implementation of symmetric copies and permutations +***************************************************************************/ +namespace internal { + +template +struct traits > : traits { +}; + +template +void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm) +{ + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + typedef SparseMatrix Dest; + typedef Matrix VectorI; + + Dest& dest(_dest.derived()); + enum { + StorageOrderMatch = Dest::IsRowMajor == MatrixType::IsRowMajor + }; + eigen_assert(perm==0); + Index size = mat.rows(); + VectorI count; + count.resize(size); + count.setZero(); + dest.resize(size,size); + for(Index j = 0; jj) || (UpLo==Upper && ij) || (UpLo==Upper && i +void permute_symm_to_symm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm) +{ + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + typedef SparseMatrix Dest; + Dest& dest(_dest.derived()); + typedef Matrix VectorI; + + Index size = mat.rows(); + VectorI count(size); + count.setZero(); + dest.resize(size,size); + for(Index j = 0; jj)) + continue; + + Index ip = perm ? perm[i] : i; + count[DstUpLo==Lower ? std::min(ip,jp) : std::max(ip,jp)]++; + } + } + dest._outerIndexPtr()[0] = 0; + for(Index j=0; jj)) + continue; + + Index ip = perm? perm[i] : i; + Index k = count[DstUpLo==Lower ? std::min(ip,jp) : std::max(ip,jp)]++; + dest._innerIndexPtr()[k] = DstUpLo==Lower ? std::max(ip,jp) : std::min(ip,jp); + dest._valuePtr()[k] = it.value(); + } + } +} + +} + +template +class SparseSymmetricPermutationProduct + : public EigenBase > +{ + typedef PermutationMatrix Perm; + public: + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef Matrix VectorI; + typedef typename MatrixType::Nested MatrixTypeNested; + typedef typename internal::remove_all::type _MatrixTypeNested; + + SparseSymmetricPermutationProduct(const MatrixType& mat, const Perm& perm) + : m_matrix(mat), m_perm(perm) + {} + + inline Index rows() const { return m_matrix.rows(); } + inline Index cols() const { return m_matrix.cols(); } + + template void evalTo(SparseMatrix& _dest) const + { + internal::permute_symm_to_fullsymm(m_matrix,_dest,m_perm.indices().data()); + } + + template void evalTo(SparseSelfAdjointView& dest) const + { + internal::permute_symm_to_symm(m_matrix,dest.matrix(),m_perm.indices().data()); + } + + protected: + const MatrixTypeNested m_matrix; + const Perm& m_perm; + +}; + #endif // EIGEN_SPARSE_SELFADJOINTVIEW_H