EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Emrys::MixtureParams< Component_, Allocator_ > Class Template Reference

A weighted sum of components of one type, all in one space. More...

#include <EmrysFilter/Distributions/Mixture.h>

Classes

struct  Entry
 One weighted component. More...
class  MutableEntry
 Writable access to one entry during forEach(). More...

Public Types

using ComponentType = Params<Component_>
 a component
using SpaceType = typename ComponentType::SpaceType
 the components' space
using allocator_type = Allocator_
 the allocator, re-bound per buffer
using MomentsType = typename ComponentType::MomentsType
 a mean and covariance together
using Scalar = typename ComponentType::Scalar
 the scalar type
using Index = Eigen::Index
 Eigen's index type.
using VectorType = typename MomentsType::VectorType
 a value, such as a mean
using DifferenceVectorType = typename MomentsType::DifferenceVectorType
 a difference
using MatrixType = typename MomentsType::MatrixType
 a matrix over differences
using DensityType = Mixture<Component_, Allocator_>
 the view toDensity() returns
using LineageType = MixtureLineage<Scalar, Allocator_>
 what lineage() returns
using const_iterator = typename internal::Buffer<Entry, Allocator_>::const_iterator
 iterates the entries
template<bool ReturnRemovedWeight>
using RemovalResult = std::conditional_t<ReturnRemovedWeight, std::expected<Scalar, WeightError>, void>
 Result of removeIf(): the log of the removed fraction of the total weight, or nothing when ReturnRemovedWeight is false.

Public Member Functions

 MixtureParams (Allocator_ const &allocator)
 Constructs an empty mixture that allocates through allocator.
 MixtureParams (Capacity capacity, Allocator_ const &allocator={})
 Constructs an empty mixture in a FixedSizeSpace that reserves room for capacity components.
 MixtureParams (Index valueDimension, Allocator_ const &allocator={})
 Constructs an empty mixture whose components will have valueDimension value coordinates.
 MixtureParams (SpaceType space, Allocator_ const &allocator={})
 Constructs an empty mixture in space.
 MixtureParams (SpaceType space, Capacity capacity, Allocator_ const &allocator={})
 Constructs an empty mixture in space that reserves room for capacity components.
 MixtureParams (SpaceType space, Index valueDimension, Allocator_ const &allocator={})
 Constructs an empty mixture in space whose components will have valueDimension value coordinates.
 MixtureParams (MixtureParams const &other)
 Copies the entries and their factorizations into storage from other's allocator, with its capacity (see Allocation).
 MixtureParams (MixtureParams const &other, Allocator_ const &allocator)
 Copies the entries and their factorizations into storage from allocator, with other's capacity and no lineage.
 MixtureParams (MixtureParams &&other) noexcept
 Takes other's entries and storage; a view of other may not be read afterward.
 MixtureParams (MixtureParams &&other, Allocator_ const &allocator)
 Moves other's entries into storage from allocator, taking its storage when the allocators are equal.
MixtureParams & operator= (MixtureParams const &other)
 Copies other's entries and space into this mixture's storage, which keeps its allocator and capacity.
MixtureParams & operator= (MixtureParams &&other) noexcept
 Takes other's entries, space, and lineage, and its storage when the allocators are equal or propagate; otherwise moves the entries into this mixture's storage, which keeps its capacity.
allocator_type get_allocator () const
Index size () const
bool empty () const
std::optional< Index > capacity () const
void setCapacity (Index capacity)
 Reserves room for capacity components, and the scratch for that many, and makes holding more a precondition violation.
Index valueDimension () const
Index differenceDimension () const
SpaceType const & space () const
void resizeComponents (Index n)
 Resizes every component, and a space with one resizable block, to n value coordinates.
template<typename Path, typename MeanDerived, typename CovDerived, typename CrossDerived>
requires (isGaussian<ComponentType>)
void insert (Index element, Eigen::MatrixBase< MeanDerived > const &mean, Eigen::MatrixBase< CovDerived > const &cov, Eigen::MatrixBase< CrossDerived > const &cross)
 Inserts the entries mean into the resizable block named by the tag path Path of every component, before its element element, with covariance cov and cross-covariance cross with each component's existing entries.
template<typename Path, typename MeanDerived, typename CovDerived>
requires (isGaussian<ComponentType>)
void insert (Index element, Eigen::MatrixBase< MeanDerived > const &mean, Eigen::MatrixBase< CovDerived > const &cov)
 insert() of entries independent of the existing ones.
