48template <
typename Model_,
typename Method_>
53 "a fixed-step model carries its own method; give the method to fixedStep() in place of withMethod()"
55 static_assert(internal::checkPredictionMethod<Method_>());
64 : m_model{std::move(
model)}
65 , m_method{std::move(
method)}
69 [[nodiscard]] Model_
const &
76 [[nodiscard]] Model_ &
83 [[nodiscard]] Method_
const &
99template <
typename Model>
100inline constexpr bool isModelWithMethod =
false;
103template <
typename Model_,
typename Method_>
104inline constexpr bool isModelWithMethod<ModelWithMethod<Model_, Method_>> =
true;
111template <
typename Model>
118template <
typename Model_,
typename Method_>
119struct ModeModelOf<ModelWithMethod<Model_, Method_>>
125template <
typename Model>
126using ModeModel =
typename ModeModelOf<Model>::type;
129template <
typename Entry>
131modeModel(Entry & entry)
133 if constexpr (isModelWithMethod<std::remove_const_t<Entry>>)
135 return entry.model();
146template <
typename Entry,
typename Fallback>
147[[nodiscard]]
auto const &
148modeMethod(Entry
const & entry, Fallback
const & fallback)
152 return entry.method();
167template <
typename Model, TransformMethod Method>
171 return {std::move(model), std::move(method)};
212template <DiscreteSpace ModeSpace_, RealScalar Scalar_,
typename Path_,
typename... Models>
215 static_assert(
sizeof...(Models) > 0,
"a switching model needs a process model");
220 "a switching model's process models are all fixed-step or none are"
233 static constexpr bool Shared =
sizeof...(Models) == 1 && std::is_same_v<Path_, ModeSpace_>;
239 : m_chain{std::move(
chain)}
240 , m_models{std::move(models)...}
246 [](
auto const & first,
auto const &... rest) {
247 return ((rest.timeStep() == first.timeStep()) && ...);
251 &&
"a switching model's fixed-step models must share one step"
256 using Axis = internal::PathTag<Path_>;
258 Axis::Cardinality == Eigen::Dynamic || Axis::Cardinality == int(
sizeof...(Models)),
259 "give one process model per value of the axis that selects it, "
260 "or no path for one model shared by every mode"
263 selector().cardinality == Eigen::Index(
sizeof...(Models))
264 &&
"give one process model per value of the axis that selects it, "
265 "or no path for one model shared by every mode"
274 template <
typename... Others>
276 sizeof...(Others) ==
sizeof...(Models) && !(std::is_same_v<Others, Models> && ...)
277 && (std::is_convertible_v<Others const &, Models> && ...)
284 [[nodiscard]] ChainType
const &
291 [[nodiscard]] ChainType &
298 [[nodiscard]] ModeSpace_
const &
301 return m_chain.space();
305 template <std::
size_t I>
306 [[nodiscard]]
auto const &
309 return internal::modeModel(std::get<I>(m_models));
313 template <std::
size_t I>
317 return internal::modeModel(std::get<I>(m_models));
321 [[nodiscard]] std::size_t
324 EMRYS_FILTER_ASSERT(mode >= 0 && mode <
modeSpace().cardinality() &&
"the mode is out of range");
331 auto const location = selector();
332 return std::size_t((mode / location.stride) % location.cardinality);
337 template <
typename F>
339 visit(Eigen::Index mode, F && f)
const
341 return visitEntry(mode, [&](
auto const & entry) ->
decltype(
auto) {
342 return f(internal::modeModel(entry));
350 template <
typename Fallback,
typename F>
352 visit(Eigen::Index mode, Fallback
const & fallback, F && f)
const
354 return visitEntry(mode, [&](
auto const & entry) ->
decltype(
auto) {
355 return f(internal::modeModel(entry), internal::modeMethod(entry, fallback));
362 template <
typename Space>
363 [[nodiscard]]
static consteval internal::StaticPartition
366 using internal::StaticPartition;
367 constexpr auto each = std::array<StaticPartition,
sizeof...(Models)>{
368 internal::staticPartition<internal::ModeModel<Models>,
Space>()...
370 if (std::ranges::find(each, StaticPartition::fails) != each.end())
372 return StaticPartition::fails;
374 return std::ranges::all_of(
376 [](StaticPartition p) {
377 return p == StaticPartition::holds;
380 ? StaticPartition::holds
381 : StaticPartition::unknown;
385 template <
typename Space>
390 [&](
auto const &... models) {
391 return (internal::modeModel(models).
partitions(space) && ...);
402 template <
typename F>
404 visitEntry(Eigen::Index mode, F
const & f)
const
406 std::size_t
const index = modelIndex(mode);
407 return [&]<std::size_t... I>(std::index_sequence<I...>) ->
decltype(
auto) {
408 using Result =
decltype(f(std::get<0>(m_models)));
409 if constexpr (std::is_void_v<Result>)
411 ((I == index ? (void)f(std::get<I>(m_models)) : void()), ...);
415 auto result = Result{};
416 ((I == index ? (void)(result = f(std::get<I>(m_models))) : void()), ...);
419 }(std::index_sequence_for<Models...>{});
423 template <
typename Other, std::size_t... I>
425 :
SwitchingModel{other.chain(), Models(other.template model<I>())...}
432 Eigen::Index cardinality;
436 [[nodiscard]] Selector
439 auto const [stride, axis] = internal::locateAxisByPath<Path_>(modeSpace());
440 return {stride, axis->cardinality()};
444 std::tuple<Models...> m_models;
450template <
typename ModeSpace_,
typename Scalar_,
typename Path_,
typename... Models>
460template <
typename ModeSpace_,
typename Scalar_,
typename Path_,
typename First,
typename... Rest>
461struct DefaultMethodOf<SwitchingModel<ModeSpace_, Scalar_, Path_, First, Rest...>>
464 using type = std::conditional_t<isFixedStep<First> || isUnboundStep<First>, ModelsMethod, methods::Linearized>;
470template <
typename ModeSpace_,
typename Scalar_,
typename Path_,
typename... Models>
471[[nodiscard]] ModelsMethod
472predictionMethod(SwitchingModel<ModeSpace_, Scalar_, Path_, Models...>
const &, ModelsMethod method)
478template <
typename ModeSpace_,
typename Scalar_,
typename Path_,
typename... Models,
typename Space,
typename Scalar>
479struct BoundStepOf<SwitchingModel<ModeSpace_, Scalar_, Path_, Models...>, Space, Scalar>
481 using type = SwitchingModel<ModeSpace_, Scalar_, Path_, BoundStep<Models, Space, Scalar>...>;
488template <
typename ModeSpace_,
typename Scalar_,
typename Path_,
typename... Models,
typename Method>
489inline constexpr bool predictsBy<SwitchingModel<ModeSpace_, Scalar_, Path_, Models...>, Method>{
490 !
isFixedStep<SwitchingModel<ModeSpace_, Scalar_, Path_, Models...>> || std::is_same_v<Method, ModelsMethod>
496template <
typename ModeSpace,
typename Scalar,
typename... Models>
497SwitchingModel(MarkovChain<ModeSpace, Scalar>, Models...) -> SwitchingModel<ModeSpace, Scalar, ModeSpace, Models...>;
508template <
typename P,
typename ModeSpace,
typename Scalar,
typename... Models>
509[[nodiscard]] SwitchingModel<ModeSpace, Scalar, P, Models...>
512 return {std::move(chain), std::move(models)...};
540template <
typename Path_, Measurement... Measurements>
543 static_assert(
sizeof...(Measurements) > 0,
"a switching measurement needs a measurement");
549 static constexpr std::size_t
Count =
sizeof...(Measurements);
552 template <std::
size_t I>
557 : m_measurements{std::move(measurements)...}
559 using Axis = internal::PathTag<Path_>;
561 Axis::Cardinality == Eigen::Dynamic || Axis::Cardinality == int(
sizeof...(Measurements)),
562 "give one measurement per value of the axis that selects it"
567 template <std::
size_t I>
568 [[nodiscard]] MeasurementType<I>
const &
571 return std::get<I>(m_measurements);
577 template <
typename F>
579 visit(std::size_t value, F && f)
const
581 EMRYS_FILTER_ASSERT(value <
Count &&
"the switching measurement has no measurement for this value of the axis");
582 return visitFrom<0>(value, f);
588 template <std::
size_t I,
typename F>
590 visitFrom(std::size_t value, F & f)
const
592 if constexpr (I + 1 == Count)
594 return f(std::get<I>(m_measurements));
600 return f(std::get<I>(m_measurements));
602 return visitFrom<I + 1>(value, f);
606 std::tuple<Measurements...> m_measurements;
616template <
typename P, Measurement... Measurements>
617[[nodiscard]] SwitchingMeasurement<P, Measurements...>
628inline constexpr bool isSwitchingMeasurement =
false;
631template <
typename Path,
typename... Measurements>
632inline constexpr bool isSwitchingMeasurement<SwitchingMeasurement<Path, Measurements...>> =
true;
The distribution over a discrete space (decisions.md [discrete-spaces], [params-and-density]): Catego...
Discrete spaces (decisions.md [discrete-spaces]): the DiscreteSpace concept; Finite,...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Measurement models and their observations (decisions.md [model-policies], [sensors],...
Process models as functions with reads and writes (decisions.md [model-policies], [continuous-time-no...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Subspaces, and growing and shrinking blocks (decisions.md [several-resizable-blocks]).
A Markov chain on a discrete space: the probability of moving from each value to each value in one st...
Definition Categorical.h:829
A process model and the prediction method that one mode of a SwitchingModel predicts it by,...
Definition SwitchingModel.h:50
Model_ const & model() const
Definition SwitchingModel.h:70
Model_ ModelType
the process model
Definition SwitchingModel.h:59
ModelWithMethod(Model_ model, Method_ method)
model, predicted by method.
Definition SwitchingModel.h:63
Method_ const & method() const
Definition SwitchingModel.h:84
Method_ MethodType
the prediction method
Definition SwitchingModel.h:60
Model_ & model()
Definition SwitchingModel.h:77
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
static constexpr std::size_t Count
the number of measurements
Definition SwitchingModel.h:549
SwitchingMeasurement(Measurements... measurements)
measurements, one per value of the axis Path_, in order.
Definition SwitchingModel.h:556
std::tuple_element_t< I, std::tuple< Measurements... > > MeasurementType
Measurement I, for value I of the axis.
Definition SwitchingModel.h:553
Path_ PathType
the mode axis that selects the measurement
Definition SwitchingModel.h:547
MeasurementType< I > const & measurement() const
Definition SwitchingModel.h:569
A process model that switches between modes: a Markov chain on a discrete mode space,...
Definition SwitchingModel.h:214
SwitchingModel(SwitchingModel< ModeSpace_, Scalar_, Path_, Others... > const &other)
other with each of its models converted to this one's: how a filter binds a switching model of fixedS...
Definition SwitchingModel.h:279
decltype(auto) visit(Eigen::Index mode, F &&f) const
Definition SwitchingModel.h:339
MarkovChain< ModeSpace_, Scalar_ > ChainType
the chain's type
Definition SwitchingModel.h:227
ModeSpace_ ModeSpaceType
the discrete mode space
Definition SwitchingModel.h:226
auto & model()
Definition SwitchingModel.h:315
std::size_t modelIndex(Eigen::Index mode) const
Definition SwitchingModel.h:322
bool partitions(Space const &space) const
Definition SwitchingModel.h:387
auto const & model() const
Definition SwitchingModel.h:307
decltype(auto) visit(Eigen::Index mode, Fallback const &fallback, F &&f) const
Definition SwitchingModel.h:352
SwitchingModel(ChainType chain, Models... models)
The chain chain on the modes, and models, one per value of the axis Path_ (one shared by every mode i...
Definition SwitchingModel.h:238
static consteval internal::StaticPartition staticPartition()
Definition SwitchingModel.h:364
ChainType & chain()
Definition SwitchingModel.h:292
ModeSpace_ const & modeSpace() const
Definition SwitchingModel.h:299
static constexpr bool Shared
Definition SwitchingModel.h:233
ChainType const & chain() const
Definition SwitchingModel.h:285
Scalar_ Scalar
the scalar type of the chain's probabilities
Definition SwitchingModel.h:225
A type usable as the space of a distribution.
Definition Space.h:186
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
ModelWithMethod< Model, Method > withMethod(Model model, Method method)
Definition SwitchingModel.h:169
constexpr bool isFixedStep
Whether Model is a FixedStepModel, whose predictions take no time step.
Definition ProcessModel.h:2776
SwitchingMeasurement< P, Measurements... > switchingMeasurement(Measurements... measurements)
Definition SwitchingModel.h:618
SwitchingModel< ModeSpace, Scalar, P, Models... > switchingModel(MarkovChain< ModeSpace, Scalar > chain, Models... models)
Definition SwitchingModel.h:510
constexpr bool isUnboundStep
Whether Model is a fixed step not yet bound to a state space: an UnboundFixedStep,...
Definition ProcessModel.h:2792