69template <
typename ComponentUpdate,
typename Scalar =
double,
typename Allocator = DefaultAllocator>
79 :
components(internal::ReBound<Allocator, ComponentUpdate>(allocator))
80 , m_posteriorEnds(internal::ReBound<Allocator, Eigen::Index>(allocator))
84 [[nodiscard]] Allocator
94 return m_logLikelihood;
105 [[nodiscard]] std::ranges::iota_view<Eigen::Index, Eigen::Index>
108 EMRYS_FILTER_ASSERT(i >= 0 && i < Eigen::Index(m_posteriorEnds.size()) &&
"prior component index out of range");
109 Eigen::Index
const first = i == 0 ? 0 : m_posteriorEnds[std::size_t(i - 1)];
110 return std::views::iota(first, m_posteriorEnds[std::size_t(i)]);
118 friend struct internal::UpdateAccess;
120 Scalar m_logLikelihood = 0;
123 internal::Buffer<Eigen::Index, Allocator> m_posteriorEnds;
144template <Space Space_, RealScalar Scalar_ =
double,
typename Allocator_ = DefaultAllocator>
256 requires std::same_as<typename Recursion_::ModelType, Model_>
257 && std::same_as<typename Recursion_::MethodType, Method_>
259 :
public internal::HeldUpkeep<MixtureFilter<Component_, Model_, Method_, Allocator_, Recursion_, Upkeep_>, Upkeep_>
261 using UpkeepBase = internal::HeldUpkeep<MixtureFilter, Upkeep_>;
264 internal::predictsBy<Model_, Method_>,
265 "a filter with a fixed-step model predicts by the model's method"
267 static_assert(internal::checkPredictionMethod<Method_>());
288 template <Measurement M>
290 internal::RebindUpdateAllocator<typename RecursionType::template UpdateType<M>::value_type, Allocator_>,
295 template <Measurement M>
306 std::type_identity_t<Upkeep_>
upkeep = {}
308 : UpkeepBase{std::move(upkeep)}
309 , m_state{std::move(
state)}
310 , m_recursion{makeRecursion(std::move(
model), std::move(
method), m_state)}
320 requires(!std::same_as<Upkeep_, Emrys::upkeep::None>)
330 : UpkeepBase{std::move(
upkeep)}
331 , m_state{std::move(state)}
332 , m_recursion{std::move(recursion)}
333 , m_posterior{m_state.space(), m_state.get_allocator()}
339 [[nodiscard]] allocator_type
342 return m_state.get_allocator();
346 [[nodiscard]] StateType
const &
357 [[nodiscard]] StateType &
372 EMRYS_FILTER_ASSERT(!
state.empty() &&
"the mixture must have a component");
373 m_state = std::move(
state);
374 if (m_posterior.get_allocator() != m_state.get_allocator() || m_posterior.space() != m_state.space()
375 || m_posterior.capacity() != m_state.capacity())
378 m_posterior =
StateType{m_state.space(), m_state.get_allocator()};
380 if constexpr (
requires { m_recursion.resetScratch(componentAllocator()); })
382 if (m_recursion.get_allocator() != componentAllocator())
384 m_recursion.resetScratch(componentAllocator());
391 [[nodiscard]] RecursionType
const &
398 [[nodiscard]] Model_
const &
401 return m_recursion.model();
405 [[nodiscard]] Model_ &
408 return m_recursion.model();
412 [[nodiscard]] Method_
const &
415 return m_recursion.method();
426 template <
typename... Inputs>
443 assertRunsUnder<P>();
444 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the mixture must have a component");
445 Scalar const step = internal::toScalarTime<Scalar>(dt);
446 return predictComponents(std::forward<P>(policy), [&](
ComponentType & component) {
447 return m_recursion.predict(component, step, inputs...);
454 template <
typename... Inputs>
455 requires(
isFixedStep<Model_> && !internal::leadsWithPolicy<Inputs...> && !internal::leadsWithSteps<Inputs...>)
459 internal::rejectTimeStep<Inputs...>();
467 predict(P && policy, Inputs
const &... inputs)
469 internal::rejectTimeStep<Inputs...>();
470 assertRunsUnder<P>();
471 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the mixture must have a component");
472 return predictComponents(std::forward<P>(policy), [&](
ComponentType & component) {
473 return m_recursion.predict(component, inputs...);
480 template <
typename... Inputs>
496 EMRYS_FILTER_ASSERT(steps.
count >= 0 &&
"the number of steps must be nonnegative");
497 using Result =
decltype(
predict(policy, inputs...));
498 if constexpr (std::is_void_v<Result>)
500 for (Eigen::Index i = 0; i < steps.
count; ++i)
507 for (Eigen::Index i = 0; i < steps.
count; ++i)
509 if (Result result =
predict(policy, inputs...); !result)
525 template <
typename... Inputs>
527 [[nodiscard]] JointType
530 auto joint = emptyJoint();
538 template <
typename JointAllocator,
typename... Inputs>
544 Inputs
const &... inputs
553 template <
ExecutionPolicy P,
typename JointAllocator,
typename... Inputs>
560 Inputs
const &... inputs
563 Scalar const step = internal::toScalarTime<Scalar>(dt);
564 recordJoint(std::forward<P>(policy), joint, [&](
ComponentType & component) {
565 return m_recursion.predictJoint(component, step, inputs...);
574 template <
typename... Inputs>
577 && !internal::leadsWithSteps<Inputs...>
579 [[nodiscard]] JointType
582 internal::rejectTimeStep<Inputs...>();
583 auto joint = emptyJoint();
589 template <
typename JointAllocator,
typename... Inputs>
600 template <
ExecutionPolicy P,
typename JointAllocator,
typename... Inputs>
606 Inputs
const &... inputs
609 recordJoint(std::forward<P>(policy), joint, [&](
ComponentType & component) {
610 return m_recursion.predictJoint(component, inputs...);
630 template <Measurement M,
typename Policy = reductions::Collapse>
635 [[nodiscard]] UpdateType<M>
636 update(M
const & measurement, Policy
const & policy = {})
645 template <ExecutionPolicy P, Measurement M,
typename Policy = reductions::Collapse>
648 || MixtureReductionPolicy<Policy, internal::MeasuredUpdate<ComponentType, M>, Component_>
650 [[nodiscard]] UpdateType<M>
651 update(P && executionPolicy, M
const & measurement, Policy
const & policy = {})
653 auto result = emptyResult<ResultType<M>>();
654 auto const updated =
update(std::forward<P>(executionPolicy), measurement, policy, result);
657 return std::unexpected{updated.error()};
668 template <Measurement M,
typename Policy,
typename ResultAllocator>
673 [[nodiscard]] std::expected<void, NumericError>
675 M
const & measurement,
676 Policy
const & policy,
686 template <ExecutionPolicy P, Measurement M,
typename Policy,
typename ResultAllocator>
691 [[nodiscard]] std::expected<void, NumericError>
693 P && executionPolicy,
694 M
const & measurement,
695 Policy
const & policy,
699 if constexpr (keepsBranches<M, Policy>())
701 return updateBranches(std::forward<P>(executionPolicy), measurement, policy, result);
707 auto const reading = internal::WithStatistics<Policy>{policy};
708 return updateComponents(
709 std::forward<P>(executionPolicy),
711 [&]<
typename Update>(
ComponentType & component, Update & slot) {
712 return m_recursion.update(component, measurement, reading, slot);
715 return m_recursion.update(component, measurement, reading);
729 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the initial mixture must have a component");
730 internal::assertPartitions(m_recursion.model(), m_state.space());
731 if (
auto const capacity = m_state.capacity())
733 m_posterior.setCapacity(*capacity);
737 m_posterior.reserve(m_state.size());
742 template <
typename P>
743 static constexpr void
747 internal::isSequential<P> || RecursionType::Reentrant,
748 "a recursion with scratch, such as the IMM's, runs the components in order: pass Sequential"
758 if constexpr (std::is_constructible_v<
762 decltype(componentAllocator(state))>)
764 return RecursionType{std::move(model), std::move(method), componentAllocator(state)};
768 return RecursionType{std::move(model), std::move(method)};
775 [[nodiscard]]
static auto
776 componentAllocator(StateType
const & state)
778 if constexpr (
requires(ComponentType
const & c) { c.get_allocator(); })
780 EMRYS_FILTER_ASSERT(!state.empty() &&
"the initial mixture must have a component");
781 return state.begin()->component.get_allocator();
785 return state.get_allocator();
791 componentAllocator()
const
793 return componentAllocator(m_state);
801 template <Measurement M,
typename Policy>
802 [[nodiscard]]
static consteval bool
807 using Measured =
typename decltype(internal::updateBranches<true>(
808 std::declval<ComponentType const &>(),
809 std::declval<M const &>()
811 return !internal::keepsOne<Policy, typename Measured::Container, ComponentType>;
826 template <ExecutionPolicy P,
typename PredictOne>
828 predictComponents(P && policy, PredictOne
const & predictOne)
830 using Moved = std::invoke_result_t<PredictOne const &, ComponentType &>;
831 if constexpr (std::is_void_v<Moved>)
833 m_state.forEach(std::forward<P>(policy), [&](
auto & entry) {
834 entry.updateComponent(predictOne);
840 auto failed = std::atomic_flag{};
841 auto error =
typename Moved::error_type{};
842 m_state.forEach(std::forward<P>(policy), [&](
auto & entry) {
843 Moved
const moved = entry.updateComponent(predictOne);
844 if (!moved && !failed.test_and_set())
846 error = moved.error();
849 return failed.test() ? Moved{std::unexpected{error}} : Moved{};
854 [[nodiscard]] JointType
858 internal::bufferOf<Scalar>(get_allocator()),
859 internal::bufferOf<PredictedJoint<SpaceType, Scalar>>(get_allocator()),
860 typename JointType::LineageType(get_allocator())
868 template <ExecutionPolicy P,
typename Jo
intAllocator,
typename PredictOne>
873 PredictOne
const & predictOne
876 assertRunsUnder<P>();
877 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the mixture must have a component");
878 std::size_t
const count = std::size_t(m_state.size());
879 internal::MixtureLineageAccess::assign(joint.lineage, m_state.lineage());
880 joint.logWeights.clear();
881 for (
auto const & entry : m_state)
883 joint.logWeights.push_back(entry.logWeight);
885 joint.joints.resize(count);
886 m_state.forEach(std::forward<P>(policy), [&](
auto & entry) {
887 joint.joints[std::size_t(entry.index())] = entry.updateComponent([&](ComponentType & component) {
888 return predictOne(component);
891 m_state.startLineage();
895 template <
typename Result>
899 auto result = Result{get_allocator()};
900 result.components.reserve(std::size_t(m_state.size()));
901 internal::UpdateAccess::posteriorEnds(result).reserve(std::size_t(m_state.size()));
909 template <
typename Result>
911 posteriorEndsFor(Result & result)
const
913 auto & ends = internal::UpdateAccess::posteriorEnds(result);
914 if (
auto const capacity = m_state.capacity())
916 ends.reserve(std::size_t(*capacity));
918 ends.resize(std::size_t(m_state.size()));
925 template <
typename Result>
927 keepPriorIndices(Result & result)
const
929 auto & ends = internal::UpdateAccess::posteriorEnds(result);
930 std::iota(ends.begin(), ends.end(), Eigen::Index{1});
945 template <ExecutionPolicy P,
typename Result,
typename UpdateInto,
typename UpdateNew>
946 [[nodiscard]] std::expected<void, NumericError>
947 updateComponents(P && executionPolicy, Result & result, UpdateInto
const & updateInto, UpdateNew
const & updateNew)
949 assertRunsUnder<P>();
950 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the mixture must have a component");
952 auto const logTotal = m_state.logTotalWeight();
955 return std::unexpected{logTotal.error()};
957 Eigen::Index
const count = m_state.size();
958 using Update =
typename Result::ComponentUpdateType;
960 if constexpr (internal::isSequential<P>)
965 Eigen::Index
const held = std::min(Eigen::Index(result.components.size()), count);
966 result.components.erase(result.components.begin() + held, result.components.end());
967 auto failure = std::optional<GaussianError>{};
973 auto const updated = [&]() -> std::expected<void, NumericError> {
974 if (entry.index() < held)
976 return entry.updateComponent([&](ComponentType & component) {
977 return updateInto(component, result.components[std::size_t(entry.index())]);
980 else if constexpr (internal::EmptyFromAllocator<Update, Allocator_>)
982 result.components.push_back(internal::emptyUpdate<Update>(get_allocator()));
983 return entry.updateComponent([&](ComponentType & component) {
984 return updateInto(component, result.components.back());
989 auto update = entry.updateComponent([&](ComponentType & component) {
990 return updateNew(component);
994 return std::unexpected{
update.error()};
996 result.components.push_back(std::move(*
update));
1002 failure = updated.error();
1007 return std::unexpected{*failure};
1012 using Updated = std::remove_cvref_t<decltype(updateNew(std::declval<ComponentType &>()))>;
1013 auto slots = internal::bufferOf<std::optional<Updated>>(get_allocator());
1014 slots.resize(std::size_t(count));
1015 m_state.forEach(std::forward<P>(executionPolicy), [&](
auto & entry) {
1016 slots[std::size_t(entry.index())].emplace(entry.updateComponent([&](ComponentType & component) {
1017 return updateNew(component);
1020 result.components.clear();
1021 for (
auto & slot : slots)
1025 return std::unexpected{slot->error()};
1027 result.components.push_back(std::move(**slot));
1032 auto const logWeightOf = [&](Eigen::Index i) {
1033 return m_state[i].logWeight - *logTotal + result.components[std::size_t(i)].logLikelihood();
1035 auto const logKeptOf = [&](Eigen::Index i) {
1036 return logWeightOf(i) + logKeptWeightOf(result.components[std::size_t(i)]);
1041 bool accepted =
false;
1042 for (Eigen::Index i = 0; i < count; ++i)
1044 evidence.add(logWeightOf(i));
1047 || (result.components[std::size_t(i)].accepted && logKeptOf(i) > -Eigen::NumTraits<Scalar>::infinity());
1049 internal::UpdateAccess::logLikelihood(result) = evidence.
value();
1050 result.accepted = accepted;
1051 auto & ends = posteriorEndsFor(result);
1055 for (
auto & component : result.components)
1057 component.accepted =
false;
1059 keepPriorIndices(result);
1065 std::transform_inclusive_scan(
1066 result.components.begin(),
1067 result.components.end(),
1070 [](
auto const & component) {
1071 return Eigen::Index(component.accepted);
1075 for (Eigen::Index i = 0; i < count; ++i)
1077 if (result.components[std::size_t(i)].accepted)
1079 m_state.setLogWeight(i, logKeptOf(i));
1082 m_state.removeIf([&](Eigen::Index i,
auto const &) {
1083 return !result.components[std::size_t(i)].accepted;
1085 [[maybe_unused]]
auto const normalized = m_state.normalize();
1086 EMRYS_FILTER_ASSERT(normalized &&
"an accepted component keeps a nonzero weight");
1099 template <ExecutionPolicy P, Measurement M,
typename Policy,
typename Result>
1100 [[nodiscard]] std::expected<void, NumericError>
1101 updateBranches(P && executionPolicy, M
const & measurement, Policy
const & policy, Result & result)
1103 EMRYS_FILTER_ASSERT(!m_state.empty() &&
"the mixture must have a component");
1104 auto const logTotal = m_state.logTotalWeight();
1107 return std::unexpected{logTotal.error()};
1109 Eigen::Index
const count = m_state.size();
1110 using Update =
typename Result::ComponentUpdateType;
1112 m_posterior.clear();
1113 internal::MixtureLineageAccess::startFrom(m_posterior, m_state);
1114 auto & ends = posteriorEndsFor(result);
1119 auto const reduce = [&](Eigen::Index i,
auto & measured) {
1120 Scalar
const logWeight = m_state[i].logWeight - *logTotal + measured.logLikelihood();
1121 evidence.add(logWeight);
1122 auto out = PosteriorOutput{*
this, i, logWeight};
1123 internal::reduceInto(policy, std::move(measured.branches), out);
1125 ends[std::size_t(i)] = m_posterior.size();
1128 if constexpr (internal::isSequential<P>)
1130 Eigen::Index
const held = std::min(Eigen::Index(result.components.size()), count);
1131 result.components.erase(result.components.begin() + held, result.components.end());
1132 for (Eigen::Index i = 0; i < count; ++i)
1135 auto const updated = internal::updateSlot<true>(
1139 m_state[i].component,
1141 [&](
auto & measured) {
1142 return reduce(i, measured);
1154 decltype(internal::updateBranches<true>(std::declval<ComponentType const &>(), measurement));
1155 auto measuredAll = internal::bufferOf<std::optional<Measured>>(get_allocator());
1156 measuredAll.resize(std::size_t(count));
1157 internal::forEachIndex(std::forward<P>(executionPolicy), count, [&](Eigen::Index i) {
1158 measuredAll[std::size_t(i)].emplace(internal::updateBranches<true>(m_state[i].component, measurement));
1160 for (
auto const & measured : measuredAll)
1164 return std::unexpected{measured->error()};
1167 result.components.clear();
1168 for (Eigen::Index i = 0; i < count; ++i)
1170 auto & measured = **measuredAll[std::size_t(i)];
1171 bool const accepted = reduce(i, measured);
1172 if constexpr (internal::EmptyFromAllocator<Update, Allocator_>)
1174 result.components.push_back(internal::emptyUpdate<Update>(get_allocator()));
1175 internal::filterUpdateInto(measured, accepted, result.components.back());
1179 result.components.push_back(internal::filterUpdate(std::move(measured), accepted));
1183 internal::UpdateAccess::logLikelihood(result) = evidence.
value();
1186 result.accepted = !m_posterior.empty() && m_posterior.normalize().has_value();
1187 if (!result.accepted)
1189 for (
auto & component : result.components)
1191 component.accepted =
false;
1193 keepPriorIndices(result);
1196 m_state.swap(m_posterior);
1205 struct PosteriorOutput
1207 using ComponentType = Params<Component_>;
1208 static constexpr bool HoldsSeveral =
true;
1210 MixtureFilter & filter;
1217 add(Scalar weight, ComponentType && component)
1219 filter.m_posterior.add(logWeight + weight, std::move(component));
1220 internal::MixtureLineageAccess::inherit(filter.m_posterior, filter.m_state, prior);
1226 add(Scalar weight, ComponentType
const & component)
1228 add(weight, ComponentType(component));
1236 template <
typename Update>
1237 [[nodiscard]]
static Scalar
1238 logKeptWeightOf(Update
const &
update)
1240 if constexpr (internal::isFilterUpdate<Update>)
1242 return Scalar(internal::MixtureEvidenceAccess::logKeptWeight(
update));
1251 RecursionType m_recursion;
1252 StateType m_posterior;
1256template <Component C,
typename Model,
typename Method = DefaultMethodFor<Model>,
typename Allocator>
1257 requires(!Recursion<Model> && !internal::UpkeepArgument<Method>)
1258MixtureFilter(Model, MixtureParams<C, Allocator>, Method = {}) -> MixtureFilter<
1260 internal::BoundStep<Model,
typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1264template <Component C, RecursionOver<C> R,
typename Allocator>
1265MixtureFilter(R, MixtureParams<C, Allocator>)
1266 -> MixtureFilter<C, typename R::ModelType, typename R::MethodType, Allocator, R>;
1268template <Component C,
typename Model,
typename Allocator,
typename U>
1269 requires(!Recursion<Model> && internal::UpkeepArgument<U>)
1270MixtureFilter(Model, MixtureParams<C, Allocator>, U) -> MixtureFilter<
1272 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1273 DefaultMethodFor<Model>,
1275 internal::RecursionForType<
1277 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1278 DefaultMethodFor<Model>,
1282template <Component C,
typename Model,
typename Method,
typename Allocator,
typename U>
1283 requires(!Recursion<Model>)
1284MixtureFilter(Model, MixtureParams<C, Allocator>, Method, U) -> MixtureFilter<
1286 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1289 internal::RecursionForType<
1291 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1296template <Component C, RecursionOver<C> R,
typename Allocator,
typename U>
1297 requires internal::UpkeepArgument<U>
1298MixtureFilter(R, MixtureParams<C, Allocator>, U)
1299 -> MixtureFilter<C, typename R::ModelType, typename R::MethodType, Allocator, R, U>;
1324 typename Method_ = DefaultMethodFor<Model_>,
1325 RealScalar Scalar_ = double,
1327 typename Upkeep_ = upkeep::None>
1330 Gaussian<Space_, Scalar_>,
1334 internal::RecursionForType<Gaussian<Space_, Scalar_>, Model_, Method_, Allocator_>,
1345 internal::RecursionForType<Gaussian<Space_, Scalar_>, Model_, Method_, Allocator_>,
1352 template <
typename... Args>
1354 std::constructible_from<
Base, Args...>
1355 && !(
sizeof...(Args) == 1 && (std::is_same_v<std::remove_cvref_t<Args>,
GaussianMixtureFilter> && ...))
1358 :
Base(std::forward<Args>(args)...)
1367 typename Method = DefaultMethodFor<Model>,
1370 requires(!internal::UpkeepArgument<Method>)
1371GaussianMixtureFilter(Model, MixtureParams<Gaussian<Space, Scalar>, Allocator>, Method = {})
1372 -> GaussianMixtureFilter<Space, internal::BoundStep<Model, Space, Scalar>, Method, Scalar, Allocator>;
1374template <
typename Space,
typename Model,
typename Scalar,
typename Allocator,
typename U>
1375 requires internal::UpkeepArgument<U>
1376GaussianMixtureFilter(Model, MixtureParams<Gaussian<Space, Scalar>, Allocator>, U) -> GaussianMixtureFilter<
1378 internal::BoundStep<Model, Space, Scalar>,
1379 DefaultMethodFor<Model>,
1384template <
typename Space,
typename Model,
typename Method,
typename Scalar,
typename Allocator,
typename U>
1385GaussianMixtureFilter(Model, MixtureParams<Gaussian<Space, Scalar>, Allocator>, Method, U)
1386 -> GaussianMixtureFilter<Space, internal::BoundStep<Model, Space, Scalar>, Method, Scalar, Allocator, U>;
1391#ifndef EMRYS_FILTER_NO_IO
1401 typename Component_,
1404 typename Allocator_,
1405 typename Recursion_,
1409 std::ostream & stream,
1410 MixtureFilter<Component_, Model_, Method_, Allocator_, Recursion_, Upkeep_>
const & filter,
1414 describeFilter(stream,
"mixture filter", filter.state(), indent);
1418template <
typename Space_,
typename Model_,
typename Method_,
typename Scalar_,
typename Allocator_,
typename Upkeep_>
1421 std::ostream & stream,
1422 GaussianMixtureFilter<Space_, Model_, Method_, Scalar_, Allocator_, Upkeep_>
const & filter,
1426 describeFilter(stream,
"Gaussian mixture filter", filter.state(), indent);
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
What a container of several Gaussians needs of each one (decisions.md [component-first]): the Compone...
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
The upkeep a filter holds (decisions.md [upkeep]): internal::HeldUpkeep, the base that gives every fi...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
ImmRecursion and ImmFilter (decisions.md [switching-models], [imm], [filters-and-recursions]): a Hybr...
KalmanRecursion and KalmanFilter (decisions.md [templated-measurements] and [filters-and-recursions])...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
The update of a Gaussian by a measurement (decisions.md [templated-measurements], [weighted-branches]...
The mixture: the parameters MixtureParams of weighted components of one type (decisions....
Printing: operator<< and std::formatter for every distribution, every filter (which prints its name a...
Process models as functions with reads and writes (decisions.md [model-policies], [continuous-time-no...
The Recursion concept (decisions.md [filters-and-recursions], [user-extension-points]): what a Kalman...
Reducing an update's branches (decisions.md [weighted-branches], [reduction-policies],...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
MixtureFilter< Gaussian< Space_, Scalar_ >, Model_, Method_, Allocator_, internal::RecursionForType< Gaussian< Space_, Scalar_ >, Model_, Method_, Allocator_ >, Upkeep_ > Base
the filter this is
Definition MixtureFilter.h:1340
GaussianMixtureFilter(Args &&... args)
The filter MixtureFilter's constructor makes from args.
Definition MixtureFilter.h:1357
The density of a Gaussian whose covariance has been factorized: a read-only view.
Definition Gaussian.h:1011
Streaming log-sum-exp: accumulates without overflow.
Definition Weights.h:46
Scalar value() const
Definition Weights.h:133
MixtureFilter(Model_ model, StateType state, std::type_identity_t< Upkeep_ > upkeep)
A filter with process model model, initial state state, the default prediction method,...
Definition MixtureFilter.h:319
auto predict(Inputs const &... inputs)
Moves each component forward by the fixed-step model's step, with inputs passed as in Emrys::predict(...
Definition MixtureFilter.h:457
Method_ const & method() const
Definition MixtureFilter.h:413
Model_ & model()
Definition MixtureFilter.h:406
RecursionType const & recursion() const
Definition MixtureFilter.h:392
JointType predictJoint(Inputs const &... inputs)
Moves each Gaussian component forward as predict(inputs...) does with a fixed-step model,...
Definition MixtureFilter.h:580
StateType & state()
Definition MixtureFilter.h:358
std::expected< ResultType< M >, NumericError > UpdateType
What update() with M returns: the ResultType in a std::expected (decisions.md [innovation-cholesky]).
Definition MixtureFilter.h:296
typename Params< Component_ >::SpaceType SpaceType
the state space
Definition MixtureFilter.h:272
Recursion_ RecursionType
the steps each component runs (see Recursion)
Definition MixtureFilter.h:280
void predictJoint(P &&policy, GaussianMixturePredictedJoint< SpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
predictJoint(joint, inputs...) under policy, as predictJoint(policy, dt, joint, inputs....
Definition MixtureFilter.h:603
typename Params< Component_ >::Scalar Scalar
the scalar type
Definition MixtureFilter.h:271
void predictJoint(GaussianMixturePredictedJoint< SpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(inputs...), but into joint, whose storage is reused.
Definition MixtureFilter.h:592
UpdateType< M > update(M const &measurement, Policy const &policy={})
Conditions each component on measurement, by the measurement's own method, reduces its branches with ...
Definition MixtureFilter.h:636
Allocator_ allocator_type
the state's allocator
Definition MixtureFilter.h:277
std::expected< void, NumericError > update(M const &measurement, Policy const &policy, MixtureFilterUpdate< typename ResultType< M >::ComponentUpdateType, Scalar, ResultAllocator > &result)
As update(measurement, policy), but into result, whose storage is reused: with the same result at eve...
Definition MixtureFilter.h:674
StateType const & state() const
Definition MixtureFilter.h:347
auto predict(TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Moves each component forward by dt, any TimeStep (see Time steps), through the process model,...
Definition MixtureFilter.h:429
void predictJoint(P &&policy, TimeStep< Scalar > auto const &dt, GaussianMixturePredictedJoint< SpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
predictJoint(dt, joint, inputs...) under policy, a for-each over the components into the joint's slot...
Definition MixtureFilter.h:556
auto predict(Steps steps, Inputs const &... inputs)
Moves each component forward by steps of the fixed-step model, as that many calls of predict(inputs....
Definition MixtureFilter.h:483
UpdateType< M > update(P &&executionPolicy, M const &measurement, Policy const &policy={})
update(measurement, policy) under executionPolicy: each component's update is a for-each into slots m...
Definition MixtureFilter.h:651
Model_ const & model() const
Definition MixtureFilter.h:399
Model_ ModelType
the process model
Definition MixtureFilter.h:273
auto predict(P &&policy, Inputs const &... inputs)
predict(inputs...) under policy, as predict(policy, dt, inputs...) runs.
Definition MixtureFilter.h:467
JointType predictJoint(TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Moves each Gaussian component forward as predict(dt, inputs...) does, and starts the state's lineage ...
Definition MixtureFilter.h:528
auto predict(P &&policy, Steps steps, Inputs const &... inputs)
predict(steps, inputs...) under policy, as that many calls of predict(policy, inputs....
Definition MixtureFilter.h:494
MixtureFilter(Recursion_ recursion, StateType state, std::type_identity_t< Upkeep_ > upkeep={})
A filter that runs recursion, the library's or one of the user's own (see Recursion),...
Definition MixtureFilter.h:329
MixtureFilter(Model_ model, StateType state, MethodFor< Model_, Method_ > method={}, std::type_identity_t< Upkeep_ > upkeep={})
A filter with process model model, initial state state, prediction method method, which a fixed-step ...
Definition MixtureFilter.h:302
auto predict(P &&policy, TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
predict(dt, inputs...) under policy, a for-each over the components, so the result is Sequential's (s...
Definition MixtureFilter.h:441
void setState(StateType state)
Replaces the state estimate, as when reinitializing, with one that has at least one component and who...
Definition MixtureFilter.h:370
Method_ MethodType
the prediction method
Definition MixtureFilter.h:274
allocator_type get_allocator() const
Definition MixtureFilter.h:340
MixtureParams< Component_, Allocator_ > StateType
the state the filter owns
Definition MixtureFilter.h:275
GaussianMixturePredictedJoint< SpaceType, Scalar, Allocator_ > JointType
what predictJoint() returns, for Gaussian components
Definition MixtureFilter.h:283
void predictJoint(TimeStep< Scalar > auto const &dt, GaussianMixturePredictedJoint< SpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(dt, inputs...), but into joint, whose storage is reused: with the same joint at every...
Definition MixtureFilter.h:541
std::expected< void, NumericError > update(P &&executionPolicy, M const &measurement, Policy const &policy, MixtureFilterUpdate< typename ResultType< M >::ComponentUpdateType, Scalar, ResultAllocator > &result)
update(measurement, policy, result) under executionPolicy, as update(executionPolicy,...
Definition MixtureFilter.h:692
Params< Component_ > ComponentType
one component of the state
Definition MixtureFilter.h:276
MixtureFilterUpdate< internal::RebindUpdateAllocator< typename RecursionType::template UpdateType< M >::value_type, Allocator_ >, Scalar, Allocator_ > ResultType
What update() with M fills when given a result: one component's update per component,...
Definition MixtureFilter.h:289
How each component of a Mixture descends from the components it had at its last startLineage(): each ...
Definition Mixture.h:127
A weighted sum of components of one type, all in one space.
Definition Mixture.h:579
The distribution that a container of several holds one of per element (decisions.md [component-first]...
Definition Component.h:299
An execution policy: execution::sequential, a policy of the standard library such as std::execution::...
Definition Execution.h:459
A reduction policy a MixtureFilter over Component_ takes for Update: one that reduces the branches in...
Definition Reduction.h:643
A Recursion whose steps act on the parameters of the component Component_, the constraint a filter ov...
Definition Recursion.h:87
A step of time that converts to Scalar: Scalar itself, or any type with a TimeTraits,...
Definition Time.h:128
std::allocator< std::byte > DefaultAllocator
The allocator a type with a run-time count uses unless given one.
Definition Allocation.h:47
NumericError
Reasons a computation from parameters the caller gave can fail: a matrix that does not factorize or a...
Definition NumericError.h:30
constexpr bool isGaussian
Whether C is a Gaussian in covariance form: the component for which a container offers the convenienc...
Definition Component.h:111
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
typename internal::DefaultMethodOf< Model >::type DefaultMethodFor
The prediction method of a filter with process model Model, unless it is given one: Linearized,...
Definition ProcessModel.h:3220
constexpr bool isFixedStep
Whether Model is a FixedStepModel, whose predictions take no time step.
Definition ProcessModel.h:2776
std::expected< CategoricalUpdate< Space, Scalar >, WeightError > update(CategoricalParams< Space, Scalar > const &prior, E const &emission)
Definition Emission.h:97
std::conditional_t< isFixedStep< Model >, ModelsMethod, Method > MethodFor
The type of a filter constructor's method argument: Method, or ModelsMethod for a fixed-step Model,...
Definition ProcessModel.h:3236
The upkeep operations, each made by its factory (decisions.md [policy-factories], [upkeep]): the acti...
Definition Upkeep.h:380
One prediction of a mixture of Gaussians as its smoother needs it: the weights the step started from,...
Definition MixtureFilter.h:146
internal::Buffer< Scalar_, Allocator_ > LogWeightsType
the components' log-weights
Definition MixtureFilter.h:151
LineageType lineage
Definition MixtureFilter.h:156
Scalar_ Scalar
the scalar type
Definition MixtureFilter.h:147
PredictedJoint< Space_, Scalar_ > JointType
one component's joint
Definition MixtureFilter.h:149
LogWeightsType logWeights
Definition MixtureFilter.h:154
internal::Buffer< JointType, Allocator_ > JointsType
the components' joints
Definition MixtureFilter.h:150
Space_ SpaceType
the state space
Definition MixtureFilter.h:148
MixtureLineage< Scalar_, Allocator_ > LineageType
the components' descent
Definition MixtureFilter.h:152
JointsType joints
Definition MixtureFilter.h:155
What a mixture filter's update did: each prior component's update before reduction,...
Definition MixtureFilter.h:71
MixtureFilterUpdate(Allocator const &allocator)
An empty result whose components come from allocator.
Definition MixtureFilter.h:78
std::ranges::iota_view< Eigen::Index, Eigen::Index > posteriorIndices(Eigen::Index i) const
Definition MixtureFilter.h:106
ComponentUpdate ComponentUpdateType
one component's update
Definition MixtureFilter.h:72
internal::Buffer< ComponentUpdate, Allocator > ComponentsType
the components' container
Definition MixtureFilter.h:73
MixtureFilterUpdate()=default
an empty result, from a default-constructed allocator
bool accepted
whether any component accepted the measurement
Definition MixtureFilter.h:114
Allocator get_allocator() const
Definition MixtureFilter.h:85
ComponentsType components
one per prior component, in order
Definition MixtureFilter.h:113
Scalar logLikelihood() const
Definition MixtureFilter.h:92
One prediction step as a joint: the Gaussian the step started from, the Gaussian it predicted,...
Definition ProcessModel.h:2817
A count of a fixed-step model's steps, for predict(Steps{n}).
Definition Time.h:136
Eigen::Index count
the number of steps, at least zero
Definition Time.h:137
The upkeep a filter holds when it is given none: it takes any state, changes nothing,...
Definition Upkeep.h:889