smooth
A C++ library for Lie theory
Loading...
Searching...
No Matches
tr_solver.hpp
Go to the documentation of this file.
1// Copyright (C) 2023 Petter Nilsson. MIT License.
2
3#pragma once
4
10#include <optional>
11#include <utility>
12
13#include <Eigen/Cholesky>
14#include <Eigen/Sparse>
15#include <Eigen/SparseCholesky>
16
17#include "smooth/version.hpp"
18
19SMOOTH_BEGIN_NAMESPACE
20
47template<typename D2, typename D3>
49 const auto & J,
50 const Eigen::MatrixBase<D2> & d,
51 const Eigen::MatrixBase<D3> & r,
52 const double lambda,
53 std::optional<std::reference_wrapper<double>> dphi = {})
54 -> Eigen::Vector<typename std::decay_t<decltype(J)>::Scalar, std::decay_t<decltype(J)>::ColsAtCompileTime>
55{
56 using JType = std::decay_t<decltype(J)>;
57 using Scalar = typename JType::Scalar;
58 static constexpr auto N = JType::ColsAtCompileTime; // num variables
59
60 static constexpr bool is_sparse = std::is_base_of_v<Eigen::SparseMatrixBase<JType>, JType>;
61
62 using Ht = std::
63 conditional_t<is_sparse, Eigen::SparseMatrix<typename JType::Scalar>, Eigen::Matrix<typename JType::Scalar, N, N>>;
64
65 using LDLTt = std::conditional_t<is_sparse, Eigen::SimplicialLDLT<Ht>, Eigen::LDLT<Ht>>;
66
67 Ht H = J.transpose() * J;
68 for (auto i = 0u; i < H.rows(); ++i) { H.coeffRef(i, i) += lambda * d(i) * d(i); }
69
70 const LDLTt ldlt(H);
71 const Eigen::Vector<Scalar, N> x = ldlt.solve(-J.transpose() * r);
72
73 if (dphi.has_value()) {
74 const Eigen::Vector<Scalar, N> Dx = -d.cwiseProduct(x);
75 const Eigen::Vector<Scalar, N> d_q = d.cwiseProduct(Dx);
76 const Eigen::Vector<Scalar, N> y = ldlt.solve(d_q);
77 dphi->get() = -d.cwiseProduct(Dx.normalized()).dot(y);
78 }
79
80 return x;
81}
82
131template<typename D2, typename D3>
133 const auto & J, const Eigen::MatrixBase<D2> & d, const Eigen::MatrixBase<D3> & r, const double Delta) -> std::
134 pair<Eigen::Vector<typename std::decay_t<decltype(J)>::Scalar, std::decay_t<decltype(J)>::ColsAtCompileTime>, double>
135{
136 const double lambda = 1. / Delta;
137
138 const auto dx = solve_linear_ldlt(J, d, r, lambda);
139
140 return {dx, lambda};
141}
142
143SMOOTH_END_NAMESPACE
typename traits::man< M >::Scalar Scalar
Manifold scalar type.
Definition manifold.hpp:88
SMOOTH_BEGIN_NAMESPACE auto solve_linear_ldlt(const auto &J, const Eigen::MatrixBase< D2 > &d, const Eigen::MatrixBase< D3 > &r, const double lambda, std::optional< std::reference_wrapper< double > > dphi={}) -> Eigen::Vector< typename std::decay_t< decltype(J)>::Scalar, std::decay_t< decltype(J)>::ColsAtCompileTime >
Solve least-squares problem using LDL' decomposition.
Definition tr_solver.hpp:48
auto solve_trust_region(const auto &J, const Eigen::MatrixBase< D2 > &d, const Eigen::MatrixBase< D3 > &r, const double Delta) -> std::pair< Eigen::Vector< typename std::decay_t< decltype(J)>::Scalar, std::decay_t< decltype(J)>::ColsAtCompileTime >, double >
Approximately solve trust-region step determination problem.