61template <
typename ModeUpdate,
typename Scalar_ =
double,
typename Allocator = DefaultAllocator>
72 :
modes(internal::ReBound<Allocator, ModeUpdate>(allocator))
76 [[nodiscard]] Allocator
79 return Allocator(
modes.get_allocator());
86 return m_logLikelihood;
94 friend struct internal::UpdateAccess;
96 Scalar m_logLikelihood = 0;
103template <
typename ModeUpdate,
typename Scalar,
typename Old,
typename Allocator>
104struct RebindUpdateAllocatorOf<
ImmFilterUpdate<ModeUpdate, Scalar, Old>, Allocator>
136template <Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ =
double,
typename Allocator_ = DefaultAllocator>
146 using PredictionsType = internal::Buffer<GaussianParams<Space_, Scalar_>, Allocator_>;
166 return joints[std::size_t(from)].predicted;
168 Eigen::Index
const count = Eigen::Index(
joints.size());
169 return throughOtherModels[std::size_t(from * (count - 1) + (model < from ? model : model - 1))];
179template <
typename C,
typename M,
bool = isOtherGaussianForm<C>>
183 using type =
typename decltype(
Emrys::update(std::declval<C const &>(), std::declval<M const &>()))::value_type;
189template <
typename C,
typename M>
190struct ImmMeasured<C, M, true>
193 using type =
typename decltype(updateInPlace<true>(std::declval<C &>(), std::declval<M const &>()))::value_type;
201template <
typename Lazy,
typename Policy>
202struct UnlessGivenBlock
204 using type =
typename Lazy::type;
208template <
typename Lazy,
typename Space,
typename P,
typename Value>
209struct UnlessGivenBlock<Lazy, GivenBlock<Space, P, Value>>
218struct MeasurementModeAxisOf
225 requires(M::ModelType::template has<PolicyKind::additiveNoise>)
226struct MeasurementModeAxisOf<M>
229 using type = NoiseModeAxis<typename M::ModelType::template Policy<PolicyKind::additiveNoise>>;
236inline constexpr bool isByMode = !std::is_void_v<typename MeasurementModeAxisOf<M>::type>;
242template <
typename Space,
typename P,
typename One,
typename Value>
246 GivenComponent(One one, Space whole, Value
const &
given)
247 : measurement{std::move(one)}
248 , space{std::move(whole)}
249 , pinned{space, measurement}
254 GivenComponent(GivenComponent
const & other)
255 : GivenComponent{other.measurement, other.space, other.value}
260 PinnedMeasurement<Space, P, One> pinned;
315 internal::predictsBy<Model_, Method_>,
316 "a filter with fixed-step models predicts each mode by its model's own method, so it takes "
317 "ModelsMethod, the default, as its method"
319 static_assert(internal::checkPredictionMethod<Method_>());
322 static constexpr bool IsForm = internal::isOtherGaussianForm<Params<Component_>>;
343 template <Measurement M>
344 using MeasuredType =
typename internal::ImmMeasured<ComponentType, M>::type;
349 template <Measurement M>
352 internal::isByMode<M>,
357 internal::FilterUpdateWithScratch<
367 template <Measurement M>
371 template <Measurement M>
380 template <
typename S>
386 template <
typename S>
392 template <Measurement M,
typename Space,
typename P>
394 std::declval<ComponentType const &>(),
395 std::declval<internal::PinnedMeasurement<Space, P, M>
const &>(),
396 std::declval<
typename Moments<internal::PathTag<P>,
Scalar>::VectorType
const &>()
402 template <Measurement M,
typename Space,
typename P>
405 internal::isByMode<M>,
407 internal::FilterUpdateWithScratch<
417 template <Measurement M,
typename Space,
typename P>
425 : m_model{std::move(
model)}
426 , m_method{internal::predictionMethod(m_model, std::move(
method))}
427 , m_predicted(ComponentAllocator(allocator))
428 , m_posterior(ComponentAllocator(allocator))
446 m_predicted = ConditionalsType(ComponentAllocator(allocator));
447 m_posterior = ConditionalsType(ComponentAllocator(allocator));
452 [[nodiscard]] Model_
const &
459 [[nodiscard]] Model_ &
468 [[nodiscard]] Method_
const &
478 return m_model.modeSpace();
485 return m_model.partitions(space);
496 template <
typename... Inputs>
501 Scalar const step = internal::toScalarTime<Scalar>(dt);
502 if constexpr (IsForm)
505 return internal::predictInPlace(
method, moved,
model, step, inputs...);
520 template <
typename... Inputs>
525 if constexpr (IsForm)
527 return moveModes(state, [&](
ComponentType & moved,
auto const &
model,
auto const &) {
528 return internal::predictInPlace(moved,
model, inputs...);
544 template <
typename... Inputs>
557 template <
typename JointAllocator,
typename... Inputs>
564 Inputs
const &... inputs
567 Scalar const step = internal::toScalarTime<Scalar>(dt);
578 predict(state, step, inputs...);
585 template <
typename... Inputs>
596 template <
typename JointAllocator,
typename... Inputs>
602 Inputs
const &... inputs
633 template <Measurement M,
typename Policy = reductions::Collapse>
634 requires(!internal::isGivenBlock<Policy>)
635 [[nodiscard]]
typename internal::UnlessGivenBlock<UpdateTypeOf<M>, Policy>::type
639 auto const updated =
update(state, measurement, policy, result);
642 return std::unexpected{updated.error()};
653 template <Measurement M,
typename Policy,
typename ModeUpdate,
typename ResultAllocator>
654 [[nodiscard]] std::expected<void, NumericError>
657 M
const & measurement,
658 Policy
const & policy,
662 if constexpr (internal::isByMode<M>)
664 return updateByAxis(state, measurement, policy, result, [](
auto one) {
674 [&](Eigen::Index,
auto const & updateMode) {
675 return updateMode(measurement);
677 [](
auto &, Eigen::Index) {}
692 result.modes.reserve(std::size_t(state.size()));
693 auto const updated =
update(state, measurement, policy, result);
696 return std::unexpected{updated.error()};
706 template <
typename P, Measurement... Ms,
typename Policy,
typename ModeUpdate,
typename ResultAllocator>
707 [[nodiscard]] std::expected<void, NumericError>
711 Policy
const & policy,
716 internal::pathResolves<P, ModeSpaceType>(),
717 "a switching measurement is selected by a mode axis that the filter's mode space does not have"
720 !(internal::isByMode<Ms> || ...),
721 "a measurement of a switching measurement has noise by mode axis, byMode<Axis>(): give each value's "
722 "measurement the noise it has in the modes with that value"
726 "the measurements of a switching measurement update a mode into one type: give them one measurement "
727 "space, and noise that is Gaussian in all of them or a mixture in all of them"
729 if constexpr (internal::pathResolves<P, ModeSpaceType>())
731 auto const [stride, axis] = internal::locateAxisByPath<P>(state.modeSpace());
732 Eigen::Index
const values = axis->cardinality();
734 values == Eigen::Index(
sizeof...(Ms)) &&
"give one measurement per value of the axis that selects it"
740 [&, stride](Eigen::Index m,
auto const & updateMode) {
741 return measurement.
visit(std::size_t((m / stride) % values), updateMode);
743 [](
auto &, Eigen::Index) {}
748 return std::expected<void, NumericError>{};
759 template <Measurement M,
typename Policy,
typename ModeUpdate,
typename ResultAllocator,
typename Wrap>
760 [[nodiscard]] std::expected<void, NumericError>
763 M
const & measurement,
764 Policy
const & policy,
769 using Axis =
typename internal::MeasurementModeAxisOf<M>::type;
771 internal::pathResolves<Axis, ModeSpaceType>(),
772 "the measurement's noise is by a mode axis, byMode<Axis>(), that the filter's mode space does not have"
774 if constexpr (internal::pathResolves<Axis, ModeSpaceType>())
776 return updateByAxisIn<Axis>(state, measurement, policy, result, wrap);
780 return std::expected<void, NumericError>{};
790 typename ResultAllocator,
792 [[nodiscard]] std::expected<void, NumericError>
795 M
const & measurement,
796 Policy
const & policy,
797 ImmFilterUpdate<ModeUpdate, Scalar, ResultAllocator> & result,
801 auto const [stride, axis] = internal::locateAxisByPath<Axis>(state.modeSpace());
802 Eigen::Index
const values = axis->cardinality();
803 auto const & noise = measurement.model().template policy<internal::PolicyKind::additiveNoise>().distribution();
804 EMRYS_FILTER_ASSERT(noise.size() == values &&
"the noise needs one component per value of the mode axis");
805 using Component = std::remove_cvref_t<
decltype(noise.begin()->component)>;
806 using One = internal::WithNoiseComponent<M, Component>;
808 auto const componentOf = [=](Eigen::Index m) {
809 return (m / stride) % values;
815 [&](Eigen::Index m,
auto const & updateMode) {
816 return updateMode(wrap(One{measurement, noise[componentOf(m)].component}));
818 [&](
auto & measured, Eigen::Index m) {
819 auto & branch = measured.branches.front();
820 branch.component = componentOf(m);
821 branch.logWeight =
Scalar(0);
836 template <Measurement M,
typename Space,
typename P,
typename Value,
typename Policy = reductions::Collapse>
841 M
const & measurement,
843 Policy
const & policy = {}
847 auto const updated =
update(state, measurement, pinned, policy, result);
850 return std::unexpected{updated.error()};
866 typename ResultAllocator>
868 [[nodiscard]] std::expected<void, NumericError>
871 M
const & measurement,
873 Policy
const & policy,
877 if constexpr (internal::isByMode<M>)
880 return updateByAxis(state, measurement, policy, result, [&]<
typename One>(One one) {
881 return internal::GivenComponent<Space, P, One, Value>{std::move(one), pinned.
space, pinned.
value};
886 auto const f = internal::PinnedMeasurement<Space, P, M>{pinned.
space, measurement};
904 typename ResultAllocator>
905 requires(!IsForm && !internal::isByMode<M>)
906 [[nodiscard]] std::expected<void, NumericError>
909 internal::PinnedMeasurement<Space, P, M>
const & f,
911 Policy
const & policy,
915 using Given = internal::GivenMeasurement<internal::PinnedMeasurement<Space, P, M>
const &, Value>;
920 [&](Eigen::Index,
auto const & updateMode) {
921 return updateMode(Given{f, value});
923 [](
auto &, Eigen::Index) {}
930 template <Measurement M>
932 emptyUpdate(Allocator_
const & allocator, Eigen::Index modes)
const
935 auto result = Result{allocator};
936 result.
modes.reserve(std::size_t(modes));
943 template <Measurement M,
typename Space,
typename P>
948 result.
modes.reserve(std::size_t(modes));
959 m_model.chain().matrix(),
962 joint.
joints.reserve(std::size_t(state.size()));
970 using ComponentAllocator =
typename ConditionalsType::allocator_type;
976 auto const modes = std::size_t(m_model.modeSpace().cardinality());
977 m_predicted.reserve(modes);
978 if constexpr (!IsForm)
980 m_posterior.reserve(modes);
993 template <
typename PredictMode>
995 moveModes(
StateType & state, PredictMode
const & predictMode)
997 if constexpr (IsForm)
999 auto failure = std::expected<void, NumericError>{};
1000 auto const keepFirst = [&](std::expected<void, NumericError>
const & moved) {
1001 if (!moved && failure)
1008 [&](Eigen::Index j,
auto const &
model,
auto const &
method) {
1009 keepFirst(state.updateConditional(j, [&](
ComponentType & own) {
1010 return predictMode(own, model, method);
1014 m_predicted.push_back(std::move(mixed));
1015 keepFirst(predictMode(m_predicted.back(),
model,
method));
1024 [&](Eigen::Index j,
auto const &
model,
auto const &
method) {
1025 m_predicted.push_back(predictMode(state.conditional(j),
model,
method));
1028 m_predicted.push_back(predictMode(mixed,
model,
method));
1038 template <
typename MoveOwn,
typename MoveMixed>
1040 moveModesBy(
StateType & state, MoveOwn
const & moveOwn, MoveMixed
const & moveMixed)
1042 Eigen::Index
const count = state.size();
1043 auto const & logPrior = state.modes().logWeights();
1044 auto const & transitions = m_model.chain().matrix();
1045 m_predicted.clear();
1046 if (transitions.isIdentity(
Scalar(0)))
1050 for (Eigen::Index j = 0; j < count; ++j)
1052 m_model.visit(j, m_method, [&](
auto const &
model,
auto const &
method) {
1056 if constexpr (!IsForm)
1058 state.swapConditionals(m_predicted);
1062 CategoricalParams<ModeSpaceType, Scalar>
const predictedModes =
Emrys::predict(state.modes(), m_model.chain());
1064 auto const conditional = [&](Eigen::Index i) ->
ComponentType const & {
1065 return state.conditional(i);
1067 auto logMixing =
typename StateType::ModesType::ArrayType{};
1068 logMixing.resize(count);
1069 for (Eigen::Index j = 0; j < count; ++j)
1072 bool const reachable = predictedModes.logWeight(j) > -Eigen::NumTraits<Scalar>::infinity();
1073 for (Eigen::Index i = 0; i < count; ++i)
1075 logMixing(i) = reachable ? Eigen::numext::log(transitions(i, j)) + logPrior(i)
1076 : (i == j ?
Scalar(0) : -Eigen::NumTraits<
Scalar>::infinity());
1078 ComponentType mixed = ComponentTraits<ComponentType>::collapse(count, conditional, [&](Eigen::Index i) {
1079 return logMixing(i);
1081 m_model.visit(j, m_method, [&](
auto const &
model,
auto const &
method) {
1085 state.swapConditionals(m_predicted);
1086 state.setModes(predictedModes);
1094 template <
typename Jo
intAllocator,
typename PredictMode,
typename PredictThrough>
1098 HybridPredictedJoint<SpaceType, ModeSpaceType, Scalar, JointAllocator> & joint,
1099 PredictMode
const & predictMode,
1100 PredictThrough
const & predictThrough
1103 Eigen::Index
const count = state.size();
1104 joint.modes = state.modes();
1105 joint.transitions = m_model.chain().matrix();
1106 joint.joints.clear();
1107 joint.joints.reserve(std::size_t(count));
1108 joint.throughOtherModels.clear();
1109 joint.throughOtherModels.reserve(std::size_t(count * (count - 1)));
1110 for (Eigen::Index j = 0; j < count; ++j)
1112 m_model.visit(j, m_method, [&](
auto const &
model,
auto const &
method) {
1113 joint.joints.push_back(predictMode(state.conditional(j),
model,
method));
1115 for (Eigen::Index i = 0; i < count; ++i)
1119 m_model.visit(i, m_method, [&](
auto const &
model,
auto const &
method) {
1120 joint.throughOtherModels.push_back(predictThrough(state.conditional(j),
model,
method));
1147 typename ModeUpdate,
1148 typename ResultAllocator,
1149 typename WithMeasurement,
1151 [[nodiscard]] std::expected<void, NumericError>
1154 Policy
const & policy,
1155 ImmFilterUpdate<ModeUpdate, Scalar, ResultAllocator> & result,
1156 WithMeasurement
const & withMeasurement,
1157 Relabel
const & relabel
1161 auto const logTotal = state.modes().logTotalWeight();
1164 return std::unexpected{logTotal.error()};
1166 Eigen::Index
const count = state.size();
1167 Eigen::Index
const held = std::min(Eigen::Index(result.modes.size()), count);
1168 result.modes.erase(result.modes.begin() + held, result.modes.end());
1169 internal::UpdateAccess::logLikelihood(result) =
Scalar(0);
1170 result.accepted =
false;
1171 m_posterior.clear();
1172 auto logLikelihoods =
typename StateType::ModesType::ArrayType{};
1174 for (Eigen::Index m = 0; m < count; ++m)
1176 auto const updateMode = [&](
auto const & measurement) -> std::expected<void, NumericError> {
1177 if constexpr (IsForm)
1180 internal::isCollapsePolicy<Policy>,
1181 "a square-root form has one branch and takes the Collapse policy alone; gating and selection "
1182 "among noise components are the covariance form's (decisions.md [gaussian-forms])"
1184 auto updated = state.updateConditional(m, [&](
ComponentType & conditional) {
1185 return internal::updateInPlace<true>(conditional, measurement);
1189 result.accepted =
false;
1190 return std::unexpected{updated.error()};
1192 relabel(*updated, m);
1193 updated->branches.front().mode = m;
1195 result.accepted =
true;
1196 if (std::size_t(m) == result.modes.size())
1198 result.modes.push_back(std::move(*updated));
1202 result.modes[std::size_t(m)] = std::move(*updated);
1207 auto const updated = internal::updateSlot<true>(
1210 ResultAllocator(result.modes.get_allocator()),
1211 state.conditional(m),
1213 [&](
auto & measured) {
1214 relabel(measured, m);
1215 for (auto & branch : measured.branches)
1220 ReductionPolicy<Policy, std::remove_cvref_t<
decltype(measured)>,
ComponentType>,
1221 "an IMM filter keeps one component per mode, so its policy must keep one: Collapse, "
1222 "Select, or a Gate over them"
1224 auto kept = std::optional<ComponentType>{};
1227 internal::reduceInto(policy, std::move(measured.branches), out);
1229 logLikelihoods(m) = out.added ? measured.logLikelihood() + out.logWeight
1230 : -Eigen::NumTraits<Scalar>::infinity();
1231 m_posterior.push_back(out.added ? std::move(*kept) : state.conditional(m));
1232 result.accepted = result.accepted || out.added;
1238 result.accepted =
false;
1244 if (
auto const updated = withMeasurement(m, updateMode); !updated)
1249 auto evidence = LogSumExp<Scalar>{};
1250 for (Eigen::Index m = 0; m < count; ++m)
1252 evidence.add(state.modes().logWeight(m) + result.modes[std::size_t(m)].logLikelihood());
1254 internal::UpdateAccess::logLikelihood(result) = evidence.value() - *logTotal;
1255 if (!result.accepted)
1260 CategoricalParams<ModeSpaceType, Scalar> modes = state.modes();
1265 result.accepted =
false;
1266 for (
auto & mode : result.modes)
1268 mode.accepted =
false;
1272 if constexpr (!IsForm)
1274 state.swapConditionals(m_posterior);
1276 state.setModes(std::move(modes));
1284 ConditionalsType m_predicted;
1286 ConditionalsType m_posterior;
1294 Component Component_,
1295 DiscreteSpace ModeSpace_,
1296 typename HybridAllocator,
1300struct RecursionFor<Hybrid<Component_, ModeSpace_, HybridAllocator>, Model, Method, Allocator>
1302 using type = ImmRecursion<Component_, Model, Method, HybridAllocator>;
1376 Component Component_,
1378 typename Method_ = DefaultMethodFor<Model_>,
1380 typename Upkeep_ = upkeep::None>
1381class ImmFilter :
public internal::HeldUpkeep<ImmFilter<Component_, Model_, Method_, Allocator_, Upkeep_>, Upkeep_>
1383 using UpkeepBase = internal::HeldUpkeep<ImmFilter, Upkeep_>;
1408 std::type_identity_t<Upkeep_>
upkeep = {}
1410 : UpkeepBase{std::move(upkeep)}
1411 , m_state{std::move(state)}
1412 , m_recursion{std::move(model), std::move(method), m_state.get_allocator()}
1414 EMRYS_FILTER_ASSERT(
1415 m_recursion.modeSpace() == m_state.modeSpace() &&
"the model and the state have different modes"
1417 internal::assertPartitions(
1418 m_recursion.model(),
1420 "every process model must write every coordinate of the state space once"
1428 requires(!std::same_as<Upkeep_, Emrys::upkeep::None>)
1433 [[nodiscard]] allocator_type
1436 return m_state.get_allocator();
1440 [[nodiscard]] StateType
const &
1450 [[nodiscard]] StateType &
1463 EMRYS_FILTER_ASSERT(
state.modeSpace() == m_recursion.modeSpace() &&
"the state has different modes");
1464 internal::assertPartitions(
1465 m_recursion.model(),
1467 "every process model must write every coordinate of the state space once"
1469 m_state = std::move(
state);
1470 if (m_state.get_allocator() != m_recursion.get_allocator())
1473 m_recursion.resetScratch(m_state.get_allocator());
1478 [[nodiscard]] RecursionType
const &
1485 [[nodiscard]] Model_
const &
1488 return m_recursion.model();
1492 [[nodiscard]] Model_ &
1495 return m_recursion.model();
1501 [[nodiscard]] Method_
const &
1504 return m_recursion.method();
1514 template <
typename... Inputs>
1519 return m_recursion.predict(m_state, internal::toScalarTime<Scalar>(dt), inputs...);
1526 template <
typename... Inputs>
1531 internal::rejectTimeStep<Inputs...>();
1532 return m_recursion.predict(m_state, inputs...);
1539 template <
typename... Inputs>
1544 EMRYS_FILTER_ASSERT(steps.
count >= 0 &&
"the number of steps must be nonnegative");
1545 using Result =
decltype(m_recursion.predict(m_state, inputs...));
1546 if constexpr (std::is_void_v<Result>)
1548 for (Eigen::Index i = 0; i < steps.
count; ++i)
1550 m_recursion.predict(m_state, inputs...);
1555 for (Eigen::Index i = 0; i < steps.
count; ++i)
1557 if (Result result = m_recursion.predict(m_state, inputs...); !result)
1571 template <
typename... Inputs>
1573 [[nodiscard]] JointType
1576 return m_recursion.predictJoint(m_state, internal::toScalarTime<Scalar>(dt), inputs...);
1582 template <
typename JointAllocator,
typename... Inputs>
1588 Inputs
const &... inputs
1591 m_recursion.predictJoint(m_state, internal::toScalarTime<Scalar>(dt), joint, inputs...);
1598 template <
typename... Inputs>
1600 [[nodiscard]] JointType
1603 internal::rejectTimeStep<Inputs...>();
1604 return m_recursion.predictJoint(m_state, inputs...);
1608 template <
typename JointAllocator,
typename... Inputs>
1613 Inputs
const &... inputs
1616 m_recursion.predictJoint(m_state, joint, inputs...);
1628 template <Measurement M,
typename Policy = reductions::Collapse>
1630 update(M
const & measurement, Policy
const & policy = {})
1632 return m_recursion.update(m_state, measurement, policy);
1640 template <Measurement M,
typename Policy,
typename ModeUpdate,
typename ResultAllocator>
1641 [[nodiscard]] std::expected<void, NumericError>
1644 return m_recursion.update(m_state, measurement, policy, result);
1655 return m_recursion.update(m_state, measurement, policy);
1663 template <
typename P, Measurement... Ms,
typename Policy,
typename ModeUpdate,
typename ResultAllocator>
1664 [[nodiscard]] std::expected<void, NumericError>
1667 Policy
const & policy,
1671 return m_recursion.update(m_state, measurement, policy, result);
1677 RecursionType m_recursion;
1685 typename Method = DefaultMethodFor<Model>,
1688 requires(!internal::UpkeepArgument<Method>)
1689ImmFilter(Model, HybridParams<C, ModeSpace, Allocator>, Method = {}) -> ImmFilter<
1691 internal::BoundStep<Model,
typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1695template <Component C,
typename Model,
typename Allocator,
typename ModeSpace,
typename U>
1696 requires internal::UpkeepArgument<U>
1697ImmFilter(Model, HybridParams<C, ModeSpace, Allocator>, U) -> ImmFilter<
1699 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1700 DefaultMethodFor<Model>,
1704template <Component C,
typename Model,
typename Method,
typename Allocator,
typename ModeSpace,
typename U>
1705ImmFilter(Model, HybridParams<C, ModeSpace, Allocator>, Method, U) -> ImmFilter<
1707 internal::BoundStep<Model, typename Params<C>::SpaceType,
typename Params<C>::Scalar>,
1715#ifndef EMRYS_FILTER_NO_IO
1724template <
typename Component_,
typename Model_,
typename Method_,
typename Allocator_,
typename Upkeep_>
1727 std::ostream & stream,
1728 ImmFilter<Component_, Model_, Method_, Allocator_, Upkeep_>
const & filter,
1732 describeFilter(stream,
"interacting multiple model filter", filter.state(), indent);
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
The distribution over a discrete space (decisions.md [discrete-spaces], [params-and-density]): Catego...
What a container of several Gaussians needs of each one (decisions.md [component-first]): the Compone...
Discrete spaces (decisions.md [discrete-spaces]): the DiscreteSpace concept; Finite,...
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,...
The hybrid state of a discrete mode and a component per mode (decisions.md [imm], [component-first]):...
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]...
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...
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...
SwitchingModel (decisions.md [switching-models], [imm]): a Markov chain on a discrete mode space and ...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
The parameters of a probability distribution over a discrete space: one weight per value.
Definition Categorical.h:257
A Gaussian distribution: a mean and covariance in a space.
Definition Gaussian.h:259
The parameters of a hybrid state: a discrete mode, and a component conditioned on each mode.
Definition Hybrid.h:86
internal::Buffer< ComponentType, Allocator_ > ConditionalsType
Definition Hybrid.h:105
RecursionType const & recursion() const
Definition ImmFilter.h:1479
Method_ MethodType
Definition ImmFilter.h:1393
Model_ & model()
Definition ImmFilter.h:1493
void setState(StateType state)
Replaces the state, as when reinitializing, with one that has the model's modes and whose space every...
Definition ImmFilter.h:1461
typename RecursionType::StateType StateType
Definition ImmFilter.h:1395
void predictJoint(TimeStep< Scalar > auto const &dt, HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(dt, inputs...), but into joint, whose storage is reused: with the same joint at every...
Definition ImmFilter.h:1585
Model_ const & model() const
Definition ImmFilter.h:1486
auto predict(TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Mixes the modes' components through the chain, moves each by dt, any TimeStep (see Time steps),...
Definition ImmFilter.h:1517
StateType const & state() const
Definition ImmFilter.h:1441
typename RecursionType::Scalar Scalar
Definition ImmFilter.h:1390
typename RecursionType::ModeSpaceType ModeSpaceType
Definition ImmFilter.h:1394
typename RecursionType::SpaceType SpaceType
Definition ImmFilter.h:1391
ImmRecursion< Component_, Model_, Method_, Allocator_ > RecursionType
Definition ImmFilter.h:1388
Method_ const & method() const
Definition ImmFilter.h:1502
JointType predictJoint(Inputs const &... inputs)
Moves the state forward as predict(inputs...) does with fixed-step models.
Definition ImmFilter.h:1601
auto predict(Steps steps, Inputs const &... inputs)
Moves the state forward by steps of the fixed-step models, as that many calls of predict(inputs....
Definition ImmFilter.h:1542
auto update(SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy={})
As update(measurement, policy), but with a measurement per value of the mode axis that measurement na...
Definition ImmFilter.h:1653
allocator_type get_allocator() const
Definition ImmFilter.h:1434
Params< Component_ > ComponentType
Definition ImmFilter.h:1396
std::expected< void, NumericError > update(SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
As update(measurement, policy) with a SwitchingMeasurement, but into result, whose storage is reused.
Definition ImmFilter.h:1665
auto predict(Inputs const &... inputs)
Mixes the modes' components through the chain, moves each by its mode's fixed-step model's step,...
Definition ImmFilter.h:1529
auto update(M const &measurement, Policy const &policy={})
Conditions each mode's component on measurement, by the measurement's own method, reduces its branche...
Definition ImmFilter.h:1630
Allocator_ allocator_type
Definition ImmFilter.h:1397
StateType & state()
Definition ImmFilter.h:1451
typename RecursionType::JointType JointType
Definition ImmFilter.h:1398
void predictJoint(HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(inputs...), but into joint, whose storage is reused.
Definition ImmFilter.h:1611
JointType predictJoint(TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Moves the state forward as predict(dt, inputs...) does.
Definition ImmFilter.h:1574
Model_ ModelType
Definition ImmFilter.h:1392
ImmFilter(Model_ model, StateType state, std::type_identity_t< Upkeep_ > upkeep)
A filter with switching model model, initial state state, the default prediction method,...
Definition ImmFilter.h:1427
ImmFilter(Model_ model, StateType state, MethodFor< Model_, Method_ > method={}, std::type_identity_t< Upkeep_ > upkeep={})
A filter with switching model model, initial state state, prediction method method,...
Definition ImmFilter.h:1404
std::expected< void, NumericError > update(M const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
As update(measurement, policy), but into result, whose storage is reused: with the same result at eve...
Definition ImmFilter.h:1642
The interacting multiple model (IMM) filter's steps over a hybrid state, without the state: a switchi...
Definition ImmFilter.h:313
std::expected< SwitchingResultType< S >, NumericError > SwitchingUpdateType
What update() with the SwitchingMeasurement S returns: the SwitchingResultType in a std::expected.
Definition ImmFilter.h:387
ResultType< M > emptyUpdate(Allocator_ const &allocator, Eigen::Index modes) const
Definition ImmFilter.h:932
allocator_type get_allocator() const
Definition ImmFilter.h:435
Model_ const & model() const
Definition ImmFilter.h:453
ModeSpaceType const & modeSpace() const
Definition ImmFilter.h:476
typename Model_::ModeSpaceType ModeSpaceType
the discrete mode space
Definition ImmFilter.h:330
std::expected< void, NumericError > update(StateType &state, SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
As update(state, measurement, policy) with a SwitchingMeasurement, but into result,...
Definition ImmFilter.h:708
Method_ const & method() const
Definition ImmFilter.h:469
std::expected< void, NumericError > updateGiven(StateType &state, internal::PinnedMeasurement< Space, P, M > const &f, Value const &value, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
Definition ImmFilter.h:907
Model_ ModelType
the switching model
Definition ImmFilter.h:328
Allocator_ allocator_type
the scratch's allocator
Definition ImmFilter.h:333
ImmFilterUpdate< std::conditional_t< internal::isByMode< M >, FilterUpdate< typename MeasuredType< M >::MeasurementSpaceType, 1, Scalar >, std::conditional_t< IsForm, MeasuredType< M >, internal::FilterUpdateWithScratch< SpaceType, typename MeasuredType< M >::MeasurementSpaceType, MeasuredType< M >::BranchCount, Scalar, Allocator_ > > >, Scalar, Allocator_ > ResultType
What update() with M fills when given a result: one branch per mode for noise by mode axis,...
Definition ImmFilter.h:350
auto predict(StateType &state, TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Mixes state's components through the chain, moves each by dt, any TimeStep (see Time steps),...
Definition ImmFilter.h:499
typename Params< Component_ >::SpaceType SpaceType
the state space
Definition ImmFilter.h:327
void predictJoint(StateType &state, TimeStep< Scalar > auto const &dt, HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(state, dt, inputs...), but into joint, whose storage is reused: with the same joint a...
Definition ImmFilter.h:560
typename Params< Component_ >::Scalar Scalar
the scalar type
Definition ImmFilter.h:326
JointType predictJoint(StateType &state, Inputs const &... inputs)
Moves state forward as predict(state, inputs...) does with fixed-step models.
Definition ImmFilter.h:588
Model_ & model()
Definition ImmFilter.h:460
void predictJoint(StateType &state, HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs)
As predictJoint(state, inputs...), but into joint, whose storage is reused.
Definition ImmFilter.h:599
auto predict(StateType &state, Inputs const &... inputs)
Mixes state's components through the chain, moves each by its mode's fixed-step model's step,...
Definition ImmFilter.h:523
Params< Component_ > ComponentType
one mode's component
Definition ImmFilter.h:331
std::expected< void, NumericError > update(StateType &state, M const &measurement, GivenBlock< Space, P, Value > const &pinned, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
As update(state, measurement, pinned, policy), but into result, whose storage is reused.
Definition ImmFilter.h:869
HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, Allocator_ > JointType
what predictJoint() records
Definition ImmFilter.h:336
typename internal::ImmMeasured< ComponentType, M >::type MeasuredType
The MeasurementUpdate of M on one mode's component, or, for a square-root form, the FilterUpdate of i...
Definition ImmFilter.h:344
static constexpr bool Reentrant
Definition ImmFilter.h:338
ResultType< typename S::template MeasurementType< 0 > > SwitchingResultType
What update() with the SwitchingMeasurement S fills when given a result: the ResultType of its first ...
Definition ImmFilter.h:381
SwitchingUpdateType< SwitchingMeasurement< P, Ms... > > update(StateType &state, SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy={})
As update(state, measurement, policy), but with a measurement per value of the mode axis that measure...
Definition ImmFilter.h:689
void resetScratch(Allocator_ const &allocator)
Replaces the scratch with storage from allocator, when a state from another allocator arrives.
Definition ImmFilter.h:444
JointType emptyJoint(StateType const &state) const
Definition ImmFilter.h:954
std::expected< GivenResultType< M, Space, P >, NumericError > GivenUpdateType
What update(state, measurement, pinned, policy) with M returns.
Definition ImmFilter.h:418
GivenUpdateType< M, Space, P > update(StateType &state, M const &measurement, GivenBlock< Space, P, Value > const &pinned, Policy const &policy={})
As update(state, measurement, policy), but with state a hybrid over the rest of a state and the block...
Definition ImmFilter.h:839
typename decltype(internal::updateBranchesWith< true >( std::declval< ComponentType const & >(), std::declval< internal::PinnedMeasurement< Space, P, M > const & >(), std::declval< typename Moments< internal::PathTag< P >, Scalar >::VectorType const & >()))::value_type GivenMeasuredType
The MeasurementUpdate of M on one mode's Gaussian, with the block named by the path P of a state in S...
Definition ImmFilter.h:393
ImmRecursion(Model_ model, MethodFor< Model_, Method_ > method={}, Allocator_ const &allocator={})
The recursion with switching model model and prediction method method, which the modes whose models c...
Definition ImmFilter.h:424
bool partitions(SpaceType const &space) const
Definition ImmFilter.h:483
JointType predictJoint(StateType &state, TimeStep< Scalar > auto const &dt, Inputs const &... inputs)
Moves state forward as predict(state, dt, inputs...) does.
Definition ImmFilter.h:547
ImmFilterUpdate< std::conditional_t< internal::isByMode< M >, FilterUpdate< typename GivenMeasuredType< M, Space, P >::MeasurementSpaceType, 1, Scalar >, internal::FilterUpdateWithScratch< SpaceType, typename GivenMeasuredType< M, Space, P >::MeasurementSpaceType, GivenMeasuredType< M, Space, P >::BranchCount, Scalar, Allocator_ > >, Scalar, Allocator_ > GivenResultType
What update(state, measurement, pinned, policy) with M fills when given a result: one branch per mode...
Definition ImmFilter.h:403
Method_ MethodType
the prediction method
Definition ImmFilter.h:329
GivenResultType< M, Space, P > emptyGivenUpdate(Allocator_ const &allocator, Eigen::Index modes) const
Definition ImmFilter.h:945
HybridParams< Component_, ModeSpaceType, Allocator_ > StateType
the state the steps act on
Definition ImmFilter.h:332
internal::UnlessGivenBlock< UpdateTypeOf< M >, Policy >::type update(StateType &state, M const &measurement, Policy const &policy={})
Conditions each of state's components on measurement, by the measurement's own method,...
Definition ImmFilter.h:636
std::expected< ResultType< M >, NumericError > UpdateType
What update() with M returns: the ResultType in a std::expected (decisions.md [innovation-cholesky]).
Definition ImmFilter.h:368
std::expected< void, NumericError > update(StateType &state, M const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result)
As update(state, measurement, policy), but into result, whose storage is reused: with the same result...
Definition ImmFilter.h:655
Eigen::Matrix< Scalar_, CardinalityAtCompileTime, CardinalityAtCompileTime, Eigen::RowMajor, MaxCardinalityAtCompileTime, MaxCardinalityAtCompileTime > MatrixType
The transition matrix's type: a row per value moved from, a column per value moved to.
Definition Categorical.h:838
First and second moments (mean and covariance) of a distribution.
Definition Moments.h:55
A measurement that switches between modes: one Measurement per value of a mode axis,...
Definition SwitchingModel.h:542
decltype(auto) visit(std::size_t value, F &&f) const
Definition SwitchingModel.h:579
The distribution that a container of several holds one of per element (decisions.md [component-first]...
Definition Component.h:299
A measurement: an observed value with its model and the call's inputs, and the method a Kalman update...
Definition MeasurementModel.h:1337
A type usable as the space of a distribution.
Definition Space.h:186
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
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
NumericError
Reasons a computation from parameters the caller gave can fail: a matrix that does not factorize or a...
Definition NumericError.h:30
CategoricalParams< Space, Scalar > predict(CategoricalParams< Space, Scalar > const &prior, MarkovChain< Space, Scalar > const &chain)
Definition Categorical.h:1049
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
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
GivenBlock< Space, P, Value > given(Space const &space, Value const &value)
Definition Measurement.h:917
constexpr bool isFixedStep
Whether Model is a FixedStepModel, whose predictions take no time step.
Definition ProcessModel.h:2776
PredictedJoint< typename Prior::SpaceType, typename Prior::Scalar > predictJoint(Method const &method, Prior const &prior, Model const &model, TimeStep< typename Prior::Scalar > auto const &time, Args const &... args)
Definition ProcessModel.h:3362
std::expected< CategoricalUpdate< Space, Scalar >, WeightError > update(CategoricalParams< Space, Scalar > const &prior, E const &emission)
Definition Emission.h:97
Eigen::Array< typename Derived::Scalar, Eigen::Dynamic, 1 > logLikelihoods(M const &measurement, Space const &space, Eigen::MatrixBase< Derived > const &states)
Definition Likelihood.h:408
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
What a filter's update did: the branches of the update before reduction, with their weights and innov...
Definition MeasurementUpdate.h:251
A block of a state given from outside the Gaussian being updated, as given() makes it,...
Definition Measurement.h:723
Value const & value
the block's value, known or an uncertain input
Definition Measurement.h:725
Space space
the whole state space
Definition Measurement.h:724
One IMM prediction as its smoother needs it: the mode probabilities the step started from,...
Definition ImmFilter.h:138
ModesType modes
Definition ImmFilter.h:148
internal::Buffer< JointType, Allocator_ > JointsType
the modes' joints
Definition ImmFilter.h:144
PredictionsType throughOtherModels
Definition ImmFilter.h:155
CategoricalParams< ModeSpace_, Scalar_ > ModesType
the mode weights' type
Definition ImmFilter.h:142
internal::Buffer< GaussianParams< Space_, Scalar_ >, Allocator_ > PredictionsType
predictions alone
Definition ImmFilter.h:146
PredictedJoint< Space_, Scalar_ > JointType
one mode's joint
Definition ImmFilter.h:143
TransitionsType transitions
Definition ImmFilter.h:150
JointsType joints
Definition ImmFilter.h:149
typename MarkovChain< ModeSpace_, Scalar_ >::MatrixType TransitionsType
the chain's matrix
Definition ImmFilter.h:145
ModeSpace_ ModeSpaceType
the discrete mode space
Definition ImmFilter.h:141
Scalar_ Scalar
the scalar type
Definition ImmFilter.h:139
Space_ SpaceType
the continuous state space
Definition ImmFilter.h:140
GaussianParams< Space_, Scalar_ > const & predictedThrough(Eigen::Index from, Eigen::Index model) const
Definition ImmFilter.h:162
What an IMM filter's update did: each mode's update before reduction, the observation's log-likelihoo...
Definition ImmFilter.h:63
Scalar logLikelihood() const
Definition ImmFilter.h:84
internal::Buffer< ModeUpdate, Allocator > ModeUpdatesType
the modes' container
Definition ImmFilter.h:66
ModeUpdate ModeUpdateType
one mode's update
Definition ImmFilter.h:65
Scalar_ Scalar
the scalar type
Definition ImmFilter.h:64
ImmFilterUpdate()=default
an empty result, from a default-constructed allocator
ModeUpdatesType modes
one per mode, in flat-index order
Definition ImmFilter.h:89
Allocator get_allocator() const
Definition ImmFilter.h:77
bool accepted
whether any mode accepted the measurement
Definition ImmFilter.h:90
ImmFilterUpdate(Allocator const &allocator)
An empty result whose modes' updates come from allocator.
Definition ImmFilter.h:71
UpdateType<M>, named without being formed (see internal::UnlessGivenBlock).
Definition ImmFilter.h:373
UpdateType< M > type
the update's type
Definition ImmFilter.h:374
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
Reduction policy that moment-matches an update's branches into one Gaussian: soft outlier rejection,...
Definition Reduction.h:241