24#include <Eigen/Cholesky>
68template <
typename M,
typename Space>
69class ResolvedMeasurement :
public ResolvedReads<typename M::ModelType, typename M::ArgumentsType, Space>
72 using Base = ResolvedReads<typename M::ModelType, typename M::ArgumentsType, Space>;
76 using ObservedType = M;
77 using Model =
typename M::ModelType;
78 using Function =
typename Model::FunctionType;
79 using Method =
typename M::MethodType;
81 static constexpr bool HasFunction = Model::HasFunction;
82 static constexpr bool HasMethod = M::HasMethod;
83 static constexpr bool HasObservation = M::HasObservation;
84 static constexpr bool OwnNoise =
requires { M::OwnNoise; };
87 static constexpr bool HasAdditiveNoise = OwnNoise || Model::template has<PolicyKind::additiveNoise>;
90 static constexpr bool HasLogLikelihood = Model::template has<PolicyKind::logLikelihood>;
93 static constexpr bool HasSample = Model::template has<PolicyKind::sample>;
96 static constexpr bool BatchedLikelihood = [] {
97 if constexpr (HasLogLikelihood)
99 return isBatched<
decltype(Model::template Policy<PolicyKind::logLikelihood>::function)>;
107 using Base::ArgumentCount;
108 using Base::InputCount;
109 using Base::ItemCount;
110 using Base::StateCount;
111 using typename Base::In;
112 using typename Base::Reads;
113 using typename Base::StatePaths;
116 template <std::
size_t I>
117 using Item =
typename Base::template Item<I>;
120 template <std::
size_t J>
121 using Argument =
typename Base::template Argument<J>;
124 template <
typename T>
125 using InVector =
typename Base::template InVector<T>;
129 using Base::argumentIsUncertain;
130 using Base::argumentOf;
131 using Base::inputIndexOf;
132 using Base::inputItems;
134 using Base::m_differenceRows;
137 using Base::m_stateDifferenceSize;
138 using Base::m_valueRows;
139 using Base::stateIndexOf;
140 using Base::stateItems;
143 using ProbeScalar = double;
146 static constexpr bool OutputFromNoise = [] {
147 if constexpr (Model::template has<PolicyKind::outputSpace> || Model::template has<PolicyKind::writes>)
151 else if constexpr (Model::template has<PolicyKind::additiveNoise>)
153 return Model::template Policy<PolicyKind::additiveNoise>::HasOwnSpace;
165 [[nodiscard]]
static consteval auto
168 if constexpr (Model::template has<PolicyKind::outputSpace>)
170 using Policy =
typename Model::template Policy<PolicyKind::outputSpace>;
171 return std::type_identity<decltype(std::declval<Policy const &>().in(std::declval<Space const &>()))>{};
173 else if constexpr (Model::template has<PolicyKind::writes>)
175 return std::type_identity<typename Model::template Policy<PolicyKind::writes>::OutputSpace>{};
177 else if constexpr (OutputFromNoise)
179 return std::type_identity<
180 typename Model::template Policy<PolicyKind::additiveNoise>::Distribution::SpaceType>{};
182 else if constexpr (
requires {
typename Function::OutputSpaceType; })
184 return std::type_identity<typename Function::OutputSpaceType>{};
186 else if constexpr (HasFunction && functionForm<Function, In, NoOutputSpace, InVector<ProbeScalar>> == 0)
190 using Refused [[maybe_unused]] =
decltype(callForm(
191 std::declval<Function const &>(),
192 std::declval<In const &>(),
193 std::declval<NoOutputSpace const &>(),
194 std::declval<InVector<ProbeScalar>
const &>()
196 return std::type_identity<Linear<1>>{};
198 else if constexpr (HasFunction)
200 using Returned =
decltype(vectorReturned(callForm(
201 std::declval<Function const &>(),
202 std::declval<In const &>(),
203 std::declval<NoOutputSpace const &>(),
204 std::declval<InVector<ProbeScalar>
const &>()
206 using Evaluated = std::remove_cvref_t<decltype(valueOf(std::declval<Returned>()).eval())>;
207 static_assert(Evaluated::ColsAtCompileTime == 1,
"a measurement model's function returns a column vector");
208 return std::type_identity<Linear<Evaluated::RowsAtCompileTime, Evaluated::MaxRowsAtCompileTime>>{};
212 return std::type_identity<NoOutputSpace>{};
219 using Out =
typename decltype(outputType())::type;
221 static constexpr bool HasOutputSpace = !std::is_same_v<Out, NoOutputSpace>;
224 using NoiseType =
typename decltype([] {
225 if constexpr (OwnNoise)
227 return std::type_identity<typename M::NoiseType>{};
229 else if constexpr (HasAdditiveNoise)
233 "additive noise needs the model's output space, from writes(), outputSpace(), or its function's result"
235 return std::type_identity<
decltype(placeNoise(
236 std::declval<Out const &>(),
237 std::declval<Model const &>().
template policy<PolicyKind::additiveNoise>()
242 return std::type_identity<NoNoise>{};
247 static constexpr bool MixtureNoise = [] {
248 if constexpr (HasAdditiveNoise)
250 return isGaussianMixture<typename NoiseType::Distribution>;
261 using InnovationRepair =
typename M::InnovationRepair;
264 using ConsiderType =
typename M::ConsiderType;
267 ResolvedMeasurement(M
const & measurement, Space
const & space)
268 : Base{measurement.arguments(), space}
269 , m_measurement{measurement}
270 , m_out{makeOut(measurement, space)}
271 , m_noise{makeNoise(measurement)}
275 [[nodiscard]] M
const &
278 return m_measurement;
282 [[nodiscard]] Model
const &
285 return m_measurement.model();
289 [[nodiscard]] Method
const &
292 return m_measurement.method();
296 [[nodiscard]]
decltype(
auto)
298 requires HasObservation
300 return m_measurement.observation();
304 [[nodiscard]]
decltype(
auto)
305 covarianceUpdate()
const
307 return m_measurement.covarianceUpdate();
311 [[nodiscard]] Out
const &
313 requires HasOutputSpace
319 [[nodiscard]] NoiseType
const &
321 requires HasAdditiveNoise
331 template <
typename Joint,
typename... Inputs>
333 evaluate(Joint
const & joint, Inputs
const &... inputs)
const
335 static_assert(
sizeof...(Inputs) == InputCount,
"the function takes one vector per uncertain input");
336 using T =
typename Joint::Scalar;
337 return split<false>(call(this->
template gather<T>(joint, std::tuple<Inputs const &...>{inputs...})));
345 template <
typename State,
typename... Inputs>
347 evaluateAtState(State
const & state, Inputs
const &... inputs)
const
350 sizeof...(Inputs) == InputCount ||
sizeof...(Inputs) == 0,
351 "the function takes one vector per uncertain input, or none to read each at its mean"
353 using T =
typename State::Scalar;
355 call(this->
template gatherFromRows<T>(state, Eigen::Index{0}, std::tuple<Inputs
const &...>{inputs...}))
362 template <
typename State>
364 logLikelihoodAt(State
const & state)
const
365 requires(HasLogLikelihood && HasObservation)
367 return logLikelihoodAtRows(state, Eigen::Index{0});
373 template <
typename Rows>
375 logLikelihoodAtRows(Rows
const & rows, Eigen::Index start)
const
376 requires(HasLogLikelihood && HasObservation)
378 using T =
typename Rows::Scalar;
379 if constexpr (BatchedLikelihood)
382 auto x = InMatrix<T>{};
384 this->
template gatherColumnsFromRows<T>(
386 [&](Eigen::Index) -> Rows
const & {
391 auto result = Eigen::Matrix<T, 1, 1>{T(0)};
392 batchedLogLikelihoods(x, result);
397 return callWithScalar<T>(
398 model().
template policy<PolicyKind::logLikelihood>().function,
400 this->
template gatherFromRows<T>(rows, start, std::tuple<>{}),
401 m_measurement.observation()
410 template <
typename State,
typename G,
typename... Inputs>
412 sampleAtState(State
const & state, G & rng, Inputs
const &... inputs)
const
416 sizeof...(Inputs) == InputCount ||
sizeof...(Inputs) == 0,
417 "the draw takes one vector per uncertain input, or none to read each at its mean"
419 using T =
typename State::Scalar;
420 return callWithScalar<T>(
421 model().
template policy<PolicyKind::sample>().function,
423 this->
template gatherFromRows<T>(state, Eigen::Index{0}, std::tuple<Inputs
const &...>{inputs...}),
429 template <
typename T>
430 using InMatrix = MatrixOf<
438 static constexpr bool BatchedFunction = takesBatches<Function>;
441 template <
typename T,
typename S = Out>
449 template <
typename X,
typename Y>
451 evaluateBatch(X
const & x, Y && y)
const
452 requires BatchedFunction
454 callBatched(m_measurement.model().function(), m_in, m_out, x, y);
461 template <
typename X,
typename Y,
typename J>
463 evaluateBatchWithInputJacobians(X
const & x, Y & y, J & jacobians)
const
464 requires BatchedFunction
466 auto wanted = std::array<bool, std::tuple_size_v<InputBlocks<In>>>{};
467 [&]<std::size_t... I>(std::index_sequence<I...>) {
468 ((wanted[I] = argumentIsUncertain(I)), ...);
469 }(std::make_index_sequence<ItemCount>{});
470 callBatchedWithJacobians(m_measurement.model().function(), m_in, m_out, x, wanted, y, jacobians);
477 template <
typename Y,
typename Joint,
typename... Inputs>
479 gatherColumns(Joint
const & joint, Inputs
const &... inputs)
const
481 static_assert(
sizeof...(Inputs) == InputCount);
482 using T =
typename Joint::Scalar;
486 Y::ColsAtCompileTime,
488 Y::MaxColsAtCompileTime>;
491 for (Eigen::Index j = 0; j < joint.cols(); ++j)
493 x.col(j) = this->
template gather<T>(joint.col(j), std::tuple{inputs.col(j)...});
503 template <
typename Y,
typename Joint,
typename... Inputs>
505 evaluateColumns(Y & y, Joint
const & joint, Inputs
const &... inputs)
const
506 requires BatchedFunction
508 callBatched(m_measurement.model().function(), m_in, m_out, gatherColumns<Y>(joint, inputs...), y);
515 template <
typename Y,
typename States,
typename... Inputs>
517 evaluateStateColumns(Y & y, States
const & states, Inputs
const &... inputs)
const
518 requires BatchedFunction
520 static_assert(
sizeof...(Inputs) == InputCount);
521 using T =
typename States::Scalar;
525 Y::ColsAtCompileTime,
527 Y::MaxColsAtCompileTime>;
530 for (Eigen::Index j = 0; j < states.cols(); ++j)
532 x.col(j) = this->
template gatherFromRows<T>(states.col(j), Eigen::Index{0}, std::tuple{inputs.col(j)...});
534 callBatched(m_measurement.model().function(), m_in, m_out, x, y);
541 template <
typename Y,
typename J,
typename Joint,
typename... Inputs>
543 evaluateColumnsWithAffineJacobians(Y & y, J & jacobians, Joint
const & joint, Inputs
const &... inputs)
const
544 requires BatchedFunction
546 auto wanted = std::array<bool, std::tuple_size_v<InputBlocks<In>>>{};
547 [&]<std::size_t... I>(std::index_sequence<I...>) {
548 ((wanted[I] = Base::template itemFactored<I>()), ...);
549 }(std::make_index_sequence<ItemCount>{});
550 auto const x = gatherColumns<Y>(joint, inputs...);
551 callBatchedWithJacobians(m_measurement.model().function(), m_in, m_out, x, wanted, y, jacobians);
558 template <
typename X,
typename Result>
560 batchedLogLikelihoods(X
const & x, Result && result)
const
561 requires(BatchedLikelihood && HasObservation)
563 using T =
typename X::Scalar;
564 using Likelihood =
typename Model::template Policy<PolicyKind::logLikelihood>;
565 using Output = BatchedOutput<In, Linear<1>, T,
typename decltype(Likelihood::function)::MarkType>;
566 EMRYS_FILTER_ASSERT(result.size() == x.cols() &&
"give one entry per column of the batch");
568 typename Output::ValuesType{result.data(), 1, x.cols()},
569 typename Output::JacobiansType{
nullptr, 1, 0},
574 model().
template policy<PolicyKind::logLikelihood>().function.function,
577 m_measurement.observation(),
587 [[nodiscard]]
static Out
588 makeOut([[maybe_unused]] M
const & measurement, [[maybe_unused]] Space
const & space)
590 if constexpr (Model::template has<PolicyKind::outputSpace>)
592 return measurement.model().template policy<PolicyKind::outputSpace>().in(space);
594 else if constexpr (OutputFromNoise)
596 return measurement.model().template policy<PolicyKind::additiveNoise>().distribution().space();
598 else if constexpr (FixedSizeSpace<Out> || !HasOutputSpace)
605 requires(Function
const & f) { f.outputRows(); },
606 "a function that returns a vector of run-time size names its output with writes() or outputSpace()"
608 return Out{measurement.model().function().outputRows()};
615 [[nodiscard]] NoiseType
616 makeNoise([[maybe_unused]] M
const & measurement)
const
618 if constexpr (OwnNoise)
620 return measurement.noise();
622 else if constexpr (HasAdditiveNoise)
624 return placeNoise(m_out, measurement.model().template policy<PolicyKind::additiveNoise>());
635 template <
typename X>
637 call(X
const & x)
const
639 static_assert(HasFunction,
"a measurement model known by its likelihood alone has no function to evaluate");
640 return vectorReturned(callForm(m_measurement.model().function(), m_in, m_out, x));
648 template <
bool Whole,
typename R>
650 split(R && returned)
const
652 using Plain = std::remove_cvref_t<R>;
653 if constexpr (!isWithJacobian<Plain>)
655 return std::forward<R>(returned);
659 using J = std::remove_cvref_t<
decltype(returned.jacobian)>;
662 "a measurement model's function returns its Jacobian as one matrix over its input's differences, "
665 auto const & jacobian = returned.jacobian;
668 &&
"a returned Jacobian has a column per difference coordinate of the model's input"
670 using Scalar =
typename J::Scalar;
671 constexpr int Rows = J::RowsAtCompileTime;
672 constexpr int MaxRows = J::MaxRowsAtCompileTime;
674 constexpr int MaxCols =
676 using StateBlock = MatrixOf<Scalar, Rows, Cols, MaxRows, MaxCols>;
677 StateBlock stateBlock =
678 StateBlock::Zero(jacobian.rows(), Whole ? m_stateDifferenceSize : m_reads.differenceIndices().size());
679 [&]<std::size_t... K>(std::index_sequence<K...>) {
680 ((stateBlock.middleCols(
681 Whole ? m_reads.differenceRows(K).start : m_reads.jointDifferenceStart(K),
682 m_differenceRows[stateItems(K)].size
683 ) = jacobian.middleCols(m_differenceRows[stateItems(K)].start, m_differenceRows[stateItems(K)].size)),
685 }(std::make_index_sequence<StateCount>{});
686 if constexpr (InputCount == 0)
688 return withJacobian(std::move(returned.value), std::move(stateBlock));
692 auto blocks = [&]<std::size_t... P>(std::index_sequence<P...>) {
693 return std::tuple{std::move(stateBlock), inputBlock<P>(jacobian)...};
694 }(std::make_index_sequence<InputCount>{});
695 return withJacobian(std::move(returned.value), std::move(blocks));
701 template <std::
size_t P,
typename J>
703 inputBlock(J
const & jacobian)
const
706 std::remove_cvref_t<
decltype(inputOf(std::declval<Argument<argumentOf(inputItems(P))>
const &>()))>;
707 using Block = MatrixOf<
709 J::RowsAtCompileTime,
710 Input::DifferenceDimensionAtCompileTime,
711 J::MaxRowsAtCompileTime,
712 Input::MaxDifferenceDimensionAtCompileTime>;
713 BlockRows
const & rows = m_differenceRows[inputItems(P)];
714 Block
block = jacobian.middleCols(rows.start, rows.size);
718 M
const & m_measurement;
729class ResolvedFunction
734 static constexpr bool EvaluatesBatches = R::BatchedFunction;
737 explicit ResolvedFunction(R
const & resolved)
738 : m_resolved{resolved}
742 template <
typename Joint,
typename... Inputs>
744 operator()(Joint
const & joint, Inputs
const &... inputs)
const
746 return m_resolved.evaluate(joint, inputs...);
752 template <
typename Y,
typename Joint,
typename... Inputs>
754 evaluateBatch(Y & y, Joint
const & joint, Inputs
const &... inputs)
const
755 requires EvaluatesBatches
757 m_resolved.evaluateColumns(y, joint, inputs...);
763 template <
typename Y,
typename J,
typename Joint,
typename... Inputs>
765 evaluateBatchWithAffineJacobians(Y & y, J & jacobians, Joint
const & joint, Inputs
const &... inputs)
const
766 requires EvaluatesBatches
768 m_resolved.evaluateColumnsWithAffineJacobians(y, jacobians, joint, inputs...);
773 R
const & m_resolved;
777template <
typename Space,
typename M>
778[[nodiscard]] ResolvedMeasurement<M, Space>
779resolveMeasurement(M
const & measurement, Space
const & space)
781 return ResolvedMeasurement<M, Space>{measurement, space};
789template <
typename Scalar,
typename R,
typename Space>
791observedValue(R
const & resolved, Space
const & space)
794 auto const & observation = resolved.observation();
796 observation.size() ==
valueDimension(space) &&
"the observation must be a value in the measurement space"
798 Vector result = observation.template cast<Scalar>();
799 EMRYS_FILTER_ASSERT(result.allFinite() &&
"the observation must be finite");
807template <
typename Scalar,
typename R,
typename Space,
typename Predicted>
809observedResidual(R
const & resolved, Space
const & space, Eigen::MatrixBase<Predicted>
const & predicted)
812 return Difference{
Emrys::minus(space, observedValue<Scalar>(resolved, space), predicted)};
818template <
typename R,
typename Method,
typename F,
typename... Args>
820transformPrediction(R
const & resolved, Method
const & method, F
const & f, Args
const &... args)
822 return transformBy(method, f, resolved.space(), args...);
829template <
typename R,
typename Method,
typename F,
typename Read>
831transformMeasurement(R
const & resolved, Method
const & method, F
const & f, Read
const & read)
834 [&](
auto const &... inputs) {
835 if constexpr (isSigmaPointMethod<Method> && R::factorsAffine())
837 auto const factored = FactoredAt<R::affineSize(), R::affineMaxSize(), Method>{
839 resolved.template affineCoordinates<false>()
841 return transformPrediction(resolved, factored, f,
withCross(read), inputs...);
845 return transformPrediction(resolved, method, f,
withCross(read), inputs...);
855template <
typename R,
typename Method,
typename F,
typename G,
typename... Args>
856[[nodiscard]]
decltype(
auto)
857linearizePrediction(R
const & resolved, Method
const & method, F
const & f, G
const & g, Args
const &... args)
859 using Problem = Transform<F
const,
typename R::Out, Args...>;
860 auto const problem = Problem{f, resolved.space(), args...};
861 return g(problem, linearizeAt(method, problem));
867template <
typename R,
typename Method,
typename F,
typename Read,
typename G>
868[[nodiscard]]
decltype(
auto)
869linearizeMeasurement(R
const & resolved, Method
const & method, F
const & f, Read
const & read, G
const & g)
872 [&](
auto const &... inputs) ->
decltype(
auto) {
873 return linearizePrediction(resolved, method, f, g,
withCross(read), inputs...);
884template <
typename Space,
typename Vector,
typename Jacobian,
typename Cross>
885class PredictionMoments
892 PredictionMoments(Space
const & space, Vector
const & mean, Jacobian
const & jacobian, Cross
const & cross)
895 , m_jacobian{jacobian}
900 [[nodiscard]] Space
const &
907 [[nodiscard]] Vector
const &
915 covarianceLower()
const
917 return multiply(m_jacobian, m_cross);
923 template <
typename Matrix,
typename Noise>
925 covariancePlus(Noise
const & noise)
const
927 Matrix result = noise;
928 result.noalias() += multiply(m_jacobian, m_cross);
933 [[nodiscard]] Eigen::Index
934 valueDimension()
const
940 [[nodiscard]] Eigen::Index
941 differenceDimension()
const
948 Space
const & m_space;
949 Vector
const & m_mean;
950 Jacobian
const & m_jacobian;
951 Cross
const & m_cross;
958template <
typename Matrix,
typename Output,
typename Noise>
960innovationCovariancePlus(Output
const & y, Noise
const & noise)
962 if constexpr (
requires { y.template covariancePlus<Matrix>(noise); })
964 return y.template covariancePlus<Matrix>(noise);
968 Matrix result = noise;
969 result += y.covarianceLower();
986template <
typename G,
typename Accept = AcceptEvery>
994template <
typename Sink>
995inline constexpr bool isIntoPrior =
false;
998template <
typename G,
typename Accept>
999inline constexpr bool isIntoPrior<IntoPrior<G, Accept>>{
true};
1010template <
typename Update>
1017template <
typename Sink>
1018inline constexpr bool isReusedUpdate =
false;
1021template <
typename Update>
1022inline constexpr bool isReusedUpdate<ReusedUpdate<Update>>{
true};
1030template <
typename Space,
typename MeasurementSpace,
typename Scalar,
typename Sink>
1031[[nodiscard]]
decltype(
auto)
1032mixtureUpdateFor(Sink & sink)
1034 if constexpr (isReusedUpdate<Sink>)
1036 using Update = std::remove_cvref_t<
decltype(*sink.update)>;
1038 std::is_same_v<typename Update::SpaceType, Space>
1039 && std::is_same_v<typename Update::MeasurementSpaceType, MeasurementSpace>
1040 && Update::BranchCount == std::dynamic_extent,
1041 "the update reused must be over the state and the innovation, with a run-time number of branches"
1043 Update & result = *sink.update;
1044 result.branches.clear();
1049 return MeasurementUpdate<Space, MeasurementSpace, std::dynamic_extent, Scalar>{};
1057template <
typename Sink,
typename Update>
1058using MixtureOutcome =
1059 std::conditional_t<isReusedUpdate<Sink>, std::expected<void, GaussianError>, std::expected<Update, GaussianError>>;
1064template <
typename Sink,
typename Update>
1065[[nodiscard]] MixtureOutcome<Sink, Update>
1066mixtureOutcome(Update &
update)
1068 if constexpr (isReusedUpdate<Sink>)
1074 return std::move(
update);
1088template <
typename Jacobian,
typename Indices,
typename Error>
1089struct ReadLinearization
1092 Indices
const & indices;
1097template <
typename Jacobian,
typename Indices,
typename Error>
1098ReadLinearization(Jacobian, Indices
const &, Error) -> ReadLinearization<Jacobian, Indices, Error>;
1106template <
typename Matrix,
typename R,
typename Problem,
typename Jacobian>
1108inputsCovariance(R
const & resolved, Problem
const & problem, Jacobian
const & jacobian)
1110 using Scalar =
typename Matrix::Scalar;
1111 Eigen::Index
const m = jacobian.rows();
1112 Matrix result = Matrix::Zero(m, m);
1113 auto const inputs = resolved.inputs();
1114 [&]<std::size_t... P>(std::index_sequence<P...>) {
1115 [[maybe_unused]]
auto const add = [&]<std::size_t K>(std::integral_constant<std::size_t, K>) {
1116 auto const & input = inputOf(std::get<K>(inputs));
1117 using Input = std::remove_cvref_t<
decltype(input)>;
1118 using NoiseMatrix = MatrixOf<
1120 Input::DifferenceDimensionAtCompileTime,
1121 Input::DifferenceDimensionAtCompileTime,
1122 Input::MaxDifferenceDimensionAtCompileTime,
1123 Input::MaxDifferenceDimensionAtCompileTime>;
1124 using InputJacobian = MatrixOf<
1126 Matrix::RowsAtCompileTime,
1127 Input::DifferenceDimensionAtCompileTime,
1128 Matrix::MaxRowsAtCompileTime,
1129 Input::MaxDifferenceDimensionAtCompileTime>;
1130 Eigen::Index
const d = input.differenceDimension();
1131 InputJacobian
const block = jacobian.middleCols(problem.differenceOffset(K + 1), d);
1132 NoiseMatrix
const cov = symmetricFromLower<NoiseMatrix>(covarianceLowerOf(input));
1133 result.noalias() += multiply(multiply(
block, cov),
block.transpose());
1135 (add(std::integral_constant<std::size_t, P>{}), ...);
1136 }(std::make_index_sequence<R::InputCount>{});
1137 if constexpr (R::InputCount > 0)
1139 result = (Scalar(0.5) * (result + result.transpose())).eval();
1145template <
typename P,
typename... Qs>
1146inline constexpr bool liesInNoOther = ((std::is_same_v<P, Qs> || !pathLiesIn<P, Qs>) && ...);
1149template <
typename C>
1150struct ConsideredRowsOf;
1153template <
typename... Paths>
1154struct ConsideredRowsOf<Consider<Paths...>>
1157 template <
typename Space>
1158 [[nodiscard]]
static ConsideredRows<
sizeof...(Paths)>
1159 resolve([[maybe_unused]] Space
const & space)
1162 ([]<
typename First,
typename... Rest>(TagPath<First, Rest...> *) {
1163 return countTag<First, Space>() > 0;
1164 }(
static_cast<Paths *
>(
nullptr))
1166 "a path of consider() names no block of the state"
1168 static_assert((liesInNoOther<Paths, Paths...> && ...),
"a block of consider() lies in another it names");
1169 return {differenceBlockRows<Paths>(space)...};
1178template <
typename R,
typename Space>
1180consideredRows(Space
const & space)
1182 return ConsideredRowsOf<typename R::ConsiderType>::resolve(space);
1193[[nodiscard]]
decltype(
auto)
1194conditionOnPrediction(
1195 Prior
const & prior,
1198 Cross
const & cross,
1199 Jacobian
const & readJacobian,
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
Batched functions (decisions.md [batched-functions]): batched(), the mark that a function takes every...
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
The coordinate types (decisions.md [no-bounded-coordinates]): Linear, plain coordinates,...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
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],...
What an update returns (decisions.md [weighted-branches], [innovation-statistics]): an UpdateBranch p...
The mixture: the parameters MixtureParams of weighted components of one type (decisions....
Products of fixed-size matrices by Eigen's fixed-size product at every size: multiply() is by Eigen'...
The policies a model is built from, and the marks on a step's arguments (decisions....
Product: the product of independent densities, each on its own block of a space, built with on<Path>(...
How a model's reads() meet a state and a call, all internal (decisions.md [model-policies],...
Solving by a factorization of a small matrix: transposedSolve() gives , the shape of a Kalman gain an...
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...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
DifferenceVector< Space_, Scalar > DifferenceVectorType
a difference, such as a residual
Definition Moments.h:75
ValueVector< Space_, Scalar > VectorType
a value, such as the mean
Definition Moments.h:74
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
std::expected< CategoricalUpdate< Space, Scalar >, WeightError > update(CategoricalParams< Space, Scalar > const &prior, E const &emission)
Definition Emission.h:97
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
auto block(Space auto const &space, X &&x)
Definition TagPath.h:979
auto minus(S const &space, Eigen::MatrixBase< ADerived > const &a, Eigen::MatrixBase< BDerived > const &b)
Definition Space.h:715
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
constexpr int maxValueDimensionAtCompileTime
The largest valid value dimension of Space, or Eigen::Dynamic if it is unbounded.
Definition Space.h:258
void normalizeValues(S const &space, Eigen::MatrixBase< Derived > const &block)
Brings the values in block (rows are space's coordinates, columns samples) into canonical form,...
Definition Space.h:331