Skip to content

Commit 775a1b7

Browse files
committed
decompositions: add LDLT decomposition
1 parent c775c55 commit 775a1b7

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ SET(${PROJECT_NAME}_SOLVERS_HEADERS
9090
SET(${PROJECT_NAME}_DECOMPOSITIONS_HEADERS
9191
include/eigenpy/decompositions/decompositions.hpp
9292
include/eigenpy/decompositions/EigenSolver.hpp
93+
include/eigenpy/decompositions/LDLT.hpp
9394
include/eigenpy/decompositions/LLT.hpp
9495
include/eigenpy/decompositions/SelfAdjointEigenSolver.hpp
9596
)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2020 INRIA
3+
*/
4+
5+
#ifndef __eigenpy_decomposition_ldlt_hpp__
6+
#define __eigenpy_decomposition_ldlt_hpp__
7+
8+
#include <boost/python.hpp>
9+
#include <Eigen/Core>
10+
#include <Eigen/Cholesky>
11+
12+
#include "eigenpy/utils/scalar-name.hpp"
13+
14+
namespace eigenpy
15+
{
16+
17+
template<typename _MatrixType>
18+
struct LDLTSolverVisitor
19+
: public boost::python::def_visitor< LDLTSolverVisitor<_MatrixType> >
20+
{
21+
22+
typedef _MatrixType MatrixType;
23+
typedef typename MatrixType::Scalar Scalar;
24+
typedef typename MatrixType::RealScalar RealScalar;
25+
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,MatrixType::Options> VectorType;
26+
typedef Eigen::LDLT<MatrixType> Solver;
27+
28+
template<class PyClass>
29+
void visit(PyClass& cl) const
30+
{
31+
namespace bp = boost::python;
32+
cl
33+
.def(bp::init<>("Default constructor"))
34+
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
35+
"Default constructor with memory preallocation"))
36+
.def(bp::init<MatrixType>(bp::arg("matrix"),
37+
"Constructs a LDLT factorization from a given matrix."))
38+
39+
.def("isNegative",&Solver::isNegative,bp::arg("self"),
40+
"Returns true if the matrix is negative (semidefinite).")
41+
.def("isPositive",&Solver::isPositive,bp::arg("self"),
42+
"Returns true if the matrix is positive (semidefinite).")
43+
44+
.def("matrixL",&matrixL,bp::arg("self"),
45+
"Returns the lower triangular matrix L.")
46+
.def("matrixU",&matrixU,bp::arg("self"),
47+
"Returns the upper triangular matrix U.")
48+
.def("vectorD",&vectorD,bp::arg("self"),
49+
"Returns the coefficients of the diagonal matrix D.")
50+
.def("transpositionsP",&transpositionsP,bp::arg("self"),
51+
"Returns the permutation matrix P.")
52+
53+
.def("matrixLDLT",&Solver::matrixLDLT,bp::arg("self"),
54+
"Returns the LDLT decomposition matrix.",
55+
bp::return_value_policy<bp::return_by_value>())
56+
57+
.def("rankUpdate",(Solver (Solver::*)(const VectorType &, const RealScalar &))&Solver::template rankUpdate<VectorType>,
58+
bp::args("self","vector","sigma"))
59+
60+
.def("adjoint",&Solver::adjoint,bp::arg("self"),
61+
"Returns the adjoint, that is, a reference to the decomposition itself as if the underlying matrix is self-adjoint.",
62+
bp::return_value_policy<bp::reference_existing_object>())
63+
64+
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute,
65+
bp::args("self","matrix"),
66+
"Computes the LDLT of given matrix.",
67+
bp::return_value_policy<bp::reference_existing_object>())
68+
69+
.def("info",&Solver::info,bp::arg("self"),
70+
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
71+
72+
.def("rcond",&Solver::rcond,bp::arg("self"),
73+
"Returns an estimate of the reciprocal condition number of the matrix.")
74+
.def("reconstructedMatrix",&Solver::reconstructedMatrix,bp::arg("self"),
75+
"Returns the matrix represented by the decomposition, i.e., it returns the product: L L^*. This function is provided for debug purpose.")
76+
.def("solve",&solve<VectorType>,bp::args("self","b"),
77+
"Returns the solution x of A x = b using the current decomposition of A.")
78+
79+
.def("setZero",&Solver::setZero,bp::arg("self"),
80+
"Clear any existing decomposition.")
81+
;
82+
}
83+
84+
static void expose()
85+
{
86+
static const std::string classname = "LDLT" + scalar_name<Scalar>::shortname();
87+
expose(classname);
88+
}
89+
90+
static void expose(const std::string & name)
91+
{
92+
namespace bp = boost::python;
93+
bp::class_<Solver>(name.c_str(),
94+
"Robust Cholesky decomposition of a matrix with pivoting.\n\n"
95+
"Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite matrix $ A $ such that $ A = P^TLDL^*P $, where P is a permutation matrix, L is lower triangular with a unit diagonal and D is a diagonal matrix.\n\n"
96+
"The decomposition uses pivoting to ensure stability, so that L will have zeros in the bottom right rank(A) - n submatrix. Avoiding the square root on D also stabilizes the computation.",
97+
bp::no_init)
98+
.def(LDLTSolverVisitor());
99+
}
100+
101+
private:
102+
103+
static MatrixType matrixL(const Solver & self) { return self.matrixL(); }
104+
static MatrixType matrixU(const Solver & self) { return self.matrixU(); }
105+
static VectorType vectorD(const Solver & self) { return self.vectorD(); }
106+
107+
static MatrixType transpositionsP(const Solver & self)
108+
{
109+
return self.transpositionsP() * MatrixType::Identity(self.matrixL().rows(),
110+
self.matrixL().rows());
111+
}
112+
113+
template<typename VectorType>
114+
static VectorType solve(const Solver & self, const VectorType & vec)
115+
{
116+
return self.solve(vec);
117+
}
118+
};
119+
120+
} // namespace eigenpy
121+
122+
#endif // ifndef __eigenpy_decomposition_ldlt_hpp__

src/decompositions/decompositions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "eigenpy/decompositions/EigenSolver.hpp"
99
#include "eigenpy/decompositions/SelfAdjointEigenSolver.hpp"
1010
#include "eigenpy/decompositions/LLT.hpp"
11+
#include "eigenpy/decompositions/LDLT.hpp"
1112

1213
namespace eigenpy
1314
{
@@ -19,6 +20,7 @@ namespace eigenpy
1920
EigenSolverVisitor<Eigen::MatrixXd>::expose("EigenSolver");
2021
SelfAdjointEigenSolverVisitor<Eigen::MatrixXd>::expose("SelfAdjointEigenSolver");
2122
LLTSolverVisitor<Eigen::MatrixXd>::expose("LLT");
23+
LDLTSolverVisitor<Eigen::MatrixXd>::expose("LDLT");
2224

2325
{
2426
using namespace Eigen;

0 commit comments

Comments
 (0)