template<typename Path>
requires (isGaussian<ComponentType>)
void erase (Index element, Index count=1)
 Removes count elements of the resizable block named by the tag path Path from every component, starting at its element element.
void reserve (Index n)
 Reserves room for n components without setting a capacity.
void clear ()
 Removes every component; the space, capacity, scratch, and lineage's mark stay.
void swap (MixtureParams &other)
 Exchanges the entries, space, and lineage with other, which must come from an equal allocator.
LineageType const & lineage () const
void startLineage ()
 Makes the current components the parents of the lineage, each its own, and counts the mark.
const_iterator begin () const
const_iterator end () const
Entry const & operator[] (Index i) const
Index add (Scalar logWeight, ComponentType component)
 Appends component, which must be in the mixture's space, with log-weight logWeight, and no parent in the lineage.
Index add (Scalar logWeight, MomentsType moments)
 Appends the Gaussian with moments.
template<MatrixExpression Mean, MatrixExpression Cov>
requires (isGaussian<ComponentType>)
Index add (Scalar logWeight, Mean &&mean, Cov &&cov)
 add() of the Gaussian with mean mean and covariance cov, moving either one passed as an rvalue of the stored type.
void remove (Index i)
 Removes entry i by moving the last entry into its place.
void setComponent (Index i, ComponentType component)
 Replaces component i with component, which must be in the mixture's space.
void setMoments (Index i, MomentsType moments)
 Sets the mean and covariance of Gaussian i to moments.
template<MatrixExpression Mean>
requires (isGaussian<ComponentType>)
void setMean (Index i, Mean &&mean)
 Sets the mean of Gaussian i; see GaussianParams::setMean().
template<MatrixExpression Cov>
requires (isGaussian<ComponentType>)
void setCovariance (Index i, Cov &&cov)
 Sets the covariance of Gaussian i; see GaussianParams::setCovariance().
void setLogWeight (Index i, Scalar logWeight)
 Sets the log-weight of entry i.
void scaleWeight (Index i, Scalar logScale)
 Multiplies the weight of entry i by \( e^{\mathrm{logScale}} \).
void scaleWeights (Scalar logScale)
 Multiplies every weight by \( e^{\mathrm{logScale}} \).
std::expected< Scalar, WeightError > logTotalWeight () const
std::expected< void, WeightError > normalize ()
 Scales the weights so they sum to one.
std::expected< Scalar, WeightError > ess () const
Index mostProbable () const
template<std::ranges::input_range R>
void assign (R &&components)
 Replaces the components with those in components, a range of (log-weight, component) pairs, or of (log-weight, moments) pairs for Gaussian components, or other structured-bindable pairs, such as uniformComponents()'s.
void append (MixtureParams const &other)
 Appends copies of other's entries, which must be in the same space, with no parent in the lineage.
template<typename F>
void forEach (F &&f)
 Calls f on each entry as a MutableEntry&, returning nothing; reweight() takes one that returns a log scale factor.
template<ExecutionPolicy P, typename F>
void forEach (P &&policy, F &&f)
 forEach() under policy, a for-each over the entries (see Execution policies).
template<typename F>
void reweight (F &&f)
 Calls f on each entry as a MutableEntry&, as forEach() does, and adds what it returns, a log scale factor in a floating-point type, to that entry's log-weight.
template<ExecutionPolicy P, typename F>
void reweight (P &&policy, F &&f)
 reweight() under policy, as forEach() under it runs.
Index merge (Index keep, Index absorb)
 Merges absorb into keep.
ComponentType merged (Index first, Index second) const
Index merge (Index keep, Index absorb, ComponentType component)
 Merges absorb into keep.
Index merge (Index keep, Index absorb, MomentsType moments)
 Merges absorb into keep.
template<std::ranges::forward_range R>
void split (Index i, R &&children)
 Replaces component i with children.
template<bool ReturnRemovedWeight = false, typename Pred>
requires (!ReturnRemovedWeight)
void removeIf (Pred pred)
 Removes every entry for which pred(Entry const &), or pred(Index, Entry const &) with the entry's position, is true.
template<bool ReturnRemovedWeight, typename Pred>
requires ReturnRemovedWeight
std::expected< Scalar, WeightError > removeIf (Pred pred)
 As above, returning the log of the removed fraction of the total weight, or the WeightError that left the mixture unchanged.
