EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
ParticleGaussian.h
Go to the documentation of this file.
1#pragma once
2
10
11#include <expected>
12#include <random>
13#include <span>
14#include <type_traits>
15#include <utility>
16
34
35namespace Emrys
36{
37
38template <
39 Space Space_,
40 typename Path_,
41 typename Covariance_ = SharedCovariance,
42 RealScalar Scalar_ = double,
43 typename Allocator_ = DefaultAllocator,
46
47template <
48 Space Space_,
49 typename Path_,
50 typename Model_,
51 typename Covariance_,
52 typename Method_,
53 RealScalar Scalar_,
54 typename Allocator_,
55 typename Upkeep_>
57
58namespace internal
59{
60
62template <typename Space_, typename Split, typename Particles>
63class ParticlePoints
64{
65public:
66
67 using Scalar = typename Particles::Scalar;
68 using SpaceType = Space_;
69 using PathType = typename Split::PathType;
70 using PinnedSpace = typename Split::PinnedSpace;
71 using RestSpace = typename Split::RestSpace;
72 static constexpr bool HasKernels = false;
73
75 ParticlePoints(Space_ const & space, Split const & split, Particles const & particles)
76 : m_space{space}
77 , m_split{split}
78 , m_particles{particles}
79 {}
80
82 [[nodiscard]] Space_ const &
83 space() const
84 {
85 return m_space;
86 }
87
89 [[nodiscard]] RestSpace const &
90 restSpace() const
91 {
92 return m_split.restSpace();
93 }
94
96 [[nodiscard]] BlockRows
97 pinnedRows() const
98 {
99 return m_split.pinnedRows();
100 }
101
103 [[nodiscard]] auto const &
104 restIndices() const
105 {
106 return m_split.restIndices();
107 }
108
110 [[nodiscard]] BlockRows
111 pinnedDifferenceRows() const
112 {
113 return m_split.pinnedDifferenceRows();
114 }
115
117 [[nodiscard]] auto const &
118 restDifferenceIndices() const
119 {
120 return m_split.restDifferenceIndices();
121 }
122
124 [[nodiscard]] Eigen::Index
125 size() const
126 {
127 return m_particles.size();
128 }
129
131 [[nodiscard]] auto
132 center(Eigen::Index i) const
133 {
134 return m_particles.state(i);
135 }
136
137private:
138
139 Space_ const & m_space;
140 Split const & m_split;
141 Particles const & m_particles;
142};
143
144} // namespace internal
145
184template <
185 Space Space_,
186 typename Path_,
187 typename Covariance_ = SharedCovariance,
188 RealScalar Scalar_ = double,
189 typename Allocator_ = DefaultAllocator,
192{
193 static_assert(internal::CovarianceForm<Covariance_>, "the covariance is SharedCovariance or PerPointCovariance");
194 static constexpr bool Shared = std::is_same_v<Covariance_, SharedCovariance>;
195 using Split = internal::BlockSplit<Space_, Path_>;
196
198 static constexpr bool IsHybrid = internal::isGaussianHybrid<Params<Component_>>;
199
200 static_assert(
201 std::is_same_v<
204 || IsHybrid,
205 "a particle holds a Gaussian or a hybrid of Gaussians"
206 );
207 static_assert(
208 std::is_same_v<typename Params<Component_>::SpaceType, typename Split::RestSpace>
209 && std::is_same_v<typename Params<Component_>::Scalar, Scalar_>,
210 "a particle's distribution is over the rest of the state, in the state's scalar"
211 );
212 static_assert(
213 !(IsHybrid && Shared),
214 "mixing a particle's modes gives each particle covariances of its own, so a hybrid per particle needs "
215 "PerPointCovariance"
216 );
217
218public:
219
220 using Scalar = Scalar_;
221 using SpaceType = Space_;
222 using PathType = Path_;
223 using PinnedSpace = typename Split::PinnedSpace;
224 using RestSpace = typename Split::RestSpace;
225 using CovarianceType = Covariance_;
227 using allocator_type = Allocator_;
234
235 static constexpr bool IsParams = true;
236
241 : m_space{std::move(space)}
242 , m_split{m_space}
243 , m_particles{std::move(particles)}
244 , m_kept(IndexAllocator(m_particles.get_allocator()))
245 , m_conditionals{conditional, m_particles.size(), m_particles.get_allocator()}
246 {
247 check();
248 EMRYS_FILTER_ASSERT(conditional.space() == restSpace() && "the Gaussian must be over the rest of the state");
249 }
250
256 template <typename MeansDerived>
258 Space_ space,
260 Eigen::MatrixBase<MeansDerived> const & means,
261 typename Moments<RestSpace, Scalar_>::MatrixType const & cov,
262 Covariance_ = {}
263 )
264 requires(!IsHybrid)
265 : m_space{std::move(space)}
266 , m_split{m_space}
267 , m_particles{std::move(particles)}
268 , m_kept(IndexAllocator(m_particles.get_allocator()))
269 , m_conditionals{
270 ConditionalType{m_split.restSpace(), means.col(0), cov},
271 m_particles.size(),
272 m_particles.get_allocator()
273 }
274 {
275 check();
276 EMRYS_FILTER_ASSERT(
277 means.cols() == size() && means.rows() == valueDimension(restSpace())
278 && "give one mean over the rest of the state per particle"
279 );
280 if constexpr (Shared)
281 {
282 m_conditionals.means() = means;
283 }
284 else
285 {
286 for (Eigen::Index i = 1; i < size(); ++i)
287 {
288 m_conditionals.conditional(i).setMean(means.col(i));
289 }
290 }
291 }
292
296 ParticleGaussianParams(Space_ space, ParticlesType particles, std::span<ConditionalType const> conditionals)
297 requires(!Shared)
298 : ParticleGaussianParams{std::move(space), std::move(particles), conditionals.front()}
299 {
300 EMRYS_FILTER_ASSERT(Eigen::Index(conditionals.size()) == size() && "give one Gaussian per particle");
301 for (Eigen::Index i = 0; i < size(); ++i)
302 {
303 EMRYS_FILTER_ASSERT(
304 conditionals[std::size_t(i)].space() == restSpace()
305 && "the Gaussians must be over the rest of the state"
306 );
307 m_conditionals.conditional(i) = conditionals[std::size_t(i)];
308 }
309 }
310
312 [[nodiscard]] Space_ const &
313 space() const
314 {
315 return m_space;
316 }
317
319 [[nodiscard]] PinnedSpace const &
321 {
322 return m_split.pinnedSpace();
323 }
324
326 [[nodiscard]] RestSpace const &
327 restSpace() const
328 {
329 return m_split.restSpace();
330 }
331
333 [[nodiscard]] BlockRows
335 {
336 return m_split.pinnedRows();
337 }
338
340 [[nodiscard]] auto const &
342 {
343 return m_split.restIndices();
344 }
345
347 [[nodiscard]] BlockRows
349 {
350 return m_split.pinnedDifferenceRows();
351 }
352
354 [[nodiscard]] auto const &
356 {
357 return m_split.restDifferenceIndices();
358 }
359
361 [[nodiscard]] Eigen::Index
362 size() const
363 {
364 return m_particles.size();
365 }
366
368 [[nodiscard]] allocator_type
370 {
371 return m_particles.get_allocator();
372 }
373
377 void
378 setCapacity(Eigen::Index capacity)
379 {
380 m_stamp.touchShape();
381 m_particles.setCapacity(capacity);
382 m_conditionals.reserve(capacity);
383 m_kept.reserve(std::size_t(capacity));
384 }
385
387 [[nodiscard]] ParticlesType const &
388 particles() const
389 {
390 return m_particles;
391 }
392
394 [[nodiscard]] auto
395 particle(Eigen::Index i) const
396 {
397 return m_particles.state(i);
398 }
399
401 [[nodiscard]] LogWeightsType
403 {
404 return m_particles.logWeights();
405 }
406
408 [[nodiscard]] Scalar
409 logWeight(Eigen::Index i) const
410 {
411 return m_particles.logWeight(i);
412 }
413
415 [[nodiscard]] std::expected<Scalar, WeightError>
417 {
418 return m_particles.logTotalWeight();
419 }
420
422 template <ExecutionPolicy P>
423 [[nodiscard]] std::expected<Scalar, WeightError>
424 logTotalWeight(P && policy) const
425 {
426 return m_particles.logTotalWeight(std::forward<P>(policy));
427 }
428
430 [[nodiscard]] std::expected<Scalar, WeightError>
431 ess() const
432 {
433 return m_particles.ess();
434 }
435
437 template <ExecutionPolicy P>
438 [[nodiscard]] std::expected<Scalar, WeightError>
439 ess(P && policy) const
440 {
441 return m_particles.ess(std::forward<P>(policy));
442 }
443
445 [[nodiscard]] Eigen::Index
447 {
448 Eigen::Index best = 0;
449 logWeights().maxCoeff(&best);
450 return best;
451 }
452
454 [[nodiscard]] decltype(auto)
455 conditional(Eigen::Index i) const
456 {
457 EMRYS_FILTER_ASSERT(i >= 0 && i < size() && "the particle is out of range");
458 return m_conditionals.conditional(i);
459 }
460
465 [[nodiscard]] auto
466 modes() const
467 requires IsHybrid
468 {
469 return internal::summedModes(m_conditionals, logWeights());
470 }
471
473 [[nodiscard]] typename Moments<RestSpace, Scalar_>::MatrixType const &
475 requires Shared
476 {
477 return m_conditionals.sharedCovariance();
478 }
479
487 [[nodiscard]] std::expected<void, NumericError>
488 factorize() const
489 {
490 if (auto const total = m_particles.logTotalWeight(); !total)
491 {
492 return std::unexpected{total.error()};
493 }
494 return m_conditionals.factorize();
495 }
496
501 [[nodiscard]] std::expected<DensityType, NumericError>
502 toDensity() const &
503 {
504 if (auto result = factorize(); !result)
505 {
506 return std::unexpected{result.error()};
507 }
508 return DensityType{*this};
509 }
510
512 void
513 toDensity() const && = delete;
514
521 template <std::uniform_random_bit_generator G, typename R = resamplers::Systematic>
522 requires Resampler<R, Scalar, G>
523 [[nodiscard]] std::expected<void, WeightError>
524 resample(G & rng, Eigen::Index newSize, R const & resampler = {})
525 {
526 return resample(execution::sequential, rng, newSize, resampler);
527 }
528
530 template <std::uniform_random_bit_generator G, typename R = resamplers::Systematic>
531 requires Resampler<R, Scalar, G>
532 [[nodiscard]] std::expected<void, WeightError>
533 resample(G & rng, R const & resampler = {})
534 {
535 return resample(execution::sequential, rng, size(), resampler);
536 }
537
541 template <ExecutionPolicy P, std::uniform_random_bit_generator G, typename R = resamplers::Systematic>
542 requires Resampler<R, Scalar, G>
543 [[nodiscard]] std::expected<void, WeightError>
544 resample(P && policy, G & rng, Eigen::Index newSize, R const & resampler = {})
545 {
546 auto const resampled = m_particles.resample(policy, rng, newSize, resampler);
547 if (!resampled)
548 {
549 return resampled;
550 }
551 m_stamp.touchShape();
552 m_conditionals.select(std::forward<P>(policy), m_particles.ancestors());
553 return {};
554 }
555
557 template <ExecutionPolicy P, std::uniform_random_bit_generator G, typename R = resamplers::Systematic>
558 requires Resampler<R, Scalar, G>
559 [[nodiscard]] std::expected<void, WeightError>
560 resample(P && policy, G & rng, R const & resampler = {})
561 {
562 return resample(std::forward<P>(policy), rng, size(), resampler);
563 }
564
571 [[nodiscard]] std::expected<Scalar, WeightError>
572 pruneBelow(Scalar logThreshold)
573 {
574 return pruneWith(internal::PruneBelowRule<Scalar>{logThreshold});
575 }
576
584 [[nodiscard]] std::expected<Scalar, WeightError>
585 pruneTail(Scalar logFraction)
586 {
587 return pruneWith(internal::PruneTailRule<Scalar>{logFraction});
588 }
589
596 [[nodiscard]] std::expected<Scalar, WeightError>
597 pruneToSize(Eigen::Index maxSize)
598 {
599 return pruneWith(internal::PruneToSizeRule{maxSize});
600 }
601
605 template <typename Derived>
606 void
607 setParticleStates(Eigen::MatrixBase<Derived> const & states)
608 {
609 EMRYS_FILTER_ASSERT(states.cols() == size() && "give one value per particle");
610 m_stamp.touchValues();
611 m_particles.setStates(states);
612 }
613
614private:
615
617 template <Space, typename, typename, typename, typename, RealScalar, typename, typename>
618 friend class RbParticleFilter;
619
620 friend DensityType;
621
623 template <typename>
624 friend class internal::ValuesCheck;
625
627 using ConditionalsType = internal::Conditionals<RestSpace, Covariance_, Scalar_, Allocator_, ConditionalType>;
628
630 using IndexAllocator = internal::ReBound<Allocator_, Eigen::Index>;
631
635 template <typename Rule>
636 [[nodiscard]] std::expected<Scalar, WeightError>
637 pruneWith(Rule const & rule)
638 {
639 m_kept.clear();
640 auto const removed = internal::ParticleSetAccess::prune(m_particles, rule, [&](Eigen::Index i) {
641 m_kept.push_back(i);
642 });
643 if (removed)
644 {
645 m_stamp.touchShape();
646 m_conditionals.keep(std::span<Eigen::Index const>{m_kept.data(), m_kept.size()});
647 }
648 return removed;
649 }
650
652 [[nodiscard]] internal::ParticlePoints<Space_, Split, ParticlesType>
653 points() const
654 {
655 return {m_space, m_split, m_particles};
656 }
657
663 [[nodiscard]] GaussianParams<Space_, Scalar>
664 collapseParticles() const
665 {
666 if constexpr (IsHybrid)
667 {
668 return internal::collapseGivenHybrids(points(), m_conditionals, logWeights(), get_allocator());
669 }
670 else
671 {
672 return internal::collapseGivenPoints(points(), m_conditionals, logWeights());
673 }
674 }
675
677 void
678 check() const
679 {
680 EMRYS_FILTER_ASSERT(!m_particles.empty() && "a Rao-Blackwellized state needs a particle");
681 EMRYS_FILTER_ASSERT(m_particles.valueDimension() == pinnedRows().size && "the particles do not fit the block");
682 }
683
694 template <ExecutionPolicy P, typename Derived>
695 [[nodiscard]] std::pair<Scalar, bool>
696 reweight(P && policy, Eigen::ArrayBase<Derived> const & logLikelihoods, ConditionalsType & posterior)
697 {
698 return reweightThen(std::forward<P>(policy), logLikelihoods, [&] {
699 m_conditionals.swap(posterior);
700 });
701 }
702
709 template <ExecutionPolicy P, typename Derived>
710 [[nodiscard]] std::pair<Scalar, bool>
711 reweight(P && policy, Eigen::ArrayBase<Derived> const & logLikelihoods)
712 {
713 return reweightThen(std::forward<P>(policy), logLikelihoods, [] {});
714 }
715
719 template <ExecutionPolicy P, typename Derived, typename Place>
720 [[nodiscard]] std::pair<Scalar, bool>
721 reweightThen(P && policy, Eigen::ArrayBase<Derived> const & logLikelihoods, Place const & place)
722 {
723 EMRYS_FILTER_ASSERT(logLikelihoods.size() == size() && "give one log-likelihood per particle");
724 auto const logTotal = m_particles.logTotalWeight(policy);
725 EMRYS_FILTER_ASSERT(logTotal && "the particles' weights must be valid");
726 if (!logTotal)
727 {
728 return {Eigen::NumTraits<Scalar>::quiet_NaN(), false};
729 }
730 auto const logWeights = m_particles.logWeights() - *logTotal + logLikelihoods.derived();
731 // A NaN log-likelihood at any particle makes the evidence NaN.
732 Scalar const logLikelihood = logSumExp(std::forward<P>(policy), logWeights);
733 EMRYS_FILTER_ASSERT(!isNaN(logLikelihood) && "the measurement's log-likelihood must not be NaN");
734 if (logLikelihood == -Eigen::NumTraits<Scalar>::infinity())
735 {
736 return {logLikelihood, false};
737 }
738 m_stamp.touchShape();
739 internal::ParticleSetAccess::setNormalizedLogWeights(m_particles, logWeights - logLikelihood);
740 place();
741 return {logLikelihood, true};
742 }
743
744 Space_ m_space;
745 Split m_split;
746 ParticlesType m_particles;
747 internal::Buffer<Eigen::Index, Allocator_> m_kept;
748
749 ConditionalsType m_conditionals;
750 internal::Stamp m_stamp;
751};
752
771template <
772 Space Space_,
773 typename Path_,
774 typename Covariance_,
775 RealScalar Scalar_,
776 typename Allocator_,
777 typename Component_>
778class ParticleGaussian
779{
780public:
781
784 using Scalar = Scalar_;
785 using SpaceType = Space_;
791 using allocator_type = Allocator_;
792
793 static constexpr bool IsParams = false;
794
796 [[nodiscard]] Space_ const &
797 space() const
798 {
799 return source().space();
800 }
801
803 [[nodiscard]] Eigen::Index
804 size() const
805 {
806 return source().size();
807 }
808
810 [[nodiscard]] ParticlesType const &
811 particles() const
812 {
813 return source().particles();
814 }
815
817 [[nodiscard]] decltype(auto)
818 conditional(Eigen::Index i) const
819 {
820 return source().conditional(i);
821 }
822
828 collapsed() const
829 {
830 return source().collapseParticles();
831 }
832
834 [[nodiscard]] MomentsType
835 moments() const
836 {
837 return collapsed().moments();
838 }
839
840private:
841
842 friend ParamsType;
843
847 explicit ParticleGaussian(ParamsType const & source)
848 : m_check{source}
849 {}
850
852 [[nodiscard]] ParamsType const &
853 source() const
854 {
855 return m_check.get();
856 }
857
858 internal::ValuesCheck<ParamsType> m_check;
859};
860
866template <typename P, Space S, typename Scalar, typename Allocator, typename Covariance = SharedCovariance>
867[[nodiscard]] auto
869 S space,
870 ParticleSet<typename internal::BlockSplit<S, P>::PinnedSpace, Scalar, Allocator> particles,
871 GaussianParams<typename internal::BlockSplit<S, P>::RestSpace, Scalar> const & conditional,
872 Covariance covariance = {}
873)
874{
875 return ParticleGaussianParams<S, P, Covariance, Scalar, Allocator>{
876 std::move(space),
877 std::move(particles),
878 conditional,
879 covariance
880 };
881}
882
888template <
889 typename P,
890 Space S,
891 typename Scalar,
892 typename Allocator,
893 typename Component,
894 typename ModeSpace,
895 typename HybridAllocator>
896[[nodiscard]] auto
898 S space,
899 ParticleSet<typename internal::BlockSplit<S, P>::PinnedSpace, Scalar, Allocator> particles,
901)
902{
904 S,
905 P,
907 Scalar,
908 Allocator,
909 Hybrid<Component, ModeSpace, HybridAllocator>>{std::move(space), std::move(particles), conditional};
910}
911
918template <
919 typename P,
920 typename Covariance = SharedCovariance,
921 typename S,
922 typename Scalar,
923 std::uniform_random_bit_generator G,
924 typename Allocator = DefaultAllocator>
925[[nodiscard]] auto
927 GaussianParams<S, Scalar> const & joint,
928 Eigen::Index count,
929 G & rng,
930 Covariance = {},
931 Allocator const & allocator = {}
932)
933{
936 using PinnedNormals = SampleSet<DifferenceSpace<typename Result::PinnedSpace>, Scalar>;
937 EMRYS_FILTER_ASSERT(count > 0 && "draw at least one particle");
938 auto const split = internal::BlockSplit<S, P>{joint.space()};
939 auto const conditioning = internal::pinnedConditioning(split, joint.covarianceLower());
940 PinnedNormals const z = internal::standardNormal<PinnedNormals>(split.pinnedDifferenceRows().size, count, rng);
941 auto pinned = PinnedSamples{split.pinnedRows().size, count};
942 auto means = typename Result::MeansType{split.restIndices().size(), count};
943 for (Eigen::Index i = 0; i < count; ++i)
944 {
945 internal::drawPinned(split, conditioning, joint.mean(), z.col(i), pinned.col(i), means.col(i));
946 }
947 auto particles = typename Result::ParticlesType{split.pinnedSpace(), pinned, allocator};
948 return Result{joint.space(), std::move(particles), means, conditioning.cov, Covariance{}};
949}
950
951} // namespace Emrys
952
953#ifndef EMRYS_FILTER_NO_IO
954
955namespace Emrys
956{
957
958namespace internal
959{
960
965template <
966 typename Space_,
967 typename Path_,
968 typename Covariance_,
969 typename Scalar_,
970 typename Allocator_,
971 typename Component_>
972void
973describe(
974 std::ostream & stream,
975 ParticleGaussianParams<Space_, Path_, Covariance_, Scalar_, Allocator_, Component_> const & state,
976 Indent indent
977)
978{
979 Eigen::Index const dimension = valueDimension(state.space());
980 stream << indent << "Rao-Blackwellized particle set of ";
981 printCount(stream, state.size(), "particle");
982 printDimension(stream, dimension, differenceDimension(state.space()));
983 auto const ess = state.ess();
984 auto const density = state.toDensity();
985 if (ess)
986 {
987 stream << ", effective sample size " << *ess;
988 }
989 if (density)
990 {
991 printMoments(stream, indent.deeper(), density->moments());
992 }
993 else
994 {
995 stream << '\n';
996 describe(stream, density.error(), indent.deeper());
997 }
998}
999
1000} // namespace internal
1001
1002} // namespace Emrys
1003
1004#endif // EMRYS_FILTER_NO_IO
What the Rao-Blackwellized states share (decisions.md [rao-blackwellized-core], [rb-particle-filter])...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
The hybrid state of a discrete mode and a component per mode (decisions.md [imm], [component-first]):...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Moments: the mean and covariance that a Gaussian carries and that a mixture or a sample set is moment...
Params and Density: the traits that pair a distribution's parameters with its density,...
The particle set: ParticleSet, the weighted samples, with resampling, upkeep of weights and particles...
Printing: operator<< and std::formatter for every distribution, every filter (which prints its name a...
The resamplers: function objects that draw ancestors in proportion to weights, which ParticleSet::res...
SampleSet: a matrix whose columns are samples in a space, which the samplers return and the unscented...
Drawing samples: SamplesWithLogDensity and SampleWithLogDensity, the Gaussian draws drawSamples(),...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
What parameters and their views share (decisions.md [view-stamp], [params-and-density]): Stamp,...
Tag paths and the index utilities (decisions.md [tag-addressing], [index-names]): TagPath and TagPath...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
A Gaussian distribution: a mean and covariance in a space.
Definition Gaussian.h:259
MatrixType const & covarianceLower() const
Definition Gaussian.h:543
MomentsType const & moments() const
Definition Gaussian.h:526
VectorType const & mean() const
Definition Gaussian.h:533
Space_ const & space() const
Definition Gaussian.h:519
The density of a Gaussian whose covariance has been factorized: a read-only view.
Definition Gaussian.h:1011
The parameters of a hybrid state: a discrete mode, and a component conditioned on each mode.
Definition Hybrid.h:86
The density of a hybrid state, a checked view of its HybridParams (decisions.md [params-and-density],...
Definition Hybrid.h:528
First and second moments (mean and covariance) of a distribution.
Definition Moments.h:55
DifferenceMatrix< Space_, Space_, Scalar > MatrixType
a matrix over differences, such as the covariance
Definition Moments.h:76
The parameters of a Rao-Blackwellized particle filter's state: weighted particles for one block of th...
Definition ParticleGaussian.h:192
auto const & restDifferenceIndices() const
Definition ParticleGaussian.h:355
ParticleGaussianParams(Space_ space, ParticlesType particles, std::span< ConditionalType const > conditionals)
particles of the block in space, particle i with the Gaussian, or the hybrid, conditionals[i] over th...
Definition ParticleGaussian.h:296
std::expected< DensityType, NumericError > toDensity() const &
Checks the state (factorize()) and views it.
Definition ParticleGaussian.h:502
auto particle(Eigen::Index i) const
Definition ParticleGaussian.h:395
ParticleGaussianParams(Space_ space, ParticlesType particles, Eigen::MatrixBase< MeansDerived > const &means, typename Moments< RestSpace, Scalar_ >::MatrixType const &cov, Covariance_={})
particles of the block in space, particle i with the mean means.col(i) over the rest and the covarian...
Definition ParticleGaussian.h:257
SampleSet< RestSpace, Scalar_ > MeansType
means over the rest, one per column
Definition ParticleGaussian.h:231
std::expected< Scalar, WeightError > logTotalWeight() const
Definition ParticleGaussian.h:416
std::expected< Scalar, WeightError > pruneTail(Scalar logFraction)
Removes the lightest particles, with their Gaussians, as many as can be while their combined normaliz...
Definition ParticleGaussian.h:585
std::expected< void, WeightError > resample(G &rng, R const &resampler={})
Resamples to the current size().
Definition ParticleGaussian.h:533
Eigen::Index size() const
Definition ParticleGaussian.h:362
Covariance_ CovarianceType
SharedCovariance or PerPointCovariance.
Definition ParticleGaussian.h:225
RestSpace const & restSpace() const
Definition ParticleGaussian.h:327
ParticleGaussian< Space_, Path_, Covariance_, Scalar_, Allocator_, Component_ > DensityType
what toDensity() returns
Definition ParticleGaussian.h:232
BlockRows pinnedRows() const
Definition ParticleGaussian.h:334
std::expected< Scalar, WeightError > pruneBelow(Scalar logThreshold)
Removes every particle whose normalized log-weight is below logThreshold, with its Gaussian,...
Definition ParticleGaussian.h:572
typename ParticlesType::WeightArrayType WeightArrayType
one entry per particle
Definition ParticleGaussian.h:229
Allocator_ allocator_type
the allocator, re-bound per buffer
Definition ParticleGaussian.h:227
Params< Component_ > ConditionalType
a particle's distribution over the rest: a Gaussian or a hybrid
Definition ParticleGaussian.h:226
std::expected< Scalar, WeightError > ess() const
Definition ParticleGaussian.h:431
decltype(auto) conditional(Eigen::Index i) const
Definition ParticleGaussian.h:455
ParticlesType const & particles() const
Definition ParticleGaussian.h:388
allocator_type get_allocator() const
Definition ParticleGaussian.h:369
BlockRows pinnedDifferenceRows() const
Definition ParticleGaussian.h:348
PinnedSpace const & pinnedSpace() const
Definition ParticleGaussian.h:320
Space_ SpaceType
the whole state space
Definition ParticleGaussian.h:221
typename Split::PinnedSpace PinnedSpace
the sampled block's space
Definition ParticleGaussian.h:223
Scalar logWeight(Eigen::Index i) const
Definition ParticleGaussian.h:409
void toDensity() const &&=delete
A density of a temporary would outlive it.
Scalar_ Scalar
the scalar type
Definition ParticleGaussian.h:220
std::expected< void, WeightError > resample(P &&policy, G &rng, Eigen::Index newSize, R const &resampler={})
resample() under policy, as ParticleSet::resample() runs under one, with the ancestors' Gaussians gat...
Definition ParticleGaussian.h:544
typename Split::RestSpace RestSpace
the rest's space, in order
Definition ParticleGaussian.h:224
std::expected< Scalar, WeightError > logTotalWeight(P &&policy) const
logTotalWeight() under policy, a reduction over the particles (see Execution policies).
Definition ParticleGaussian.h:424
std::expected< void, WeightError > resample(G &rng, Eigen::Index newSize, R const &resampler={})
Definition ParticleGaussian.h:524
std::expected< void, NumericError > factorize() const
Checks the weights and factorizes each particle's Gaussian, the one they share once,...
Definition ParticleGaussian.h:488
LogWeightsType logWeights() const
Definition ParticleGaussian.h:402
typename ParticlesType::LogWeightsType LogWeightsType
the particles' log-weights map
Definition ParticleGaussian.h:230
auto const & restIndices() const
Definition ParticleGaussian.h:341
std::expected< Scalar, WeightError > pruneToSize(Eigen::Index maxSize)
Removes the lightest particles, with their Gaussians, until at most maxSize, at least one,...
Definition ParticleGaussian.h:597
Eigen::Index mostProbable() const
Definition ParticleGaussian.h:446
Path_ PathType
the path naming the sampled block
Definition ParticleGaussian.h:222
auto modes() const
Definition ParticleGaussian.h:466
void setCapacity(Eigen::Index capacity)
Reserves room for capacity particles and their Gaussians, and makes holding more a precondition viola...
Definition ParticleGaussian.h:378
ParticleSet< PinnedSpace, Scalar_, Allocator_ > ParticlesType
the particles of the block
Definition ParticleGaussian.h:228
ParticleGaussianParams(Space_ space, ParticlesType particles, ConditionalType const &conditional, Covariance_={})
particles of the block in space, each with conditional as its Gaussian, or its hybrid,...
Definition ParticleGaussian.h:240
std::expected< void, WeightError > resample(P &&policy, G &rng, R const &resampler={})
resample() to the current size() under policy.
Definition ParticleGaussian.h:560
Moments< RestSpace, Scalar_ >::MatrixType const & sharedCovariance() const
Definition ParticleGaussian.h:474
void setParticleStates(Eigen::MatrixBase< Derived > const &states)
Replaces the particles' values of the sampled block with the columns of states, one per particle,...
Definition ParticleGaussian.h:607
std::expected< Scalar, WeightError > ess(P &&policy) const
ess() under policy, reductions over the particles (see Execution policies).
Definition ParticleGaussian.h:439
The density of a Rao-Blackwellized particle filter's state, a checked view of its ParticleGaussianPar...
Definition ParticleGaussian.h:779
Space_ const & space() const
Definition ParticleGaussian.h:797
Scalar_ Scalar
the scalar type
Definition ParticleGaussian.h:784
typename ParamsType::RestSpace RestSpace
the rest's space, in order
Definition ParticleGaussian.h:787
MomentsType moments() const
Definition ParticleGaussian.h:835
static constexpr bool IsParams
a view: it checks its parameters
Definition ParticleGaussian.h:793
GaussianParams< Space_, Scalar_ > collapsed() const
Definition ParticleGaussian.h:828
ParticlesType const & particles() const
Definition ParticleGaussian.h:811
typename ParamsType::ConditionalType ConditionalType
a particle's distribution over the rest
Definition ParticleGaussian.h:788
Allocator_ allocator_type
the parameters' allocator
Definition ParticleGaussian.h:791
decltype(auto) conditional(Eigen::Index i) const
Definition ParticleGaussian.h:818
ParticleGaussianParams< Space_, Path_, Covariance_, Scalar_, Allocator_, Component_ > ParamsType
the parameters
Definition ParticleGaussian.h:782
typename ParamsType::PinnedSpace PinnedSpace
the sampled block's space
Definition ParticleGaussian.h:786
Space_ SpaceType
the whole state space
Definition ParticleGaussian.h:785
Eigen::Index size() const
Definition ParticleGaussian.h:804
Moments< Space_, Scalar_ > MomentsType
a mean and covariance of the whole state
Definition ParticleGaussian.h:790
typename ParamsType::ParticlesType ParticlesType
the particles of the block
Definition ParticleGaussian.h:789
A set of weighted samples: the empirical distribution.
Definition ParticleSet.h:279
Eigen::Map< WeightArrayType const > LogWeightsType
Definition ParticleSet.h:301
std::expected< void, WeightError > resample(G &rng, Index newSize, R const &resampler={})
Replaces the particles with newSize draws chosen by resampler in proportion to their weights,...
Definition ParticleSet.h:1236
Eigen::Array< Scalar, Eigen::Dynamic, 1 > WeightArrayType
Definition ParticleSet.h:298
std::span< Index const > ancestors() const
Definition ParticleSet.h:1321
A Rao-Blackwellized particle filter: particles for one block of the state, each carrying a Kalman fil...
Definition RbParticleFilter.h:319
The distribution that a container of several holds one of per element (decisions.md [component-first]...
Definition Component.h:299
A type usable as the scalar of a distribution: a real number type such as float, double,...
Definition Math.h:80
Requirements on a resampler for scalar type Scalar and random generator G.
Definition Resampling.h:61
A type usable as the space of a distribution.
Definition Space.h:186
std::allocator< std::byte > DefaultAllocator
The allocator a type with a run-time count uses unless given one.
Definition Allocation.h:47
Scalar logSumExp(P &&policy, Eigen::Index count, LogAt const &logAt)
Definition Weights.h:151
bool isNaN(T const &x)
Definition Math.h:329
NumericError WeightError
Reasons a collection of log-weights cannot be normalized: Empty, ZeroSum, or NonFinite of NumericErro...
Definition NumericError.h:53
Eigen::Matrix< Scalar, valueDimensionAtCompileTime< Space >, Eigen::Dynamic,(maxValueDimensionAtCompileTime< Space >==1 ? Eigen::RowMajor :Eigen::ColMajor), maxValueDimensionAtCompileTime< Space >, Eigen::Dynamic > SampleSet
A matrix whose columns are samples in Space (see Spaces), with the space's size and storage bound.
Definition SampleSet.h:33
auto particleGaussian(S space, ParticleSet< typename internal::BlockSplit< S, P >::PinnedSpace, Scalar, Allocator > particles, GaussianParams< typename internal::BlockSplit< S, P >::RestSpace, Scalar > const &conditional, Covariance covariance={})
Definition ParticleGaussian.h:868
auto drawParticleGaussian(GaussianParams< S, Scalar > const &joint, Eigen::Index count, G &rng, Covariance={}, Allocator const &allocator={})
Definition ParticleGaussian.h:926
typename ParamsOf< D >::type Params
The parameters of the density D: GaussianParams for a Gaussian, and D itself for a distribution whose...
Definition Params.h:42
constexpr Sequential sequential
The default execution policy: plain loops on the calling thread, in index order (Sequential).
Definition Execution.h:128
Derived::Scalar logLikelihood(M const &measurement, Space const &space, Eigen::MatrixBase< Derived > const &x)
Definition Likelihood.h:433
Eigen::Array< typename Derived::Scalar, Eigen::Dynamic, 1 > logLikelihoods(M const &measurement, Space const &space, Eigen::MatrixBase< Derived > const &states)
Definition Likelihood.h:408
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
The resamplers, each made by its factory (decisions.md [policy-factories]): multinomial(),...
Definition Resampling.h:210
Rows of a contiguous block of a space.
Definition TagPath.h:825
A covariance per point.
Definition Conditionals.h:59
One covariance for every point.
Definition Conditionals.h:49