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 1963 additions and 125 deletions
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-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2014-2023 CNRS INRIA
*/
#ifndef __eigenpy_angle_axis_hpp__
#define __eigenpy_angle_axis_hpp__
#include "eigenpy/fwd.hpp"
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Geometry>
namespace eigenpy
{
namespace bp = boost::python;
template<typename AngleAxis> class AngleAxisVisitor;
namespace internal
{
template<typename Scalar>
struct call_expose< Eigen::AngleAxis<Scalar> >
{
typedef Eigen::AngleAxis<Scalar> type;
static inline void run()
{
AngleAxisVisitor<type>::expose();
}
};
} // namespace internal
template<typename AngleAxis>
class AngleAxisVisitor
: public bp::def_visitor< AngleAxisVisitor<AngleAxis> >
{
typedef typename AngleAxis::Scalar Scalar;
typedef typename AngleAxis::Vector3 Vector3;
typedef typename AngleAxis::Matrix3 Matrix3;
typedef typename Eigen::Quaternion<Scalar,0> Quaternion;
public:
template<class PyClass>
void visit(PyClass& cl) const
{
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Scalar,Vector3>
((bp::arg("angle"),bp::arg("axis")),
"Initialize from angle and axis."))
.def(bp::init<Matrix3>
((bp::arg("rotationMatrix")),
"Initialize from a rotation matrix"))
.def(bp::init<Quaternion>(bp::arg("quaternion"),"Initialize from a quaternion."))
.def(bp::init<AngleAxis>(bp::arg("copy"),"Copy constructor."))
/* --- Properties --- */
.add_property("axis",
bp::make_function((const Vector3 & (AngleAxis::*)()const)&AngleAxis::axis,
bp::return_value_policy<bp::copy_const_reference>()),
&AngleAxisVisitor::setAxis,"The rotation axis.")
.add_property("angle",
(Scalar (AngleAxis::*)()const)&AngleAxis::angle,
&AngleAxisVisitor::setAngle,"The rotation angle.")
/* --- Methods --- */
.def("inverse",&AngleAxis::inverse,"Return the inverse rotation.")
.def("fromRotationMatrix",&AngleAxis::template fromRotationMatrix<Matrix3>,
bp::arg("Sets *this from a 3x3 rotation matrix."),bp::return_self<>())
.def("toRotationMatrix",&AngleAxis::toRotationMatrix,"Constructs and returns an equivalent 3x3 rotation matrix.")
.def("matrix",&AngleAxis::matrix,"Returns an equivalent rotation matrix.")
.def("isApprox",(bool (AngleAxis::*)(const AngleAxis &))&AngleAxis::isApprox,
"Returns true if *this is approximately equal to other.")
.def("isApprox",(bool (AngleAxis::*)(const AngleAxis &, const Scalar prec))&AngleAxis::isApprox,
bp::args("other","prec"),
"Returns true if *this is approximately equal to other, within the precision determined by prec.")
/* --- Operators --- */
.def(bp::self * bp::other<Vector3>())
.def(bp::self * bp::other<Quaternion>())
.def(bp::self * bp::self)
.def("__eq__",&AngleAxisVisitor::__eq__)
.def("__ne__",&AngleAxisVisitor::__ne__)
.def("__str__",&print)
.def("__repr__",&print)
;
}
private:
static void setAxis(AngleAxis & self, const Vector3 & axis)
{ self.axis() = axis; }
static void setAngle( AngleAxis & self, const Scalar & angle)
{ self.angle() = angle; }
static bool __eq__(const AngleAxis & u, const AngleAxis & v)
{ return u.isApprox(v); }
static bool __ne__(const AngleAxis & u, const AngleAxis & v)
{ return !__eq__(u,v); }
static std::string print(const AngleAxis & self)
{
std::stringstream ss;
ss << "angle: " << self.angle() << std::endl;
ss << "axis: " << self.axis().transpose() << std::endl;
return ss.str();
}
public:
static void expose()
{
bp::class_<AngleAxis>("AngleAxis",
"AngleAxis representation of rotations.\n\n",
bp::no_init)
.def(AngleAxisVisitor<AngleAxis>());
}
};
} // namespace eigenpy
#endif //ifndef __eigenpy_angle_axis_hpp__
#include "eigenpy/eigenpy.hpp"
namespace eigenpy {
template <typename AngleAxis>
class AngleAxisVisitor;
template <typename Scalar>
struct call<Eigen::AngleAxis<Scalar> > {
typedef Eigen::AngleAxis<Scalar> AngleAxis;
static inline void expose() { AngleAxisVisitor<AngleAxis>::expose(); }
static inline bool isApprox(
const AngleAxis& self, const AngleAxis& other,
const Scalar& prec = Eigen::NumTraits<Scalar>::dummy_precision()) {
return self.isApprox(other, prec);
}
};
template <typename AngleAxis>
class AngleAxisVisitor : public bp::def_visitor<AngleAxisVisitor<AngleAxis> > {
typedef typename AngleAxis::Scalar Scalar;
typedef typename AngleAxis::Vector3 Vector3;
typedef typename AngleAxis::Matrix3 Matrix3;
typedef typename Eigen::Quaternion<Scalar, 0> Quaternion;
typedef Eigen::RotationBase<AngleAxis, 3> RotationBase;
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,
call<AngleAxis>::isApprox, 2, 3)
public:
template <class PyClass>
void visit(PyClass& cl) const {
cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
.def(bp::init<Scalar, Vector3>(bp::args("self", "angle", "axis"),
"Initialize from angle and axis."))
.def(bp::init<Matrix3>(bp::args("self", "R"),
"Initialize from a rotation matrix"))
.def(bp::init<Quaternion>(bp::args("self", "quaternion"),
"Initialize from a quaternion."))
.def(bp::init<AngleAxis>(bp::args("self", "copy"), "Copy constructor."))
/* --- Properties --- */
.add_property(
"axis",
bp::make_function((Vector3 & (AngleAxis::*)()) & AngleAxis::axis,
bp::return_internal_reference<>()),
&AngleAxisVisitor::setAxis, "The rotation axis.")
.add_property("angle", (Scalar(AngleAxis::*)() const)&AngleAxis::angle,
&AngleAxisVisitor::setAngle, "The rotation angle.")
/* --- Methods --- */
.def("inverse", &AngleAxis::inverse, bp::arg("self"),
"Return the inverse rotation.")
.def("fromRotationMatrix",
&AngleAxis::template fromRotationMatrix<Matrix3>,
(bp::arg("self"), bp::arg("rotation matrix")),
"Sets *this from a 3x3 rotation matrix", bp::return_self<>())
.def("toRotationMatrix", &AngleAxis::toRotationMatrix,
// bp::arg("self"),
"Constructs and returns an equivalent rotation matrix.")
.def("matrix", &AngleAxis::matrix, bp::arg("self"),
"Returns an equivalent rotation matrix.")
.def("isApprox", &call<AngleAxis>::isApprox,
isApproxAngleAxis_overload(
bp::args("self", "other", "prec"),
"Returns true if *this is approximately equal to other, "
"within the precision determined by prec."))
/* --- Operators --- */
.def(bp::self * bp::other<Vector3>())
.def(bp::self * bp::other<Quaternion>())
.def(bp::self * bp::self)
.def("__eq__", &AngleAxisVisitor::__eq__)
.def("__ne__", &AngleAxisVisitor::__ne__)
.def("__str__", &print)
.def("__repr__", &print);
}
private:
static void setAxis(AngleAxis& self, const Vector3& axis) {
self.axis() = axis;
}
static void setAngle(AngleAxis& self, const Scalar& angle) {
self.angle() = angle;
}
static bool __eq__(const AngleAxis& u, const AngleAxis& v) {
return u.axis() == v.axis() && v.angle() == u.angle();
}
static bool __ne__(const AngleAxis& u, const AngleAxis& v) {
return !__eq__(u, v);
}
static std::string print(const AngleAxis& self) {
std::stringstream ss;
ss << "angle: " << self.angle() << std::endl;
ss << "axis: " << self.axis().transpose() << std::endl;
return ss.str();
}
public:
static void expose() {
bp::class_<AngleAxis>(
"AngleAxis", "AngleAxis representation of a rotation.\n\n", bp::no_init)
.def(AngleAxisVisitor<AngleAxis>())
.def(IdVisitor<AngleAxis>());
// Cast to Eigen::RotationBase
bp::implicitly_convertible<AngleAxis, RotationBase>();
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_angle_axis_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decompositions_computation_info_hpp__
#define __eigenpy_decompositions_computation_info_hpp__
#include "eigenpy/fwd.hpp"
namespace eigenpy {
inline void exposeComputationInfo() {
boost::python::enum_<Eigen::ComputationInfo>("ComputationInfo")
.value("Success", Eigen::Success)
.value("NumericalIssue", Eigen::NumericalIssue)
.value("NoConvergence", Eigen::NoConvergence)
.value("InvalidInput", Eigen::InvalidInput);
}
} // namespace eigenpy
#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__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decompositions_eigen_solver_hpp__
#define __eigenpy_decompositions_eigen_solver_hpp__
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include "eigenpy/eigen-to-python.hpp"
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy {
template <typename _MatrixType>
struct EigenSolverVisitor
: public boost::python::def_visitor<EigenSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef Eigen::EigenSolver<MatrixType> Solver;
template <class PyClass>
void visit(PyClass& cl) const {
cl.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(
bp::arg("size"), "Default constructor with memory preallocation"))
.def(bp::init<MatrixType, bp::optional<bool> >(
bp::args("matrix", "compute_eigen_vectors"),
"Computes eigendecomposition of given matrix"))
.def("eigenvalues", &Solver::eigenvalues, bp::arg("self"),
"Returns the eigenvalues of given matrix.",
bp::return_internal_reference<>())
.def("eigenvectors", &Solver::eigenvectors, bp::arg("self"),
"Returns the eigenvectors of given matrix.")
.def("compute", &EigenSolverVisitor::compute_proxy<MatrixType>,
bp::args("self", "matrix"),
"Computes the eigendecomposition of given matrix.",
bp::return_self<>())
.def("compute",
(Solver &
(Solver::*)(const Eigen::EigenBase<MatrixType>& matrix, bool)) &
Solver::compute,
bp::args("self", "matrix", "compute_eigen_vectors"),
"Computes the eigendecomposition of given matrix.",
bp::return_self<>())
.def("getMaxIterations", &Solver::getMaxIterations, bp::arg("self"),
"Returns the maximum number of iterations.")
.def("setMaxIterations", &Solver::setMaxIterations,
bp::args("self", "max_iter"),
"Sets the maximum number of iterations allowed.",
bp::return_self<>())
.def("pseudoEigenvalueMatrix", &Solver::pseudoEigenvalueMatrix,
bp::arg("self"),
"Returns the block-diagonal matrix in the "
"pseudo-eigendecomposition.")
.def("pseudoEigenvectors", &Solver::pseudoEigenvectors, bp::arg("self"),
"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.");
}
static void expose() {
static const std::string classname =
"EigenSolver" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(EigenSolverVisitor())
.def(IdVisitor<Solver>());
}
private:
template <typename MatrixType>
static Solver& compute_proxy(Solver& self,
const Eigen::EigenBase<MatrixType>& matrix) {
return self.compute(matrix);
}
};
} // namespace eigenpy
#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-2024 INRIA
*/
#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 {
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<>())
.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
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"), "Computes the LDLT of given matrix.",
bp::return_self<>())
.def("info", &Solver::info, bp::arg("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("rcond", &Solver::rcond, bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the "
"matrix.")
#endif
.def("reconstructedMatrix", &Solver::reconstructedMatrix,
bp::arg("self"),
"Returns the matrix represented by the decomposition, i.e., it "
"returns the product: L L^*. This function is provided for debug "
"purpose.")
.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"),
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.")
.def("setZero", &Solver::setZero, bp::arg("self"),
"Clear any existing decomposition.");
}
static void expose() {
static const std::string classname =
"LDLT" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"Robust Cholesky decomposition of a matrix with pivoting.\n\n"
"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"
"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.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LDLTSolverVisitor());
}
private:
static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
static MatrixType matrixU(const Solver &self) { return self.matrixU(); }
static VectorXs vectorD(const Solver &self) { return self.vectorD(); }
static MatrixType transpositionsP(const Solver &self) {
return self.transpositionsP() *
MatrixType::Identity(self.matrixL().rows(), self.matrixL().rows());
}
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
return self.solve(vec);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_ldlt_hpp__
/*
* Copyright 2020-2024 INRIA
*/
#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 {
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<>())
#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
.def("rankUpdate",
(Solver(Solver::*)(
const VectorXs &,
const RealScalar &))&Solver::template rankUpdate<VectorXs>,
bp::args("self", "vector", "sigma"))
#endif
#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
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> &matrix)) &
Solver::compute,
bp::args("self", "matrix"), "Computes the LLT of given matrix.",
bp::return_self<>())
.def("info", &Solver::info, bp::arg("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("rcond", &Solver::rcond, bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the "
"matrix.")
#endif
.def("reconstructedMatrix", &Solver::reconstructedMatrix,
bp::arg("self"),
"Returns the matrix represented by the decomposition, i.e., it "
"returns the product: L L^*. This function is provided for debug "
"purpose.")
.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"),
"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 =
"LLT" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string &name) {
bp::class_<Solver>(
name.c_str(),
"Standard Cholesky decomposition (LL^T) of a matrix and associated "
"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 "
"lower triangular.\n\n"
"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.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LLTSolverVisitor());
}
private:
static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
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__
/*
* Copyright 2020-2024 INRIA
*/
#ifndef __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
#define __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include "eigenpy/eigen-to-python.hpp"
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy {
template <typename _MatrixType>
struct SelfAdjointEigenSolverVisitor
: public boost::python::def_visitor<
SelfAdjointEigenSolverVisitor<_MatrixType> > {
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef Eigen::SelfAdjointEigenSolver<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::optional<int> >(
bp::args("self", "matrix", "options"),
"Computes eigendecomposition of given matrix"))
.def("eigenvalues", &Solver::eigenvalues, bp::arg("self"),
"Returns the eigenvalues of given matrix.",
bp::return_internal_reference<>())
.def("eigenvectors", &Solver::eigenvectors, bp::arg("self"),
"Returns the eigenvectors of given matrix.",
bp::return_internal_reference<>())
.def("compute",
&SelfAdjointEigenSolverVisitor::compute_proxy<MatrixType>,
bp::args("self", "matrix"),
"Computes the eigendecomposition of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType>& matrix,
int options)) &
Solver::compute,
bp::args("self", "matrix", "options"),
"Computes the eigendecomposition of given matrix.",
bp::return_self<>())
.def("computeDirect",
&SelfAdjointEigenSolverVisitor::computeDirect_proxy,
bp::args("self", "matrix"),
"Computes eigendecomposition of given matrix using a closed-form "
"algorithm.",
bp::return_self<>())
.def("computeDirect",
(Solver & (Solver::*)(const MatrixType& matrix, int options)) &
Solver::computeDirect,
bp::args("self", "matrix", "options"),
"Computes eigendecomposition of given matrix using a closed-form "
"algorithm.",
bp::return_self<>())
.def("operatorInverseSqrt", &Solver::operatorInverseSqrt,
bp::arg("self"), "Computes the inverse square root of the matrix.")
.def("operatorSqrt", &Solver::operatorSqrt, bp::arg("self"),
"Computes the inverse square root of the matrix.")
.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 const std::string classname =
"SelfAdjointEigenSolver" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(IdVisitor<Solver>())
.def(SelfAdjointEigenSolverVisitor());
}
private:
template <typename MatrixType>
static Solver& compute_proxy(Solver& self,
const Eigen::EigenBase<MatrixType>& matrix) {
return self.compute(matrix);
}
static Solver& computeDirect_proxy(Solver& self, const MatrixType& matrix) {
return self.computeDirect(matrix);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decompositions_self_adjoint_eigen_solver_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decompositions_decompositions_hpp__
#define __eigenpy_decompositions_decompositions_hpp__
#include "eigenpy/config.hpp"
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__
/*
* Copyright 2021 INRIA
*/
#ifndef __eigenpy_decompositions_minres_hpp__
#define __eigenpy_decompositions_minres_hpp__
#include <Eigen/Core>
#include <iostream>
#include <unsupported/Eigen/IterativeSolvers>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy {
template <typename _Solver>
struct IterativeSolverBaseVisitor
: public boost::python::def_visitor<IterativeSolverBaseVisitor<_Solver> > {
typedef _Solver Solver;
typedef typename Solver::MatrixType MatrixType;
typedef typename Solver::Preconditioner Preconditioner;
typedef typename Solver::Scalar Scalar;
typedef typename Solver::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
MatrixType::Options>
MatrixXs;
template <class PyClass>
void visit(PyClass& cl) const {
cl.def("analyzePattern",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType>& matrix)) &
Solver::analyzePattern,
bp::args("self", "A"),
"Initializes the iterative solver for the sparsity pattern of the "
"matrix A for further solving Ax=b problems.",
bp::return_self<>())
.def(
"factorize",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType>& matrix)) &
Solver::factorize,
bp::args("self", "A"),
"Initializes the iterative solver with the numerical values of the "
"matrix A for further solving Ax=b problems.",
bp::return_self<>())
.def(
"compute",
(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType>& matrix)) &
Solver::compute,
bp::args("self", "A"),
"Initializes the iterative solver with the matrix A for further "
"solving Ax=b problems.",
bp::return_self<>())
.def("rows", &Solver::rows, bp::arg("self"),
"Returns the number of rows.")
.def("cols", &Solver::cols, bp::arg("self"),
"Returns the number of columns.")
.def("tolerance", &Solver::tolerance, bp::arg("self"),
"Returns the tolerance threshold used by the stopping criteria.")
.def("setTolerance", &Solver::setTolerance,
bp::args("self", "tolerance"),
"Sets the tolerance threshold used by the stopping criteria.\n"
"This value is used as an upper bound to the relative residual "
"error: |Ax-b|/|b|.\n"
"The default value is the machine precision given by "
"NumTraits<Scalar>::epsilon().",
bp::return_self<>())
.def("preconditioner",
(Preconditioner & (Solver::*)()) & Solver::preconditioner,
bp::arg("self"),
"Returns a read-write reference to the preconditioner for custom "
"configuration.",
bp::return_internal_reference<>())
.def("maxIterations", &Solver::maxIterations, bp::arg("self"),
"Returns the max number of iterations.\n"
"It is either the value setted by setMaxIterations or, by "
"default, twice the number of columns of the matrix.")
.def("setMaxIterations", &Solver::setMaxIterations,
bp::args("self", "max_iterations"),
"Sets the max number of iterations.\n"
"Default is twice the number of columns of the matrix.",
bp::return_self<>())
.def(
"iterations", &Solver::iterations, bp::arg("self"),
"Returns the number of iterations performed during the last solve.")
.def("error", &Solver::error, bp::arg("self"),
"Returns the tolerance error reached during the last solve.\n"
"It is a close approximation of the true relative residual error "
"|Ax-b|/|b|.")
.def("info", &Solver::error, bp::arg("info"),
"Returns Success if the iterations converged, and NoConvergence "
"otherwise.")
.def("solveWithGuess", &solveWithGuess<MatrixXs, MatrixXs>,
bp::args("self", "b", "x0"),
"Returns the solution x of A x = b using the current "
"decomposition of A and x0 as an initial solution.")
.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 or vector.");
}
private:
template <typename MatrixOrVector1, typename MatrixOrVector2>
static MatrixOrVector1 solveWithGuess(const Solver& self,
const MatrixOrVector1& b,
const MatrixOrVector2& guess) {
return self.solveWithGuess(b, guess);
}
template <typename MatrixOrVector>
static MatrixOrVector solve(const Solver& self,
const MatrixOrVector& mat_or_vec) {
MatrixOrVector res = self.solve(mat_or_vec);
return res;
}
};
template <typename _MatrixType>
struct MINRESSolverVisitor
: public boost::python::def_visitor<MINRESSolverVisitor<_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::MINRES<MatrixType> Solver;
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"),
"Initialize the solver with matrix A for further Ax=b solving.\n"
"This constructor is a shortcut for the default constructor "
"followed by a call to compute()."))
.def(IterativeSolverBaseVisitor<Solver>());
}
static void expose() {
static const std::string classname =
"MINRES" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string& name) {
bp::class_<Solver, boost::noncopyable>(
name.c_str(),
"A minimal residual solver for sparse symmetric problems.\n"
"This class allows to solve for A.x = b sparse linear problems using "
"the MINRES algorithm of Paige and Saunders (1975). The sparse matrix "
"A must be symmetric (possibly indefinite). The vectors x and b can be "
"either dense or sparse.\n"
"The maximal number of iterations and tolerance value can be "
"controlled via the setMaxIterations() and setTolerance() methods. The "
"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(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_minres_hpp__