std::expected< Scalar, WeightError > pruneBelow (Scalar logThreshold)
 Removes every component whose normalized log-weight is below logThreshold, and normalizes the weights of the rest; the most probable component is always kept, the first of them if several are.
std::expected< Scalar, WeightError > pruneTail (Scalar logFraction)
 Removes the lightest components, as many as can be while their combined normalized weight stays below \( e^{\mathrm{logFraction}} \), and normalizes the weights of the rest.
std::expected< Scalar, WeightError > pruneToSize (Index maxSize)
 Removes the lightest components until at most maxSize, at least one, remain, and normalizes the weights of the rest.
template<typename Path>
auto marginal () const &
template<typename Path>
void marginal () const &&=delete
 A marginal of a temporary would outlive it.
template<typename Path>
auto marginal (Index element) const &
 marginal() of one repetition of a repeated block; see GaussianParams::marginal(element).
template<typename Path>
void marginal (Index element) const &&=delete
 A marginal of a temporary would outlive it.
template<typename GivenPath, typename Derived>
requires (isGaussian<ComponentType>)
auto conditional (Eigen::MatrixBase< Derived > const &values) const
std::expected< void, MixtureError > factorize () const
 Validates the weights and factorizes every component that has changed.
template<typename R>
std::expected< void, MixtureError > factorize (R const &repair)
 factorize(), repairing each covariance that is not positive definite by repair (see GaussianParams::factorize(R const &)): m.factorize(roots::ridge()).
std::expected< DensityType, MixtureError > toDensity () const &
 Factorizes as needed (see factorize()).
void toDensity () const &&=delete
 A density of a temporary would outlive it.
template<typename R>
std::expected< DensityType, MixtureError > toDensity (R const &repair) &
 toDensity(), repairing covariances that are not positive definite by repair (see factorize(R const &)): m.toDensity(roots::ridge()).
template<typename R>
void toDensity (R const &) &&=delete
 A density of a temporary would outlive it.

Static Public Attributes

static constexpr int ValueDimensionAtCompileTime = ComponentType::ValueDimensionAtCompileTime
 the length of a value, or Eigen::Dynamic
static constexpr int MaxValueDimensionAtCompileTime = ComponentType::MaxValueDimensionAtCompileTime
 a bound on the length of a value, or Eigen::Dynamic
static constexpr int DifferenceDimensionAtCompileTime = ComponentType::DifferenceDimensionAtCompileTime
 the length of a difference and the rows of a covariance, or Eigen::Dynamic
static constexpr int MaxDifferenceDimensionAtCompileTime = ComponentType::MaxDifferenceDimensionAtCompileTime
 a bound on the length of a difference, or Eigen::Dynamic
static constexpr bool IsParams = true
 parameters, which views check

Detailed Description

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
class Emrys::MixtureParams< Component_, Allocator_ >

A weighted sum of components of one type, all in one space.

A mixture model with unnormalized weights. Each entry has a log-weight and a component (see Component): a Gaussian, which makes the mixture a Gaussian mixture, GaussianMixtureParams; or a Hybrid, which makes it a mixture of hybrid states, the state of a mixture of interacting multiple model filters (decisions.md [component-first], [filters-and-recursions]). Weights need not be normalized; a log-weight of -inf is a zero weight. All components share the mixture's space, and so its valueDimension() and differenceDimension().

Entries are read by index, mixture[i], or in order through const iterators, and changed only through this object's methods, which take an entry's index, as a ParticleSet's do (decisions.md [mixture-entries]). Adding keeps every index and may invalidate every iterator; removal moves the last entry into the gap, so an index is held only while nothing is removed.

toDensity() validates the weights, factorizes every component that has changed, and returns a Mixture, which checks this object for changes: reading it after this object has changed in any way is a programmer error caught by EMRYS_FILTER_ASSERT (decisions.md [view-stamp]). So is changing the mixture from inside a forEach() or removeIf() callback.

What only a Gaussian has is offered for Gaussian components alone, and a mixture of other components says so at the call: the members that take or give a component's moments (add() of moments, setMoments(), setMean(), setCovariance(), merge() with moments, insert(), erase(), and resizeComponents()), the marginal() and conditional() views, and sampling. Every mixture adds and replaces whole components, collapses a pair with merge(keep, absorb), and reweights, truncates, and removes.

