mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-22 17:49:36 +08:00
Oops, here the actual LLT and LDLT patch.
This commit is contained in:
parent
0523b64fe9
commit
c7303a876f
@ -62,16 +62,29 @@ template<typename MatrixType> class LDLT
|
|||||||
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
|
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
|
||||||
typedef Matrix<int, 1, MatrixType::RowsAtCompileTime> IntRowVectorType;
|
typedef Matrix<int, 1, MatrixType::RowsAtCompileTime> IntRowVectorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Default Constructor.
|
||||||
|
*
|
||||||
|
* The default constructor is useful in cases in which the user intends to
|
||||||
|
* perform decompositions via LDLT::compute(const MatrixType&).
|
||||||
|
*/
|
||||||
|
LDLT() : m_matrix(), m_p(), m_transpositions(), m_isInitialized(false) {}
|
||||||
|
|
||||||
LDLT(const MatrixType& matrix)
|
LDLT(const MatrixType& matrix)
|
||||||
: m_matrix(matrix.rows(), matrix.cols()),
|
: m_matrix(matrix.rows(), matrix.cols()),
|
||||||
m_p(matrix.rows()),
|
m_p(matrix.rows()),
|
||||||
m_transpositions(matrix.rows())
|
m_transpositions(matrix.rows()),
|
||||||
|
m_isInitialized(false)
|
||||||
{
|
{
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the lower triangular matrix L */
|
/** \returns the lower triangular matrix L */
|
||||||
inline Part<MatrixType, UnitLowerTriangular> matrixL(void) const { return m_matrix; }
|
inline Part<MatrixType, UnitLowerTriangular> matrixL(void) const
|
||||||
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
|
return m_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
/** \returns a vector of integers, whose size is the number of rows of the matrix being decomposed,
|
/** \returns a vector of integers, whose size is the number of rows of the matrix being decomposed,
|
||||||
* representing the P permutation i.e. the permutation of the rows. For its precise meaning,
|
* representing the P permutation i.e. the permutation of the rows. For its precise meaning,
|
||||||
@ -79,17 +92,30 @@ template<typename MatrixType> class LDLT
|
|||||||
*/
|
*/
|
||||||
inline const IntColVectorType& permutationP() const
|
inline const IntColVectorType& permutationP() const
|
||||||
{
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
return m_p;
|
return m_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the coefficients of the diagonal matrix D */
|
/** \returns the coefficients of the diagonal matrix D */
|
||||||
inline Diagonal<MatrixType,0> vectorD(void) const { return m_matrix.diagonal(); }
|
inline Diagonal<MatrixType,0> vectorD(void) const
|
||||||
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
|
return m_matrix.diagonal();
|
||||||
|
}
|
||||||
|
|
||||||
/** \returns true if the matrix is positive (semidefinite) */
|
/** \returns true if the matrix is positive (semidefinite) */
|
||||||
inline bool isPositive(void) const { return m_sign == 1; }
|
inline bool isPositive(void) const
|
||||||
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
|
return m_sign == 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** \returns true if the matrix is negative (semidefinite) */
|
/** \returns true if the matrix is negative (semidefinite) */
|
||||||
inline bool isNegative(void) const { return m_sign == -1; }
|
inline bool isNegative(void) const
|
||||||
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
|
return m_sign == -1;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RhsDerived, typename ResDerived>
|
template<typename RhsDerived, typename ResDerived>
|
||||||
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
||||||
@ -110,6 +136,7 @@ template<typename MatrixType> class LDLT
|
|||||||
IntColVectorType m_p;
|
IntColVectorType m_p;
|
||||||
IntColVectorType m_transpositions;
|
IntColVectorType m_transpositions;
|
||||||
int m_sign;
|
int m_sign;
|
||||||
|
bool m_isInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix
|
/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix
|
||||||
@ -126,6 +153,7 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
|
|||||||
m_p.setZero();
|
m_p.setZero();
|
||||||
m_transpositions.setZero();
|
m_transpositions.setZero();
|
||||||
m_sign = ei_real(a.coeff(0,0))>0 ? 1:-1;
|
m_sign = ei_real(a.coeff(0,0))>0 ? 1:-1;
|
||||||
|
m_isInitialized = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +233,8 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
|
|||||||
for(int k = size-1; k >= 0; --k) {
|
for(int k = size-1; k >= 0; --k) {
|
||||||
std::swap(m_p.coeffRef(k), m_p.coeffRef(m_transpositions.coeff(k)));
|
std::swap(m_p.coeffRef(k), m_p.coeffRef(m_transpositions.coeff(k)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||||
@ -222,6 +252,7 @@ template<typename RhsDerived, typename ResDerived>
|
|||||||
bool LDLT<MatrixType>
|
bool LDLT<MatrixType>
|
||||||
::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
||||||
{
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
const int size = m_matrix.rows();
|
const int size = m_matrix.rows();
|
||||||
ei_assert(size==b.rows() && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
|
ei_assert(size==b.rows() && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||||
*result = b;
|
*result = b;
|
||||||
@ -243,6 +274,7 @@ template<typename MatrixType>
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||||
{
|
{
|
||||||
|
ei_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
const int size = m_matrix.rows();
|
const int size = m_matrix.rows();
|
||||||
ei_assert(size == bAndX.rows());
|
ei_assert(size == bAndX.rows());
|
||||||
|
|
||||||
|
@ -65,14 +65,27 @@ template<typename MatrixType> class LLT
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Default Constructor.
|
||||||
|
*
|
||||||
|
* The default constructor is useful in cases in which the user intends to
|
||||||
|
* perform decompositions via LLT::compute(const MatrixType&).
|
||||||
|
*/
|
||||||
|
LLT() : m_matrix(), m_isInitialized(false) {}
|
||||||
|
|
||||||
LLT(const MatrixType& matrix)
|
LLT(const MatrixType& matrix)
|
||||||
: m_matrix(matrix.rows(), matrix.cols())
|
: m_matrix(matrix.rows(), matrix.cols()),
|
||||||
|
m_isInitialized(false)
|
||||||
{
|
{
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the lower triangular matrix L */
|
/** \returns the lower triangular matrix L */
|
||||||
inline Part<MatrixType, LowerTriangular> matrixL(void) const { return m_matrix; }
|
inline Part<MatrixType, LowerTriangular> matrixL(void) const
|
||||||
|
{
|
||||||
|
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||||
|
return m_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RhsDerived, typename ResDerived>
|
template<typename RhsDerived, typename ResDerived>
|
||||||
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
||||||
@ -88,6 +101,7 @@ template<typename MatrixType> class LLT
|
|||||||
* The strict upper part is not used and even not initialized.
|
* The strict upper part is not used and even not initialized.
|
||||||
*/
|
*/
|
||||||
MatrixType m_matrix;
|
MatrixType m_matrix;
|
||||||
|
bool m_isInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
|
/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
|
||||||
@ -109,7 +123,10 @@ void LLT<MatrixType>::compute(const MatrixType& a)
|
|||||||
x = ei_real(a.coeff(0,0));
|
x = ei_real(a.coeff(0,0));
|
||||||
m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
||||||
if(size==1)
|
if(size==1)
|
||||||
|
{
|
||||||
|
m_isInitialized = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
||||||
for (int j = 1; j < size; ++j)
|
for (int j = 1; j < size; ++j)
|
||||||
{
|
{
|
||||||
@ -130,6 +147,8 @@ void LLT<MatrixType>::compute(const MatrixType& a)
|
|||||||
- m_matrix.col(j).end(endSize) ) / x;
|
- m_matrix.col(j).end(endSize) ) / x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||||
@ -149,6 +168,7 @@ template<typename MatrixType>
|
|||||||
template<typename RhsDerived, typename ResDerived>
|
template<typename RhsDerived, typename ResDerived>
|
||||||
bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
||||||
{
|
{
|
||||||
|
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||||
const int size = m_matrix.rows();
|
const int size = m_matrix.rows();
|
||||||
ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||||
return solveInPlace((*result) = b);
|
return solveInPlace((*result) = b);
|
||||||
@ -169,6 +189,7 @@ template<typename MatrixType>
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool LLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
bool LLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||||
{
|
{
|
||||||
|
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||||
const int size = m_matrix.rows();
|
const int size = m_matrix.rows();
|
||||||
ei_assert(size==bAndX.rows());
|
ei_assert(size==bAndX.rows());
|
||||||
matrixL().solveTriangularInPlace(bAndX);
|
matrixL().solveTriangularInPlace(bAndX);
|
||||||
|
@ -112,29 +112,25 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename MatrixType> void cholesky_verify_assert()
|
||||||
void doSomeRankPreservingOperations(Eigen::MatrixBase<Derived>& m)
|
|
||||||
{
|
{
|
||||||
typedef typename Derived::RealScalar RealScalar;
|
MatrixType tmp;
|
||||||
for(int a = 0; a < 3*(m.rows()+m.cols()); a++)
|
|
||||||
{
|
|
||||||
RealScalar d = Eigen::ei_random<RealScalar>(-1,1);
|
|
||||||
int i = Eigen::ei_random<int>(0,m.rows()-1); // i is a random row number
|
|
||||||
int j;
|
|
||||||
do {
|
|
||||||
j = Eigen::ei_random<int>(0,m.rows()-1);
|
|
||||||
} while (i==j); // j is another one (must be different)
|
|
||||||
m.row(i) += d * m.row(j);
|
|
||||||
|
|
||||||
i = Eigen::ei_random<int>(0,m.cols()-1); // i is a random column number
|
LLT<MatrixType> llt;
|
||||||
do {
|
VERIFY_RAISES_ASSERT(llt.matrixL())
|
||||||
j = Eigen::ei_random<int>(0,m.cols()-1);
|
VERIFY_RAISES_ASSERT(llt.solve(tmp,&tmp))
|
||||||
} while (i==j); // j is another one (must be different)
|
VERIFY_RAISES_ASSERT(llt.solveInPlace(&tmp))
|
||||||
m.col(i) += d * m.col(j);
|
|
||||||
}
|
LDLT<MatrixType> ldlt;
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.matrixL())
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.permutationP())
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.vectorD())
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.isPositive())
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.isNegative())
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.solve(tmp,&tmp))
|
||||||
|
VERIFY_RAISES_ASSERT(ldlt.solveInPlace(&tmp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_cholesky()
|
void test_cholesky()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < g_repeat; i++) {
|
for(int i = 0; i < g_repeat; i++) {
|
||||||
@ -147,4 +143,9 @@ void test_cholesky()
|
|||||||
CALL_SUBTEST( cholesky(MatrixXd(17,17)) );
|
CALL_SUBTEST( cholesky(MatrixXd(17,17)) );
|
||||||
CALL_SUBTEST( cholesky(MatrixXf(200,200)) );
|
CALL_SUBTEST( cholesky(MatrixXf(200,200)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CALL_SUBTEST( cholesky_verify_assert<Matrix3f>() );
|
||||||
|
CALL_SUBTEST( cholesky_verify_assert<Matrix3d>() );
|
||||||
|
CALL_SUBTEST( cholesky_verify_assert<MatrixXf>() );
|
||||||
|
CALL_SUBTEST( cholesky_verify_assert<MatrixXd>() );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user