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 1703 additions and 563 deletions
doc/pictures/footer.jpg

23.1 KiB

Copy in this directory the image you wish to use in the footer of the documentation or edit file sot-core/doc/footer.html and
remove this file.
File deleted
FROM ubuntu:22.04
RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -qqy \
build-essential \
cmake \
cmake-curses-gui \
vim \
gdb \
git \
libboost-all-dev \
libeigen3-dev \
liburdfdom-dev \
python3-numpy
WORKDIR /src
RUN git clone --recursive -j2 -b devel https://github.com/stack-of-tasks/eigenpy
ENV CTEST_OUTPUT_ON_FAILURE=ON
ENV CTEST_PROGRESS_OUTPUT=ON
ENV CTEST_PARALLEL_LEVEL=2
WORKDIR /src/eigenpy/build
RUN cmake -DPYTHON_EXECUTABLE=$(which python3) -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..
RUN make -sj2
{
"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
*/
#ifndef __eigenpy_alignment_hpp__
#define __eigenpy_alignment_hpp__
#include <boost/python/detail/referent_storage.hpp>
#include <boost/python/converter/arg_from_python.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <eigenpy/utils/is-aligned.hpp>
namespace eigenpy {
template <std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES>
struct aligned_storage {
union type {
typename ::boost::aligned_storage<size, alignment>::type data;
char bytes[size];
};
};
template <class Data>
struct aligned_instance {
PyObject_VAR_HEAD PyObject *dict;
PyObject *weakrefs;
boost::python::instance_holder *objects;
typename aligned_storage<sizeof(Data)>::type storage;
};
inline void *aligned_malloc(
std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES) {
void *original = std::malloc(size + alignment);
if (original == 0) return 0;
if (is_aligned(original, alignment)) return original;
void *aligned =
reinterpret_cast<void *>((reinterpret_cast<std::size_t>(original) &
~(std::size_t(alignment - 1))) +
alignment);
*(reinterpret_cast<void **>(aligned) - 1) = original;
return aligned;
}
} // namespace eigenpy
namespace boost {
namespace python {
namespace detail {
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
int MaxCols>
struct referent_storage<
Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
int MaxCols>
struct referent_storage<
const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
typedef
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;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Options>
struct referent_storage<const Eigen::Quaternion<Scalar, Options> &> {
typedef Eigen::Quaternion<Scalar, Options> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
} // namespace detail
} // namespace python
} // namespace boost
namespace boost {
namespace python {
namespace objects {
// Force alignment of instance with value_holder
template <typename Derived>
struct instance<value_holder<Derived> >
: ::eigenpy::aligned_instance<value_holder<Derived> > {};
} // namespace objects
} // namespace python
} // namespace boost
namespace eigenpy {
template <class T>
struct call_destructor {
static void run(void *bytes) {
typedef typename boost::remove_const<
typename boost::remove_reference<T>::type>::type T_;
static_cast<T_ *>((void *)bytes)->~T_();
}
};
template <class T>
struct rvalue_from_python_data
: ::boost::python::converter::rvalue_from_python_storage<T> {
#if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) && \
(!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) && \
(!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) && \
!defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing \
this */
// This must always be a POD struct with m_data its first member.
BOOST_STATIC_ASSERT(
BOOST_PYTHON_OFFSETOF(
::boost::python::converter::rvalue_from_python_storage<T>, stage1) ==
0);
#endif
// The usual constructor
rvalue_from_python_data(
::boost::python::converter::rvalue_from_python_stage1_data const
&_stage1) {
this->stage1 = _stage1;
}
// This constructor just sets m_convertible -- used by
// implicitly_convertible<> to perform the final step of the
// conversion, where the construct() function is already known.
rvalue_from_python_data(void *convertible) {
this->stage1.convertible = convertible;
}
// Destroys any object constructed in the storage.
~rvalue_from_python_data() {
if (this->stage1.convertible == this->storage.bytes) {
void *storage = reinterpret_cast<void *>(this->storage.bytes);
call_destructor<T>::run(storage);
}
}
};
} // namespace eigenpy
#endif // __eigenpy_alignment_hpp__
/* /*
* Copyright 2014-2020 CNRS INRIA * Copyright 2014-2023 CNRS INRIA
*/ */
#ifndef __eigenpy_angle_axis_hpp__ #ifndef __eigenpy_angle_axis_hpp__
...@@ -7,145 +7,124 @@ ...@@ -7,145 +7,124 @@
#include "eigenpy/eigenpy.hpp" #include "eigenpy/eigenpy.hpp"
#include <Eigen/Core> namespace eigenpy {
#include <Eigen/Geometry>
template <typename AngleAxis>
namespace eigenpy class AngleAxisVisitor;
{
template <typename Scalar>
namespace bp = boost::python; struct call<Eigen::AngleAxis<Scalar> > {
typedef Eigen::AngleAxis<Scalar> AngleAxis;
template<typename AngleAxis> class AngleAxisVisitor;
static inline void expose() { AngleAxisVisitor<AngleAxis>::expose(); }
template<typename Scalar>
struct call< Eigen::AngleAxis<Scalar> > static inline bool isApprox(
{ const AngleAxis& self, const AngleAxis& other,
typedef Eigen::AngleAxis<Scalar> AngleAxis; const Scalar& prec = Eigen::NumTraits<Scalar>::dummy_precision()) {
return self.isApprox(other, prec);
static inline void expose() }
{ };
AngleAxisVisitor<AngleAxis>::expose();
} template <typename AngleAxis>
class AngleAxisVisitor : public bp::def_visitor<AngleAxisVisitor<AngleAxis> > {
static inline bool isApprox(const AngleAxis & self, const AngleAxis & other, typedef typename AngleAxis::Scalar Scalar;
const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) typedef typename AngleAxis::Vector3 Vector3;
{ typedef typename AngleAxis::Matrix3 Matrix3;
return self.isApprox(other,prec);
} typedef typename Eigen::Quaternion<Scalar, 0> Quaternion;
}; typedef Eigen::RotationBase<AngleAxis, 3> RotationBase;
template<typename AngleAxis> BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,
class AngleAxisVisitor call<AngleAxis>::isApprox, 2, 3)
: public bp::def_visitor< AngleAxisVisitor<AngleAxis> >
{ public:
template <class PyClass>
typedef typename AngleAxis::Scalar Scalar; void visit(PyClass& cl) const {
typedef typename AngleAxis::Vector3 Vector3; cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
typedef typename AngleAxis::Matrix3 Matrix3; .def(bp::init<Scalar, Vector3>(bp::args("self", "angle", "axis"),
"Initialize from angle and axis."))
typedef typename Eigen::Quaternion<Scalar,0> Quaternion; .def(bp::init<Matrix3>(bp::args("self", "R"),
typedef Eigen::RotationBase<AngleAxis,3> RotationBase; "Initialize from a rotation matrix"))
.def(bp::init<Quaternion>(bp::args("self", "quaternion"),
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,call<AngleAxis>::isApprox,2,3) "Initialize from a quaternion."))
.def(bp::init<AngleAxis>(bp::args("self", "copy"), "Copy constructor."))
public:
/* --- Properties --- */
template<class PyClass> .add_property(
void visit(PyClass& cl) const "axis",
{ bp::make_function((Vector3 & (AngleAxis::*)()) & AngleAxis::axis,
cl bp::return_internal_reference<>()),
.def(bp::init<>(bp::arg("self"),"Default constructor")) &AngleAxisVisitor::setAxis, "The rotation axis.")
.def(bp::init<Scalar,Vector3> .add_property("angle", (Scalar(AngleAxis::*)() const)&AngleAxis::angle,
((bp::arg("self"),bp::arg("angle"),bp::arg("axis")), &AngleAxisVisitor::setAngle, "The rotation angle.")
"Initialize from angle and axis."))
.def(bp::init<Matrix3> /* --- Methods --- */
((bp::arg("self"),bp::arg("rotation matrix")), .def("inverse", &AngleAxis::inverse, bp::arg("self"),
"Initialize from a rotation matrix")) "Return the inverse rotation.")
.def(bp::init<Quaternion>((bp::arg("self"),bp::arg("quaternion")), .def("fromRotationMatrix",
"Initialize from a quaternion.")) &AngleAxis::template fromRotationMatrix<Matrix3>,
.def(bp::init<AngleAxis>((bp::arg("self"),bp::arg("copy")), (bp::arg("self"), bp::arg("rotation matrix")),
"Copy constructor.")) "Sets *this from a 3x3 rotation matrix", bp::return_self<>())
.def("toRotationMatrix", &AngleAxis::toRotationMatrix,
/* --- Properties --- */ // bp::arg("self"),
.add_property("axis", "Constructs and returns an equivalent rotation matrix.")
bp::make_function((Vector3 & (AngleAxis::*)())&AngleAxis::axis, .def("matrix", &AngleAxis::matrix, bp::arg("self"),
bp::return_internal_reference<>()), "Returns an equivalent rotation matrix.")
&AngleAxisVisitor::setAxis,"The rotation axis.")
.add_property("angle", .def("isApprox", &call<AngleAxis>::isApprox,
(Scalar (AngleAxis::*)()const)&AngleAxis::angle, isApproxAngleAxis_overload(
&AngleAxisVisitor::setAngle,"The rotation angle.") bp::args("self", "other", "prec"),
"Returns true if *this is approximately equal to other, "
/* --- Methods --- */ "within the precision determined by prec."))
.def("inverse",&AngleAxis::inverse,
bp::arg("self"), /* --- Operators --- */
"Return the inverse rotation.") .def(bp::self * bp::other<Vector3>())
.def("fromRotationMatrix",&AngleAxis::template fromRotationMatrix<Matrix3>, .def(bp::self * bp::other<Quaternion>())
(bp::arg("self"),bp::arg("rotation matrix")), .def(bp::self * bp::self)
"Sets *this from a 3x3 rotation matrix", .def("__eq__", &AngleAxisVisitor::__eq__)
bp::return_self<>()) .def("__ne__", &AngleAxisVisitor::__ne__)
.def("toRotationMatrix",
// bp::arg("self"), .def("__str__", &print)
&AngleAxis::toRotationMatrix, .def("__repr__", &print);
"Constructs and returns an equivalent 3x3 rotation matrix.") }
.def("matrix",&AngleAxis::matrix,
bp::arg("self"), private:
"Returns an equivalent rotation matrix.") static void setAxis(AngleAxis& self, const Vector3& axis) {
self.axis() = axis;
.def("isApprox", }
&call<AngleAxis>::isApprox,
isApproxAngleAxis_overload(bp::args("self","other","prec"), static void setAngle(AngleAxis& self, const Scalar& angle) {
"Returns true if *this is approximately equal to other, within the precision determined by prec.")) self.angle() = angle;
}
/* --- Operators --- */
.def(bp::self * bp::other<Vector3>()) static bool __eq__(const AngleAxis& u, const AngleAxis& v) {
.def(bp::self * bp::other<Quaternion>()) return u.axis() == v.axis() && v.angle() == u.angle();
.def(bp::self * bp::self) }
.def("__eq__",&AngleAxisVisitor::__eq__)
.def("__ne__",&AngleAxisVisitor::__ne__) static bool __ne__(const AngleAxis& u, const AngleAxis& v) {
return !__eq__(u, v);
.def("__str__",&print) }
.def("__repr__",&print)
; static std::string print(const AngleAxis& self) {
} std::stringstream ss;
ss << "angle: " << self.angle() << std::endl;
private: ss << "axis: " << self.axis().transpose() << std::endl;
static void setAxis(AngleAxis & self, const Vector3 & axis) return ss.str();
{ self.axis() = axis; } }
static void setAngle( AngleAxis & self, const Scalar & angle) public:
{ self.angle() = angle; } static void expose() {
bp::class_<AngleAxis>(
static bool __eq__(const AngleAxis & u, const AngleAxis & v) "AngleAxis", "AngleAxis representation of a rotation.\n\n", bp::no_init)
{ return u.axis() == v.axis() && v.angle() == u.angle(); } .def(AngleAxisVisitor<AngleAxis>())
.def(IdVisitor<AngleAxis>());
static bool __ne__(const AngleAxis & u, const AngleAxis & v)
{ return !__eq__(u,v); } // Cast to Eigen::RotationBase
bp::implicitly_convertible<AngleAxis, RotationBase>();
static std::string print(const AngleAxis & self) }
{ };
std::stringstream ss;
ss << "angle: " << self.angle() << std::endl; } // namespace eigenpy
ss << "axis: " << self.axis().transpose() << std::endl;
#endif // ifndef __eigenpy_angle_axis_hpp__
return ss.str();
}
public:
static void expose()
{
bp::class_<AngleAxis>("AngleAxis",
"AngleAxis representation of a rotation.\n\n",
bp::no_init)
.def(AngleAxisVisitor<AngleAxis>());
// Cast to Eigen::RotationBase
bp::implicitly_convertible<AngleAxis,RotationBase>();
}
};
} // namespace eigenpy
#endif //ifndef __eigenpy_angle_axis_hpp__
...@@ -7,17 +7,14 @@ ...@@ -7,17 +7,14 @@
#include "eigenpy/fwd.hpp" #include "eigenpy/fwd.hpp"
namespace eigenpy namespace eigenpy {
{ inline void exposeComputationInfo() {
inline void exposeComputationInfo() boost::python::enum_<Eigen::ComputationInfo>("ComputationInfo")
{ .value("Success", Eigen::Success)
boost::python::enum_<Eigen::ComputationInfo>("ComputationInfo") .value("NumericalIssue", Eigen::NumericalIssue)
.value("Success",Eigen::Success) .value("NoConvergence", Eigen::NoConvergence)
.value("NumericalIssue",Eigen::NumericalIssue) .value("InvalidInput", Eigen::InvalidInput);
.value("NoConvergence",Eigen::NoConvergence) }
.value("InvalidInput",Eigen::InvalidInput) } // namespace eigenpy
;
}
} // namespace eigenpy
#endif // define __eigenpy_decompositions_computation_info_hpp__ #endif // define __eigenpy_decompositions_computation_info_hpp__
//
// Copyright (c) 2016-2023 CNRS INRIA
// Copyright (c) 2023 Heriot-Watt University
//
#ifndef __eigenpy_utils_copyable_hpp__
#define __eigenpy_utils_copyable_hpp__
#include <boost/python.hpp>
namespace eigenpy {
///
/// \brief Add the Python method copy to allow a copy of this by calling the
/// copy constructor.
///
template <class C>
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
#endif // ifndef __eigenpy_utils_copyable_hpp__
/*
* 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,97 +2,92 @@ ...@@ -2,97 +2,92 @@
* Copyright 2020 INRIA * Copyright 2020 INRIA
*/ */
#ifndef __eigenpy_decomposition_eigen_solver_hpp__ #ifndef __eigenpy_decompositions_eigen_solver_hpp__
#define __eigenpy_decomposition_eigen_solver_hpp__ #define __eigenpy_decompositions_eigen_solver_hpp__
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/eigen-to-python.hpp"
#include <Eigen/Core> #include <Eigen/Core>
#include <Eigen/Eigenvalues> #include <Eigen/Eigenvalues>
#include "eigenpy/eigen-to-python.hpp"
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp" #include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy namespace eigenpy {
{
template <typename _MatrixType>
template<typename _MatrixType> struct EigenSolverVisitor
struct EigenSolverVisitor : public boost::python::def_visitor<EigenSolverVisitor<_MatrixType> > {
: public boost::python::def_visitor< EigenSolverVisitor<_MatrixType> > typedef _MatrixType MatrixType;
{ typedef typename MatrixType::Scalar Scalar;
typedef Eigen::EigenSolver<MatrixType> Solver;
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar; template <class PyClass>
typedef Eigen::EigenSolver<MatrixType> Solver; void visit(PyClass& cl) const {
cl.def(bp::init<>("Default constructor"))
template<class PyClass> .def(bp::init<Eigen::DenseIndex>(
void visit(PyClass& cl) const bp::arg("size"), "Default constructor with memory preallocation"))
{ .def(bp::init<MatrixType, bp::optional<bool> >(
namespace bp = boost::python; bp::args("matrix", "compute_eigen_vectors"),
cl "Computes eigendecomposition of given matrix"))
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"), .def("eigenvalues", &Solver::eigenvalues, bp::arg("self"),
"Default constructor with memory preallocation")) "Returns the eigenvalues of given matrix.",
.def(bp::init<MatrixType,bp::optional<bool> >(bp::args("matrix","compute_eigen_vectors"), bp::return_internal_reference<>())
"Computes eigendecomposition of given matrix")) .def("eigenvectors", &Solver::eigenvectors, bp::arg("self"),
"Returns the eigenvectors of given matrix.")
.def("eigenvalues",&Solver::eigenvalues,bp::arg("self"),
"Returns the eigenvalues of given matrix.", .def("compute", &EigenSolverVisitor::compute_proxy<MatrixType>,
bp::return_internal_reference<>()) bp::args("self", "matrix"),
.def("eigenvectors",&Solver::eigenvectors,bp::arg("self"), "Computes the eigendecomposition of given matrix.",
"Returns the eigenvectors of given matrix.") bp::return_self<>())
.def("compute",
.def("compute",&EigenSolverVisitor::compute_proxy<MatrixType>, (Solver &
bp::args("self","matrix"), (Solver::*)(const Eigen::EigenBase<MatrixType>& matrix, bool)) &
"Computes the eigendecomposition of given matrix.", Solver::compute,
bp::return_self<>()) bp::args("self", "matrix", "compute_eigen_vectors"),
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix, bool))&Solver::compute, "Computes the eigendecomposition of given matrix.",
bp::args("self","matrix","compute_eigen_vectors"), bp::return_self<>())
"Computes the eigendecomposition of given matrix.",
bp::return_self<>()) .def("getMaxIterations", &Solver::getMaxIterations, bp::arg("self"),
"Returns the maximum number of iterations.")
.def("getMaxIterations",&Solver::getMaxIterations,bp::arg("self"), .def("setMaxIterations", &Solver::setMaxIterations,
"Returns the maximum number of iterations.") bp::args("self", "max_iter"),
.def("setMaxIterations",&Solver::setMaxIterations,bp::args("self","max_iter"), "Sets the maximum number of iterations allowed.",
"Sets the maximum number of iterations allowed.", bp::return_self<>())
bp::return_self<>())
.def("pseudoEigenvalueMatrix", &Solver::pseudoEigenvalueMatrix,
.def("pseudoEigenvalueMatrix",&Solver::pseudoEigenvalueMatrix,bp::arg("self"), bp::arg("self"),
"Returns the block-diagonal matrix in the pseudo-eigendecomposition.") "Returns the block-diagonal matrix in the "
.def("pseudoEigenvectors",&Solver::pseudoEigenvectors ,bp::arg("self"), "pseudo-eigendecomposition.")
"Returns the pseudo-eigenvectors of given matrix.", .def("pseudoEigenvectors", &Solver::pseudoEigenvectors, bp::arg("self"),
bp::return_internal_reference<>()) "Returns the pseudo-eigenvectors of given matrix.",
bp::return_internal_reference<>())
.def("info",&Solver::info,bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.") .def("info", &Solver::info, bp::arg("self"),
; "NumericalIssue if the input contains INF or NaN values or "
} "overflow occured. Returns Success otherwise.");
}
static void expose()
{ static void expose() {
static const std::string classname = "EigenSolver" + scalar_name<Scalar>::shortname(); static const std::string classname =
expose(classname); "EigenSolver" + scalar_name<Scalar>::shortname();
} expose(classname);
}
static void expose(const std::string & name)
{ static void expose(const std::string& name) {
namespace bp = boost::python; bp::class_<Solver>(name.c_str(), bp::no_init)
bp::class_<Solver>(name.c_str(), .def(EigenSolverVisitor())
bp::no_init) .def(IdVisitor<Solver>());
.def(EigenSolverVisitor()); }
}
private:
private: template <typename MatrixType>
static Solver& compute_proxy(Solver& self,
template<typename MatrixType> const Eigen::EigenBase<MatrixType>& matrix) {
static Solver & compute_proxy(Solver & self, const Eigen::EigenBase<MatrixType> & matrix) return self.compute(matrix);
{ }
return self.compute(matrix); };
}
} // namespace eigenpy
};
} // 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__ #ifndef __eigenpy_decompositions_ldlt_hpp__
#define __eigenpy_decomposition_ldlt_hpp__ #define __eigenpy_decompositions_ldlt_hpp__
#include "eigenpy/eigenpy.hpp"
#include <Eigen/Core>
#include <Eigen/Cholesky> #include <Eigen/Cholesky>
#include <Eigen/Core>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp" #include "eigenpy/utils/scalar-name.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
namespace eigenpy {
template <typename _MatrixType>
struct LDLTSolverVisitor
: public boost::python::def_visitor<LDLTSolverVisitor<_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::LDLT<MatrixType> Solver;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
.def(bp::init<Eigen::DenseIndex>(
bp::args("self", "size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(
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"),
"Returns true if the matrix is positive (semidefinite).")
.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("vectorD", &vectorD, bp::arg("self"),
"Returns the coefficients of the diagonal matrix D.")
.def("transpositionsP", &transpositionsP, bp::arg("self"),
"Returns the permutation matrix P.")
.def("matrixLDLT", &Solver::matrixLDLT, bp::arg("self"),
"Returns the LDLT decomposition matrix.",
bp::return_internal_reference<>())
namespace eigenpy .def("rankUpdate",
{ (Solver & (Solver::*)(const Eigen::MatrixBase<VectorXs> &,
const RealScalar &)) &
template<typename _MatrixType> Solver::template rankUpdate<VectorXs>,
struct LDLTSolverVisitor bp::args("self", "vector", "sigma"), bp::return_self<>())
: public boost::python::def_visitor< LDLTSolverVisitor<_MatrixType> >
{ #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
.def("adjoint", &Solver::adjoint, bp::arg("self"),
typedef _MatrixType MatrixType; "Returns the adjoint, that is, a reference to the decomposition "
typedef typename MatrixType::Scalar Scalar; "itself as if the underlying matrix is self-adjoint.",
typedef typename MatrixType::RealScalar RealScalar; bp::return_self<>())
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,MatrixType::Options> VectorXs;
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic,MatrixType::Options> MatrixXs;
typedef Eigen::LDLT<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(bp::arg("matrix"),
"Constructs a LDLT factorization from a given matrix."))
.def("isNegative",&Solver::isNegative,bp::arg("self"),
"Returns true if the matrix is negative (semidefinite).")
.def("isPositive",&Solver::isPositive,bp::arg("self"),
"Returns true if the matrix is positive (semidefinite).")
.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("vectorD",&vectorD,bp::arg("self"),
"Returns the coefficients of the diagonal matrix D.")
.def("transpositionsP",&transpositionsP,bp::arg("self"),
"Returns the permutation matrix P.")
.def("matrixLDLT",&Solver::matrixLDLT,bp::arg("self"),
"Returns the LDLT decomposition matrix.",
bp::return_internal_reference<>())
.def("rankUpdate",(Solver & (Solver::*)(const Eigen::MatrixBase<VectorXs> &, const RealScalar &))&Solver::template rankUpdate<VectorXs>,
bp::args("self","vector","sigma"),
bp::return_self<>())
#if EIGEN_VERSION_AT_LEAST(3,3,0)
.def("adjoint",&Solver::adjoint,bp::arg("self"),
"Returns the adjoint, that is, a reference to the decomposition itself as if the underlying matrix is self-adjoint.",
bp::return_self<>())
#endif #endif
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute, .def(
bp::args("self","matrix"), "compute",
"Computes the LDLT of given matrix.", (Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
bp::return_self<>()) Solver::compute,
bp::args("self", "matrix"), "Computes the LDLT of given matrix.",
.def("info",&Solver::info,bp::arg("self"), bp::return_self<>())
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3,3,0) .def("info", &Solver::info, bp::arg("self"),
.def("rcond",&Solver::rcond,bp::arg("self"), "NumericalIssue if the input contains INF or NaN values or "
"Returns an estimate of the reciprocal condition number of the matrix.") "overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
.def("rcond", &Solver::rcond, bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the "
"matrix.")
#endif #endif
.def("reconstructedMatrix",&Solver::reconstructedMatrix,bp::arg("self"), .def("reconstructedMatrix", &Solver::reconstructedMatrix,
"Returns the matrix represented by the decomposition, i.e., it returns the product: L L^*. This function is provided for debug purpose.") bp::arg("self"),
.def("solve",&solve<VectorXs>,bp::args("self","b"), "Returns the matrix represented by the decomposition, i.e., it "
"Returns the solution x of A x = b using the current decomposition of A.") "returns the product: L L^*. This function is provided for debug "
.def("solve",&solve<MatrixXs>,bp::args("self","B"), "purpose.")
"Returns the solution X of A X = B using the current decomposition of A where B is a right hand side matrix.") .def("solve", &solve<VectorXs>, bp::args("self", "b"),
"Returns the solution x of A x = b using the current "
.def("setZero",&Solver::setZero,bp::arg("self"), "decomposition of A.")
"Clear any existing 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() .def("setZero", &Solver::setZero, bp::arg("self"),
{ "Clear any existing decomposition.");
static const std::string classname = "LDLT" + scalar_name<Scalar>::shortname(); }
expose(classname);
} static void expose() {
static const std::string classname =
static void expose(const std::string & name) "LDLT" + scalar_name<Scalar>::shortname();
{ expose(classname);
namespace bp = boost::python; }
bp::class_<Solver>(name.c_str(),
"Robust Cholesky decomposition of a matrix with pivoting.\n\n" static void expose(const std::string &name) {
"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" bp::class_<Solver>(
"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.", name.c_str(),
bp::no_init) "Robust Cholesky decomposition of a matrix with pivoting.\n\n"
.def(LDLTSolverVisitor()); "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 "
private: "and D is a diagonal matrix.\n\n"
"The decomposition uses pivoting to ensure stability, so that L will "
static MatrixType matrixL(const Solver & self) { return self.matrixL(); } "have zeros in the bottom right rank(A) - n submatrix. Avoiding the "
static MatrixType matrixU(const Solver & self) { return self.matrixU(); } "square root on D also stabilizes the computation.",
static VectorXs vectorD(const Solver & self) { return self.vectorD(); } bp::no_init)
.def(IdVisitor<Solver>())
static MatrixType transpositionsP(const Solver & self) .def(LDLTSolverVisitor());
{ }
return self.transpositionsP() * MatrixType::Identity(self.matrixL().rows(),
self.matrixL().rows()); private:
} static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
static MatrixType matrixU(const Solver &self) { return self.matrixU(); }
template<typename MatrixOrVector> static VectorXs vectorD(const Solver &self) { return self.vectorD(); }
static MatrixOrVector solve(const Solver & self, const MatrixOrVector & vec)
{ static MatrixType transpositionsP(const Solver &self) {
return self.solve(vec); return self.transpositionsP() *
} MatrixType::Identity(self.matrixL().rows(), self.matrixL().rows());
}; }
} // namespace eigenpy template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
#endif // ifndef __eigenpy_decomposition_ldlt_hpp__ return self.solve(vec);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_ldlt_hpp__
/* /*
* Copyright 2020-2021 INRIA * Copyright 2020-2024 INRIA
*/ */
#ifndef __eigenpy_decomposition_llt_hpp__ #ifndef __eigenpy_decompositions_llt_hpp__
#define __eigenpy_decomposition_llt_hpp__ #define __eigenpy_decompositions_llt_hpp__
#include "eigenpy/eigenpy.hpp"
#include <Eigen/Core>
#include <Eigen/Cholesky> #include <Eigen/Cholesky>
#include <Eigen/Core>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp" #include "eigenpy/utils/scalar-name.hpp"
#include "eigenpy/eigen/EigenBase.hpp"
namespace eigenpy {
template <typename _MatrixType>
struct LLTSolverVisitor
: public boost::python::def_visitor<LLTSolverVisitor<_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::LLT<MatrixType> Solver;
template <class PyClass>
void visit(PyClass &cl) const {
cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
.def(bp::init<Eigen::DenseIndex>(
bp::args("self", "size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(
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"),
"Returns the upper triangular matrix U.")
.def("matrixLLT", &Solver::matrixLLT, bp::arg("self"),
"Returns the LLT decomposition matrix.",
bp::return_internal_reference<>())
namespace eigenpy #if EIGEN_VERSION_AT_LEAST(3, 3, 90)
{ .def("rankUpdate",
(Solver & (Solver::*)(const VectorXs &, const RealScalar &)) &
template<typename _MatrixType> Solver::template rankUpdate<VectorXs>,
struct LLTSolverVisitor bp::args("self", "vector", "sigma"), bp::return_self<>())
: public boost::python::def_visitor< LLTSolverVisitor<_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::LLT<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(bp::arg("matrix"),
"Constructs a LLT factorization from a given matrix."))
.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("matrixLLT",&Solver::matrixLLT,bp::arg("self"),
"Returns the LLT decomposition matrix.",
bp::return_internal_reference<>())
#if EIGEN_VERSION_AT_LEAST(3,3,90)
.def("rankUpdate",(Solver& (Solver::*)(const VectorXs &, const RealScalar &))&Solver::template rankUpdate<VectorXs>,
bp::args("self","vector","sigma"), bp::return_self<>())
#else #else
.def("rankUpdate",(Solver (Solver::*)(const VectorXs &, const RealScalar &))&Solver::template rankUpdate<VectorXs>, .def("rankUpdate",
bp::args("self","vector","sigma")) (Solver(Solver::*)(
const VectorXs &,
const RealScalar &))&Solver::template rankUpdate<VectorXs>,
bp::args("self", "vector", "sigma"))
#endif #endif
#if EIGEN_VERSION_AT_LEAST(3,3,0) #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
.def("adjoint",&Solver::adjoint,bp::arg("self"), .def("adjoint", &Solver::adjoint, bp::arg("self"),
"Returns the adjoint, that is, a reference to the decomposition itself as if the underlying matrix is self-adjoint.", "Returns the adjoint, that is, a reference to the decomposition "
bp::return_self<>()) "itself as if the underlying matrix is self-adjoint.",
bp::return_self<>())
#endif #endif
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute, .def(
bp::args("self","matrix"), "compute",
"Computes the LLT of given matrix.", (Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
bp::return_self<>()) Solver::compute,
bp::args("self", "matrix"), "Computes the LLT of given matrix.",
.def("info",&Solver::info,bp::arg("self"), bp::return_self<>())
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3,3,0) .def("info", &Solver::info, bp::arg("self"),
.def("rcond",&Solver::rcond,bp::arg("self"), "NumericalIssue if the input contains INF or NaN values or "
"Returns an estimate of the reciprocal condition number of the matrix.") "overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
.def("rcond", &Solver::rcond, bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the "
"matrix.")
#endif #endif
.def("reconstructedMatrix",&Solver::reconstructedMatrix,bp::arg("self"), .def("reconstructedMatrix", &Solver::reconstructedMatrix,
"Returns the matrix represented by the decomposition, i.e., it returns the product: L L^*. This function is provided for debug purpose.") bp::arg("self"),
.def("solve",&solve<VectorXs>,bp::args("self","b"), "Returns the matrix represented by the decomposition, i.e., it "
"Returns the solution x of A x = b using the current decomposition of A.") "returns the product: L L^*. This function is provided for debug "
.def("solve",&solve<MatrixXs>,bp::args("self","B"), "purpose.")
"Returns the solution X of A X = B using the current decomposition of A where B is a right hand side matrix.") .def("solve", &solve<VectorXs>, bp::args("self", "b"),
; "Returns the solution x of A x = b using the current "
} "decomposition of A.")
.def("solve", &solve<MatrixXs>, bp::args("self", "B"),
static void expose() "Returns the solution X of A X = B using the current "
{ "decomposition of A where B is a right hand side matrix.");
static const std::string classname = "LLT" + scalar_name<Scalar>::shortname(); }
expose(classname);
} static void expose() {
static const std::string classname =
static void expose(const std::string & name) "LLT" + scalar_name<Scalar>::shortname();
{ expose(classname);
namespace bp = boost::python; }
bp::class_<Solver>(name.c_str(),
"Standard Cholesky decomposition (LL^T) of a matrix and associated features.\n\n" static void expose(const std::string &name) {
"This class performs a LL^T Cholesky decomposition of a symmetric, positive definite matrix A such that A = LL^* = U^*U, where L is lower triangular.\n\n" bp::class_<Solver>(
"While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b, for that purpose, we recommend the Cholesky decomposition without square root which is more stable and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other situations like generalised eigen problems with hermitian matrices.", name.c_str(),
bp::no_init) "Standard Cholesky decomposition (LL^T) of a matrix and associated "
.def(LLTSolverVisitor()); "features.\n\n"
} "This class performs a LL^T Cholesky decomposition of a symmetric, "
"positive definite matrix A such that A = LL^* = U^*U, where L is "
private: "lower triangular.\n\n"
"While the Cholesky decomposition is particularly useful to solve "
static MatrixType matrixL(const Solver & self) { return self.matrixL(); } "selfadjoint problems like D^*D x = b, for that purpose, we recommend "
static MatrixType matrixU(const Solver & self) { return self.matrixU(); } "the Cholesky decomposition without square root which is more stable "
"and even faster. Nevertheless, this standard Cholesky decomposition "
template<typename MatrixOrVector> "remains useful in many other situations like generalised eigen "
static MatrixOrVector solve(const Solver & self, const MatrixOrVector & vec) "problems with hermitian matrices.",
{ bp::no_init)
return self.solve(vec); .def(IdVisitor<Solver>())
} .def(LLTSolverVisitor());
}; }
} // namespace eigenpy private:
static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
#endif // ifndef __eigenpy_decomposition_llt_hpp__ static MatrixType matrixU(const Solver &self) { return self.matrixU(); }
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
};
} // namespace eigenpy
#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__