26#include <Eigen/Cholesky>
62template <
bool Statistics, UncertainInput Prior,
typename R,
typename Sink,
typename Reference = NoReference>
63[[nodiscard]]
decltype(
auto)
64updateResolved(Prior
const & prior, R
const & resolved, Sink sink, Reference
const & reference = {})
66 using Scalar =
typename Prior::Scalar;
67 using Space =
typename Prior::SpaceType;
68 using Reads =
typename R::Reads;
74 "a Kalman update pushes the prior through the model by a method: observe(method, model, z)"
78 "a Kalman update needs the model's function; a model known by its likelihood alone serves the filters that "
81 auto const & reads = resolved.reads();
82 auto const read = GaussianMarginal<Prior, typename Reads::Selection, typename Reads::JointSpace>{
87 auto const f = ResolvedFunction{resolved};
88 auto const & method = resolved.method();
89 using Method = std::remove_cvref_t<
decltype(method)>;
90 auto const all = internal::consecutiveIndices<N, NMax>(0, prior.differenceDimension());
92 using StateReadMatrix = internal::MatrixOf<Scalar, N, Reads::DifferenceSize, NMax, Reads::DifferenceMaxSize>;
93 StateReadMatrix
const stateRead =
94 internal::lowerSymmetricBlock(covarianceLowerOf(prior), all, reads.differenceIndices());
96 if constexpr (isLinearizedAbout<Reference>)
100 static_assert(checkReference<Method, Reference, Space>());
103 using ReadVector =
typename MovedInput<std::remove_cvref_t<
decltype(read)>>::VectorType;
105 Vector
const point = reference.mean();
107 point.size() == prior.valueDimension() &&
"a point to linearize about must have the prior's value dimension"
109 Difference
const step =
Emrys::minus(prior.space(), point, prior.mean());
110 ReadVector
const readMean = read.mean();
111 ReadDifference
const readStep = step(reads.differenceIndices());
112 auto const condition = [&](
auto const & y,
auto const & cross,
auto const & readJacobian) ->
decltype(
auto) {
113 return conditionOnPrediction<Statistics>(prior, resolved, y, cross, readJacobian, sink);
115 if constexpr (isLinearMethod<Method>)
117 return linearizeReadsAt<Space, Scalar>(
131 else if constexpr (Reference::IsDistribution)
133 using ReadMatrix = internal::MatrixOf<
135 Reads::DifferenceSize,
136 Reads::DifferenceSize,
137 Reads::DifferenceMaxSize,
138 Reads::DifferenceMaxSize>;
140 ReadMatrix
const spreadCov = internal::lowerSymmetricBlock(
141 reference.reference.covarianceLower(),
142 reads.differenceIndices(),
143 reads.differenceIndices()
145 return linearizeReadsAt<Space, Scalar>(
160 else if constexpr (isIterated<Method>)
162 if constexpr (R::MixtureNoise)
166 static_assert(!isIntoPrior<Sink>,
"conditioning in place takes noise of one component");
167 auto const & noise = resolved.noise().distribution();
168 using Component = std::remove_cvref_t<
decltype(noise.begin()->component)>;
169 using One = WithNoiseComponent<typename R::ObservedType, Component>;
171 typename decltype(updateInto<true>(prior, std::declval<One const &>(), NewPosteriors{}))::value_type;
172 using MeasurementSpace =
typename Single::MeasurementSpaceType;
173 auto const total = noise.logTotalWeight();
174 EMRYS_FILTER_ASSERT(total &&
"the noise mixture's weights must be valid");
175 decltype(
auto) result = mixtureUpdateFor<Space, MeasurementSpace, Scalar>(sink);
176 using Outcome = MixtureOutcome<Sink, std::remove_cvref_t<
decltype(result)>>;
177 result.branches.reserve(std::size_t(noise.size()));
178 auto evidence = LogSumExp<Scalar>{};
180 for (
auto const & entry : noise)
182 auto const one = One{resolved.observed(), entry.component};
183 auto single = updateInto<true>(prior, one, NewPosteriors{});
186 return Outcome{std::unexpected{single.error()}};
188 auto & branch = single->branches.front();
189 branch.component = k++;
190 branch.logWeight = entry.logWeight - *total + branch.logLikelihood();
191 evidence.add(branch.logWeight);
192 result.branches.push_back(std::move(branch));
194 auto const logEvidence = evidence.value();
195 MixtureEvidenceAccess::setMixtureLogLikelihood(result, logEvidence);
196 for (
auto & branch : result.branches)
198 branch.logWeight -= logEvidence;
200 return mixtureOutcome<Sink>(result);
204 return iteratedUpdate<Statistics>(prior, resolved, reads, read, f, stateRead, sink);
207 else if constexpr (internal::isLinearMethod<Method>)
212 auto const condition = [&](
auto const & problem,
auto const &
linearized) ->
decltype(
auto) {
213 using Problem = std::remove_cvref_t<
decltype(problem)>;
214 using Predicted = OutputWithCross<Space, typename Problem::OutputSpaceType, JacobianForm, Scalar>;
216 Eigen::Index
const readSize = reads.differenceIndices().size();
217 auto const readJacobian = ReadLinearization{
218 jacobian.template middleCols<Reads::DifferenceSize>(problem.differenceOffset(0), readSize),
219 reads.differenceIndices(),
221 using Error =
typename Problem::OutputMatrix;
222 return internal::inputsCovariance<Error>(resolved, problem, jacobian);
225 auto cross =
typename Predicted::CrossMatrix{};
226 cross.noalias() = internal::multiply(stateRead, readJacobian.jacobian.transpose());
227 if constexpr (R::InputCount > 0)
229 typename Problem::CrossMatrix
const joint =
230 internal::multiply(problem.covarianceLower(), jacobian.transpose());
231 auto const y = internal::PredictionMoments{problem.outputSpace(),
linearized.mean, jacobian, joint};
232 return internal::conditionOnPrediction<Statistics>(prior, resolved, y, cross, readJacobian, sink);
238 auto const joint = std::as_const(cross)(reads.differenceIndices(), Eigen::placeholders::all);
239 auto const y = internal::PredictionMoments{problem.outputSpace(),
linearized.mean, jacobian, joint};
240 return internal::conditionOnPrediction<Statistics>(prior, resolved, y, cross, readJacobian, sink);
243 return internal::linearizeMeasurement(resolved, method, f, read,
condition);
250 auto const predicted = internal::transformMeasurement(resolved, method, f, read);
251 using Predicted = std::remove_cvref_t<
decltype(predicted)>;
252 using Solved =
typename Predicted::CrossMatrix;
253 Solved
const solved = internal::solveWithRoot<Solved>(predicted.root(), predicted.whitenedCross());
254 using MeasurementSpace = std::remove_cvref_t<
decltype(predicted.output().space())>;
256 internal::multiply(stateRead, solved);
258 auto const readJacobian =
259 internal::ReadLinearization{solved.transpose(), reads.differenceIndices(), [&] {
260 using Error =
typename Predicted::OutputMatrix;
262 predicted.inputsCovariance() + predicted.unexplainedCovariance()
265 return internal::conditionOnPrediction<Statistics>(
282template <
bool Statistics, UncertainInput Prior, Measurement M,
typename Sink,
typename Reference = NoReference>
283[[nodiscard]]
decltype(
auto)
284updateInto(Prior
const & prior, M
const & measurement, Sink sink, Reference
const & reference = {})
286 auto const resolved = resolveMeasurement(measurement, prior.space());
287 return updateResolved<Statistics>(prior, resolved, std::move(sink), reference);
294template <
bool Statistics, UncertainInput Prior, Measurement M,
typename Reference = NoReference>
296updateBranches(Prior
const & prior, M
const & measurement, Reference
const & reference = {})
298 return updateInto<Statistics>(prior, measurement, NewPosteriors{}, reference);
304template <UncertainInput Prior, Measurement M>
305using MeasuredUpdate =
306 typename decltype(updateBranches<false>(std::declval<Prior const &>(), std::declval<M const &>()))::value_type;
317 UncertainInput Prior,
320 typename MeasurementSpace,
323 typename Reference = NoReference>
324[[nodiscard]] std::expected<void, GaussianError>
327 M
const & measurement,
328 MeasurementUpdate<Space, MeasurementSpace, std::dynamic_extent, Scalar, Allocator> & into,
329 Reference
const & reference = {}
332 using Update = MeasurementUpdate<Space, MeasurementSpace, std::dynamic_extent, Scalar, Allocator>;
333 return updateInto<Statistics>(prior, measurement, ReusedUpdate<Update>{&into}, reference);
354 typename Reference = NoReference,
355 typename Accept = AcceptEvery>
358 GaussianParams<Space, Scalar> & state,
359 M
const & measurement,
360 Reference
const & reference = {},
361 Accept
const & accept = {}
364 return updateInto<Statistics>(
365 std::as_const(state),
367 IntoPrior<GaussianParams<Space, Scalar>, Accept>{state, accept},
419template <UncertainInput Prior, Measurement M>
421update(Prior
const & prior, M
const & measurement)
423 return internal::updateBranches<false>(internal::withCovariance(prior), measurement);
442template <UncertainInput Prior, Measurement M,
typename Reference>
446 return internal::updateBranches<false>(internal::withCovariance(prior), measurement, about);
467[[nodiscard]]
decltype(
auto)
468conditionOnPrediction(
473 [[maybe_unused]] Jacobian
const & readJacobian,
477 using Scalar =
typename Prior::Scalar;
478 using Space =
typename Prior::SpaceType;
479 using MeasurementSpace = std::remove_cvref_t<
decltype(y.space())>;
483 MeasurementVector
const observed = observedValue<Scalar>(resolved, y.space());
489 auto const & form = resolved.covarianceUpdate();
490 using Form = std::remove_cvref_t<
decltype(form)>;
491 auto const linearization = [&] {
492 if constexpr (std::is_same_v<Form, updates::Joseph>)
494 using Result = StatisticalLinearization<Space, MeasurementSpace, Scalar>;
495 typename Result::JacobianMatrix jacobian =
496 Result::JacobianMatrix::Zero(y.differenceDimension(), prior.differenceDimension());
497 jacobian(Eigen::placeholders::all, readJacobian.indices) = readJacobian.jacobian;
498 typename Result::ErrorMatrix errorCov = readJacobian.error();
499 return Result{std::move(jacobian), std::move(errorCov)};
503 return std::tuple<>{};
507 constexpr bool MixtureParams = R::MixtureNoise;
509 !(MixtureParams && isIntoPrior<std::remove_cvref_t<Sink>>),
510 "conditioning in place takes noise of one component"
512 using Branch = UpdateBranch<Space, MeasurementSpace, Scalar>;
513 constexpr bool InPlace = isIntoPrior<std::remove_cvref_t<Sink>>;
514 constexpr bool BranchStatistics = Statistics || MixtureParams;
515 using BranchRepair =
typename R::InnovationRepair;
517 auto const considered = consideredRows<R>(prior.space());
522 auto const termsFor = [&]([[maybe_unused]] InnovationMatrix
const & noise) {
523 if constexpr (std::is_same_v<Form, updates::Joseph>)
527 using Linearization = StatisticalLinearization<Space, MeasurementSpace, Scalar>;
528 return JosephTerms<typename Linearization::JacobianMatrix const &, InnovationMatrix>{
529 linearization.jacobian,
530 InnovationMatrix{linearization.errorCov + noise}
536 return std::tuple<>{};
544 auto const condition = [&](MeasurementVector
const & mean,
545 auto const & makeCov,
546 InnovationMatrix
const & noise,
547 Eigen::Index component) -> std::expected<Branch, GaussianError> {
549 InnovationMatrix cov = makeCov();
550 auto conditioned = kalmanCondition<BranchStatistics, BranchRepair>(
561 return std::unexpected{conditioned.error()};
565 std::move(conditioned->posterior),
566 {std::move(residual), std::move(cov), conditioned->statistics},
572 if constexpr (MixtureParams)
574 auto const & noise = resolved.noise().distribution();
575 auto const total = noise.logTotalWeight();
576 EMRYS_FILTER_ASSERT(total &&
"the noise mixture's weights must be valid");
577 decltype(
auto) result = mixtureUpdateFor<Space, MeasurementSpace, Scalar>(sink);
578 using Outcome = MixtureOutcome<std::remove_cvref_t<Sink>, std::remove_cvref_t<
decltype(result)>>;
579 result.branches.reserve(std::size_t(noise.size()));
580 auto evidence = LogSumExp<Scalar>{};
583 for (
auto const & entry : noise)
586 Emrys::plus(y.space(), y.mean(), entry.component.mean()),
588 return innovationCovariancePlus<InnovationMatrix>(y, entry.component.covarianceLower());
590 entry.component.covarianceLower(),
595 return Outcome{std::unexpected{branch.error()}};
597 branch->logWeight = entry.logWeight - *total + branch->logLikelihood();
598 evidence.add(branch->logWeight);
599 result.branches.push_back(std::move(*branch));
601 auto const logEvidence = evidence.value();
602 MixtureEvidenceAccess::setMixtureLogLikelihood(result, logEvidence);
603 for (
auto & branch : result.branches)
605 branch.logWeight -= logEvidence;
607 return mixtureOutcome<std::remove_cvref_t<Sink>>(result);
618 using InPlaceUpdate = FilterUpdate<MeasurementSpace, 1, Scalar>;
619 auto const inPlace = [&](
auto & into,
620 MeasurementVector
const & mean,
621 auto const & makeCov,
622 InnovationMatrix
const & noise) -> std::expected<InPlaceUpdate, GaussianError> {
623 auto failure = std::optional<GaussianError>{};
624 bool accepted =
true;
625 auto const terms = termsFor(noise);
626 auto result = std::expected<void, GaussianError>{}.transform([&] {
627 return InPlaceUpdate{
628 {FilterBranch<MeasurementSpace, Scalar>{
630 Innovation<MeasurementSpace, Scalar>{
632 InnovationVector{
Emrys::minus(y.space(), observed, mean)},
634 [&](
auto const &
residual,
auto & cov) {
635 auto conditioned = kalmanConditionInPlace<Statistics, BranchRepair>(
647 failure = conditioned.error();
648 return std::optional<InnovationStatistics<Scalar>>{};
650 accepted = conditioned->accepted;
651 return conditioned->statistics;
663 result = std::unexpected{*failure};
667 result->accepted = accepted;
673 auto const single = [&](MeasurementVector
const & mean,
auto const & makeCov, InnovationMatrix
const & noise) {
674 if constexpr (InPlace)
676 return inPlace(sink, mean, makeCov, noise);
680 using One = MeasurementUpdate<Space, MeasurementSpace, 1, Scalar>;
681 auto branch =
condition(mean, makeCov, noise, 0);
684 return std::expected<One, GaussianError>{std::unexpected{branch.error()}};
686 return std::expected<One, GaussianError>{One{{std::move(*branch)}}};
689 if constexpr (!R::HasAdditiveNoise)
694 return InnovationMatrix{y.covarianceLower()};
696 InnovationMatrix::Zero(y.differenceDimension(), y.differenceDimension())
701 auto const & noise = resolved.noise().distribution();
705 return innovationCovariancePlus<InnovationMatrix>(y, noise.covarianceLower());
707 noise.covarianceLower()
721template <
typename Space,
typename P,
typename Value>
735template <
typename Space,
typename P,
typename M>
736class PinnedMeasurement
741 using ResolvedType = ResolvedMeasurement<M, Space>;
745 using Reads =
typename ResolvedType::Reads;
748 static constexpr int D =
756 static constexpr int RestD = D == Eigen::Dynamic || PinnedD == Eigen::Dynamic ? Eigen::Dynamic : D - PinnedD;
758 static constexpr int RestDMax = RestD == Eigen::Dynamic ? DMax : RestD;
764 static constexpr int RestN = N == Eigen::Dynamic || PinnedN == Eigen::Dynamic ? Eigen::Dynamic : N - PinnedN;
766 static constexpr int RestNMax = RestN == Eigen::Dynamic ? NMax : RestN;
773 PinnedMeasurement(
Space const & space, M
const & measurement)
774 : m_resolved{measurement, space}
775 , m_rows{blockRows<P>(space)}
776 , m_differenceRows{differenceBlockRows<P>(space)}
780 m_rest.resize(m_size - m_rows.size);
782 for (Eigen::Index i = 0; i < m_size; ++i)
784 if (i < m_rows.start || i >= m_rows.start + m_rows.size)
792 [[nodiscard]] ResolvedType
const &
799 [[nodiscard]] Eigen::Index
802 return m_rest.size();
810 template <
typename X,
typename Pinned,
typename... Inputs>
812 operator()(X
const & x, Pinned
const & p, Inputs
const &... inputs)
const
815 EMRYS_FILTER_ASSERT(x.size() == m_rest.size() && p.size() == m_rows.size &&
"the blocks do not fit the space");
816 auto state = Eigen::Matrix<T, N, 1, Eigen::ColMajor, NMax, 1>{};
817 state.resize(m_size);
819 middleRowsOf<PinnedN>(state, m_rows.start, m_rows.size) = p.template cast<T>();
820 using Returned = std::remove_cvref_t<
decltype(m_resolved.evaluateAtState(state, inputs...))>;
821 if constexpr (!isWithJacobian<Returned>)
823 return m_resolved.evaluateAtState(state, inputs...);
827 auto returned = m_resolved.evaluateAtState(state, inputs...);
829 std::move(returned.value),
830 splitJacobian(returned.jacobian, std::integral_constant<std::size_t,
sizeof...(Inputs)>{})
837 static constexpr bool EvaluatesBatches = ResolvedType::BatchedFunction;
844 template <
typename Y,
typename Xs,
typename Pinned,
typename... Inputs>
846 evaluateBatch(Y & y, Xs
const & xs, Pinned
const & p, Inputs
const &... inputs)
const
847 requires EvaluatesBatches
849 using T =
typename Xs::Scalar;
850 using States = MatrixOf<T, N, Y::ColsAtCompileTime, NMax, Y::MaxColsAtCompileTime>;
851 Eigen::Index
const count = xs.cols();
853 xs.rows() == m_rest.size() && p.rows() == m_rows.size && (p.cols() == 1 || p.cols() == count)
854 &&
"the blocks do not fit the space"
856 auto states = States{};
857 states.resize(m_size, count);
858 for (Eigen::Index j = 0; j < count; ++j)
860 auto state = states.col(j);
861 state(m_rest) = xs.col(j);
862 middleRowsOf<PinnedN>(state, m_rows.start, m_rows.size) = p.col(p.cols() == 1 ? 0 : j).template cast<T>();
864 m_resolved.evaluateStateColumns(y, states, inputs...);
873 template <
typename Blocks, std::
size_t InputCount>
875 splitJacobian(Blocks
const & blocks, std::integral_constant<std::size_t, InputCount>)
const
877 auto const & whole = jacobianBlock<0>(blocks);
878 using Whole = std::remove_cvref_t<
decltype(whole)>;
879 using Scalar =
typename Whole::Scalar;
880 constexpr int Rows = Whole::RowsAtCompileTime;
881 constexpr int MaxRows = Whole::MaxRowsAtCompileTime;
882 using RestJacobian = MatrixOf<Scalar, Rows, RestD, MaxRows, RestDMax>;
883 using GivenJacobian =
884 MatrixOf<Scalar, Rows, PinnedD, MaxRows, maxValueDimensionAtCompileTime<DifferenceSpace<PathTag<P>>>>;
885 Eigen::Index
const before = m_differenceRows.start;
886 Eigen::Index
const after = m_differenceSize - m_differenceRows.start - m_differenceRows.size;
887 RestJacobian rest(whole.rows(), before + after);
888 rest.leftCols(before) = whole.leftCols(before);
889 rest.rightCols(after) = whole.rightCols(after);
890 GivenJacobian
given = middleColsOf<PinnedD>(whole, m_differenceRows.start, m_differenceRows.size);
891 return [&]<std::size_t... K>(std::index_sequence<K...>) {
893 std::tuple<RestJacobian, GivenJacobian, std::remove_cvref_t<decltype(jacobianBlock<1 + K>(blocks))>...>;
894 return ArgumentJacobians<Tuple>{Tuple{std::move(rest), std::move(
given), jacobianBlock<1 + K>(blocks)...}};
895 }(std::make_index_sequence<InputCount>{});
898 ResolvedType m_resolved;
902 Eigen::Index m_differenceSize;
903 IndexVector<RestN, RestNMax> m_rest;
915template <
typename P,
typename Space,
typename Value>
916[[nodiscard]] GivenBlock<Space, P, Value>
919 return {space, value};
927template <
typename P,
typename Space,
typename Value>
938template <
bool Statistics, UncertainInput Prior,
typename Space,
typename P,
typename M,
typename Value>
940updateBranchesWith(Prior
const & prior, PinnedMeasurement<Space, P, M>
const & f, Value
const & value)
942 auto const & resolved = f.resolved();
943 using R = std::remove_cvref_t<
decltype(resolved)>;
946 "a Kalman update pushes the prior through the model by a method: observe(method, model, z)"
948 static_assert(!internal::isIterated<typename R::Method>,
"an update given a block does not support Iterated yet");
951 "an update given a block, as a Rao-Blackwellized filter's, does not consider blocks yet (decisions.md "
955 prior.valueDimension() == f.restSize() &&
"the prior must cover the state outside the given block"
957 auto const & method = resolved.method();
958 auto const predicted = std::apply(
959 [&](
auto const &... inputs) {
960 return internal::transformPrediction(resolved, method, f,
withCross(prior), value, inputs...);
967 auto const all = internal::consecutiveIndices<N, NMax>(0, prior.differenceDimension());
968 using Predicted = std::remove_cvref_t<
decltype(predicted)>;
969 auto const & cross = predicted.crossCovariance();
970 return internal::conditionOnPrediction<Statistics>(
975 internal::ReadLinearization{
976 typename Predicted::JacobianMatrix{predicted.jacobian()},
979 using Error = typename Predicted::OutputMatrix;
980 return Error{predicted.inputsCovariance() + predicted.unexplainedCovariance()};
989inline constexpr bool isGivenBlock =
false;
992template <
typename Space,
typename P,
typename Value>
993inline constexpr bool isGivenBlock<GivenBlock<Space, P, Value>> =
true;
999template <
typename F,
typename Value>
1000struct GivenMeasurement
1003 Value
const & value;
1009template <
typename G>
1010concept GivenMeasurementLike =
requires(G
const &
given) {
1011 given.pinned.resolved();
1018template <
bool Statistics, UncertainInput Prior, Measurement M,
typename Space,
typename P,
typename Value>
1020updateBranches(Prior
const & prior, M
const & measurement, GivenBlock<Space, P, Value>
const & pinned)
1022 auto const f = PinnedMeasurement<Space, P, M>{pinned.space, measurement};
1023 return updateBranchesWith<Statistics>(prior, f, pinned.value);
1048template <UncertainInput Prior, Measurement M,
typename Space,
typename P,
typename Value>
1052 return internal::updateBranches<false>(internal::withCovariance(prior), measurement, pinned);
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
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 iterated measurement update, all internal (decisions.md [iterated-update], [sigma-point-sets]): t...
The likelihoods that sample-based filters weight by (decisions.md [likelihood-measurements],...
The macros every header includes first.
Measurement models and their observations (decisions.md [model-policies], [sensors],...
How an update reads a measurement, all internal (decisions.md [model-policies], [measurement-space-fu...
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'...
Product: the product of independent densities, each on its own block of a space, built with on<Path>(...
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...
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition Gaussian.h:267
typename MomentsType::VectorType VectorType
a value, such as the mean
Definition Gaussian.h:265
typename MomentsType::DifferenceVectorType DifferenceVectorType
a difference, such as a residual
Definition Gaussian.h:266
internal::CrossMatrixOf< InputSpace, OutputSpace, Scalar > CrossMatrix
The cross-covariance's type, and 's: input differences by output differences.
Definition Linearization.h:258
A type usable as the space of a distribution.
Definition Space.h:186
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
GivenBlock< Space, P, Value > given(Space const &space, Value const &value)
Definition Measurement.h:917
std::expected< CategoricalUpdate< Space, Scalar >, WeightError > update(CategoricalParams< Space, Scalar > const &prior, E const &emission)
Definition Emission.h:97
constexpr Residual< Inner > residual(Inner inner={})
Definition Resampling.h:544
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
auto plus(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d)
Definition Space.h:675
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
Rows of a contiguous block of a space.
Definition TagPath.h:825
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
Where a step linearizes its input: a point, or a distribution, in place of the input's own mean and s...
Definition TransformArgs.h:156
What a model reads, as reads() declares it: the items, each a path into the state or the tag of an in...
Definition Policies.h:173