Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • jcarpent/eigenpy
  • gsaurel/eigenpy
  • stack-of-tasks/eigenpy
3 results
Show changes
Showing
with 1216 additions and 27 deletions
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1738453229,
"narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1738410390,
"narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3a228057f5b619feb3186e986dbe76278d707b6e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1738452942,
"narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
{
description = "Bindings between Numpy and Eigen using Boost.Python";
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = inputs.nixpkgs.lib.systems.flakeExposed;
perSystem =
{ pkgs, self', ... }:
{
apps.default = {
type = "app";
program = pkgs.python3.withPackages (_: [ self'.packages.default ]);
};
devShells.default = pkgs.mkShell { inputsFrom = [ self'.packages.default ]; };
packages = {
default = self'.packages.eigenpy;
eigenpy = pkgs.python3Packages.eigenpy.overrideAttrs (_: {
src = pkgs.lib.fileset.toSource {
root = ./.;
fileset = pkgs.lib.fileset.unions [
./CMakeLists.txt
./doc
./include
./package.xml
./python
./src
./unittest
];
};
});
};
};
};
}
/*
* Copyright 2023, INRIA
* Copyright 2023 INRIA
*/
#ifndef __eigenpy_alignment_hpp__
......@@ -67,6 +67,23 @@ struct referent_storage<
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
#ifdef EIGENPY_WITH_TENSOR_SUPPORT
template <typename Scalar, int Rank, int Options, typename IndexType>
struct referent_storage<Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Rank, int Options, typename IndexType>
struct referent_storage<
const Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
#endif
template <typename Scalar, int Options>
struct referent_storage<Eigen::Quaternion<Scalar, Options> &> {
typedef Eigen::Quaternion<Scalar, Options> T;
......
......@@ -55,8 +55,7 @@ class AngleAxisVisitor : public bp::def_visitor<AngleAxisVisitor<AngleAxis> > {
bp::make_function((Vector3 & (AngleAxis::*)()) & AngleAxis::axis,
bp::return_internal_reference<>()),
&AngleAxisVisitor::setAxis, "The rotation axis.")
.add_property("angle",
(Scalar(AngleAxis::*)() const) & AngleAxis::angle,
.add_property("angle", (Scalar(AngleAxis::*)() const)&AngleAxis::angle,
&AngleAxisVisitor::setAngle, "The rotation angle.")
/* --- Methods --- */
......@@ -118,7 +117,8 @@ class AngleAxisVisitor : public bp::def_visitor<AngleAxisVisitor<AngleAxis> > {
static void expose() {
bp::class_<AngleAxis>(
"AngleAxis", "AngleAxis representation of a rotation.\n\n", bp::no_init)
.def(AngleAxisVisitor<AngleAxis>());
.def(AngleAxisVisitor<AngleAxis>())
.def(IdVisitor<AngleAxis>());
// Cast to Eigen::RotationBase
bp::implicitly_convertible<AngleAxis, RotationBase>();
......
//
// Copyright (c) 2016-2021 CNRS INRIA
// Copyright (c) 2016-2023 CNRS INRIA
// Copyright (c) 2023 Heriot-Watt University
//
#ifndef __eigenpy_utils_copyable_hpp__
......@@ -18,10 +19,14 @@ struct CopyableVisitor : public bp::def_visitor<CopyableVisitor<C> > {
template <class PyClass>
void visit(PyClass& cl) const {
cl.def("copy", &copy, bp::arg("self"), "Returns a copy of *this.");
cl.def("__copy__", &copy, bp::arg("self"), "Returns a copy of *this.");
cl.def("__deepcopy__", &deepcopy, bp::args("self", "memo"),
"Returns a deep copy of *this.");
}
private:
static C copy(const C& self) { return C(self); }
static C deepcopy(const C& self, bp::dict) { return C(self); }
};
} // namespace eigenpy
......
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_col_piv_houselholder_qr_hpp__
#define __eigenpy_decompositions_col_piv_houselholder_qr_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include <Eigen/QR>
namespace eigenpy {
template <typename _MatrixType>
struct ColPivHouseholderQRSolverVisitor
: public boost::python::def_visitor<
ColPivHouseholderQRSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
VectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
MatrixXs;
typedef Eigen::ColPivHouseholderQR<MatrixType> Solver;
typedef Solver Self;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"),
"Default constructor.\n"
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"HouseholderQR.compute(matrix)"))
.def(bp::init<Eigen::DenseIndex, Eigen::DenseIndex>(
bp::args("self", "rows", "cols"),
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. "))
.def(bp::init<MatrixType>(
bp::args("self", "matrix"),
"Constructs a QR factorization from a given matrix.\n"
"This constructor computes the QR factorization of the matrix "
"matrix by calling the method compute()."))
.def("absDeterminant", &Self::absDeterminant, bp::arg("self"),
"Returns the absolute value of the determinant of the matrix of "
"which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices.")
.def("logAbsDeterminant", &Self::logAbsDeterminant, bp::arg("self"),
"Returns the natural log of the absolute value of the determinant "
"of the matrix of which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices. This method is useful to "
"work around the risk of overflow/underflow that's inherent to "
"determinant computation.")
.def("dimensionOfKernel", &Self::dimensionOfKernel, bp::arg("self"),
"Returns the dimension of the kernel of the matrix of which *this "
"is the QR decomposition.")
.def("info", &Self::info, bp::arg("self"),
"Reports whether the QR factorization was successful.\n"
"Note: This function always returns Success. It is provided for "
"compatibility with other factorization routines.")
.def("isInjective", &Self::isInjective, bp::arg("self"),
"Returns true if the matrix associated with this QR decomposition "
"represents an injective linear map, i.e. has trivial kernel; "
"false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isInvertible", &Self::isInvertible, bp::arg("self"),
"Returns true if the matrix associated with the QR decomposition "
"is invertible.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isSurjective", &Self::isSurjective, bp::arg("self"),
"Returns true if the matrix associated with this QR decomposition "
"represents a surjective linear map; false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("maxPivot", &Self::maxPivot, bp::arg("self"),
"Returns the absolute value of the biggest pivot, i.e. the "
"biggest diagonal coefficient of U.")
.def("nonzeroPivots", &Self::nonzeroPivots, bp::arg("self"),
"Returns the number of nonzero pivots in the QR decomposition. "
"Here nonzero is meant in the exact sense, not in a fuzzy sense. "
"So that notion isn't really intrinsically interesting, but it is "
"still useful when implementing algorithms.")
.def("rank", &Self::rank, bp::arg("self"),
"Returns the rank of the matrix associated with the QR "
"decomposition.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("setThreshold",
(Self & (Self::*)(const RealScalar &)) & Self::setThreshold,
bp::args("self", "threshold"),
"Allows to prescribe a threshold to be used by certain methods, "
"such as rank(), who need to determine when pivots are to be "
"considered nonzero. This is not used for the QR decomposition "
"itself.\n"
"\n"
"When it needs to get the threshold value, Eigen calls "
"threshold(). By default, this uses a formula to automatically "
"determine a reasonable threshold. Once you have called the "
"present method setThreshold(const RealScalar&), your value is "
"used instead.\n"
"\n"
"Note: A pivot will be considered nonzero if its absolute value "
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
"maxpivot is the biggest pivot.",
bp::return_self<>())
.def("threshold", &Self::threshold, bp::arg("self"),
"Returns the threshold that will be used by certain methods such "
"as rank().")
.def("matrixQR", &Self::matrixQR, bp::arg("self"),
"Returns the matrix where the Householder QR decomposition is "
"stored in a LAPACK-compatible way.",
bp::return_value_policy<bp::copy_const_reference>())
.def("matrixR", &Self::matrixR, bp::arg("self"),
"Returns the matrix where the result Householder QR is stored.",
bp::return_value_policy<bp::copy_const_reference>())
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"),
"Computes the QR factorization of given matrix.",
bp::return_self<>())
.def("inverse", inverse, bp::arg("self"),
"Returns the inverse of the matrix associated with the QR "
"decomposition..")
.def("solve", &solve<MatrixXs>, bp::args("self", "B"),
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.");
}
static void expose() {
static const std::string classname =
"ColPivHouseholderQR" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"This class performs a rank-revealing QR decomposition of a matrix A "
"into matrices P, Q and R such that:\n"
"AP=QR\n"
"by using Householder transformations. Here, P is a permutation "
"matrix, Q a unitary matrix and R an upper triangular matrix.\n"
"\n"
"This decomposition performs column pivoting in order to be "
"rank-revealing and improve numerical stability. It is slower than "
"HouseholderQR, and faster than FullPivHouseholderQR.",
bp::no_init)
.def(ColPivHouseholderQRSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
static MatrixXs inverse(const Self &self) { return self.inverse(); }
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_col_piv_houselholder_qr_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_complete_orthogonal_decomposition_hpp__
#define __eigenpy_decompositions_complete_orthogonal_decomposition_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include <Eigen/QR>
namespace eigenpy {
template <typename _MatrixType>
struct CompleteOrthogonalDecompositionSolverVisitor
: public boost::python::def_visitor<
CompleteOrthogonalDecompositionSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
VectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
MatrixXs;
typedef Eigen::CompleteOrthogonalDecomposition<MatrixType> Solver;
typedef Solver Self;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"),
"Default constructor.\n"
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"CompleteOrthogonalDecomposition.compute(matrix)"))
.def(bp::init<Eigen::DenseIndex, Eigen::DenseIndex>(
bp::args("self", "rows", "cols"),
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. "))
.def(bp::init<MatrixType>(bp::args("self", "matrix"),
"Constructs a complete orthogonal "
"factorization from a given matrix.\n"
"This constructor computes the complete "
"orthogonal factorization of the matrix "
"matrix by calling the method compute()."))
.def("absDeterminant", &Self::absDeterminant, bp::arg("self"),
"Returns the absolute value of the determinant of the matrix "
"associated with the complete orthogonal decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the complete orthogonal "
"decomposition has "
"already been computed.\n"
"Note: This is only for square matrices.")
.def("logAbsDeterminant", &Self::logAbsDeterminant, bp::arg("self"),
"Returns the natural log of the absolute value of the determinant "
"of the matrix of which *this is the complete orthogonal "
"decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the complete orthogonal "
"decomposition has "
"already been computed.\n"
"Note: This is only for square matrices. This method is useful to "
"work around the risk of overflow/underflow that's inherent to "
"determinant computation.")
.def("dimensionOfKernel", &Self::dimensionOfKernel, bp::arg("self"),
"Returns the dimension of the kernel of the matrix of which *this "
"is the complete orthogonal decomposition.")
.def("info", &Self::info, bp::arg("self"),
"Reports whether the complete orthogonal factorization was "
"successful.\n"
"Note: This function always returns Success. It is provided for "
"compatibility with other factorization routines.")
.def("isInjective", &Self::isInjective, bp::arg("self"),
"Returns true if the matrix associated with this complete "
"orthogonal decomposition "
"represents an injective linear map, i.e. has trivial kernel; "
"false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isInvertible", &Self::isInvertible, bp::arg("self"),
"Returns true if the matrix associated with the complete "
"orthogonal decomposition "
"is invertible.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isSurjective", &Self::isSurjective, bp::arg("self"),
"Returns true if the matrix associated with this complete "
"orthogonal decomposition "
"represents a surjective linear map; false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("maxPivot", &Self::maxPivot, bp::arg("self"),
"Returns the absolute value of the biggest pivot, i.e. the "
"biggest diagonal coefficient of U.")
.def("nonzeroPivots", &Self::nonzeroPivots, bp::arg("self"),
"Returns the number of nonzero pivots in the complete orthogonal "
"decomposition. "
"Here nonzero is meant in the exact sense, not in a fuzzy sense. "
"So that notion isn't really intrinsically interesting, but it is "
"still useful when implementing algorithms.")
.def("rank", &Self::rank, bp::arg("self"),
"Returns the rank of the matrix associated with the complete "
"orthogonal "
"decomposition.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("setThreshold",
(Self & (Self::*)(const RealScalar &)) & Self::setThreshold,
bp::args("self", "threshold"),
"Allows to prescribe a threshold to be used by certain methods, "
"such as rank(), who need to determine when pivots are to be "
"considered nonzero. This is not used for the complete orthogonal "
"decomposition "
"itself.\n"
"\n"
"When it needs to get the threshold value, Eigen calls "
"threshold(). By default, this uses a formula to automatically "
"determine a reasonable threshold. Once you have called the "
"present method setThreshold(const RealScalar&), your value is "
"used instead.\n"
"\n"
"Note: A pivot will be considered nonzero if its absolute value "
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
"maxpivot is the biggest pivot.",
bp::return_self<>())
.def("threshold", &Self::threshold, bp::arg("self"),
"Returns the threshold that will be used by certain methods such "
"as rank().")
.def("matrixQTZ", &Self::matrixQTZ, bp::arg("self"),
"Returns the matrix where the complete orthogonal decomposition "
"is stored.",
bp::return_value_policy<bp::copy_const_reference>())
.def("matrixT", &Self::matrixT, bp::arg("self"),
"Returns the matrix where the complete orthogonal decomposition "
"is stored.",
bp::return_value_policy<bp::copy_const_reference>())
.def("matrixZ", &Self::matrixZ, bp::arg("self"),
"Returns the matrix Z.")
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"),
"Computes the complete orthogonal factorization of given matrix.",
bp::return_self<>())
.def("pseudoInverse", pseudoInverse, bp::arg("self"),
"Returns the pseudo-inverse of the matrix associated with the "
"complete orthogonal "
"decomposition.")
.def("solve", &solve<MatrixXs>, bp::args("self", "B"),
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.");
}
static void expose() {
static const std::string classname =
"CompleteOrthogonalDecomposition" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"This class performs a rank-revealing complete orthogonal "
"decomposition of a matrix A into matrices P, Q, T, and Z such that:\n"
"AP=Q[T000]Z"
"by using Householder transformations. Here, P is a permutation "
"matrix, Q and Z are unitary matrices and T an upper triangular matrix "
"of size rank-by-rank. A may be rank deficient.",
bp::no_init)
.def(CompleteOrthogonalDecompositionSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
static MatrixXs pseudoInverse(const Self &self) {
return self.pseudoInverse();
}
};
} // namespace eigenpy
#endif // ifndef
// __eigenpy_decompositions_complete_orthogonal_decomposition_hpp__
......@@ -2,8 +2,8 @@
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decomposition_eigen_solver_hpp__
#define __eigenpy_decomposition_eigen_solver_hpp__
#ifndef __eigenpy_decompositions_eigen_solver_hpp__
#define __eigenpy_decompositions_eigen_solver_hpp__
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
......@@ -75,7 +75,9 @@ struct EigenSolverVisitor
}
static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init).def(EigenSolverVisitor());
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(EigenSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
......@@ -88,4 +90,4 @@ struct EigenSolverVisitor
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_eigen_solver_hpp__
#endif // ifndef __eigenpy_decompositions_eigen_solver_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_full_piv_houselholder_qr_hpp__
#define __eigenpy_decompositions_full_piv_houselholder_qr_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include <Eigen/QR>
namespace eigenpy {
template <typename _MatrixType>
struct FullPivHouseholderQRSolverVisitor
: public boost::python::def_visitor<
FullPivHouseholderQRSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
VectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
MatrixXs;
typedef Eigen::FullPivHouseholderQR<MatrixType> Solver;
typedef Solver Self;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"),
"Default constructor.\n"
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"HouseholderQR.compute(matrix)"))
.def(bp::init<Eigen::DenseIndex, Eigen::DenseIndex>(
bp::args("self", "rows", "cols"),
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. "))
.def(bp::init<MatrixType>(
bp::args("self", "matrix"),
"Constructs a QR factorization from a given matrix.\n"
"This constructor computes the QR factorization of the matrix "
"matrix by calling the method compute()."))
.def("absDeterminant", &Self::absDeterminant, bp::arg("self"),
"Returns the absolute value of the determinant of the matrix of "
"which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices.")
.def("logAbsDeterminant", &Self::logAbsDeterminant, bp::arg("self"),
"Returns the natural log of the absolute value of the determinant "
"of the matrix of which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices. This method is useful to "
"work around the risk of overflow/underflow that's inherent to "
"determinant computation.")
.def("dimensionOfKernel", &Self::dimensionOfKernel, bp::arg("self"),
"Returns the dimension of the kernel of the matrix of which *this "
"is the QR decomposition.")
.def("isInjective", &Self::isInjective, bp::arg("self"),
"Returns true if the matrix associated with this QR decomposition "
"represents an injective linear map, i.e. has trivial kernel; "
"false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isInvertible", &Self::isInvertible, bp::arg("self"),
"Returns true if the matrix associated with the QR decomposition "
"is invertible.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("isSurjective", &Self::isSurjective, bp::arg("self"),
"Returns true if the matrix associated with this QR decomposition "
"represents a surjective linear map; false otherwise.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("maxPivot", &Self::maxPivot, bp::arg("self"),
"Returns the absolute value of the biggest pivot, i.e. the "
"biggest diagonal coefficient of U.")
.def("nonzeroPivots", &Self::nonzeroPivots, bp::arg("self"),
"Returns the number of nonzero pivots in the QR decomposition. "
"Here nonzero is meant in the exact sense, not in a fuzzy sense. "
"So that notion isn't really intrinsically interesting, but it is "
"still useful when implementing algorithms.")
.def("rank", &Self::rank, bp::arg("self"),
"Returns the rank of the matrix associated with the QR "
"decomposition.\n"
"\n"
"Note: This method has to determine which pivots should be "
"considered nonzero. For that, it uses the threshold value that "
"you can control by calling setThreshold(threshold).")
.def("setThreshold",
(Self & (Self::*)(const RealScalar &)) & Self::setThreshold,
bp::args("self", "threshold"),
"Allows to prescribe a threshold to be used by certain methods, "
"such as rank(), who need to determine when pivots are to be "
"considered nonzero. This is not used for the QR decomposition "
"itself.\n"
"\n"
"When it needs to get the threshold value, Eigen calls "
"threshold(). By default, this uses a formula to automatically "
"determine a reasonable threshold. Once you have called the "
"present method setThreshold(const RealScalar&), your value is "
"used instead.\n"
"\n"
"Note: A pivot will be considered nonzero if its absolute value "
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
"maxpivot is the biggest pivot.",
bp::return_self<>())
.def("threshold", &Self::threshold, bp::arg("self"),
"Returns the threshold that will be used by certain methods such "
"as rank().")
.def("matrixQR", &Self::matrixQR, bp::arg("self"),
"Returns the matrix where the Householder QR decomposition is "
"stored in a LAPACK-compatible way.",
bp::return_value_policy<bp::copy_const_reference>())
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"),
"Computes the QR factorization of given matrix.",
bp::return_self<>())
.def("inverse", inverse, bp::arg("self"),
"Returns the inverse of the matrix associated with the QR "
"decomposition..")
.def("solve", &solve<MatrixXs>, bp::args("self", "B"),
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.");
}
static void expose() {
static const std::string classname =
"FullPivHouseholderQR" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"This class performs a rank-revealing QR decomposition of a matrix A "
"into matrices P, P', Q and R such that:\n"
"PAP′=QR\n"
"by using Householder transformations. Here, P and P' are permutation "
"matrices, Q a unitary matrix and R an upper triangular matrix.\n"
"\n"
"This decomposition performs a very prudent full pivoting in order to "
"be rank-revealing and achieve optimal numerical stability. The "
"trade-off is that it is slower than HouseholderQR and "
"ColPivHouseholderQR.",
bp::no_init)
.def(FullPivHouseholderQRSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
static MatrixXs inverse(const Self &self) { return self.inverse(); }
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_full_piv_houselholder_qr_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_houselholder_qr_hpp__
#define __eigenpy_decompositions_houselholder_qr_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include <Eigen/QR>
namespace eigenpy {
template <typename _MatrixType>
struct HouseholderQRSolverVisitor
: public boost::python::def_visitor<
HouseholderQRSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
VectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
MatrixXs;
typedef Eigen::HouseholderQR<MatrixType> Solver;
typedef Solver Self;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"),
"Default constructor.\n"
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"HouseholderQR.compute(matrix)"))
.def(bp::init<Eigen::DenseIndex, Eigen::DenseIndex>(
bp::args("self", "rows", "cols"),
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. "))
.def(bp::init<MatrixType>(
bp::args("self", "matrix"),
"Constructs a QR factorization from a given matrix.\n"
"This constructor computes the QR factorization of the matrix "
"matrix by calling the method compute()."))
.def("absDeterminant", &Self::absDeterminant, bp::arg("self"),
"Returns the absolute value of the determinant of the matrix of "
"which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices.")
.def("logAbsDeterminant", &Self::logAbsDeterminant, bp::arg("self"),
"Returns the natural log of the absolute value of the determinant "
"of the matrix of which *this is the QR decomposition.\n"
"It has only linear complexity (that is, O(n) where n is the "
"dimension of the square matrix) as the QR decomposition has "
"already been computed.\n"
"Note: This is only for square matrices. This method is useful to "
"work around the risk of overflow/underflow that's inherent to "
"determinant computation.")
.def("matrixQR", &Self::matrixQR, bp::arg("self"),
"Returns the matrix where the Householder QR decomposition is "
"stored in a LAPACK-compatible way.",
bp::return_value_policy<bp::copy_const_reference>())
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"),
"Computes the QR factorization of given matrix.",
bp::return_self<>())
.def("solve", &solve<MatrixXs>, bp::args("self", "B"),
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.");
}
static void expose() {
static const std::string classname =
"HouseholderQR" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"This class performs a QR decomposition of a matrix A into matrices Q "
"and R such that A=QR by using Householder transformations.\n"
"Here, Q a unitary matrix and R an upper triangular matrix. The result "
"is stored in a compact way compatible with LAPACK.\n"
"\n"
"Note that no pivoting is performed. This is not a rank-revealing "
"decomposition. If you want that feature, use FullPivHouseholderQR or "
"ColPivHouseholderQR instead.\n"
"\n"
"This Householder QR decomposition is faster, but less numerically "
"stable and less feature-full than FullPivHouseholderQR or "
"ColPivHouseholderQR.",
bp::no_init)
.def(HouseholderQRSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_houselholder_qr_hpp__
/*
* Copyright 2020-2021 INRIA
* Copyright 2020-2024 INRIA
*/
#ifndef __eigenpy_decomposition_ldlt_hpp__
#define __eigenpy_decomposition_ldlt_hpp__
#ifndef __eigenpy_decompositions_ldlt_hpp__
#define __eigenpy_decompositions_ldlt_hpp__
#include <Eigen/Cholesky>
#include <Eigen/Core>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
namespace eigenpy {
......@@ -36,6 +37,8 @@ struct LDLTSolverVisitor
bp::args("self", "matrix"),
"Constructs a LDLT factorization from a given matrix."))
.def(EigenBaseVisitor<Solver>())
.def("isNegative", &Solver::isNegative, bp::arg("self"),
"Returns true if the matrix is negative (semidefinite).")
.def("isPositive", &Solver::isPositive, bp::arg("self"),
......@@ -116,6 +119,7 @@ struct LDLTSolverVisitor
"have zeros in the bottom right rank(A) - n submatrix. Avoiding the "
"square root on D also stabilizes the computation.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LDLTSolverVisitor());
}
......@@ -137,4 +141,4 @@ struct LDLTSolverVisitor
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_ldlt_hpp__
#endif // ifndef __eigenpy_decompositions_ldlt_hpp__
/*
* Copyright 2020-2021 INRIA
* Copyright 2020-2024 INRIA
*/
#ifndef __eigenpy_decomposition_llt_hpp__
#define __eigenpy_decomposition_llt_hpp__
#ifndef __eigenpy_decompositions_llt_hpp__
#define __eigenpy_decompositions_llt_hpp__
#include <Eigen/Cholesky>
#include <Eigen/Core>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
namespace eigenpy {
......@@ -36,6 +37,8 @@ struct LLTSolverVisitor
bp::args("self", "matrix"),
"Constructs a LLT factorization from a given matrix."))
.def(EigenBaseVisitor<Solver>())
.def("matrixL", &matrixL, bp::arg("self"),
"Returns the lower triangular matrix L.")
.def("matrixU", &matrixU, bp::arg("self"),
......@@ -51,8 +54,9 @@ struct LLTSolverVisitor
bp::args("self", "vector", "sigma"), bp::return_self<>())
#else
.def("rankUpdate",
(Solver(Solver::*)(const VectorXs &, const RealScalar &)) &
Solver::template rankUpdate<VectorXs>,
(Solver(Solver::*)(
const VectorXs &,
const RealScalar &))&Solver::template rankUpdate<VectorXs>,
bp::args("self", "vector", "sigma"))
#endif
......@@ -112,6 +116,7 @@ struct LLTSolverVisitor
"remains useful in many other situations like generalised eigen "
"problems with hermitian matrices.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LLTSolverVisitor());
}
......@@ -127,4 +132,4 @@ struct LLTSolverVisitor
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_llt_hpp__
#endif // ifndef __eigenpy_decompositions_llt_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_permutation_matrix_hpp__
#define __eigenpy_decompositions_permutation_matrix_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
namespace eigenpy {
template <int SizeAtCompileTime, int MaxSizeAtCompileTime = SizeAtCompileTime,
typename StorageIndex_ = int>
struct PermutationMatrixVisitor
: public boost::python::def_visitor<PermutationMatrixVisitor<
SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_> > {
typedef StorageIndex_ StorageIndex;
typedef Eigen::PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime,
StorageIndex>
PermutationMatrix;
typedef typename PermutationMatrix::DenseMatrixType DenseMatrixType;
typedef PermutationMatrix Self;
typedef Eigen::Matrix<StorageIndex, SizeAtCompileTime, 1, 0,
MaxSizeAtCompileTime, 1>
VectorIndex;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<const Eigen::DenseIndex>(bp::args("self", "size"),
"Default constructor"))
.def(bp::init<VectorIndex>(
bp::args("self", "indices"),
"The indices array has the meaning that the permutations sends "
"each integer i to indices[i].\n"
"It is your responsibility to check that the indices array that "
"you passes actually describes a permutation, i.e., each value "
"between 0 and n-1 occurs exactly once, where n is the array's "
"size."))
.def(
"indices",
+[](const PermutationMatrix &self) {
return VectorIndex(self.indices());
},
bp::arg("self"), "The stored array representing the permutation.")
.def("applyTranspositionOnTheLeft",
&PermutationMatrix::applyTranspositionOnTheLeft,
bp::args("self", "i", "j"),
"Multiplies self by the transposition (ij) on the left.",
bp::return_self<>())
.def("applyTranspositionOnTheRight",
&PermutationMatrix::applyTranspositionOnTheRight,
bp::args("self", "i", "j"),
"Multiplies self by the transposition (ij) on the right.",
bp::return_self<>())
.def("setIdentity",
(void(PermutationMatrix::*)()) & PermutationMatrix::setIdentity,
bp::arg("self"),
"Sets self to be the identity permutation matrix.")
.def("setIdentity",
(void(PermutationMatrix::*)(Eigen::DenseIndex)) &
PermutationMatrix::setIdentity,
bp::args("self", "size"),
"Sets self to be the identity permutation matrix of given size.")
.def("toDenseMatrix", &PermutationMatrix::toDenseMatrix,
bp::arg("self"),
"Returns a numpy array object initialized from this permutation "
"matrix.")
.def(
"transpose",
+[](const PermutationMatrix &self) -> PermutationMatrix {
return self.transpose();
},
bp::arg("self"), "Returns the tranpose permutation matrix.")
.def(
"inverse",
+[](const PermutationMatrix &self) -> PermutationMatrix {
return self.inverse();
},
bp::arg("self"), "Returns the inverse permutation matrix.")
.def("resize", &PermutationMatrix::resize, bp::args("self", "size"),
"Resizes to given size.")
.def(bp::self * bp::self)
.def(EigenBaseVisitor<Self>());
}
static void expose(const std::string &name) {
bp::class_<PermutationMatrix>(name.c_str(),
"Permutation matrix.\n"
"This class represents a permutation matrix, "
"internally stored as a vector of integers.",
bp::no_init)
.def(IdVisitor<PermutationMatrix>())
.def(PermutationMatrixVisitor());
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_permutation_matrix_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_qr_hpp__
#define __eigenpy_decompositions_qr_hpp__
#include "eigenpy/decompositions/HouseholderQR.hpp"
#include "eigenpy/decompositions/FullPivHouseholderQR.hpp"
#include "eigenpy/decompositions/ColPivHouseholderQR.hpp"
#include "eigenpy/decompositions/CompleteOrthogonalDecomposition.hpp"
#endif // ifndef __eigenpy_decompositions_qr_hpp__
/*
* Copyright 2020 INRIA
* Copyright 2020-2024 INRIA
*/
#ifndef __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
#define __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
#ifndef __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
#define __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
......@@ -84,6 +84,7 @@ struct SelfAdjointEigenSolverVisitor
static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(IdVisitor<Solver>())
.def(SelfAdjointEigenSolverVisitor());
}
......@@ -101,4 +102,4 @@ struct SelfAdjointEigenSolverVisitor
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
#endif // ifndef __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
......@@ -9,6 +9,15 @@
namespace eigenpy {
void EIGENPY_DLLAPI exposeDecompositions();
#ifdef EIGENPY_WITH_CHOLMOD_SUPPORT
void EIGENPY_DLLAPI exposeCholmod();
#endif
#ifdef EIGENPY_WITH_ACCELERATE_SUPPORT
void EIGENPY_DLLAPI exposeAccelerate();
#endif
} // namespace eigenpy
#endif // define __eigenpy_decompositions_decompositions_hpp__
......@@ -2,8 +2,8 @@
* Copyright 2021 INRIA
*/
#ifndef __eigenpy_decomposition_minres_hpp__
#define __eigenpy_decomposition_minres_hpp__
#ifndef __eigenpy_decompositions_minres_hpp__
#define __eigenpy_decompositions_minres_hpp__
#include <Eigen/Core>
#include <iostream>
......@@ -165,7 +165,8 @@ struct MINRESSolverVisitor
"defaults are the size of the problem for the maximal number of "
"iterations and NumTraits<Scalar>::epsilon() for the tolerance.\n",
bp::no_init)
.def(MINRESSolverVisitor());
.def(MINRESSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
......@@ -177,4 +178,4 @@ struct MINRESSolverVisitor
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_minres_hpp__
#endif // ifndef __eigenpy_decompositions_minres_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_sparse_ldlt_hpp__
#define __eigenpy_decompositions_sparse_ldlt_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/decompositions/sparse/SimplicialCholesky.hpp"
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy {
template <typename _MatrixType, int _UpLo = Eigen::Lower,
typename _Ordering =
Eigen::AMDOrdering<typename _MatrixType::StorageIndex> >
struct SimplicialLDLTVisitor
: public boost::python::def_visitor<
SimplicialLDLTVisitor<_MatrixType, _UpLo, _Ordering> > {
typedef SimplicialLDLTVisitor<_MatrixType, _UpLo, _Ordering> Visitor;
typedef _MatrixType MatrixType;
typedef Eigen::SimplicialLDLT<MatrixType> Solver;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
DenseVectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
DenseMatrixXs;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
.def(bp::init<MatrixType>(bp::args("self", "matrix"),
"Constructs and performs the LDLT "
"factorization from a given matrix."))
.def("vectorD", &vectorD, bp::arg("self"),
"Returns the diagonal vector D.")
.def(SimplicialCholeskyVisitor<Solver>());
}
static void expose() {
static const std::string classname =
"SimplicialLDLT_" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver, boost::noncopyable>(
name.c_str(),
"A direct sparse LDLT Cholesky factorizations.\n\n"
"This class provides a LDL^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.\n\n"
"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.",
bp::no_init)
.def(SimplicialLDLTVisitor())
.def(IdVisitor<Solver>());
}
private:
static DenseVectorXs vectorD(const Solver &self) { return self.vectorD(); }
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_sparse_ldlt_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_sparse_llt_hpp__
#define __eigenpy_decompositions_sparse_llt_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/decompositions/sparse/SimplicialCholesky.hpp"
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy {
template <typename _MatrixType, int _UpLo = Eigen::Lower,
typename _Ordering =
Eigen::AMDOrdering<typename _MatrixType::StorageIndex> >
struct SimplicialLLTVisitor
: public boost::python::def_visitor<
SimplicialLLTVisitor<_MatrixType, _UpLo, _Ordering> > {
typedef SimplicialLLTVisitor<_MatrixType, _UpLo, _Ordering> Visitor;
typedef _MatrixType MatrixType;
typedef Eigen::SimplicialLLT<MatrixType> Solver;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
DenseVectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
DenseMatrixXs;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
.def(bp::init<MatrixType>(bp::args("self", "matrix"),
"Constructs and performs the LLT "
"factorization from a given matrix."))
.def(SimplicialCholeskyVisitor<Solver>());
}
static void expose() {
static const std::string classname =
"SimplicialLLT_" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver, boost::noncopyable>(
name.c_str(),
"A direct sparse LLT Cholesky factorizations.\n\n"
"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.\n\n"
"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.",
bp::no_init)
.def(SimplicialLLTVisitor())
.def(IdVisitor<Solver>());
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_sparse_llt_hpp__
/*
* Copyright 2024 INRIA
*/
#ifndef __eigenpy_decompositions_sparse_simplicial_cholesky_hpp__
#define __eigenpy_decompositions_sparse_simplicial_cholesky_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
#include "eigenpy/decompositions/sparse/SparseSolverBase.hpp"
#include <Eigen/SparseCholesky>
namespace eigenpy {
template <typename SimplicialDerived>
struct SimplicialCholeskyVisitor
: public boost::python::def_visitor<
SimplicialCholeskyVisitor<SimplicialDerived> > {
typedef SimplicialDerived Solver;
typedef typename SimplicialDerived::MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
DenseVectorXs;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
DenseMatrixXs;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def("analyzePattern", &Solver::analyzePattern,
bp::args("self", "matrix"),
"Performs a symbolic decomposition on the sparcity of matrix.\n"
"This function is particularly useful when solving for several "
"problems having the same structure.")
.def(EigenBaseVisitor<Solver>())
.def(SparseSolverBaseVisitor<Solver>())
.def("matrixL", &matrixL, bp::arg("self"),
"Returns the lower triangular matrix L.")
.def("matrixU", &matrixU, bp::arg("self"),
"Returns the upper triangular matrix U.")
.def("compute",
(Solver & (Solver::*)(const MatrixType &matrix)) & Solver::compute,
bp::args("self", "matrix"),
"Computes the sparse Cholesky decomposition of a given matrix.",
bp::return_self<>())
.def("determinant", &Solver::determinant, bp::arg("self"),
"Returns the determinant of the underlying matrix from the "
"current factorization.")
.def("factorize", &Solver::factorize, bp::args("self", "matrix"),
"Performs a numeric decomposition of a given matrix.\n"
"The given matrix must has the same sparcity than the matrix on "
"which the symbolic decomposition has been performed.\n"
"See also analyzePattern().")
.def("info", &Solver::info, bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or "
"overflow occured. Returns Success otherwise.")
.def("setShift", &Solver::setShift,
(bp::args("self", "offset"), bp::arg("scale") = RealScalar(1)),
"Sets the shift parameters that will be used to adjust the "
"diagonal coefficients during the numerical factorization.\n"
"During the numerical factorization, the diagonal coefficients "
"are transformed by the following linear model: d_ii = offset + "
"scale * d_ii.\n"
"The default is the identity transformation with offset=0, and "
"scale=1.",
bp::return_self<>())
.def("permutationP", &Solver::permutationP, bp::arg("self"),
"Returns the permutation P.",
bp::return_value_policy<bp::copy_const_reference>())
.def("permutationPinv", &Solver::permutationPinv, bp::arg("self"),
"Returns the inverse P^-1 of the permutation P.",
bp::return_value_policy<bp::copy_const_reference>());
}
private:
static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
static MatrixType matrixU(const Solver &self) { return self.matrixU(); }
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_sparse_simplicial_cholesky_hpp__