2010-11-04 09:58:22 +01:00
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
2013-02-06 11:30:33 +01:00
// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
2010-11-04 09:58:22 +01:00
//
2012-07-13 14:42:47 -04:00
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2010-11-04 09:58:22 +01:00
# ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
# define EIGEN_SIMPLICIAL_CHOLESKY_H
2012-04-15 11:06:28 +01:00
namespace Eigen {
2010-11-04 09:58:22 +01:00
enum SimplicialCholeskyMode {
2012-02-27 14:28:07 +01:00
SimplicialCholeskyLLT ,
SimplicialCholeskyLDLT
2010-11-04 09:58:22 +01:00
} ;
2011-12-02 19:02:49 +01:00
/** \ingroup SparseCholesky_Module
* \ brief A direct sparse Cholesky factorizations
2010-11-04 09:58:22 +01:00
*
2011-10-09 21:45:55 +02:00
* These classes provide LL ^ T and LDL ^ T Cholesky factorizations of sparse matrices that are
* selfadjoint and positive definite . The factorization allows for solving A . X = B where
2010-11-04 09:58:22 +01:00
* X and B can be either dense or sparse .
2012-06-07 16:24:46 +02:00
*
* In order to reduce the fill - in , a symmetric permutation P is applied prior to the factorization
* such that the factorized matrix is P A P ^ - 1.
2010-11-04 09:58:22 +01:00
*
* \ tparam _MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam _UpLo the triangular part that will be used for the computations . It can be Lower
* or Upper . Default is Lower .
*
*/
2011-10-09 21:45:55 +02:00
template < typename Derived >
2012-06-04 13:22:44 +02:00
class SimplicialCholeskyBase : internal : : noncopyable
2010-11-04 09:58:22 +01:00
{
public :
2011-10-09 21:45:55 +02:00
typedef typename internal : : traits < Derived > : : MatrixType MatrixType ;
2014-07-20 14:22:58 +02:00
typedef typename internal : : traits < Derived > : : OrderingType OrderingType ;
2011-10-09 21:45:55 +02:00
enum { UpLo = internal : : traits < Derived > : : UpLo } ;
2010-11-04 09:58:22 +01:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
2011-10-09 21:45:55 +02:00
typedef Matrix < Scalar , Dynamic , 1 > VectorType ;
2010-11-04 09:58:22 +01:00
public :
2011-12-02 19:02:49 +01:00
/** Default constructor */
2011-10-09 21:45:55 +02:00
SimplicialCholeskyBase ( )
2011-12-03 18:26:08 +01:00
: m_info ( Success ) , m_isInitialized ( false ) , m_shiftOffset ( 0 ) , m_shiftScale ( 1 )
2010-11-04 09:58:22 +01:00
{ }
2011-10-09 21:45:55 +02:00
SimplicialCholeskyBase ( const MatrixType & matrix )
2011-12-03 18:26:08 +01:00
: m_info ( Success ) , m_isInitialized ( false ) , m_shiftOffset ( 0 ) , m_shiftScale ( 1 )
2010-11-04 09:58:22 +01:00
{
2012-06-01 15:51:03 +02:00
derived ( ) . compute ( matrix ) ;
2010-11-04 09:58:22 +01:00
}
2011-10-09 21:45:55 +02:00
~ SimplicialCholeskyBase ( )
2010-11-04 09:58:22 +01:00
{
}
2011-10-09 21:45:55 +02:00
Derived & derived ( ) { return * static_cast < Derived * > ( this ) ; }
const Derived & derived ( ) const { return * static_cast < const Derived * > ( this ) ; }
2010-11-04 09:58:22 +01:00
inline Index cols ( ) const { return m_matrix . cols ( ) ; }
inline Index rows ( ) const { return m_matrix . rows ( ) ; }
/** \brief Reports whether previous computation was successful.
*
* \ returns \ c Success if computation was succesful ,
* \ c NumericalIssue if the matrix . appears to be negative .
*/
ComputationInfo info ( ) const
{
eigen_assert ( m_isInitialized & & " Decomposition is not initialized. " ) ;
return m_info ;
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* \ sa compute ( )
*/
template < typename Rhs >
2011-10-09 21:45:55 +02:00
inline const internal : : solve_retval < SimplicialCholeskyBase , Rhs >
2010-11-04 09:58:22 +01:00
solve ( const MatrixBase < Rhs > & b ) const
{
2012-02-27 14:28:07 +01:00
eigen_assert ( m_isInitialized & & " Simplicial LLT or LDLT is not initialized. " ) ;
2010-11-04 09:58:22 +01:00
eigen_assert ( rows ( ) = = b . rows ( )
2011-10-09 21:45:55 +02:00
& & " SimplicialCholeskyBase::solve(): invalid number of rows of the right hand side matrix b " ) ;
return internal : : solve_retval < SimplicialCholeskyBase , Rhs > ( * this , b . derived ( ) ) ;
2010-11-04 09:58:22 +01:00
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* \ sa compute ( )
*/
2011-10-11 11:31:12 +02:00
template < typename Rhs >
inline const internal : : sparse_solve_retval < SimplicialCholeskyBase , Rhs >
solve ( const SparseMatrixBase < Rhs > & b ) const
{
2012-02-27 14:28:07 +01:00
eigen_assert ( m_isInitialized & & " Simplicial LLT or LDLT is not initialized. " ) ;
2011-10-11 11:31:12 +02:00
eigen_assert ( rows ( ) = = b . rows ( )
& & " SimplicialCholesky::solve(): invalid number of rows of the right hand side matrix b " ) ;
return internal : : sparse_solve_retval < SimplicialCholeskyBase , Rhs > ( * this , b . derived ( ) ) ;
}
2010-11-04 09:58:22 +01:00
2010-11-18 10:30:52 +01:00
/** \returns the permutation P
* \ sa permutationPinv ( ) */
2011-06-06 10:17:28 +02:00
const PermutationMatrix < Dynamic , Dynamic , Index > & permutationP ( ) const
2010-11-18 10:30:52 +01:00
{ return m_P ; }
/** \returns the inverse P^-1 of the permutation P
* \ sa permutationP ( ) */
2011-06-06 10:17:28 +02:00
const PermutationMatrix < Dynamic , Dynamic , Index > & permutationPinv ( ) const
2010-11-18 10:30:52 +01:00
{ return m_Pinv ; }
2011-10-09 21:45:55 +02:00
2011-12-03 18:26:08 +01:00
/** Sets the shift parameters that will be used to adjust the diagonal coefficients during the numerical factorization.
*
* During the numerical factorization , the diagonal coefficients are transformed by the following linear model : \ n
* \ c d_ii = \ a offset + \ a scale * \ c d_ii
*
* The default is the identity transformation with \ a offset = 0 , and \ a scale = 1.
*
* \ returns a reference to \ c * this .
*/
2012-01-26 10:34:45 +01:00
Derived & setShift ( const RealScalar & offset , const RealScalar & scale = 1 )
2011-12-03 18:26:08 +01:00
{
m_shiftOffset = offset ;
m_shiftScale = scale ;
return derived ( ) ;
}
2011-10-09 21:45:55 +02:00
# ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
template < typename Stream >
void dumpMemory ( Stream & s )
{
int total = 0 ;
s < < " L: " < < ( ( total + = ( m_matrix . cols ( ) + 1 ) * sizeof ( int ) + m_matrix . nonZeros ( ) * ( sizeof ( int ) + sizeof ( Scalar ) ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " diag: " < < ( ( total + = m_diag . size ( ) * sizeof ( Scalar ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " tree: " < < ( ( total + = m_parent . size ( ) * sizeof ( int ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " nonzeros: " < < ( ( total + = m_nonZerosPerCol . size ( ) * sizeof ( int ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " perm: " < < ( ( total + = m_P . size ( ) * sizeof ( int ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " perm^-1: " < < ( ( total + = m_Pinv . size ( ) * sizeof ( int ) ) > > 20 ) < < " Mb " < < " \n " ;
s < < " TOTAL: " < < ( total > > 20 ) < < " Mb " < < " \n " ;
}
2010-11-04 09:58:22 +01:00
/** \internal */
template < typename Rhs , typename Dest >
void _solve ( const MatrixBase < Rhs > & b , MatrixBase < Dest > & dest ) const
{
eigen_assert ( m_factorizationIsOk & & " The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric() " ) ;
eigen_assert ( m_matrix . rows ( ) = = b . rows ( ) ) ;
2011-10-09 21:45:55 +02:00
2010-11-04 09:58:22 +01:00
if ( m_info ! = Success )
return ;
2011-10-09 21:45:55 +02:00
2010-11-04 09:58:22 +01:00
if ( m_P . size ( ) > 0 )
2012-06-07 16:24:46 +02:00
dest = m_P * b ;
2010-11-04 09:58:22 +01:00
else
dest = b ;
2011-10-09 21:45:55 +02:00
if ( m_matrix . nonZeros ( ) > 0 ) // otherwise L==I
derived ( ) . matrixL ( ) . solveInPlace ( dest ) ;
if ( m_diag . size ( ) > 0 )
2010-11-04 09:58:22 +01:00
dest = m_diag . asDiagonal ( ) . inverse ( ) * dest ;
2011-10-09 21:45:55 +02:00
2012-06-15 09:16:10 +02:00
if ( m_matrix . nonZeros ( ) > 0 ) // otherwise U==I
2011-10-09 21:45:55 +02:00
derived ( ) . matrixU ( ) . solveInPlace ( dest ) ;
2010-11-04 09:58:22 +01:00
if ( m_P . size ( ) > 0 )
2012-06-07 16:24:46 +02:00
dest = m_Pinv * dest ;
2010-11-04 09:58:22 +01:00
}
2011-10-09 21:45:55 +02:00
# endif // EIGEN_PARSED_BY_DOXYGEN
2010-11-04 09:58:22 +01:00
protected :
2012-06-01 15:51:03 +02:00
/** Computes the sparse Cholesky decomposition of \a matrix */
template < bool DoLDLT >
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 ) ;
}
template < bool DoLDLT >
void factorize ( const MatrixType & a )
{
eigen_assert ( a . rows ( ) = = a . cols ( ) ) ;
int size = a . cols ( ) ;
CholMatrixType ap ( size , size ) ;
2012-06-07 16:24:46 +02:00
ap . template selfadjointView < Upper > ( ) = a . template selfadjointView < UpLo > ( ) . twistedBy ( m_P ) ;
2012-06-01 15:51:03 +02:00
factorize_preordered < DoLDLT > ( ap ) ;
}
2011-10-09 21:45:55 +02:00
2012-02-27 14:28:07 +01:00
template < bool DoLDLT >
2012-06-01 15:51:03 +02:00
void factorize_preordered ( const CholMatrixType & a ) ;
2011-10-09 21:45:55 +02:00
2012-06-01 15:51:03 +02:00
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 ) ;
2011-10-09 21:45:55 +02:00
2010-11-18 10:30:52 +01:00
/** keeps off-diagonal entries; drops diagonal entries */
struct keep_diag {
inline bool operator ( ) ( const Index & row , const Index & col , const Scalar & ) const
{
return row ! = col ;
}
} ;
2010-11-04 09:58:22 +01:00
mutable ComputationInfo m_info ;
bool m_isInitialized ;
bool m_factorizationIsOk ;
bool m_analysisIsOk ;
CholMatrixType m_matrix ;
2012-02-27 14:28:07 +01:00
VectorType m_diag ; // the diagonal coefficients (LDLT mode)
2011-10-09 21:45:55 +02:00
VectorXi m_parent ; // elimination tree
2010-11-04 09:58:22 +01:00
VectorXi m_nonZerosPerCol ;
2011-06-06 10:17:28 +02:00
PermutationMatrix < Dynamic , Dynamic , Index > m_P ; // the permutation
PermutationMatrix < Dynamic , Dynamic , Index > m_Pinv ; // the inverse permutation
2011-12-03 18:26:08 +01:00
2012-01-26 10:34:45 +01:00
RealScalar m_shiftOffset ;
2011-12-03 18:26:08 +01:00
RealScalar m_shiftScale ;
2010-11-04 09:58:22 +01:00
} ;
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo = Lower , typename _Ordering = AMDOrdering < typename _MatrixType : : Index > > class SimplicialLLT ;
template < typename _MatrixType , int _UpLo = Lower , typename _Ordering = AMDOrdering < typename _MatrixType : : Index > > class SimplicialLDLT ;
template < typename _MatrixType , int _UpLo = Lower , typename _Ordering = AMDOrdering < typename _MatrixType : : Index > > class SimplicialCholesky ;
2011-10-09 21:45:55 +02:00
namespace internal {
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering > struct traits < SimplicialLLT < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
typedef _MatrixType MatrixType ;
2014-07-20 14:22:58 +02:00
typedef _Ordering OrderingType ;
2011-10-09 21:45:55 +02:00
enum { UpLo = _UpLo } ;
2011-12-02 19:02:49 +01:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
2014-07-22 11:35:56 +02:00
typedef TriangularView < CholMatrixType , Eigen : : Lower > MatrixL ;
typedef TriangularView < typename CholMatrixType : : AdjointReturnType , Eigen : : Upper > MatrixU ;
2012-01-31 12:58:52 +01:00
static inline MatrixL getL ( const MatrixType & m ) { return m ; }
static inline MatrixU getU ( const MatrixType & m ) { return m . adjoint ( ) ; }
2011-10-09 21:45:55 +02:00
} ;
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering > struct traits < SimplicialLDLT < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
typedef _MatrixType MatrixType ;
2014-07-20 14:22:58 +02:00
typedef _Ordering OrderingType ;
2011-10-09 21:45:55 +02:00
enum { UpLo = _UpLo } ;
2011-12-02 19:02:49 +01:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
2014-07-22 11:35:56 +02:00
typedef TriangularView < CholMatrixType , Eigen : : UnitLower > MatrixL ;
typedef TriangularView < typename CholMatrixType : : AdjointReturnType , Eigen : : UnitUpper > MatrixU ;
2012-01-31 12:58:52 +01:00
static inline MatrixL getL ( const MatrixType & m ) { return m ; }
static inline MatrixU getU ( const MatrixType & m ) { return m . adjoint ( ) ; }
2011-10-09 21:45:55 +02:00
} ;
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering > struct traits < SimplicialCholesky < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
typedef _MatrixType MatrixType ;
2014-07-20 14:22:58 +02:00
typedef _Ordering OrderingType ;
2011-10-09 21:45:55 +02:00
enum { UpLo = _UpLo } ;
} ;
}
2011-12-02 19:02:49 +01:00
/** \ingroup SparseCholesky_Module
2012-02-27 14:28:07 +01:00
* \ class SimplicialLLT
* \ brief A direct sparse LLT Cholesky factorizations
2011-10-09 21:45:55 +02:00
*
* This class provides a LL ^ T Cholesky factorizations of sparse matrices that are
* selfadjoint and positive definite . The factorization allows for solving A . X = B where
* X and B can be either dense or sparse .
2012-06-07 16:24:46 +02:00
*
* In order to reduce the fill - in , a symmetric permutation P is applied prior to the factorization
* such that the factorized matrix is P A P ^ - 1.
2011-10-09 21:45:55 +02:00
*
* \ tparam _MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam _UpLo the triangular part that will be used for the computations . It can be Lower
* or Upper . Default is Lower .
2014-07-20 14:22:58 +02:00
* \ tparam _Ordering The ordering method to use , either AMDOrdering < > or NaturalOrdering < > . Default is AMDOrdering < >
2011-10-09 21:45:55 +02:00
*
2014-07-20 14:22:58 +02:00
* \ sa class SimplicialLDLT , class AMDOrdering , class NaturalOrdering
2011-10-09 21:45:55 +02:00
*/
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering >
class SimplicialLLT : public SimplicialCholeskyBase < SimplicialLLT < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
public :
typedef _MatrixType MatrixType ;
enum { UpLo = _UpLo } ;
2012-02-27 14:28:07 +01:00
typedef SimplicialCholeskyBase < SimplicialLLT > Base ;
2011-10-09 21:45:55 +02:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
typedef Matrix < Scalar , Dynamic , 1 > VectorType ;
2012-02-27 14:28:07 +01:00
typedef internal : : traits < SimplicialLLT > Traits ;
2011-10-09 21:45:55 +02:00
typedef typename Traits : : MatrixL MatrixL ;
typedef typename Traits : : MatrixU MatrixU ;
public :
2011-12-02 19:02:49 +01:00
/** Default constructor */
2012-02-27 14:28:07 +01:00
SimplicialLLT ( ) : Base ( ) { }
/** Constructs and performs the LLT factorization of \a matrix */
SimplicialLLT ( const MatrixType & matrix )
2011-10-09 21:45:55 +02:00
: Base ( matrix ) { }
2011-12-02 19:02:49 +01:00
/** \returns an expression of the factor L */
2011-10-09 21:45:55 +02:00
inline const MatrixL matrixL ( ) const {
2012-02-27 14:28:07 +01:00
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial LLT not factorized " ) ;
2011-10-09 21:45:55 +02:00
return Traits : : getL ( Base : : m_matrix ) ;
}
2011-12-02 19:02:49 +01:00
/** \returns an expression of the factor U (= L^*) */
2011-10-09 21:45:55 +02:00
inline const MatrixU matrixU ( ) const {
2012-02-27 14:28:07 +01:00
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial LLT not factorized " ) ;
2011-10-09 21:45:55 +02:00
return Traits : : getU ( Base : : m_matrix ) ;
}
2012-06-01 15:51:03 +02:00
/** Computes the sparse Cholesky decomposition of \a matrix */
2012-06-04 13:22:44 +02:00
SimplicialLLT & compute ( const MatrixType & matrix )
2012-06-01 15:51:03 +02:00
{
Base : : template compute < false > ( matrix ) ;
return * this ;
}
2011-10-09 21:45:55 +02:00
/** Performs a symbolic decomposition on the sparcity of \a matrix.
*
* This function is particularly useful when solving for several problems having the same structure .
*
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & a )
{
Base : : analyzePattern ( a , false ) ;
}
/** Performs a numeric decomposition of \a matrix
*
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed .
*
* \ sa analyzePattern ( )
*/
void factorize ( const MatrixType & a )
{
Base : : template factorize < false > ( a ) ;
}
2011-12-02 19:02:49 +01:00
/** \returns the determinant of the underlying matrix from the current factorization */
2011-10-11 11:31:12 +02:00
Scalar determinant ( ) const
{
2011-12-04 21:49:21 +01:00
Scalar detL = Base : : m_matrix . diagonal ( ) . prod ( ) ;
2013-06-10 23:40:56 +02:00
return numext : : abs2 ( detL ) ;
2011-10-11 11:31:12 +02:00
}
2011-10-09 21:45:55 +02:00
} ;
2011-12-02 19:02:49 +01:00
/** \ingroup SparseCholesky_Module
2012-02-27 14:28:07 +01:00
* \ class SimplicialLDLT
* \ brief A direct sparse LDLT Cholesky factorizations without square root .
2011-10-09 21:45:55 +02:00
*
* This class provides a LDL ^ T Cholesky factorizations without square root of sparse matrices that are
* selfadjoint and positive definite . The factorization allows for solving A . X = B where
* X and B can be either dense or sparse .
2012-06-07 16:24:46 +02:00
*
* In order to reduce the fill - in , a symmetric permutation P is applied prior to the factorization
* such that the factorized matrix is P A P ^ - 1.
2011-10-09 21:45:55 +02:00
*
* \ tparam _MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam _UpLo the triangular part that will be used for the computations . It can be Lower
* or Upper . Default is Lower .
2014-07-20 14:22:58 +02:00
* \ tparam _Ordering The ordering method to use , either AMDOrdering < > or NaturalOrdering < > . Default is AMDOrdering < >
2011-10-09 21:45:55 +02:00
*
2014-07-20 14:22:58 +02:00
* \ sa class SimplicialLLT , class AMDOrdering , class NaturalOrdering
2011-10-09 21:45:55 +02:00
*/
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering >
class SimplicialLDLT : public SimplicialCholeskyBase < SimplicialLDLT < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
public :
typedef _MatrixType MatrixType ;
enum { UpLo = _UpLo } ;
2012-02-27 14:28:07 +01:00
typedef SimplicialCholeskyBase < SimplicialLDLT > Base ;
2011-10-09 21:45:55 +02:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
typedef Matrix < Scalar , Dynamic , 1 > VectorType ;
2012-02-27 14:28:07 +01:00
typedef internal : : traits < SimplicialLDLT > Traits ;
2011-10-09 21:45:55 +02:00
typedef typename Traits : : MatrixL MatrixL ;
typedef typename Traits : : MatrixU MatrixU ;
public :
2011-12-02 19:02:49 +01:00
/** Default constructor */
2012-02-27 14:28:07 +01:00
SimplicialLDLT ( ) : Base ( ) { }
2011-12-02 19:02:49 +01:00
2012-02-27 14:28:07 +01:00
/** Constructs and performs the LLT factorization of \a matrix */
SimplicialLDLT ( const MatrixType & matrix )
2011-10-09 21:45:55 +02:00
: Base ( matrix ) { }
2011-12-02 19:02:49 +01:00
/** \returns a vector expression of the diagonal D */
2011-10-09 21:45:55 +02:00
inline const VectorType vectorD ( ) const {
2012-02-27 14:28:07 +01:00
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial LDLT not factorized " ) ;
2011-10-09 21:45:55 +02:00
return Base : : m_diag ;
}
2011-12-02 19:02:49 +01:00
/** \returns an expression of the factor L */
2011-10-09 21:45:55 +02:00
inline const MatrixL matrixL ( ) const {
2012-02-27 14:28:07 +01:00
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial LDLT not factorized " ) ;
2011-10-09 21:45:55 +02:00
return Traits : : getL ( Base : : m_matrix ) ;
}
2011-12-02 19:02:49 +01:00
/** \returns an expression of the factor U (= L^*) */
2011-10-09 21:45:55 +02:00
inline const MatrixU matrixU ( ) const {
2012-02-27 14:28:07 +01:00
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial LDLT not factorized " ) ;
2011-10-09 21:45:55 +02:00
return Traits : : getU ( Base : : m_matrix ) ;
}
2012-06-01 15:51:03 +02:00
/** Computes the sparse Cholesky decomposition of \a matrix */
2012-06-04 13:22:44 +02:00
SimplicialLDLT & compute ( const MatrixType & matrix )
2012-06-01 15:51:03 +02:00
{
Base : : template compute < true > ( matrix ) ;
return * this ;
}
2011-10-09 21:45:55 +02:00
/** Performs a symbolic decomposition on the sparcity of \a matrix.
*
* This function is particularly useful when solving for several problems having the same structure .
*
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & a )
{
Base : : analyzePattern ( a , true ) ;
}
/** Performs a numeric decomposition of \a matrix
*
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed .
*
* \ sa analyzePattern ( )
*/
void factorize ( const MatrixType & a )
{
Base : : template factorize < true > ( a ) ;
}
2011-12-02 19:02:49 +01:00
/** \returns the determinant of the underlying matrix from the current factorization */
2011-10-11 11:31:12 +02:00
Scalar determinant ( ) const
{
return Base : : m_diag . prod ( ) ;
}
2011-10-09 21:45:55 +02:00
} ;
2012-02-27 14:28:07 +01:00
/** \deprecated use SimplicialLDLT or class SimplicialLLT
2011-12-02 19:02:49 +01:00
* \ ingroup SparseCholesky_Module
* \ class SimplicialCholesky
*
2012-02-27 14:28:07 +01:00
* \ sa class SimplicialLDLT , class SimplicialLLT
2011-10-09 21:45:55 +02:00
*/
2014-07-20 14:22:58 +02:00
template < typename _MatrixType , int _UpLo , typename _Ordering >
class SimplicialCholesky : public SimplicialCholeskyBase < SimplicialCholesky < _MatrixType , _UpLo , _Ordering > >
2011-10-09 21:45:55 +02:00
{
public :
typedef _MatrixType MatrixType ;
enum { UpLo = _UpLo } ;
typedef SimplicialCholeskyBase < SimplicialCholesky > Base ;
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
typedef SparseMatrix < Scalar , ColMajor , Index > CholMatrixType ;
typedef Matrix < Scalar , Dynamic , 1 > VectorType ;
typedef internal : : traits < SimplicialCholesky > Traits ;
2012-02-27 14:28:07 +01:00
typedef internal : : traits < SimplicialLDLT < MatrixType , UpLo > > LDLTTraits ;
typedef internal : : traits < SimplicialLLT < MatrixType , UpLo > > LLTTraits ;
2011-10-09 21:45:55 +02:00
public :
2012-02-27 14:28:07 +01:00
SimplicialCholesky ( ) : Base ( ) , m_LDLT ( true ) { }
2011-11-12 14:11:27 +01:00
2011-10-09 21:45:55 +02:00
SimplicialCholesky ( const MatrixType & matrix )
2012-02-27 14:28:07 +01:00
: Base ( ) , m_LDLT ( true )
2011-10-11 11:31:12 +02:00
{
2012-06-01 15:51:03 +02:00
compute ( matrix ) ;
2011-10-11 11:31:12 +02:00
}
2011-10-09 21:45:55 +02:00
SimplicialCholesky & setMode ( SimplicialCholeskyMode mode )
{
switch ( mode )
{
2012-02-27 14:28:07 +01:00
case SimplicialCholeskyLLT :
m_LDLT = false ;
2011-10-09 21:45:55 +02:00
break ;
2012-02-27 14:28:07 +01:00
case SimplicialCholeskyLDLT :
m_LDLT = true ;
2011-10-09 21:45:55 +02:00
break ;
default :
break ;
}
return * this ;
}
inline const VectorType vectorD ( ) const {
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial Cholesky not factorized " ) ;
return Base : : m_diag ;
}
inline const CholMatrixType rawMatrix ( ) const {
eigen_assert ( Base : : m_factorizationIsOk & & " Simplicial Cholesky not factorized " ) ;
return Base : : m_matrix ;
}
2012-06-01 15:51:03 +02:00
/** Computes the sparse Cholesky decomposition of \a matrix */
2012-06-04 13:22:44 +02:00
SimplicialCholesky & compute ( const MatrixType & matrix )
2012-06-01 15:51:03 +02:00
{
if ( m_LDLT )
Base : : template compute < true > ( matrix ) ;
else
Base : : template compute < false > ( matrix ) ;
return * this ;
}
2011-10-09 21:45:55 +02:00
/** Performs a symbolic decomposition on the sparcity of \a matrix.
*
* This function is particularly useful when solving for several problems having the same structure .
*
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & a )
{
2012-02-27 14:28:07 +01:00
Base : : analyzePattern ( a , m_LDLT ) ;
2011-10-09 21:45:55 +02:00
}
/** Performs a numeric decomposition of \a matrix
*
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed .
*
* \ sa analyzePattern ( )
*/
void factorize ( const MatrixType & a )
{
2012-02-27 14:28:07 +01:00
if ( m_LDLT )
2011-10-09 21:45:55 +02:00
Base : : template factorize < true > ( a ) ;
else
Base : : template factorize < false > ( a ) ;
}
/** \internal */
template < typename Rhs , typename Dest >
void _solve ( const MatrixBase < Rhs > & b , MatrixBase < Dest > & dest ) const
{
eigen_assert ( Base : : m_factorizationIsOk & & " The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric() " ) ;
eigen_assert ( Base : : m_matrix . rows ( ) = = b . rows ( ) ) ;
if ( Base : : m_info ! = Success )
return ;
if ( Base : : m_P . size ( ) > 0 )
2012-06-07 16:24:46 +02:00
dest = Base : : m_P * b ;
2011-10-09 21:45:55 +02:00
else
dest = b ;
if ( Base : : m_matrix . nonZeros ( ) > 0 ) // otherwise L==I
{
2012-02-27 14:28:07 +01:00
if ( m_LDLT )
LDLTTraits : : getL ( Base : : m_matrix ) . solveInPlace ( dest ) ;
2011-10-09 21:45:55 +02:00
else
2012-02-27 14:28:07 +01:00
LLTTraits : : getL ( Base : : m_matrix ) . solveInPlace ( dest ) ;
2011-10-09 21:45:55 +02:00
}
if ( Base : : m_diag . size ( ) > 0 )
dest = Base : : m_diag . asDiagonal ( ) . inverse ( ) * dest ;
if ( Base : : m_matrix . nonZeros ( ) > 0 ) // otherwise I==I
{
2012-02-27 14:28:07 +01:00
if ( m_LDLT )
LDLTTraits : : getU ( Base : : m_matrix ) . solveInPlace ( dest ) ;
2011-10-09 21:45:55 +02:00
else
2012-02-27 14:28:07 +01:00
LLTTraits : : getU ( Base : : m_matrix ) . solveInPlace ( dest ) ;
2011-10-09 21:45:55 +02:00
}
if ( Base : : m_P . size ( ) > 0 )
2012-06-07 16:24:46 +02:00
dest = Base : : m_Pinv * dest ;
2011-10-09 21:45:55 +02:00
}
2011-10-11 11:31:12 +02:00
Scalar determinant ( ) const
{
2012-02-27 14:28:07 +01:00
if ( m_LDLT )
2011-10-11 11:31:12 +02:00
{
return Base : : m_diag . prod ( ) ;
}
else
{
Scalar detL = Diagonal < const CholMatrixType > ( Base : : m_matrix ) . prod ( ) ;
2013-06-10 23:40:56 +02:00
return numext : : abs2 ( detL ) ;
2011-10-11 11:31:12 +02:00
}
}
2011-10-09 21:45:55 +02:00
protected :
2012-02-27 14:28:07 +01:00
bool m_LDLT ;
2011-10-09 21:45:55 +02:00
} ;
template < typename Derived >
2012-06-01 15:51:03 +02:00
void SimplicialCholeskyBase < Derived > : : ordering ( const MatrixType & a , CholMatrixType & ap )
2010-11-18 10:30:52 +01:00
{
eigen_assert ( a . rows ( ) = = a . cols ( ) ) ;
const Index size = a . rows ( ) ;
2012-06-07 16:24:46 +02:00
// Note that amd compute the inverse permutation
2010-11-18 10:30:52 +01:00
{
CholMatrixType C ;
C = a . template selfadjointView < UpLo > ( ) ;
2014-07-20 14:22:58 +02:00
OrderingType ordering ;
ordering ( C , m_Pinv ) ;
2010-11-18 10:30:52 +01:00
}
2012-06-01 15:51:03 +02:00
2012-06-07 16:24:46 +02:00
if ( m_Pinv . size ( ) > 0 )
m_P = m_Pinv . inverse ( ) ;
2010-11-18 10:30:52 +01:00
else
2012-06-07 16:24:46 +02:00
m_P . resize ( 0 ) ;
2012-06-01 15:51:03 +02:00
ap . resize ( size , size ) ;
2012-06-07 16:24:46 +02:00
ap . template selfadjointView < Upper > ( ) = a . template selfadjointView < UpLo > ( ) . twistedBy ( m_P ) ;
2012-06-01 15:51:03 +02:00
}
2010-11-04 09:58:22 +01:00
namespace internal {
2011-10-09 21:45:55 +02:00
template < typename Derived , typename Rhs >
struct solve_retval < SimplicialCholeskyBase < Derived > , Rhs >
: solve_retval_base < SimplicialCholeskyBase < Derived > , Rhs >
2010-11-04 09:58:22 +01:00
{
2011-10-09 21:45:55 +02:00
typedef SimplicialCholeskyBase < Derived > Dec ;
2010-11-04 09:58:22 +01:00
EIGEN_MAKE_SOLVE_HELPERS ( Dec , Rhs )
template < typename Dest > void evalTo ( Dest & dst ) const
{
2011-10-09 21:45:55 +02:00
dec ( ) . derived ( ) . _solve ( rhs ( ) , dst ) ;
2010-11-04 09:58:22 +01:00
}
} ;
2011-10-09 21:45:55 +02:00
template < typename Derived , typename Rhs >
struct sparse_solve_retval < SimplicialCholeskyBase < Derived > , Rhs >
: sparse_solve_retval_base < SimplicialCholeskyBase < Derived > , Rhs >
2010-11-04 09:58:22 +01:00
{
2011-10-09 21:45:55 +02:00
typedef SimplicialCholeskyBase < Derived > Dec ;
2010-11-04 09:58:22 +01:00
EIGEN_MAKE_SPARSE_SOLVE_HELPERS ( Dec , Rhs )
template < typename Dest > void evalTo ( Dest & dst ) const
{
2013-01-25 18:17:17 +01:00
this - > defaultEvalTo ( dst ) ;
2010-11-04 09:58:22 +01:00
}
} ;
2012-04-15 11:06:28 +01:00
} // end namespace internal
} // end namespace Eigen
2010-11-04 09:58:22 +01:00
# endif // EIGEN_SIMPLICIAL_CHOLESKY_H