The record of a Gaussian mixture filter's forward pass that its smoother runs backward over: one GaussianMixturePredictedJoint per prediction, each with room for its smoothed mixture.
More...
|
|
| GaussianMixtureHistory ()=default |
| | An empty history that keeps every step.
|
|
| GaussianMixtureHistory (Allocator_ const &allocator) |
| | An empty history that keeps every step, with storage from allocator.
|
|
| GaussianMixtureHistory (Lag lag, Allocator_ const &allocator={}) |
| | An empty history that keeps the newest lag steps, with storage from allocator.
|
|
| GaussianMixtureHistory (GaussianMixtureHistory const &other) |
| | Copies the steps into nodes from other's allocator (see Allocation).
|
|
| GaussianMixtureHistory (GaussianMixtureHistory const &other, Allocator_ const &allocator) |
| | Copies other's steps into storage from allocator.
|
|
| GaussianMixtureHistory (GaussianMixtureHistory &&other)=default |
| | Takes other's steps.
|
|
| GaussianMixtureHistory (GaussianMixtureHistory &&other, Allocator_ const &allocator) |
| | Moves other's steps into storage from allocator, taking its storage when the allocators are equal.
|
|
GaussianMixtureHistory & | operator= (GaussianMixtureHistory const &other)=default |
| | Copies other's steps and lag.
|
|
GaussianMixtureHistory & | operator= (GaussianMixtureHistory &&other)=default |
| | Takes other's steps and lag, as std::list's move assignment does.
|
| allocator_type | get_allocator () const |
| std::optional< Index > | lag () const |
| Index | size () const |
| bool | empty () const |
| Step const & | front () const |
| Step const & | back () const |
| const_iterator | begin () const |
| const_iterator | end () const |
| void | push (JointType const &joint) |
| | Records a copy of joint as the newest step; it must come from the predictJoint() after the newest step's.
|
|
void | push (JointType &&joint) |
| | Records joint as the newest step, taking its storage unless the history is a full fixed-lag one, which copies it into its oldest step's.
|
|
template<typename LatestAllocator> |
| void | smooth (GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest) |
| | Fills every step's smoothed mixture by the backward step above, from the newest back, given latest, the filter's state after the newest step: its posterior \( p(x_N \mid z_{1:N}) \), which is its own smoothed mixture, with its lineage from the newest step.
|
|
template<ExecutionPolicy P, typename LatestAllocator> |
| void | smooth (P &&policy, GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest) |
| | smooth() under policy: each backward step's pairs and merges are a for-each over the step's components (see Execution policies), so the smoothed mixtures are Sequential's exactly.
|
|
void | clear () |
| | Drops every step, keeping the lag.
|
template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
class Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >
The record of a Gaussian mixture filter's forward pass that its smoother runs backward over: one GaussianMixturePredictedJoint per prediction, each with room for its smoothed mixture.
It is to a MixtureFilter of Gaussians what GaussianHistory is to a KalmanFilter (decisions.md [smoothing]): push() records the joint the filter's predictJoint() returns, and smooth() takes the filter's current state and fills every step's smoothed mixture, from the newest step back.
for (auto const & z : measurements)
{
history.
push(filter.predictJoint(dt));
static_cast<void>(reduce(filter.state()));
}
history.
smooth(filter.state());
for (auto const & step : history) { use(step.smoothed); }
void push(JointType const &joint)
Records a copy of joint as the newest step; it must come from the predictJoint() after the newest ste...
Definition GaussianMixtureHistory.h:512
GaussianMixtureHistory()=default
An empty history that keeps every step.
void smooth(GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest)
Fills every step's smoothed mixture by the backward step above, from the newest back,...
Definition GaussianMixtureHistory.h:533
constexpr Keep keep()
Definition Reduction.h:371
Between two predictions the filter's updates and reductions branch, reweight, merge, and drop components, and its state's lineage (see MixtureLineage) records how each component descends from those at the last prediction: each component's share from each of them. Each backward step reads it:
- every pair of a smoothed component p at k + 1 and a component n at k that it has a share from is smoothed by smoothStep(), from n's filtered Gaussian through its prediction to p's smoothed Gaussian;
- the pair's weight is p's smoothed weight times its share from n, \( w^s_{k+1,p} \, P(n \mid m) \), where m is the filtered component at k + 1 that p smooths;
- the pairs that share a parent n are merged into one Gaussian by moment matching, so the smoothed mixture at k has one component per filtered component at k, in the same order, with the summed weight.
A component at k that nothing at k + 1 descends from, such as one the filter pruned, keeps its filtered Gaussian with zero weight, so that the smoothed mixture lines up with the filtered one and with the lineage of the step before.
The forward-backward smoother on merged Gaussian mixtures of Rahmathullah, Svensson, and Svensson (2014), §IV and Algorithm 2, whose f-graph is the lineage and whose s-graph is the smoothed mixtures. Four departures. The paper writes each pair's weight as \( w^s_{k+1,p} \, w^f_{k+1,m}(r) \) in its (16), but its own (15), from which (16) follows, divides the branch weight by the merged node's, \( \Pr\{H^f_{k+1,m}\} = \sum_r w^f_{k+1,m}(r) \); without it, pairs through heavy nodes are counted twice over, so this takes (15), the share. The lineage keeps the share per parent rather than one weight per merged branch, which is the same once the branches from one parent are summed, as their pairs would be. The merge within each group is the full collapse to one Gaussian rather than the paper's threshold merging and pruning, which bounds the smoothed mixture by the filtered one and keeps them aligned. And the step is smoothStep(), in the cross-covariance form and the tangent space, so that it serves every prediction method and manifold states. With a policy that keeps one component per component and no merging, each component has one parent, and this is the Rauch-Tung-Striebel smoother per component; with Keep and no merging, on a plain vector space, each smoothed component has the weight and moments of the exact Gaussian-sum smoother's branches through it, since the RTS step is affine in the moments it smooths toward.
Successive records must be one predictJoint() apart, which the history asserts from the lineage's count: a filter state replaced by a copy has no lineage, and one predicted by predict() between records has no mark for it.
As with GaussianHistory, a Lag keeps the newest steps and recycles the oldest step's storage once full, so with one joint kept and refilled by predictJoint(dt, joint), at a steady number of components fixed-lag smoothing allocates nothing once the window is full. Each step's joint and smoothed mixture, and the backward step's scratch, come from the history's allocator.
- Template Parameters
-
| Space_ | the state space |
| Scalar_ | scalar type, double by default |
| Allocator_ | allocator for the steps, what they hold, and the scratch (see Allocation) |
- See also
- GaussianMixturePredictedJoint, MixtureFilter::predictJoint(), MixtureLineage, GaussianHistory, Smoothers