smooth_feedback
Control and estimation on Lie groups
Loading...
Searching...
No Matches
sparse.hpp
Go to the documentation of this file.
1// Copyright (C) 2022 Petter Nilsson. MIT License.
2
3#pragma once
4
10#include <numeric>
11#include <optional>
12
13#include <Eigen/Sparse>
14
15namespace smooth::feedback {
16
33template<typename Source, int Options>
34 requires(std::is_base_of_v<Eigen::EigenBase<Source>, Source>)
35inline void block_add(
36 Eigen::SparseMatrix<double, Options> & dest,
37 Eigen::Index row0,
38 Eigen::Index col0,
39 const Source & source,
40 double scale = 1,
41 bool upper_only = false)
42{
43 for (auto c = 0; c < source.outerSize(); ++c) {
44 for (Eigen::InnerIterator it(source, c); it; ++it) {
45 if (!upper_only || row0 + it.row() <= col0 + it.col()) {
46 dest.coeffRef(row0 + it.row(), col0 + it.col()) += scale * it.value();
47 }
48 }
49 }
50}
51
68template<typename Source, int Options>
69 requires(std::is_base_of_v<Eigen::EigenBase<Source>, Source>)
70inline void block_write(
71 Eigen::SparseMatrix<double, Options> & dest,
72 Eigen::Index row0,
73 Eigen::Index col0,
74 const Source & source,
75 double scale = 1,
76 bool upper_only = false)
77{
78 for (auto c = 0; c < source.outerSize(); ++c) {
79 for (Eigen::InnerIterator it(source, c); it; ++it) {
80 if (!upper_only || row0 + it.row() <= col0 + it.col()) {
81 dest.coeffRef(row0 + it.row(), col0 + it.col()) = scale * it.value();
82 }
83 }
84 }
85}
86
102template<int Options>
104 Eigen::SparseMatrix<double, Options> & dest, Eigen::Index row0, Eigen::Index col0, Eigen::Index n, double scale = 1)
105{
106 for (auto k = 0u; k < n; ++k) { dest.coeffRef(row0 + k, col0 + k) += scale; }
107}
108
124template<int Options>
126 Eigen::SparseMatrix<double, Options> & dest, Eigen::Index row0, Eigen::Index col0, Eigen::Index n, double scale = 1)
127{
128 for (auto k = 0u; k < n; ++k) { dest.coeffRef(row0 + k, col0 + k) = scale; }
129}
130
138template<typename SparseMat>
139 requires(std::is_base_of_v<Eigen::SparseCompressedBase<std::decay_t<SparseMat>>, std::decay_t<SparseMat>>)
140inline void set_zero(SparseMat && mat)
141{
142 if (mat.isCompressed()) {
143 mat.coeffs().setZero();
144 } else {
145 for (auto i = 0; i < mat.outerSize(); ++i) {
146 for (typename std::decay_t<decltype(mat)>::InnerIterator it(mat, i); it; ++it) { it.valueRef() = 0; }
147 }
148 }
149}
150
156template<typename Mat>
157 requires(std::is_base_of_v<Eigen::EigenBase<Mat>, Mat>)
158uint64_t count_explicit_zeros(const Mat & mat)
159{
160 uint64_t ret = 0;
161 for (auto c = 0; c < mat.outerSize(); ++c) {
162 for (Eigen::InnerIterator it(mat, c); it; ++it) {
163 if (it.value() == 0) { ++ret; }
164 }
165 }
166 return ret;
167}
168
179template<typename Mat>
180 requires(std::is_base_of_v<Eigen::EigenBase<Mat>, Mat>)
181Eigen::MatrixX<typename Mat::Scalar> mark_explicit_zeros(const Mat & mat)
182{
183 Eigen::MatrixX<typename Mat::Scalar> ret;
184 ret.setConstant(mat.rows(), mat.cols(), 0);
185 for (auto c = 0; c < mat.outerSize(); ++c) {
186 for (Eigen::InnerIterator it(mat, c); it; ++it) {
187 if (it.value() == 0) {
188 ret(it.row(), it.col()) = 9;
189 } else {
190 ret(it.row(), it.col()) = 1;
191 }
192 }
193 }
194 return ret;
195}
196
210template<typename S1, typename S2, typename S3, typename S4>
211 requires(std::is_base_of_v<Eigen::EigenBase<S1>, S1> && std::is_base_of_v<Eigen::EigenBase<S2>, S2> &&
212 std::is_base_of_v<Eigen::EigenBase<S3>, S3> && std::is_base_of_v<Eigen::EigenBase<S4>, S4>)
213inline void d2r_fog(
214 Eigen::SparseMatrix<double> & out,
215 const S1 & Jf,
216 const S2 & Hf,
217 const S3 & Jg,
218 const S4 & Hg,
219 Eigen::Index r0 = 0,
220 Eigen::Index c0 = 0)
221{
222 const auto No = Jf.rows();
223 const auto Ny = Jf.cols();
224
225 [[maybe_unused]] const auto Ni = Jg.rows();
226 const auto Nx = Jg.cols();
227
228 // check some dimensions
229 assert(Ny == Ni);
230 assert(Hf.rows() == Ny);
231 assert(Hf.cols() == No * Ny);
232 assert(Hg.rows() == Nx);
233 assert(Hg.cols() == Ni * Nx);
234
235 for (auto no = 0u; no < No; ++no) {
236 // TODO sparse-sparse-sparse product is expensive and allocates temporary
237 block_add(out, r0, c0 + no * Nx, Jg.transpose() * Hf.middleCols(no * Ny, Ny) * Jg);
238 }
239
240 for (auto i = 0u; i < Jf.outerSize(); ++i) {
241 for (Eigen::InnerIterator it(Jf, i); it; ++it) {
242 block_add(out, r0, c0 + it.row() * Nx, Hg.middleCols(it.col() * Nx, Nx), it.value());
243 }
244 }
245}
246
247} // namespace smooth::feedback
void set_zero(MeshValue< Deriv > &mv)
Reset MeshValue to zeros.
void d2r_fog(Eigen::SparseMatrix< double > &out, const S1 &Jf, const S2 &Hf, const S3 &Jg, const S4 &Hg, Eigen::Index r0=0, Eigen::Index c0=0)
(Right) Hessian of composed function .
Definition: sparse.hpp:213
void block_write(Eigen::SparseMatrix< double, Options > &dest, Eigen::Index row0, Eigen::Index col0, const Source &source, double scale=1, bool upper_only=false)
Write block into a sparse matrix.
Definition: sparse.hpp:70
void block_add_identity(Eigen::SparseMatrix< double, Options > &dest, Eigen::Index row0, Eigen::Index col0, Eigen::Index n, double scale=1)
Add identity matrix block into sparse matrix.
Definition: sparse.hpp:103
void block_add(Eigen::SparseMatrix< double, Options > &dest, Eigen::Index row0, Eigen::Index col0, const Source &source, double scale=1, bool upper_only=false)
Add block into a sparse matrix.
Definition: sparse.hpp:35
void block_write_identity(Eigen::SparseMatrix< double, Options > &dest, Eigen::Index row0, Eigen::Index col0, Eigen::Index n, double scale=1)
Write identity matrix block into sparse matrix.
Definition: sparse.hpp:125
Eigen::MatrixX< typename Mat::Scalar > mark_explicit_zeros(const Mat &mat)
Mark explicit zeros in sparse matrix.
Definition: sparse.hpp:181
uint64_t count_explicit_zeros(const Mat &mat)
Count number of explicit zeros in sparse matrix.
Definition: sparse.hpp:158