41template <
typename Prefix,
typename Name>
42struct PlacedName : Name
48template <
typename Prefix,
typename Path>
52template <
typename... Prefix,
typename... Tags>
53struct JoinPathsOf<TagPath<Prefix...>, TagPath<Tags...>>
55 using type = TagPath<Prefix..., Tags...>;
61template <
typename Prefix,
typename Path>
62using JoinPaths =
typename JoinPathsOf<Prefix, Path>::type;
65template <
typename Path>
69template <
typename First,
typename... Rest>
70struct FirstTagOf<TagPath<First, Rest...>>
78template <
typename Path,
typename S>
79inline constexpr bool startsIn = countTag<typename FirstTagOf<Path>::type, S>() > 0;
83inline constexpr bool isRename =
false;
86template <PathValue X,
typename Name>
87inline constexpr bool isRename<OnPath<X, Name>> = isTagPath<PathOf<X>> || PathValue<X>;
94template <
typename Name,
typename... Renames>
101template <
typename Name,
typename X,
typename New,
typename... Rest>
102struct RenamedOf<Name, OnPath<X, New>, Rest...>
105 std::conditional_t<std::is_same_v<PathOf<X>, TagPath<Name>>, New,
typename RenamedOf<Name, Rest...>::type>;
111template <
typename Name,
typename... Renames>
112using Renamed =
typename RenamedOf<Name, Renames...>::type;
118template <
typename Rename,
typename S,
typename Items>
121 static constexpr bool value =
false;
125template <
typename X,
typename New,
typename S,
typename... Items>
126struct RenamesAnInput<OnPath<X, New>, S, std::tuple<Items...>>
128 static constexpr bool value =
129 ((std::is_same_v<PathOf<X>, TagPath<typename Items::NameType>> && !startsIn<typename Items::PathType, S>) || ...
139 using type = std::tuple<>;
143template <
typename... Names>
144struct AffineNamesOf<AffineIn<Names...>>
146 using type = std::tuple<Names...>;
152template <
typename Model>
153using AffineNamesOfModel =
typename AffineNamesOf<typename Model::template Policy<PolicyKind::affineIn>>::type;
156template <
typename Model,
typename Name>
157inline constexpr bool declaresAffine = []<
typename... Names>(std::tuple<Names...> *) {
158 return (std::is_same_v<Names, Name> || ...);
159}(
static_cast<AffineNamesOfModel<Model> *
>(
nullptr));
162template <
typename Name,
typename... Names>
163[[nodiscard]]
consteval std::size_t
166 constexpr std::array<bool,
sizeof...(Names) + 1> same{std::is_same_v<Names, Name>...,
true};
180template <
typename Prefix,
typename Model,
typename... Renames>
183 using PrefixSpace = PathTag<Prefix>;
184 using InnerReads =
typename Model::template Policy<PolicyKind::reads>;
185 using InnerItems =
typename ItemsOf<InnerReads>::type;
188 (isRename<Renames> && ...),
189 "on<Path>(model, renames...) renames an input of the model with on<Name>(path<Tag>)"
192 (RenamesAnInput<Renames, PrefixSpace, InnerItems>::value && ... &&
true),
193 "a rename in on<Path>(model, on<Name>(path<Tag>)) names an input the model reads, a tag that is not a block of "
194 "the block Path names"
198 template <
typename Item>
201 static constexpr bool State = startsIn<typename Item::PathType, PrefixSpace>;
203 using New = Renamed<
typename Item::NameType, Renames...>;
206 State || sameLeaf<New, typename Item::NameType>,
207 "a renamed input has the same leaf beneath it as the name the model reads it under"
211 using type = std::conditional_t<
213 ReadItem<JoinPaths<Prefix, typename Item::PathType>, PlacedName<Prefix, typename Item::NameType>>,
214 ReadItem<TagPath<New>, New>>;
218 using ReadsPolicy =
typename decltype([]<
typename... Items>(std::tuple<Items...> *) {
219 return std::type_identity<Reads<typename OuterItemOf<Items>::type...>>{};
220 }(
static_cast<InnerItems *
>(
nullptr)))::type;
223 template <
typename Name>
224 using OuterName =
typename decltype([]<
typename... Items>(std::tuple<Items...> *) {
225 return std::type_identity<std::tuple_element_t<
226 nameIndex<Name,
typename Items::NameType...>(),
227 std::tuple<
typename OuterItemOf<Items>::type::NameType...>>>{};
228 }(
static_cast<InnerItems *
>(
nullptr)))::type;
231 using AffinePolicy =
typename decltype([]<
typename... Names>(std::tuple<Names...> *) {
232 return std::type_identity<AffineIn<OuterName<Names>...>>{};
233 }(
static_cast<AffineNamesOfModel<Model> *
>(
nullptr)))::type;
243template <
typename Model>
248 using InnerIn =
typename Model::template Policy<PolicyKind::reads>::InputSpace;
249 using InnerOut = OutputSpaceOf<Model>;
252 explicit PlacedStep(Model model)
253 : m_model{std::move(model)}
257 [[nodiscard]] Model
const &
264 [[nodiscard]] Model &
273 template <
typename In,
typename Out,
typename X,
typename TimeScalar>
274 [[nodiscard]]
decltype(
auto)
275 operator()(In
const & in, Out
const & out, X
const & x, TimeScalar dt)
const
276 requires MatrixExpression<X>
278 return callForm(m_model.function(), renamedInstance<InnerIn>(in), renamedInstance<InnerOut>(out), x, dt);
282 using Inner = std::remove_cvref_t<decltype(std::declval<Model const &>().function())>;
285 static constexpr bool TakesBatches = takesBatches<Inner>;
288 using MarkType = BatchMarkOrNone<Inner>;
294 template <
typename In,
typename Out,
typename X,
typename TimeScalar,
typename Y>
296 operator()(In
const & in, Out
const & out, X
const & x, TimeScalar dt, Y & y)
const
297 requires TakesBatches
299 auto const innerIn = renamedInstance<InnerIn>(in);
300 auto const innerOut = renamedInstance<InnerOut>(out);
301 auto inner = y.template renamed<InnerOut>(innerIn);
302 callForm(batchBody(m_model.function()), innerIn, innerOut, x, dt, inner);
306 template <
typename Scalar,
typename Out>
308 noiseOver(Out
const & out, Scalar dt)
const
310 return m_model.template noiseOver<Scalar>(renamedInstance<InnerOut>(out), dt);
321template <
typename Prefix,
typename Model>
322using PlacedWrites =
typename decltype([]<std::size_t... K>(std::index_sequence<K...>) {
324 (startsIn<WritePathAt<Model, K>, PathTag<Prefix>> && ...),
325 "on<Path>(model) places a model whose writes() are blocks of the block Path names"
327 return std::type_identity<WritesAs<
328 TagPaths<JoinPaths<Prefix, WritePathAt<Model, K>>...>,
329 Composite<PlacedName<Prefix, WriteNameAt<Model, K>>...>>>{};
330}(std::make_index_sequence<writeCount<Model>>{}))::type;
346template <
typename Prefix,
typename Model,
typename... Renames>
349 using RepeatedTag = PathTag<Prefix>;
351 static_assert(IsRepeated<RepeatedTag>,
"onEach<Path>(model) places a model on a repeated block of the state");
353 using Block = RepeatedBlock<RepeatedTag>;
354 using InnerReads =
typename Model::template Policy<PolicyKind::reads>;
355 using InnerItems =
typename ItemsOf<InnerReads>::type;
356 using InnerIn =
typename InnerReads::InputSpace;
357 using InnerOut = OutputSpaceOf<Model>;
359 static constexpr std::size_t ItemCount = std::tuple_size_v<InnerItems>;
362 (isRename<Renames> && ...),
363 "onEach<Path>(model, renames...) renames an input of the model with on<Name>(path<Tag>)"
366 (RenamesAnInput<Renames, Block, InnerItems>::value && ... &&
true),
367 "a rename in onEach<Path>(model, on<Name>(path<Tag>)) names an input the model reads, a tag that is not a "
368 "block of one repetition of the block Path names"
371 FixedSizeSpace<InnerIn> && FixedSizeSpace<InnerOut>,
372 "onEach<Path>(model) repeats a model whose input and output are fixed-size"
375 pathsPartition<Block, WritePathsOf<Model>>(),
376 "onEach<Path>(model) places a model that writes every coordinate of one repetition of the block exactly once"
380 template <std::
size_t K>
381 using InnerItem = std::tuple_element_t<K, InnerItems>;
384 template <std::
size_t K>
385 using NewName = Renamed<typename InnerItem<K>::NameType, Renames...>;
388 template <std::
size_t K>
389 [[nodiscard]]
static consteval EachKind
392 if constexpr (startsIn<typename InnerItem<K>::PathType, Block>)
394 return EachKind::state;
396 else if constexpr (IsRepeated<NewName<K>>)
399 sameLeaf<RepeatedBlock<NewName<K>>,
typename InnerItem<K>::NameType>,
400 "an input renamed to a Repeated tag repeats the leaf the model reads it under"
402 return EachKind::repeated;
407 sameLeaf<NewName<K>,
typename InnerItem<K>::NameType>,
408 "a renamed input has the same leaf beneath it as the name the model reads it under"
410 return EachKind::shared;
415 using ReadsPolicy =
typename decltype([]<std::size_t... K>(std::index_sequence<K...>) {
416 return std::type_identity<
decltype(std::tuple_cat(
417 std::tuple<ReadItem<Prefix, RepeatedTag>>{},
419 kind<K>() == EachKind::state,
421 std::tuple<ReadItem<TagPath<NewName<K>>, NewName<K>>>>{}...
423 }(std::make_index_sequence<ItemCount>{}))::type;
426 using ReadsOfEach =
typename decltype([]<
typename... Items>(std::tuple<Items...> *) {
427 return std::type_identity<Reads<Items...>>{};
428 }(
static_cast<ReadsPolicy *
>(
nullptr)))::type;
433 using AffinePolicy =
typename decltype([]<std::size_t... K>(std::index_sequence<K...>) {
434 constexpr bool blockAffine =
435 ((kind<K>() != EachKind::state || declaresAffine<Model, typename InnerItem<K>::NameType>) && ...);
436 return std::type_identity<
decltype(std::tuple_cat(
437 std::conditional_t<blockAffine, std::tuple<RepeatedTag>, std::tuple<>>{},
438 std::conditional_t < kind<K>() != EachKind::state && declaresAffine<Model, typename InnerItem<K>::NameType>,
439 std::tuple<NewName<K>>,
440 std::tuple < >> {}...
442 }(std::make_index_sequence<ItemCount>{}))::type;
445 using AffineOfEach =
typename decltype([]<
typename... Names>(std::tuple<Names...> *) {
446 return std::type_identity<AffineIn<Names...>>{};
447 }(
static_cast<AffinePolicy *
>(
nullptr)))::type;
460template <
typename Prefix,
typename Model,
typename... Renames>
464 using P = EachPlacement<Prefix, Model, Renames...>;
466 using RepeatedTag =
typename P::RepeatedTag;
468 using Block =
typename P::Block;
470 using InnerIn =
typename P::InnerIn;
472 using InnerOut =
typename P::InnerOut;
480 explicit EachStep(Model model)
481 : m_model{std::move(model)}
485 [[nodiscard]] Model
const &
492 [[nodiscard]] Model &
501 template <
typename In,
typename Out,
typename X,
typename TimeScalar>
503 operator()(In
const & in, Out
const & out, X
const & x, TimeScalar dt)
const
504 requires MatrixExpression<X>
508 constexpr bool ReturnsJacobian = returnsJacobianWith<Model, TimeScalar, TimeScalar>;
509 Eigen::Index
const count = pathBlock<RepeatedTag>(in).count();
510 BlockRows
const inRows = blockRows<RepeatedTag>(in);
511 BlockRows
const outRows = blockRows<RepeatedTag>(out);
513 auto jacobian = [&] {
514 if constexpr (ReturnsJacobian)
516 using Matrix = MatrixOf<
529 InnerIn
const innerIn{};
530 InnerOut
const innerOut{};
531 for (Eigen::Index i = 0; i < count; ++i)
534 [&]<std::size_t... K>(std::index_sequence<K...>) {
535 (gather<K>(in, x, i, inRows, innerIn, xi), ...);
536 }(std::make_index_sequence<P::ItemCount>{});
537 auto result = vectorReturned(callForm(m_model.function(), innerIn, innerOut, xi, dt));
538 auto const & value = valueOf(result);
539 [&]<std::size_t... W>(std::index_sequence<W...>) {
541 outRows.start + i * BlockSize + blockRows<WritePathAt<Model, W>>(Block{}).start,
542 blockRows<WritePathAt<Model, W>>(Block{}).size
545 blockRows<WriteNameAt<Model, W>>(innerOut).start,
546 blockRows<WriteNameAt<Model, W>>(innerOut).size
549 }(std::make_index_sequence<writeCount<Model>>{});
550 if constexpr (ReturnsJacobian)
552 [&]<std::size_t... W>(std::index_sequence<W...>) {
553 (jacobianRows<W>(in, out, i, innerIn, innerOut, result.jacobian, jacobian), ...);
554 }(std::make_index_sequence<writeCount<Model>>{});
557 if constexpr (ReturnsJacobian)
568 using Inner = std::remove_cvref_t<decltype(std::declval<Model const &>().function())>;
571 static constexpr bool TakesBatches = takesBatches<Inner>;
574 using MarkType = NoJacobians;
580 template <
typename In,
typename Out,
typename X,
typename TimeScalar,
typename Y>
582 operator()(In
const & in, Out
const & out, X
const & x, TimeScalar dt, Y & y)
const
583 requires TakesBatches
585 using T =
typename X::Scalar;
590 X::ColsAtCompileTime,
592 X::MaxColsAtCompileTime>;
596 X::ColsAtCompileTime,
598 X::MaxColsAtCompileTime>;
599 Eigen::Index
const repetitions = pathBlock<RepeatedTag>(in).count();
600 Eigen::Index
const points = x.cols();
601 BlockRows
const inRows = blockRows<RepeatedTag>(in);
602 BlockRows
const outRows = blockRows<RepeatedTag>(out);
603 auto & values = y.values();
605 InnerIn
const innerIn{};
606 InnerOut
const innerOut{};
611 auto column = InnerVector{};
613 for (Eigen::Index i = 0; i < repetitions; ++i)
615 for (Eigen::Index j = 0; j < points; ++j)
618 [&]<std::size_t... K>(std::index_sequence<K...>) {
619 (gather<K>(in, x.col(j), i, inRows, innerIn, column), ...);
620 }(std::make_index_sequence<P::ItemCount>{});
623 callBatched(m_model.function(), innerIn, innerOut, xi, yi, dt);
624 [&]<std::size_t... W>(std::index_sequence<W...>) {
626 outRows.start + i * BlockSize + blockRows<WritePathAt<Model, W>>(Block{}).start,
627 blockRows<WritePathAt<Model, W>>(Block{}).size
630 blockRows<WriteNameAt<Model, W>>(innerOut).start,
631 blockRows<WriteNameAt<Model, W>>(innerOut).size
634 }(std::make_index_sequence<writeCount<Model>>{});
641 template <
typename Scalar,
typename Out>
643 noiseOver(Out
const & out, Scalar dt)
const
647 Matrix q = Matrix::Zero(n, n);
648 InnerOut
const innerOut{};
649 auto const inner = m_model.template noiseOver<Scalar>(innerOut, dt);
650 Eigen::Index
const count = pathBlock<RepeatedTag>(out).count();
651 Eigen::Index
const start = differenceBlockRows<RepeatedTag>(out).start;
652 for (Eigen::Index i = 0; i < count; ++i)
654 [&]<std::size_t... W>(std::index_sequence<W...>) {
655 (noiseRows<W>(q, start + i * BlockDifferenceSize, innerOut, inner), ...);
656 }(std::make_index_sequence<writeCount<Model>>{});
664 template <std::
size_t K,
typename In,
typename X,
typename XI>
666 gather(In
const & in, X
const & x, Eigen::Index i, BlockRows
const & inRows, InnerIn
const & innerIn, XI & xi)
668 using Item =
typename P::template InnerItem<K>;
669 BlockRows
const rows = blockRows<typename Item::NameType>(innerIn);
670 if constexpr (P::template kind<K>() == EachKind::state)
672 BlockRows
const within = blockRows<typename Item::PathType>(Block{});
673 xi.segment(rows.start, rows.size) = x.segment(inRows.start + i * BlockSize + within.start, within.size);
675 else if constexpr (P::template kind<K>() == EachKind::repeated)
677 xi.segment(rows.start, rows.size) =
689 template <std::
size_t W,
typename In,
typename Out,
typename J,
typename Whole>
695 InnerIn
const & innerIn,
696 InnerOut
const & innerOut,
701 BlockRows
const innerRows = differenceBlockRows<WriteNameAt<Model, W>>(innerOut);
702 Eigen::Index
const row = differenceBlockRows<RepeatedTag>(out).start + i * BlockDifferenceSize
703 + differenceBlockRows<WritePathAt<Model, W>>(Block{}).start;
704 [&]<std::size_t... K>(std::index_sequence<K...>) {
707 using Item =
typename P::template InnerItem<K>;
708 BlockRows
const innerColumns = differenceBlockRows<typename Item::NameType>(innerIn);
709 Eigen::Index column = 0;
710 if constexpr (P::template kind<K>() == EachKind::state)
712 column = differenceBlockRows<RepeatedTag>(in).start + i * BlockDifferenceSize
713 + differenceBlockRows<typename Item::PathType>(Block{}).start;
715 else if constexpr (P::template kind<K>() == EachKind::repeated)
717 column = differenceBlockRows<typename P::template NewName<K>>(in).start + i * innerColumns.size;
721 column = differenceBlockRows<typename P::template NewName<K>>(in).start;
723 jacobian.block(row, column, innerRows.size, innerColumns.size) =
724 inner.block(innerRows.start, innerColumns.start, innerRows.size, innerColumns.size);
728 }(std::make_index_sequence<P::ItemCount>{});
734 template <std::
size_t W,
typename Q,
typename Inner>
736 noiseRows(Q & q, Eigen::Index start, InnerOut
const & innerOut, Inner
const & inner)
738 BlockRows
const innerRows = differenceBlockRows<WriteNameAt<Model, W>>(innerOut);
739 Eigen::Index
const row = start + differenceBlockRows<WritePathAt<Model, W>>(Block{}).start;
740 [&]<std::size_t... V>(std::index_sequence<V...>) {
743 BlockRows
const innerColumns = differenceBlockRows<WriteNameAt<Model, V>>(innerOut);
744 Eigen::Index
const column = start + differenceBlockRows<WritePathAt<Model, V>>(Block{}).start;
745 q.block(row, column, innerRows.size, innerColumns.size) =
746 inner.block(innerRows.start, innerColumns.start, innerRows.size, innerColumns.size);
750 }(std::make_index_sequence<writeCount<Model>>{});
763template <
typename F,
typename InnerIn>
769 explicit PlacedMeasure(F function)
770 : m_function{std::move(function)}
774 template <
typename In,
typename Out,
typename X>
775 [[nodiscard]]
decltype(
auto)
776 operator()(In
const & in, Out
const & out, X
const & x)
const
777 requires MatrixExpression<X>
779 return callForm(m_function, renamedInstance<InnerIn>(in), out, x);
783 static constexpr bool TakesBatches = takesBatches<F>;
786 using MarkType = BatchMarkOrNone<F>;
791 template <
typename In,
typename Out,
typename X,
typename Y>
793 operator()(In
const & in, Out
const & out, X
const & x, Y & y)
const
794 requires TakesBatches
796 auto const innerIn = renamedInstance<InnerIn>(in);
797 auto inner = y.template renamed<Out>(innerIn);
798 callForm(batchBody(m_function), innerIn, out, x, inner);
802 [[nodiscard]] Eigen::Index
804 requires requires(F const & f) { f.outputRows(); }
806 return m_function.outputRows();
820template <
typename G,
typename InnerIn>
821struct PlacedLikelihood
826 template <
typename In,
typename X,
typename Z>
828 operator()(In
const & in, X
const & x, Z
const & z)
const
830 return function(renamedInstance<InnerIn>(in), x, z);
840template <
typename G,
typename InnerIn>
846 template <
typename In,
typename X,
typename R>
848 operator()(In
const & in, X
const & x, R & rng)
const
850 return function(renamedInstance<InnerIn>(in), x, rng);
857template <
typename Prefix,
typename G>
858struct PlacedOutputSpace
863 template <
typename StateSpace>
865 operator()(StateSpace
const & space)
const
867 return function(pathSubspace<Prefix>(space));
876template <
typename Prefix,
typename InnerIn,
typename ReadsPolicy,
typename AffinePolicy,
typename Policy>
878placedPolicy(Policy
const & policy)
880 constexpr std::optional<PolicyKind> kind = policyKind<Policy>;
881 if constexpr (kind == PolicyKind::reads)
883 return ReadsPolicy{};
885 else if constexpr (kind == PolicyKind::affineIn)
887 return AffinePolicy{};
889 else if constexpr (kind == PolicyKind::logLikelihood)
891 using G = std::remove_cvref_t<
decltype(policy.function)>;
892 return LogLikelihood<PlacedLikelihood<G, InnerIn>>{PlacedLikelihood<G, InnerIn>{policy.function}};
894 else if constexpr (kind == PolicyKind::sample)
896 using G = std::remove_cvref_t<
decltype(policy.function)>;
897 return Sample<PlacedSample<G, InnerIn>>{PlacedSample<G, InnerIn>{policy.function}};
899 else if constexpr (kind == PolicyKind::outputSpace)
901 if constexpr (Policy::Computed)
903 using G = std::remove_cvref_t<
decltype(policy.value)>;
904 return OutputSpace<PlacedOutputSpace<Prefix, G>>{PlacedOutputSpace<Prefix, G>{policy.value}};
923template <
typename... Models>
924class MeasurementParts
929 explicit MeasurementParts(Models... models)
930 : m_parts{std::move(models)...}
934 [[nodiscard]] std::tuple<Models...>
const &
941 template <
typename In,
typename Out,
typename X>
943 operator()(In
const & in, Out
const & out, X
const & x)
const
944 requires MatrixExpression<X>
946 return stepParts<ScalarOf<X>>(m_parts, in, out, x);
950 static constexpr bool TakesBatches = anyTakesBatches<Models...>;
953 using MarkType = NoJacobians;
959 template <
typename In,
typename Out,
typename X,
typename Y>
961 operator()(In
const & in, Out
const & out, X
const & x, Y & y)
const
962 requires TakesBatches
964 stepPartsBatch(m_parts, in, out, x, y);
969 std::tuple<Models...> m_parts;
978template <
typename Out,
typename... Models>
979struct SumOfLikelihoods
981 std::tuple<Models...> parts;
984 template <
typename In,
typename X,
typename Z>
986 operator()(In
const & in, X
const & x, Z
const & z)
const
988 return [&]<std::size_t... I>(std::index_sequence<I...>) {
989 return (likelihoodOf<I>(in, x, z) + ...);
990 }(std::index_sequence_for<Models...>{});
996 template <std::
size_t I,
typename In,
typename X,
typename Z>
998 likelihoodOf(In
const & in, X
const & x, Z
const & z)
const
1000 using Part = std::tuple_element_t<I, std::tuple<Models...>>;
1001 using PartOut = OutputSpaceOf<Part>;
1002 auto const pin = partIn<Part>(in);
1003 auto const px = partVector<Part>(in, pin, x);
1005 PartOut
const pout{};
1007 [&]<
typename... Names>(std::tuple<Names...> *) {
1009 }(
static_cast<CompositeBlocks<PartOut> *
>(
nullptr));
1010 return callWithScalar<typename X::Scalar>(
1011 std::get<I>(parts).
template policy<PolicyKind::logLikelihood>().function,
1023template <
typename Model>
1025placedNoiseParts(Model
const & model)
1027 if constexpr (!Model::template has<PolicyKind::additiveNoise>)
1029 return std::tuple<>{};
1033 using Noise =
typename Model::template Policy<PolicyKind::additiveNoise>;
1034 if constexpr (Noise::Placed)
1036 return model.template policy<PolicyKind::additiveNoise>().parts();
1041 writeCount<Model> == 1,
1042 "a part of a composition whose additiveNoise() covers its whole output writes one block; place each "
1043 "part of its noise with on<Path>() to write several"
1046 typename Noise::Distribution{model.template policy<PolicyKind::additiveNoise>().distribution()}
1065template <
typename Path,
ProcessModel Model,
typename... Renames>
1067on(Model
const & model, Renames
const &...)
1069 static_assert(internal::wholeStateRefused<Model>);
1070 using Prefix = internal::AsTagPath<Path>;
1071 using Placement = internal::Placement<Prefix, Model, Renames...>;
1072 using Step = internal::PlacedStep<Model>;
1075 typename Placement::ReadsPolicy,
1076 internal::PlacedWrites<Prefix, Model>,
1077 typename Placement::AffinePolicy>{
1079 typename Placement::ReadsPolicy{},
1080 internal::PlacedWrites<Prefix, Model>{},
1081 typename Placement::AffinePolicy{}
1091template <
typename Path, MeasurementModel Model,
typename... Renames>
1093on(Model
const & model, Renames
const &...)
1095 static_assert(internal::wholeStateRefused<Model>);
1096 using Prefix = internal::AsTagPath<Path>;
1097 using Placement = internal::Placement<Prefix, Model, Renames...>;
1098 using InnerIn =
typename Model::template Policy<internal::PolicyKind::reads>::InputSpace;
1099 using ReadsPolicy =
typename Placement::ReadsPolicy;
1100 using AffinePolicy =
typename Placement::AffinePolicy;
1101 auto const function = [&] {
1102 if constexpr (Model::HasFunction)
1104 return internal::PlacedMeasure<typename Model::FunctionType, InnerIn>{model.function()};
1108 return internal::NoFunction{};
1112 [&](
auto const &... policies) {
1114 std::remove_cvref_t<
decltype(function)>,
1115 decltype(internal::placedPolicy<Prefix, InnerIn, ReadsPolicy, AffinePolicy>(policies))...>{
1117 internal::placedPolicy<Prefix, InnerIn, ReadsPolicy, AffinePolicy>(policies)...
1136template <
typename Path, ProcessModel Model,
typename... Renames>
1138onEach(Model
const & model, Renames
const &...)
1140 static_assert(internal::wholeStateRefused<Model>);
1141 using Prefix = internal::AsTagPath<Path>;
1142 using Each = internal::EachPlacement<Prefix, Model, Renames...>;
1143 using Step = internal::EachStep<Prefix, Model, Renames...>;
1146 typename Each::ReadsOfEach{},
1148 typename Each::AffineOfEach{}
1156template <
typename... Models>
1158composeMeasurements(Models... models)
1160 static_assert((wholeStateRefused<Models> && ...));
1163 ((Models::template has<PolicyKind::writes> || readsWholeState<Models>) && ...),
1164 "compose() takes measurement models that name their output with writes()"
1167 (Models::HasFunction && ...),
1168 "compose() takes measurement models with a function; one known by its likelihood alone has no output"
1171 (!Models::template has<PolicyKind::outputSpace> && ...),
1172 "compose() takes measurement models whose output writes() fixes, without outputSpace()"
1174 constexpr std::size_t likelihoods = (std::size_t{Models::template has<PolicyKind::logLikelihood>} + ...);
1176 likelihoods == 0 || likelihoods ==
sizeof...(Models),
1177 "in a composition of measurement models, every model gives logLikelihood() or none does"
1179 using AllItems =
decltype(std::tuple_cat(std::declval<ReadItemsOf<Models>>()...));
1180 using ReadsPolicy =
typename ReadUnionOf<AllItems>::type;
1181 using WritesPolicy =
typename WritesOfTuple<
1182 decltype(std::tuple_cat(std::declval<
typename PathsOf<WritePathsOf<Models>>::type>()...)),
1183 decltype(std::tuple_cat(std::declval<CompositeBlocks<OutputSpaceOf<Models>>>()...))>::type;
1184 using AffinePolicy =
typename AffineOf<ReadsPolicy, std::tuple<Models...>>::type;
1185 using Function = MeasurementParts<Models...>;
1186 auto const noise = std::tuple_cat(placedNoiseParts(models)...);
1187 auto const base = std::tuple{ReadsPolicy{}, WritesPolicy{}, AffinePolicy{}};
1188 auto const withNoise = [&] {
1189 if constexpr (std::tuple_size_v<std::remove_cvref_t<
decltype(noise)>> > 0)
1191 return std::tuple_cat(
1193 std::tuple{std::apply(
1194 [](
auto const &... parts) {
1195 return AdditiveNoise<std::remove_cvref_t<
decltype(parts)>...>{parts...};
1206 auto const policies = [&] {
1207 if constexpr (likelihoods > 0)
1209 using Sum = SumOfLikelihoods<
typename WritesPolicy::OutputSpace, Models...>;
1210 return std::tuple_cat(withNoise, std::tuple{LogLikelihood<Sum>{Sum{std::tuple{models...}}}});
1218 [&](
auto const &... each) {
1219 return MeasurementFunction<Function, std::remove_cvref_t<
decltype(each)>...>{
1220 Function{std::move(models)...},
1241 requires(
sizeof...(Models) > 0)
1245 return internal::composeMeasurements(std::remove_cvref_t<Models>{std::forward<Models>(models)}...);
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
What marginals and conditionals are built from: resolving Eigen index sets against a space; the share...
The macros every header includes first.
Measurement models and their observations (decisions.md [model-policies], [sensors],...
The transform methods, as policies made by their factories (decisions.md [policy-factories],...
Moments: the mean and covariance that a Gaussian carries and that a mixture or a sample set is moment...
The policies a model is built from, and the marks on a step's arguments (decisions....
Process models as functions with reads and writes (decisions.md [model-policies], [continuous-time-no...
How a model's reads() meet a state and a call, all internal (decisions.md [model-policies],...
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]).
Tag paths and the index utilities (decisions.md [tag-addressing], [index-names]): TagPath and TagPath...
A measurement model: a function of its input, with the policies that say what it reads,...
Definition MeasurementModel.h:156
DifferenceMatrix< Space_, Space_, Scalar > MatrixType
a matrix over differences, such as the covariance
Definition Moments.h:76
ValueVector< Space_, Scalar > VectorType
a value, such as the mean
Definition Moments.h:74
A process model: a function of its input and the step, with the policies that say what it reads,...
Definition ProcessModel.h:518
A measurement model: what measurementModel() returns, or a composition of such models (decisions....
Definition MeasurementModel.h:231
A process model: what processModel() returns, a built-in model, or a composition of process models (d...
Definition ProcessModel.h:2010
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
typename std::remove_cvref_t< X >::Scalar ScalarOf
The scalar type of the Eigen object or distribution X, for writing functions generic in it.
Definition Moments.h:26
auto on(Model const &model, Renames const &...)
Definition Placement.h:1067
auto onEach(Model const &model, Renames const &...)
Definition Placement.h:1138
auto compose(Models &&... models)
Definition Placement.h:1243
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
auto block(Space auto const &space, X &&x)
Definition TagPath.h:979
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
constexpr int valueDimensionAtCompileTime
The value dimension of Space at compile time, or Eigen::Dynamic if it is resizable.
Definition Space.h:251
ValueVector< S, Scalar > zeros(S const &space)
Definition TagPath.h:1092
constexpr int maxValueDimensionAtCompileTime
The largest valid value dimension of Space, or Eigen::Dynamic if it is unbounded.
Definition Space.h:258
What a model writes, as writes() declares it: the blocks its function's result fills (decisions....
Definition Policies.h:223