|
| 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__ |
0 commit comments