EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
UniformMixture.h
Go to the documentation of this file.
1#pragma once
2
9
10#include <concepts>
11#include <cstddef>
12#include <tuple>
13#include <type_traits>
14#include <utility>
15
26
27namespace Emrys
28{
29
56template <Space Space_, RealScalar Scalar_ = double>
58{
59public:
60
61 using Scalar = Scalar_;
62 using Index = Eigen::Index;
63 using SpaceType = Space_;
67
69 using CountsType =
70 internal::IndexVector<MomentsType::ValueDimensionAtCompileTime, MomentsType::MaxValueDimensionAtCompileTime>;
71
78
80 using const_iterator = internal::ElementIterator<UniformGrid>;
82
90 VectorType corner,
91 VectorType width,
93 MatrixType covariance,
94 Scalar relativeWidth
95 )
96 : m_space{std::move(space)}
97 , m_corner{std::move(corner)}
98 , m_width{std::move(width)}
99 , m_counts{std::move(counts)}
100 , m_covariance{std::move(covariance)}
101 {
102 EMRYS_FILTER_ASSERT(
103 isFinite(relativeWidth) && relativeWidth > Scalar(0) && "the relative width must be positive and finite"
104 );
105 EMRYS_FILTER_ASSERT(
106 m_corner.size() == m_width.size() && m_corner.size() == m_counts.size()
107 && m_covariance.rows() == m_corner.size() && m_covariance.cols() == m_corner.size()
108 && "one corner, width, count, and covariance row per coordinate"
109 );
110 Index gridded = 0;
111 for (Index i = 0; i < m_counts.size(); ++i)
112 {
113 EMRYS_FILTER_ASSERT(m_counts(i) >= 0 && "a count must not be negative");
114 if (m_counts(i) > 0)
115 {
116 ++gridded;
117 m_size *= m_counts(i);
118 Scalar const deviation = relativeWidth * m_width(i) / Scalar(m_counts(i));
119 m_covariance(i, i) = deviation * deviation;
120 }
121 }
122 EMRYS_FILTER_ASSERT(gridded > 0 && "the grid needs a gridded coordinate");
123 m_logWeight = -Eigen::numext::log(Scalar(m_size));
124 }
125
127 [[nodiscard]] SpaceType const &
128 space() const
129 {
130 return m_space;
131 }
132
134 [[nodiscard]] Index
136 {
137 return m_corner.size();
138 }
139
141 [[nodiscard]] Index
142 size() const
143 {
144 return m_size;
145 }
146
148 [[nodiscard]] CountsType const &
149 counts() const
150 {
151 return m_counts;
152 }
153
155 [[nodiscard]] Element
157 {
158 EMRYS_FILTER_ASSERT(k >= 0 && k < m_size && "component index out of range");
159 VectorType mean = m_corner;
160 Index rest = k;
161 for (Index i = 0; i < m_counts.size(); ++i)
162 {
163 Index const count = m_counts(i);
164 if (count > 0)
165 {
166 Index const j = rest % count;
167 rest /= count;
168 mean(i) = m_corner(i) + (Scalar(j) + Scalar(0.5)) * m_width(i) / Scalar(count);
169 }
170 }
171 return Element{m_logWeight, MomentsType{std::move(mean), m_covariance}};
172 }
173
175 [[nodiscard]] const_iterator
176 begin() const
177 {
178 return const_iterator{*this, 0};
179 }
180
182 [[nodiscard]] const_iterator
183 end() const
184 {
185 return const_iterator{*this, m_size};
186 }
187
188private:
189
190 SpaceType m_space;
191 VectorType m_corner;
192 VectorType m_width;
193 CountsType m_counts;
194 MatrixType m_covariance;
195 Index m_size = 1;
196 Scalar m_logWeight{};
197};
198
199namespace internal
200{
201
203template <Space S, RealScalar Scalar, typename CountOf>
204[[nodiscard]] UniformGrid<S, Scalar>
205uniformGrid(Uniform<S, Scalar> const & uniform, CountOf const & countOf, Scalar relativeWidth)
206{
207 using Grid = UniformGrid<S, Scalar>;
208 Eigen::Index const n = uniform.valueDimension();
209 typename Grid::CountsType counts(n);
210 for (Eigen::Index i = 0; i < n; ++i)
211 {
212 counts(i) = countOf(i);
213 EMRYS_FILTER_ASSERT(counts(i) >= 1 && "each coordinate needs at least one component");
214 }
215 return Grid{
216 uniform.space(),
217 uniform.lower(),
218 uniform.width(),
219 std::move(counts),
220 Grid::MatrixType::Zero(n, n),
221 relativeWidth
222 };
223}
224
226template <typename F>
227inline constexpr bool isUniform = false;
228
230template <Space S, RealScalar Scalar>
231inline constexpr bool isUniform<Uniform<S, Scalar>>{true};
233
237template <typename F>
238inline constexpr bool isGaussianFactor = isGaussian<F>;
239
241template <typename F, typename BlockSpace>
242inline constexpr bool isGaussianFactor<EachRepetition<F, BlockSpace>>{isGaussian<F>};
243
245
250template <Space S, RealScalar Scalar, typename... Factors, typename CountOf>
251[[nodiscard]] UniformGrid<S, Scalar>
252productGrid(
253 Product<S, Scalar, Factors...> const & product,
254 CountOf const & countOf,
255 Eigen::Index givenCounts,
256 Scalar relativeWidth
257)
258{
259 static_assert(
260 ((isUniform<Factors> || isGaussianFactor<Factors>) && ...),
261 "uniformComponents() of a Product takes Uniform factors placed with on<Path>() and GaussianParams factors"
262 );
263 static_assert((isUniform<Factors> || ...), "uniformComponents() of a Product needs a Uniform factor to grid");
264 using Grid = UniformGrid<S, Scalar>;
265 using Index = Eigen::Index;
266 Index const n = product.valueDimension();
267 auto corner = typename Grid::VectorType(n);
268 typename Grid::MatrixType covariance = Grid::MatrixType::Zero(n, n);
269 typename Grid::VectorType width = Grid::VectorType::Zero(n);
270 typename Grid::CountsType counts = Grid::CountsType::Zero(n);
271 [&]<std::size_t... K>(std::index_sequence<K...>) {
272 (
273 [&] {
274 auto const & factor = product.template factor<K>();
275 auto const & indices = product.template indices<K>();
276 if constexpr (isUniform<std::tuple_element_t<K, std::tuple<Factors...>>>)
277 {
278 corner(indices) = factor.lower();
279 width(indices) = factor.width();
280 counts(indices).setOnes();
281 }
282 else
283 {
284 auto const & moments = factor.moments();
285 using FactorMatrix = std::remove_cvref_t<decltype(moments.covarianceLower())>;
286 corner(indices) = moments.mean();
287 covariance(indices, indices) =
288 FactorMatrix{moments.covarianceLower().template selfadjointView<Eigen::Lower>()};
289 }
290 }(),
291 ...
292 );
293 }(std::index_sequence_for<Factors...>{});
294
295 Index gridded = 0;
296 for (Index i = 0; i < n; ++i)
297 {
298 if (counts(i) > 0)
299 {
300 counts(i) = countOf(gridded++);
301 EMRYS_FILTER_ASSERT(counts(i) >= 1 && "each gridded coordinate needs at least one component");
302 }
303 }
304 EMRYS_FILTER_ASSERT(
305 (givenCounts < 0 || givenCounts == gridded) && "give one count per coordinate of the Uniform factors"
306 );
307 return Grid{
308 product.space(),
309 std::move(corner),
310 std::move(width),
311 std::move(counts),
312 std::move(covariance),
313 relativeWidth
314 };
315}
316
317} // namespace internal
318
359template <Space S, RealScalar Scalar, typename CountsDerived>
360 requires std::integral<typename CountsDerived::Scalar>
361[[nodiscard]] UniformGrid<S, Scalar>
363 Uniform<S, Scalar> const & uniform,
364 Eigen::DenseBase<CountsDerived> const & counts,
365 std::type_identity_t<Scalar> relativeWidth = Scalar(0.6)
366)
367{
368 EMRYS_FILTER_ASSERT(counts.size() == uniform.valueDimension() && "give one count per coordinate");
369 return internal::uniformGrid(
370 uniform,
371 [&](Eigen::Index i) {
372 return Eigen::Index(counts(i));
373 },
374 relativeWidth
375 );
376}
377
381template <Space S, RealScalar Scalar>
382[[nodiscard]] UniformGrid<S, Scalar>
384 Uniform<S, Scalar> const & uniform,
385 Eigen::Index count,
386 std::type_identity_t<Scalar> relativeWidth = Scalar(0.6)
387)
388{
389 return internal::uniformGrid(
390 uniform,
391 [&](Eigen::Index) {
392 return count;
393 },
394 relativeWidth
395 );
396}
397
417template <Space S, RealScalar Scalar, typename... Factors, typename CountsDerived>
418 requires std::integral<typename CountsDerived::Scalar>
419[[nodiscard]] UniformGrid<S, Scalar>
421 Product<S, Scalar, Factors...> const & product,
422 Eigen::DenseBase<CountsDerived> const & counts,
423 std::type_identity_t<Scalar> relativeWidth = Scalar(0.6)
424)
425{
426 return internal::productGrid(
427 product,
428 [&](Eigen::Index j) {
429 EMRYS_FILTER_ASSERT(j < counts.size() && "give one count per coordinate of the Uniform factors");
430 return Eigen::Index(counts(j));
431 },
432 counts.size(),
433 relativeWidth
434 );
435}
436
441template <Space S, RealScalar Scalar, typename... Factors>
442[[nodiscard]] UniformGrid<S, Scalar>
444 Product<S, Scalar, Factors...> const & product,
445 Eigen::Index count,
446 std::type_identity_t<Scalar> relativeWidth = Scalar(0.6)
447)
448{
449 return internal::productGrid(
450 product,
451 [&](Eigen::Index) {
452 return count;
453 },
454 -1,
455 relativeWidth
456 );
457}
458
459} // namespace Emrys
What a container of several Gaussians needs of each one (decisions.md [component-first]): the Compone...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
What marginals and conditionals are built from: resolving Eigen index sets against a space; the share...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
The mixture: the parameters MixtureParams of weighted components of one type (decisions....
Moments: the mean and covariance that a Gaussian carries and that a mixture or a sample set is moment...
Product: the product of independent densities, each on its own block of a space, built with on<Path>(...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Uniform: the uniform distribution over a box, with the box taken from a space of Periodic coordinates...
First and second moments (mean and covariance) of a distribution.
Definition Moments.h:55
DifferenceMatrix< Space_, Space_, Scalar > MatrixType
Definition Moments.h:76
ValueVector< Space_, Scalar > VectorType
Definition Moments.h:74
The product of independent densities, each on its own coordinates of a space.
Definition Product.h:772
The equal-weight components of a grid over some coordinates of a space, made one at a time when read:...
Definition UniformMixture.h:58
Index valueDimension() const
Definition UniformMixture.h:135
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition UniformMixture.h:66
CountsType const & counts() const
Definition UniformMixture.h:149
internal::IndexVector< MomentsType::ValueDimensionAtCompileTime, MomentsType::MaxValueDimensionAtCompileTime > CountsType
A count of cells per coordinate, zero for a coordinate that is not gridded.
Definition UniformMixture.h:69
const_iterator begin() const
Definition UniformMixture.h:176
Eigen::Index Index
Eigen's index type.
Definition UniformMixture.h:62
Moments< Space_, Scalar_ > MomentsType
a component's mean and covariance
Definition UniformMixture.h:64
UniformGrid(SpaceType space, VectorType corner, VectorType width, CountsType counts, MatrixType covariance, Scalar relativeWidth)
The grid in space over the coordinates i with counts(i) > 0, counts(i) cells across width(i) from cor...
Definition UniformMixture.h:88
Scalar_ Scalar
the scalar type
Definition UniformMixture.h:61
const_iterator end() const
Definition UniformMixture.h:183
SpaceType const & space() const
Definition UniformMixture.h:128
internal::ElementIterator< UniformGrid > const_iterator
iterates the elements
Definition UniformMixture.h:80
Element operator[](Index k) const
Definition UniformMixture.h:156
Space_ SpaceType
the space the components live in
Definition UniformMixture.h:63
typename MomentsType::VectorType VectorType
a value, such as a mean
Definition UniformMixture.h:65
Element value_type
an element, made when read
Definition UniformMixture.h:79
Index size() const
Definition UniformMixture.h:142
const_iterator iterator
iterates the elements; they are read-only
Definition UniformMixture.h:81
The uniform distribution over a box in a space.
Definition Uniform.h:69
Index valueDimension() const
Definition Uniform.h:174
bool isFinite(T const &x)
Definition Math.h:305
constexpr bool isGaussian
Whether C is a Gaussian in covariance form: the component for which a container offers the convenienc...
Definition Component.h:111
UniformGrid< S, Scalar > uniformComponents(Uniform< S, Scalar > const &uniform, Eigen::DenseBase< CountsDerived > const &counts, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
Definition UniformMixture.h:362
One component: its log-weight and its mean and covariance.
Definition UniformMixture.h:74
Scalar logWeight
the log of the component's weight, the same for every one
Definition UniformMixture.h:75
MomentsType moments
the component's mean and covariance
Definition UniformMixture.h:76