marginal() returns a read-only view of a subset of every component's entries, which checks only this object's size and structure: values and weights may change under it, but reading it after components are added, removed, or resized, or this object is assigned to, is a programmer error. Neither view may outlive this object, and neither may be made from a temporary.

Every component shares the mixture's space (see Spaces): component means are normalized when set, and moments() averages in the space's tangent space.

The entries, and the scratch that pruneTail() and pruneToSize() use, come from the allocator (see Allocation). A mixture given a Capacity reserves room for that many components once; holding more is a precondition violation.

Template Parameters
Component_the components' type (see Component), which sets their space, scalar, dimensions, and storage bounds
Allocator_allocator for the entries and scratch (see Allocation)
See also
class Mixture, GaussianMixtureParams, class GaussianParams, class Hybrid

Constructor & Destructor Documentation

◆ MixtureParams() [1/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Emrys::MixtureParams< Component_, Allocator_ >::MixtureParams ( Capacity capacity,
Allocator_ const & allocator = {} )
inlineexplicit

Constructs an empty mixture in a FixedSizeSpace that reserves room for capacity components.

A space that holds values is given: MixtureParams(space, capacity, allocator).

◆ MixtureParams() [2/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Emrys::MixtureParams< Component_, Allocator_ >::MixtureParams ( SpaceType space,
Index valueDimension,
Allocator_ const & allocator = {} )
inline

Constructs an empty mixture in space whose components will have valueDimension value coordinates.

A space with one resizable block is resized to valueDimension; any other must already have that many.

◆ MixtureParams() [3/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Emrys::MixtureParams< Component_, Allocator_ >::MixtureParams ( MixtureParams< Component_, Allocator_ > const & other)
inline

Copies the entries and their factorizations into storage from other's allocator, with its capacity (see Allocation).

The copy has no lineage: it is a new mixture (see MixtureLineage), which views of other do not see.

Member Function Documentation

◆ add() [1/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::add ( Scalar logWeight,
ComponentType component )
inline

Appends component, which must be in the mixture's space, with log-weight logWeight, and no parent in the lineage.

Returns
the index of its entry, size() - 1.

◆ add() [2/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::add ( Scalar logWeight,
MomentsType moments )
inline

Appends the Gaussian with moments.

Returns
the index of its entry.

◆ assign()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<std::ranges::input_range R>
void Emrys::MixtureParams< Component_, Allocator_ >::assign ( R && components)
inline

Replaces the components with those in components, a range of (log-weight, component) pairs, or of (log-weight, moments) pairs for Gaussian components, or other structured-bindable pairs, such as uniformComponents()'s.

The components have no parent in the lineage, and the space and capacity stay, so a mixture made with a capacity is filled without allocating.

◆ begin()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
const_iterator Emrys::MixtureParams< Component_, Allocator_ >::begin ( ) const
inlinenodiscard
Returns
an iterator to the first entry

◆ capacity()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::optional< Index > Emrys::MixtureParams< Component_, Allocator_ >::capacity ( ) const
inlinenodiscard
Returns
the most components the mixture holds, if it has a capacity

◆ conditional()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename GivenPath, typename Derived>
requires (isGaussian<ComponentType>)
auto Emrys::MixtureParams< Component_, Allocator_ >::conditional ( Eigen::MatrixBase< Derived > const & values) const
inlinenodiscard
Returns
a copy of the distribution of the other coordinates given that the subspace named by the path GivenPath equals values, in the space of the remaining blocks (see GaussianParams::conditional()).

Each component is conditioned as in GaussianParams::conditionalWithEvidence(), and its log-weight gains the log-likelihood of values under that component's marginal. The weights are not normalized, so the result's total weight is this mixture's total weight times the marginal density of values.

Returns
the conditional mixture, or GaussianError::NotPositiveDefinite if any component's covariance of the given block is not positive definite, since that component's weight would need the density of a block known exactly (decisions.md [innovation-cholesky])

◆ differenceDimension()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::differenceDimension ( ) const
inlinenodiscard
Returns
the number of rows and columns of every component's covariance (see Spaces)

◆ empty()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
bool Emrys::MixtureParams< Component_, Allocator_ >::empty ( ) const
inlinenodiscard
Returns
whether there are no components

◆ end()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
const_iterator Emrys::MixtureParams< Component_, Allocator_ >::end ( ) const
inlinenodiscard
Returns
an iterator past the last entry

◆ erase()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename Path>
requires (isGaussian<ComponentType>)
void Emrys::MixtureParams< Component_, Allocator_ >::erase ( Index element,
Index count = 1 )
inline

Removes count elements of the resizable block named by the tag path Path from every component, starting at its element element.

See GaussianParams::erase().

◆ ess()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< Scalar, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::ess ( ) const
inlinenodiscard
Returns
the effective sample size \( 1 / \sum_i \hat w_i^2 \) of the normalized weights, between 1 and size(), or the WeightError of logTotalWeight(). It reads only the weights, which logTotalWeight() checks, so it needs no toDensity(); the moments and the collapse read the components, which only the factorization checks, so they are the density's.

◆ factorize() [1/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< void, MixtureError > Emrys::MixtureParams< Component_, Allocator_ >::factorize ( ) const
inlinenodiscard

Validates the weights and factorizes every component that has changed.

It is const because it writes only caches: the components' factorizations and the total weight that views read. So it, and toDensity(), are not safe on one object from two threads at once until a factorization has succeeded and the weights are unchanged since; after that they only read. Threads should share the GaussianMixture that toDensity() returns instead (see Distributions).

Returns
nothing on success; a WeightError if the mixture is empty or its weights cannot be normalized; or a ComponentError naming the first component that failed to factorize.
See also
toDensity()

◆ factorize() [2/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename R>
std::expected< void, MixtureError > Emrys::MixtureParams< Component_, Allocator_ >::factorize ( R const & repair)
inlinenodiscard

factorize(), repairing each covariance that is not positive definite by repair (see GaussianParams::factorize(R const &)): m.factorize(roots::ridge()).

Every repair is tried before any is kept, so a component that can't be repaired leaves the mixture as it was.

Returns
nothing on success; a WeightError if the mixture is empty or its weights cannot be normalized; or a ComponentError naming the first component whose covariance could not be repaired.
See also
Repair

◆ forEach() [1/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename F>
void Emrys::MixtureParams< Component_, Allocator_ >::forEach ( F && f)
inline

Calls f on each entry as a MutableEntry&, returning nothing; reweight() takes one that returns a log scale factor.

f may modify the entry it is given but not the mixture, which is a programmer error caught when f returns. Views of the mixture may not be read afterward.

◆ forEach() [2/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<ExecutionPolicy P, typename F>
void Emrys::MixtureParams< Component_, Allocator_ >::forEach ( P && policy,
F && f )
inline

forEach() under policy, a for-each over the entries (see Execution policies).

Under a parallel policy f runs for several entries at once, so it must read and write nothing but the entry it is given and what no other call writes.

◆ get_allocator()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
allocator_type Emrys::MixtureParams< Component_, Allocator_ >::get_allocator ( ) const
inlinenodiscard
Returns
the allocator the entries come from

◆ insert()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename Path, typename MeanDerived, typename CovDerived, typename CrossDerived>
requires (isGaussian<ComponentType>)
void Emrys::MixtureParams< Component_, Allocator_ >::insert ( Index element,
Eigen::MatrixBase< MeanDerived > const & mean,
Eigen::MatrixBase< CovDerived > const & cov,
Eigen::MatrixBase< CrossDerived > const & cross )
inline

Inserts the entries mean into the resizable block named by the tag path Path of every component, before its element element, with covariance cov and cross-covariance cross with each component's existing entries.

See GaussianParams::insert().

◆ lineage()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
LineageType const & Emrys::MixtureParams< Component_, Allocator_ >::lineage ( ) const
inlinenodiscard
Returns
how each component descends from those the mixture had at its last startLineage(), with no rows before the first (see MixtureLineage)

◆ logTotalWeight()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< Scalar, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::logTotalWeight ( ) const
inlinenodiscard
Returns
the log of the sum of the weights, or a WeightError if the mixture is empty, the weights sum to zero, or a log-weight is NaN or +inf.

◆ marginal()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename Path>
auto Emrys::MixtureParams< Component_, Allocator_ >::marginal ( ) const &
inlinenodiscard
Returns
a read-only view of the subspace named by the tag path Path (see idx()), whose space is that subspace with its parameters: a range over the components that gives each one's log-weight and marginal in turn, copying nothing (decisions.md [element-marginals]). It checks this object's shape.
See also
class MixtureMarginal

◆ merge() [1/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::merge ( Index keep,
Index absorb )
inline

Merges absorb into keep.

keep's component becomes the collapse of both, weighted by their weights (see ComponentTraits), and its weight the sum of both weights; absorb is then removed, by moving the last entry into its place.

Returns
the index of the merged entry: keep, or absorb when keep was the last

◆ merge() [2/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::merge ( Index keep,
Index absorb,
ComponentType component )
inline

Merges absorb into keep.

keep's component becomes component and its weight becomes the sum of both weights; absorb is then removed, as by merge(keep, absorb).

Returns
the index of the merged entry

◆ merge() [3/3]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::merge ( Index keep,
Index absorb,
MomentsType moments )
inline

Merges absorb into keep.

keep's moments become moments and its weight becomes the sum of both weights; absorb is then removed, as by merge(keep, absorb). moments may refer to either component.

Returns
the index of the merged entry

◆ merged()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
ComponentType Emrys::MixtureParams< Component_, Allocator_ >::merged ( Index first,
Index second ) const
inlinenodiscard
Returns
the component merge() makes of first and second, without changing the mixture: the collapse of both, weighted by their weights (see ComponentTraits).

The merge's weight is the sum of both weights. What a merge costs is the caller's to measure, from the two components and this one: for Gaussians, the weighted divergences \( w_i \, \mathrm{KL}(g_i \parallel g_{ij}) + w_j \, \mathrm{KL}(g_j \parallel g_{ij}) \) from kullbackLeibler() are the cost of Runnalls (2007).

◆ mostProbable()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::mostProbable ( ) const
inlinenodiscard
Returns
the index of the most probable component, the one with the largest weight; ties go to the lowest. It is the estimate a display shows of a multimodal mixture, where the moments can sit between the modes. A programmer error if the mixture is empty; a NaN weight has no place in the order, so with one the index is unspecified, and logTotalWeight() reports it.

◆ normalize()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< void, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::normalize ( )
inlinenodiscard

Scales the weights so they sum to one.

On failure the weights are unchanged.

See also
logTotalWeight()

◆ operator=() [1/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
MixtureParams & Emrys::MixtureParams< Component_, Allocator_ >::operator= ( MixtureParams< Component_, Allocator_ > && other)
inlinenoexcept

Takes other's entries, space, and lineage, and its storage when the allocators are equal or propagate; otherwise moves the entries into this mixture's storage, which keeps its capacity.

An allocator that propagates and differs brings other's scratch with it. A view of either object may not be read afterward.

◆ operator=() [2/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
MixtureParams & Emrys::MixtureParams< Component_, Allocator_ >::operator= ( MixtureParams< Component_, Allocator_ > const & other)
inline

Copies other's entries and space into this mixture's storage, which keeps its allocator and capacity.

An entry that already holds a component is assigned to, so the components' own storage is reused. The lineage is cleared, as a copy has none.

◆ operator[]()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Entry const & Emrys::MixtureParams< Component_, Allocator_ >::operator[] ( Index i) const
inlinenodiscard
Returns
entry i, which must be less than size(). The members that change an entry take its index too, as a particle set's do: an index is what a filter, the lineage, and an update keep, and it stays valid when the mixture grows, where an iterator need not.

◆ pruneBelow()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< Scalar, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::pruneBelow ( Scalar logThreshold)
inlinenodiscard

Removes every component whose normalized log-weight is below logThreshold, and normalizes the weights of the rest; the most probable component is always kept, the first of them if several are.

The threshold is absolute: a caller who wants it relative to something, such as the most probable component, makes it so. The components keep their order, and the lineage follows them. It reads only the weights, so it works whatever the component, and upkeep::pruneBelow() calls it.

Returns
the log of the removed fraction of the total weight, -inf if nothing was removed, or, with nothing changed, the WeightError of logTotalWeight()
See also
pruneTail(), pruneToSize()

◆ pruneTail()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< Scalar, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::pruneTail ( Scalar logFraction)
inlinenodiscard

Removes the lightest components, as many as can be while their combined normalized weight stays below \( e^{\mathrm{logFraction}} \), and normalizes the weights of the rest.

The fraction is below one, so a component is always kept. Of components equally heavy, those later in order go first. upkeep::pruneTail() calls it.

Returns
the log of the removed fraction of the total weight, -inf if nothing was removed, or, with nothing changed, the WeightError of logTotalWeight()
See also
pruneBelow(), pruneToSize()

◆ pruneToSize()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< Scalar, WeightError > Emrys::MixtureParams< Component_, Allocator_ >::pruneToSize ( Index maxSize)
inlinenodiscard

Removes the lightest components until at most maxSize, at least one, remain, and normalizes the weights of the rest.

Of components equally heavy, those later in order go first. upkeep::pruneToSize() calls it.

Returns
the log of the removed fraction of the total weight, -inf if nothing was removed, or, with nothing changed, the WeightError of logTotalWeight()
See also
pruneBelow(), pruneTail()

◆ removeIf()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<bool ReturnRemovedWeight = false, typename Pred>
requires (!ReturnRemovedWeight)
void Emrys::MixtureParams< Component_, Allocator_ >::removeIf ( Pred pred)
inline

Removes every entry for which pred(Entry const &), or pred(Index, Entry const &) with the entry's position, is true.

Template Parameters
ReturnRemovedWeightif true, returns the log of the removed fraction of the total weight. This requires normalizing the weights; if that fails, nothing is removed and the WeightError is returned.

◆ resizeComponents()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
void Emrys::MixtureParams< Component_, Allocator_ >::resizeComponents ( Index n)
inline

Resizes every component, and a space with one resizable block, to n value coordinates.

Component contents are unspecified afterward. To grow or shrink a resizable block element by element, use insert() and erase(), as a space with several resizable blocks must.

◆ setCapacity()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
void Emrys::MixtureParams< Component_, Allocator_ >::setCapacity ( Index capacity)
inline

Reserves room for capacity components, and the scratch for that many, and makes holding more a precondition violation.

It must be at least size().

◆ size()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::size ( ) const
inlinenodiscard
Returns
the number of components

◆ space()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
SpaceType const & Emrys::MixtureParams< Component_, Allocator_ >::space ( ) const
inlinenodiscard
Returns
the space every component is in, with its sizes

◆ split()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<std::ranges::forward_range R>
void Emrys::MixtureParams< Component_, Allocator_ >::split ( Index i,
R && children )
inline

Replaces component i with children.

children is a non-empty range of (log relative weight, component) pairs, or of (log relative weight, moments) pairs for Gaussian components. The parent's weight is divided among the children in proportion to their relative weights. The first child takes the parent's position; the rest are appended. Each child takes the parent's lineage. children must not refer to this mixture's components.

◆ startLineage()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
void Emrys::MixtureParams< Component_, Allocator_ >::startLineage ( )
inline

Makes the current components the parents of the lineage, each its own, and counts the mark.

A filter's predictJoint() calls it, so that the lineage of its state at the next record says how each component descends from those it recorded. With a capacity, room for a row per component is reserved, so that keeping the lineage allocates nothing afterward.

◆ swap()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
void Emrys::MixtureParams< Component_, Allocator_ >::swap ( MixtureParams< Component_, Allocator_ > & other)
inline

Exchanges the entries, space, and lineage with other, which must come from an equal allocator.

Each mixture keeps its capacity and scratch, so a filter can build a posterior in a second mixture and swap it in without allocating.

◆ toDensity() [1/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
std::expected< DensityType, MixtureError > Emrys::MixtureParams< Component_, Allocator_ >::toDensity ( ) const &
inlinenodiscard

Factorizes as needed (see factorize()).

Returns
a Mixture that checks this object, or the MixtureError from factorize().

◆ toDensity() [2/2]

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
template<typename R>
std::expected< DensityType, MixtureError > Emrys::MixtureParams< Component_, Allocator_ >::toDensity ( R const & repair) &
inlinenodiscard

toDensity(), repairing covariances that are not positive definite by repair (see factorize(R const &)): m.toDensity(roots::ridge()).

Returns
a Mixture that checks this object, or the MixtureError from factorize(R const &)

◆ valueDimension()

template<internal::ComponentOrInfoForm Component_, typename Allocator_ = DefaultAllocator>
Index Emrys::MixtureParams< Component_, Allocator_ >::valueDimension ( ) const
inlinenodiscard
Returns
the number of coordinates of every component's mean (see Spaces)

The documentation for this class was generated from the following file: