EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Distributions

The third layer (decisions.md [layered-headers]): the distributions, each stored as parameters and evaluated through a density, and what is computed from them. More...

Topics

 Divergences
 How far apart two distributions are.
 Upkeep
 Upkeep keeps a filter's representation in bounds without meaning to change the distribution much: resampling particles whose weights have degenerated, roughening them after, pruning the improbable particles, components, or cells, or repairing a covariance that rounding has left not positive definite.

Namespaces

namespace  Emrys::roots
 The axes and repairs, each made by its factory (decisions.md [policy-factories]), and the roots taken by them: cholesky(), pivoted(), principal(), symmetric(), along(), ridge(), squareRoot(), and squareRootWithReport().

Concepts

concept  Emrys::Component
 The distribution that a container of several holds one of per element (decisions.md [component-first], [params-and-density]): a Mixture's component, a Hybrid's conditional given a mode.
concept  Emrys::GaussianForm
 A Gaussian in any of its four forms (decisions.md [gaussian-forms]): GaussianParams, SqrtGaussianParams, InfoGaussianParams, or SqrtInfoGaussianParams, or a GaussianMarginal, the covariance form's marginal, so that a marginal of any form's density is a GaussianForm [form-densities].
concept  Emrys::HasLogDensity
 A density: a type that evaluates its log-density at a value in its space, such as a Gaussian, a KernelDensity, or a Uniform.
concept  Emrys::ProductFactor
 What a Product takes as a factor: a density (HasLogDensity), or parameters that toDensity() checks, such as a GaussianParams, which the product holds and checks itself.
concept  Emrys::Axes
 Axes: a way of taking a root \( S \) of a covariance \( P \), \( S S^T = P \), whose columns carry a sigma-point rule's unit points into the input (decisions.md [sigma-point-axes]).
concept  Emrys::Repair
 A repair: what turns a covariance whose root failed into one to retry (decisions.md [sigma-point-axes]).

Classes

class  Emrys::CategoricalParams< Space_, Scalar_ >
 The parameters of a probability distribution over a discrete space: one weight per value. More...
class  Emrys::Categorical< Space_, Scalar_ >
 The probabilities of a CategoricalParams whose weights define a distribution: a read-only view. More...
class  Emrys::MarkovChain< Space_, Scalar_ >
 A Markov chain on a discrete space: the probability of moving from each value to each value in one step. More...
struct  Emrys::ComponentTraits< C >
 What a container does with a component beyond the component's own members (decisions.md [component-first]): logDensity(component, x), the log-density read from the component's factorization without a check of its own, for a container's density view that already holds one [execution-policies]; collapse(count, componentAt, logWeightAt), the collapse of several components into one by moment matching; moments(component), its mean and covariance, read without a check, for a container's density view that has checked it, as a hybrid's needs no member for them; and MarginalType, the view of a subset of one component's coordinates that a marginal of the container gives per component [element-marginals]. More...
struct  Emrys::SharedCovariance
 One covariance for every point. More...
struct  Emrys::PerPointCovariance
 A covariance per point. More...
class  Emrys::ContinuousTimeMarkovChain< Space_, Scalar_ >
 A continuous-time Markov chain on a discrete space: the rate of moving from each value to each other value. More...
struct  Emrys::FitOptions< Scalar >
 Options for fitMixture(). More...
struct  Emrys::MixtureFit< Space, Scalar, Allocator >
 Result of fitMixture(), in Space, with the source's allocator. More...
class  Emrys::Gamma< Space_, Scalar_ >
 Independent Gamma distributions on the coordinates, for positive quantities such as ranges, speeds, and rates. More...
struct  Emrys::GaussianConditional< Space_, Scalar_ >
 The result of GaussianParams::conditionalWithEvidence(): the conditional distribution and the log-evidence of the given values. More...
class  Emrys::GaussianParams< Space_, Scalar_ >
 A Gaussian distribution: a mean and covariance in a space. More...
class  Emrys::Gaussian< Space_, Scalar_ >
 The density of a Gaussian whose covariance has been factorized: a read-only view. More...
class  Emrys::GaussianMarginal< Source, Selection, SubSpace >
 Read-only view of a subset of the entries of a GaussianParams or Gaussian. More...
class  Emrys::FormGaussian< Params_ >
 The density of a Gaussian in a square-root or information form: a read-only view. More...
struct  Emrys::GridAxis< Block, I >
 The axis of a regular grid of points (see regularGrid()) along coordinate I of the block Block: a run-time number of cells. More...
struct  Emrys::GridCells< Path >
 The cells of a regular grid over the block named by the path Path: the DiscreteProduct of its GridAxis axes, the last varying fastest, under a tag of its own. More...
struct  Emrys::PointCells< Path >
 The cells of a grid of given points (see pointGrid()) for the block named by the path Path: one value per point, under a tag of its own. More...
class  Emrys::PointGrid< Space_, Path_, Cells_, CellCovariance_, Scalar_, Allocator_ >
 Fixed points for the block named by the path Path_ of a state in Space_, one per value of the discrete space Cells_, such as the cells of a grid of positions. More...
class  Emrys::GridGaussianParams< Grid_, Covariance_, Component_ >
 The parameters of a Rao-Blackwellized point-mass filter's state: the cells of a grid still alive, their probabilities, and for each a Gaussian, or a hybrid of Gaussians, over the rest of the state. More...
class  Emrys::GridGaussian< Grid_, Covariance_, Component_ >
 The density of a Rao-Blackwellized point-mass filter's state, a checked view of its GridGaussianParams (decisions.md [params-and-density], [view-stamp]): \( p(x) = \sum_c P(c) \, \delta(x_p - p_c) \, \mathcal{N}(x_r; \mu_c, \Sigma_c) \) over the live cells, or the hybrid of Gaussians in each cell. More...
class  Emrys::HybridParams< Component_, ModeSpace_, Allocator_ >
 The parameters of a hybrid state: a discrete mode, and a component conditioned on each mode. More...
class  Emrys::Hybrid< Component_, ModeSpace_, Allocator_ >
 The density of a hybrid state, a checked view of its HybridParams (decisions.md [params-and-density], [view-stamp]): \( p(x, m) = P(m) \, p_m(x) \), with \( P(m) = w_m / \sum_n w_n \). More...
class  Emrys::InfoGaussianParams< Space_, Scalar_ >
 A Gaussian kept as its precision and information vector, about a reference value. More...
class  Emrys::KernelDensity< Space_, Scalar_, Allocator_ >
 Gaussian kernel density estimate over a ParticleSet. More...
struct  Emrys::ComponentError
 A mixture component that could not be factorized. More...
class  Emrys::MixtureLineage< Scalar_, Allocator_ >
 How each component of a Mixture descends from the components it had at its last startLineage(): each component's share from each of those parents. More...
class  Emrys::MixtureParams< Component_, Allocator_ >
 A weighted sum of components of one type, all in one space. More...
class  Emrys::Mixture< Component_, Allocator_ >
 The density of a Mixture whose components have been factorized: a read-only view. More...
class  Emrys::MixtureMarginal< Source, Selection, SubSpace >
 Read-only view of a subset of the coordinates of every component of a mixture or a hybrid, which iterates the components and gives each one's marginal in turn (decisions.md [element-marginals]). More...
class  Emrys::Moments< Space_, Scalar_ >
 First and second moments (mean and covariance) of a distribution. More...
struct  Emrys::ParamsOf< D >
 The parameters of the density D, as its member ParamsType: the type it borrows from, or what a marginal's copy() returns. More...
struct  Emrys::DensityOf< P >
 The density of the parameters P, as its member DensityType: what its toDensity() returns. More...
class  Emrys::ParticleGaussianParams< Space_, Path_, Covariance_, Scalar_, Allocator_, Component_ >
 The parameters of a Rao-Blackwellized particle filter's state: weighted particles for one block of the state, each carrying a Gaussian, or a hybrid of Gaussians, over the rest. More...
class  Emrys::ParticleGaussian< Space_, Path_, Covariance_, Scalar_, Allocator_, Component_ >
 The density of a Rao-Blackwellized particle filter's state, a checked view of its ParticleGaussianParams (decisions.md [params-and-density], [view-stamp]): \( p(x) = \sum_i w_i \, \delta(x_p - p_i) \, \mathcal{N}(x_r; \mu_i, \Sigma_i) \), or with a hybrid per particle, a mixture over its modes in place of each Gaussian. More...
class  Emrys::ParticleSet< Space_, Scalar_, Allocator_ >
 A set of weighted samples: the empirical distribution. More...
class  Emrys::ParticleSetMarginal< Source, Selection, SubSpace >
 Read-only view of a subset of the state entries of a ParticleSet. More...
class  Emrys::EachRepetition< F, BlockSpace >
 One factor on every repetition of a repeated block: the product of independent copies of a density, one per repetition, as a density over the whole block (decisions.md [product-factors]). More...
class  Emrys::Factors< Placed >
 The factors of a product, each placed by tag path with on() or onEach(), in no space yet: a Product once placed in one (decisions.md [product-factors]). More...
class  Emrys::Product< Space_, Scalar_, Factors_ >
 The product of independent densities, each on its own coordinates of a space. More...
struct  Emrys::roots::NoReport
 The report of axes or a repair with nothing to say, as Cholesky's: it either took the root or failed. More...
struct  Emrys::roots::ClampReport
 The report of Pivoted, Principal, and Symmetric: how many pivots or eigenvalues were below zero and taken as zero, which only rounding should give a covariance. More...
struct  Emrys::roots::RidgeReport< Scalar >
 The report of a Ridge: the ridge \( \delta \) it added to the diagonal. More...
struct  Emrys::roots::Cholesky
 Cholesky axes: the lower Cholesky factor \( L \), \( L L^T = P \), by Eigen's LLT, which fails on a covariance that is not positive definite. More...
struct  Emrys::roots::Pivoted
 Pivoted axes: \( \Pi^T L D^{1/2} \) from Eigen's pivoted LDL decomposition \( P = \Pi^T L D L^T \Pi \), with a negative pivot, which rounding can give a singular matrix, taken as zero. More...
struct  Emrys::roots::Principal
 Principal axes: \( U \Lambda^{1/2} \), the eigenvectors of \( P = U \Lambda U^T \) scaled by the roots of their eigenvalues, largest first, with a negative eigenvalue taken as zero, so that it never fails. More...
struct  Emrys::roots::Symmetric
 Symmetric axes: the principal square root \( P^{1/2} = U \Lambda^{1/2} U^T \), the one symmetric positive semidefinite root, with a negative eigenvalue taken as zero, so that it never fails. More...
struct  Emrys::roots::Along< Vector >
 Axes along a direction: a root whose first column is parallel to \( d \), so that a sigma-point rule puts its first pair of points on the line through the mean along \( d \), as a split or a probe of the nonlinearity along \( d \) needs (decisions.md [splitting-hooks]). More...
struct  Emrys::roots::Ridge< Relative, Absolute >
 The ridge repair: the Gershgorin ridge of decisions.md [covariance-repair], added to the diagonal of a covariance whose root failed so that the root can be retried. More...
struct  Emrys::roots::WithFallbacks< Head, Fallbacks >
 Axes that can fail, followed by their fallbacks, tried in order (decisions.md [sigma-point-axes]): a repair, which retries Head on the covariance it repairs, or other axes, which take the root themselves. More...
struct  Emrys::roots::RootWithReport< Matrix, Report >
 A root and the report of the axes that took it, from squareRootWithReport(). More...
struct  Emrys::roots::RootFailure< Report >
 Why squareRootWithReport() failed, and what each entry tried did. More...
struct  Emrys::SamplesWithLogDensity< Space, Scalar >
 Samples in Space together with the log of the density they were drawn from, evaluated at each. More...
struct  Emrys::SampleWithLogDensity< Space, Scalar >
 One sample in Space, in a vector sized by the space, together with the log of the density it was drawn from, evaluated at it: what drawSampleWithLogDensity() returns, so that a bounded space allocates nothing [allocation]. More...
class  Emrys::SqrtGaussianParams< Space_, Scalar_ >
 A Gaussian kept as a mean and a lower-triangular root of its covariance. More...
class  Emrys::SqrtInfoGaussianParams< Space_, Scalar_ >
 A Gaussian kept as an upper-triangular root of its precision and a whitened offset, about a reference value. More...
class  Emrys::StudentT< Space_, Scalar_ >
 The multivariate Student-t distribution: a Gaussian with heavier tails. More...
class  Emrys::Uniform< Space_, Scalar_ >
 The uniform distribution over a box in a space. More...
class  Emrys::UniformGrid< Space_, Scalar_ >
 The equal-weight components of a grid over some coordinates of a space, made one at a time when read: what uniformComponents() returns. More...

Typedefs

using Emrys::GaussianError = NumericError
 Reasons a Gaussian, in any of its forms (decisions.md [gaussian-forms]), can fail to give a density, a mean, or one of its matrices, and a root of a covariance can fail to be taken: NotPositiveDefinite, Singular, or NonFinite of NumericError.
template<Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::HybridGaussian = Hybrid<Gaussian<Space_, Scalar_>, ModeSpace_, Allocator_>
 The Hybrid of Gaussians in covariance form, the spelling for the common case (decisions.md [component-first]): \( p(x, m) = P(m) \, \mathcal{N}(x; \mu_m, \Sigma_m) \), the density of an ImmFilter's state, and the name a mixture of hybrids takes as its component.
template<Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::HybridGaussianParams = HybridParams<Gaussian<Space_, Scalar_>, ModeSpace_, Allocator_>
 The HybridParams of Gaussians in covariance form: the parameters of a HybridGaussian, an ImmFilter's state.
template<Space Space_, RealScalar Scalar_ = double>
using Emrys::InfoGaussian = FormGaussian<InfoGaussianParams<Space_, Scalar_>>
 The Gaussian in information form, which evaluates its density: what InfoGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).
using Emrys::MixtureError = std::variant<WeightError, ComponentError>
 Reasons MixtureParams::toDensity() can fail.
using Emrys::GaussianMixtureError = MixtureError
 MixtureError by the name it had when every mixture was a GaussianMixtureParams.
template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::GaussianMixtureParams = MixtureParams<Gaussian<Space_, Scalar_>, Allocator_>
 A Mixture of Gaussians in covariance form, the spelling for the common case (decisions.md [component-first]): \( \sum_i w_i \, \mathcal{N}(x; \mu_i, \Sigma_i) \).
template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::GaussianMixture = Mixture<Gaussian<Space_, Scalar_>, Allocator_>
 The Mixture of a GaussianMixtureParams, the spelling for the common case (decisions.md [component-first]).
template<typename X>
using Emrys::ScalarOf = typename std::remove_cvref_t<X>::Scalar
 The scalar type of the Eigen object or distribution X, for writing functions generic in it.
template<typename D>
using Emrys::Params = typename ParamsOf<D>::type
 The parameters of the density D: GaussianParams for a Gaussian, and D itself for a distribution whose values are always valid (decisions.md [params-and-density]).
template<typename P>
using Emrys::Density = typename DensityOf<P>::type
 The density of the parameters P: Gaussian for GaussianParams, and P itself for a type that is its own parameters (decisions.md [params-and-density]).
template<typename Derived>
using Emrys::roots::RootMatrix = internal::SquareMatrixOf<Derived>
 The type of a root of the covariance or factor Derived: square, with a row and a column per row of it and its bounds, so that a bounded matrix allocates nothing [allocation].
using Emrys::roots::DefaultAxes = WithFallbacks<Cholesky, Pivoted>
 The axes every root the library takes uses unless told otherwise, cholesky(pivoted()): the Cholesky factor of a positive definite covariance, and the pivoted root of any other, so it never fails and never repairs (decisions.md [sigma-point-axes]).
template<typename Space, typename Scalar = double>
using Emrys::SampleSet
 A matrix whose columns are samples in Space (see Spaces), with the space's size and storage bound.
template<typename Space, typename Scalar = double>
using Emrys::SampleSetMap = Eigen::Map<SampleSet<Space, Scalar>>
 A writable view of samples in Space, one per column, over memory it does not own, laid out as a SampleSet is: what to wrap a buffer from an allocator in, so that nothing is taken from the heap.
template<typename Space, typename Scalar = double>
using Emrys::ConstSampleSetMap = Eigen::Map<SampleSet<Space, Scalar> const>
 A read-only view of samples in Space, one per column, over memory it does not own, laid out as a SampleSet is: what the containers return for their states, means, and centers.
template<Space Space_, RealScalar Scalar_ = double>
using Emrys::SqrtGaussian = FormGaussian<SqrtGaussianParams<Space_, Scalar_>>
 The Gaussian in square-root form, which evaluates its density: what SqrtGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).
template<Space Space_, RealScalar Scalar_ = double>
using Emrys::SqrtInfoGaussian = FormGaussian<SqrtInfoGaussianParams<Space_, Scalar_>>
 The Gaussian in square-root information form, which evaluates its density: what SqrtInfoGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).

Enumerations

enum class  Emrys::ChainError { ChainError::Reducible }
 Reasons a Markov chain has no single stationary distribution. More...
enum class  Emrys::FitError { FitError::Degenerate , FitError::InvalidWeights }
 Reasons fitMixture() can fail. More...
enum class  Emrys::GammaError { GammaError::NotPositive , GammaError::NonFinite }
 Reasons a shape and scale fail to define a Gamma. More...
enum class  Emrys::MomentsError { MomentsError::Infinite }
 Reasons a distribution's moments() can fail. More...
enum class  Emrys::StudentTError { StudentTError::NotPositiveDefinite , StudentTError::NonFiniteScale , StudentTError::NotPositiveDegreesOfFreedom , StudentTError::NonFiniteDegreesOfFreedom }
 Reasons a location, scale matrix, and degrees of freedom fail to define a StudentT. More...
enum class  Emrys::UniformError { UniformError::Empty , UniformError::NonFinite , UniformError::WiderThanPeriod }
 Reasons bounds fail to define a Uniform. More...

Functions

template<typename Scalar, typename Space>
CategoricalParams< Space, Scalar > Emrys::predict (CategoricalParams< Space, Scalar > const &prior, MarkovChain< Space, Scalar > const &chain)
template<typename Scalar, typename Space>
std::expected< CategoricalParams< Space, Scalar >, ChainError > Emrys::stationary (MarkovChain< Space, Scalar > const &chain)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
std::vector< Eigen::Index > Emrys::drawSamples (Categorical< Space, Scalar > const &distribution, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Eigen::Index Emrys::drawSample (Categorical< Space, Scalar > const &distribution, G &rng)
template<typename Scalar, typename Space>
CategoricalParams< Space, Scalar > Emrys::predict (CategoricalParams< Space, Scalar > const &prior, ContinuousTimeMarkovChain< Space, Scalar > const &chain, TimeStep< Scalar > auto const &dt)
template<typename Scalar, typename Space>
std::expected< CategoricalParams< Space, Scalar >, ChainError > Emrys::stationary (ContinuousTimeMarkovChain< Space, Scalar > const &chain)
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (ParticleSet< Space, Scalar, Allocator > const &particles, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (GaussianMixture< Space, Scalar, Allocator > const &mixture, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
template<typename Scalar, typename Space, typename Allocator, typename SeedAllocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (ParticleSet< Space, Scalar, Allocator > const &particles, GaussianMixture< Space, Scalar, SeedAllocator > const &seedsFrom, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (P &&policy, ParticleSet< Space, Scalar, Allocator > const &particles, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
 fitMixture() of particles under policy: each E-step is a for-each over the particles, and each M-step's moments are reductions over them, which match Sequential's to rounding (see Execution policies).
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (P &&policy, GaussianMixture< Space, Scalar, Allocator > const &mixture, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
 fitMixture() of mixture under policy, a for-each and reductions over its components as fitMixture(P &&, ParticleSet const &, Eigen::Index, G &, FitOptions const &) runs over particles.
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, typename SeedAllocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture (P &&policy, ParticleSet< Space, Scalar, Allocator > const &particles, GaussianMixture< Space, Scalar, SeedAllocator > const &seedsFrom, Eigen::Index k, G &rng, FitOptions< Scalar > const &options={})
 fitMixture() of particles seeded from seedsFrom, under policy, as fitMixture(P &&, ParticleSet const &, Eigen::Index, G &, FitOptions const &) runs.
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples (Gamma< Space, Scalar > const &gamma, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (Gamma< Space, Scalar > const &gamma, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (Gamma< Space, Scalar > const &gamma, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (Gamma< Space, Scalar > const &gamma, G &rng)
template<GaussianForm G>
std::expected< GaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toGaussian (G const &form)
template<typename Params_, std::uniform_random_bit_generator G>
SampleSet< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSamples (FormGaussian< Params_ > const &gaussian, Eigen::Index n, G &rng)
template<typename Params_, std::uniform_random_bit_generator G>
Moments< typenameParams_::SpaceType, typenameParams_::Scalar >::VectorType Emrys::drawSample (FormGaussian< Params_ > const &gaussian, G &rng)
template<typename Params_, std::uniform_random_bit_generator G>
SamplesWithLogDensity< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSamplesWithLogDensity (FormGaussian< Params_ > const &gaussian, Eigen::Index n, G &rng)
template<typename Params_, std::uniform_random_bit_generator G>
SampleWithLogDensity< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSampleWithLogDensity (FormGaussian< Params_ > const &gaussian, G &rng)
template<typename P, Space S, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid (S space, Eigen::MatrixBase< Derived > const &centers, std::optional< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType > cellCovariance={}, Allocator const &allocator={})
template<typename P, Space S, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid (S space, Eigen::MatrixBase< Derived > const &centers, std::span< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType const > cellCovariances, Allocator const &allocator={})
template<FixedSizeSpace S, typename P, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid (Eigen::MatrixBase< Derived > const &centers, std::optional< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType > cellCovariance={}, Allocator const &allocator={})
 pointGrid(space, centers, ...) in the FixedSizeSpace S, named as the first template argument: pointGrid<State, Position>(centers) (decisions.md [space-storage]).
template<FixedSizeSpace S, typename P, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid (Eigen::MatrixBase< Derived > const &centers, std::span< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType const > cellCovariances, Allocator const &allocator={})
 pointGrid(space, centers, cellCovariances, ...) in the FixedSizeSpace S, named as the first template argument.
template<typename P, Space S, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid (S space, Eigen::MatrixBase< FirstDerived > const &first, Eigen::MatrixBase< SpacingDerived > const &spacing, std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const &counts, std::optional< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType > cellCovariance={}, Allocator const &allocator={})
template<typename P, Space S, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid (S space, Eigen::MatrixBase< FirstDerived > const &first, Eigen::MatrixBase< SpacingDerived > const &spacing, std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const &counts, std::span< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType const > cellCovariances, Allocator const &allocator={})
 regularGrid() with cellCovariances, each cell's covariance about its center in flat-index order, as on a latitude-longitude grid whose cells narrow toward the poles.
template<FixedSizeSpace S, typename P, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid (Eigen::MatrixBase< FirstDerived > const &first, Eigen::MatrixBase< SpacingDerived > const &spacing, std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const &counts, std::optional< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType > cellCovariance={}, Allocator const &allocator={})
 regularGrid(space, first, spacing, counts, ...) in the FixedSizeSpace S, named as the first template argument: regularGrid<State, Position>(first, spacing, {200, 200}) (decisions.md [space-storage]).
template<FixedSizeSpace S, typename P, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid (Eigen::MatrixBase< FirstDerived > const &first, Eigen::MatrixBase< SpacingDerived > const &spacing, std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const &counts, std::span< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType const > cellCovariances, Allocator const &allocator={})
 regularGrid(space, first, spacing, counts, cellCovariances, ...) in the FixedSizeSpace S, named as the first template argument.
template<Space Space_, RealScalar Scalar_>
InfoGaussianParams< Space_, Scalar_ > Emrys::multiply (InfoGaussianParams< Space_, Scalar_ > const &first, InfoGaussianParams< Space_, Scalar_ > const &second)
template<GaussianForm G>
std::expected< InfoGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toInfo (G const &form)
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SampleSet< Space, Scalar > Emrys::drawSamples (KernelDensity< Space, Scalar, Allocator > const &kde, Eigen::Index n, G &rng, R const &resampler={})
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (KernelDensity< Space, Scalar, Allocator > const &kde, G &rng)
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (KernelDensity< Space, Scalar, Allocator > const &kde, Eigen::Index n, G &rng, R const &resampler={})
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (P &&policy, KernelDensity< Space, Scalar, Allocator > const &kde, Eigen::Index n, G &rng, R const &resampler={})
 drawSamplesWithLogDensity() under policy: the draws are taken as the sequential form takes them, and their log-densities are a for-each over the draws (see Execution policies), so the result is Sequential's.
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (KernelDensity< Space, Scalar, Allocator > const &kde, G &rng)
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SampleSet< Space, Scalar > Emrys::drawSamples (Mixture< Gaussian< Space, Scalar >, Allocator > const &mixture, Eigen::Index n, G &rng, R const &resampler={})
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (Mixture< Gaussian< Space, Scalar >, Allocator > const &mixture, G &rng)
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (Mixture< Gaussian< Space, Scalar >, Allocator > const &mixture, Eigen::Index n, G &rng, R const &resampler={})
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (P &&policy, Mixture< Gaussian< Space, Scalar >, Allocator > const &mixture, Eigen::Index n, G &rng, R const &resampler={})
 drawSamplesWithLogDensity() under policy: the draws are taken as the sequential form takes them, and their log-densities are a for-each over the draws (see Execution policies), so the result is Sequential's.
template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (Mixture< Gaussian< Space, Scalar >, Allocator > const &mixture, G &rng)
template<typename P, Space S, typename Scalar, typename Allocator, typename Covariance = SharedCovariance>
auto Emrys::particleGaussian (S space, ParticleSet< typename internal::BlockSplit< S, P >::PinnedSpace, Scalar, Allocator > particles, GaussianParams< typename internal::BlockSplit< S, P >::RestSpace, Scalar > const &conditional, Covariance covariance={})
template<typename P, Space S, typename Scalar, typename Allocator, typename Component, typename ModeSpace, typename HybridAllocator>
auto Emrys::particleGaussian (S space, ParticleSet< typename internal::BlockSplit< S, P >::PinnedSpace, Scalar, Allocator > particles, HybridParams< Component, ModeSpace, HybridAllocator > const &conditional)
template<typename P, typename Covariance = SharedCovariance, typename S, typename Scalar, std::uniform_random_bit_generator G, typename Allocator = DefaultAllocator>
auto Emrys::drawParticleGaussian (GaussianParams< S, Scalar > const &joint, Eigen::Index count, G &rng, Covariance={}, Allocator const &allocator={})
template<typename Scalar, typename Space, typename Allocator>
std::expected< typename ParticleSet< Space, Scalar, Allocator >::MatrixType, WeightError > Emrys::silvermanBandwidth (ParticleSet< Space, Scalar, Allocator > const &particles)
template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator>
std::expected< typename ParticleSet< Space, Scalar, Allocator >::MatrixType, WeightError > Emrys::silvermanBandwidth (P &&policy, ParticleSet< Space, Scalar, Allocator > const &particles)
 silvermanBandwidth() under policy: the total weight, effective sample size, and covariance are reductions over the particles (see Execution policies).
template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SampleSet< BlockSpace, typename F::Scalar > Emrys::drawSamples (EachRepetition< F, BlockSpace > const &each, Eigen::Index n, G &rng)
template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
Moments< BlockSpace, typenameF::Scalar >::VectorType Emrys::drawSample (EachRepetition< F, BlockSpace > const &each, G &rng)
template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SamplesWithLogDensity< BlockSpace, typename F::Scalar > Emrys::drawSamplesWithLogDensity (EachRepetition< F, BlockSpace > const &each, Eigen::Index n, G &rng)
template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SampleWithLogDensity< BlockSpace, typename F::Scalar > Emrys::drawSampleWithLogDensity (EachRepetition< F, BlockSpace > const &each, G &rng)
template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples (Product< Space, Scalar, Factors_... > const &product, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (Product< Space, Scalar, Factors_... > const &product, G &rng)
template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (Product< Space, Scalar, Factors_... > const &product, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (Product< Space, Scalar, Factors_... > const &product, G &rng)
template<typename... Fallbacks>
constexpr auto Emrys::roots::cholesky (Fallbacks... fallbacks)
template<typename... Fallbacks>
constexpr auto Emrys::roots::pivoted (Fallbacks... fallbacks)
template<typename... Fallbacks>
constexpr auto Emrys::roots::principal (Fallbacks... fallbacks)
template<typename... Fallbacks>
constexpr auto Emrys::roots::symmetric (Fallbacks... fallbacks)
template<typename Derived, typename... Fallbacks>
auto Emrys::roots::along (Eigen::MatrixBase< Derived > const &direction, Fallbacks... fallbacks)
template<double Relative = 1.0, double Absolute = 0.0>
constexpr Ridge< Relative, Absolute > Emrys::roots::ridge ()
template<typename Head, typename First, typename... Rest>
constexpr WithFallbacks< Head, First, Rest... > Emrys::roots::withFallbacks (Head axes, First first, Rest... rest)
template<Axes A, typename Derived>
auto Emrys::roots::squareRoot (A const &axes, Eigen::MatrixBase< Derived > const &cov)
template<Axes A, typename Derived>
auto Emrys::roots::squareRootWithReport (A const &axes, Eigen::MatrixBase< Derived > const &cov)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples (Gaussian< Space, Scalar > const &gaussian, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (Gaussian< Space, Scalar > const &gaussian, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (Gaussian< Space, Scalar > const &gaussian, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (Gaussian< Space, Scalar > const &gaussian, G &rng)
template<GaussianForm G>
std::expected< SqrtGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toSqrt (G const &form)
template<Space Space_, RealScalar Scalar_>
SqrtInfoGaussianParams< Space_, Scalar_ > Emrys::multiply (SqrtInfoGaussianParams< Space_, Scalar_ > const &first, SqrtInfoGaussianParams< Space_, Scalar_ > const &second)
template<GaussianForm G>
std::expected< SqrtInfoGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toSqrtInfo (G const &form)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples (StudentT< Space, Scalar > const &t, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (StudentT< Space, Scalar > const &t, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (StudentT< Space, Scalar > const &t, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (StudentT< Space, Scalar > const &t, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples (Uniform< Space, Scalar > const &uniform, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample (Uniform< Space, Scalar > const &uniform, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity (Uniform< Space, Scalar > const &uniform, Eigen::Index n, G &rng)
template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity (Uniform< Space, Scalar > const &uniform, G &rng)
template<Space S, RealScalar Scalar, typename CountsDerived>
requires std::integral<typename CountsDerived::Scalar>
UniformGrid< S, Scalar > Emrys::uniformComponents (Uniform< S, Scalar > const &uniform, Eigen::DenseBase< CountsDerived > const &counts, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
template<Space S, RealScalar Scalar>
UniformGrid< S, Scalar > Emrys::uniformComponents (Uniform< S, Scalar > const &uniform, Eigen::Index count, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
 uniformComponents() with count components along every coordinate.
template<Space S, RealScalar Scalar, typename... Factors, typename CountsDerived>
requires std::integral<typename CountsDerived::Scalar>
UniformGrid< S, Scalar > Emrys::uniformComponents (Product< S, Scalar, Factors... > const &product, Eigen::DenseBase< CountsDerived > const &counts, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
template<Space S, RealScalar Scalar, typename... Factors>
UniformGrid< S, Scalar > Emrys::uniformComponents (Product< S, Scalar, Factors... > const &product, Eigen::Index count, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
 uniformComponents() of a Product with count components along every coordinate of its Uniform factors.

Variables

template<typename C>
constexpr bool Emrys::isGaussian = false
 Whether C is a Gaussian in covariance form: the component for which a container offers the conveniences that take or give moments [component-first].
template<GaussianForm G>
constexpr bool Emrys::isInfoForm = G::IsInfoForm
 Whether the GaussianForm G holds the precision, as InfoGaussianParams and SqrtInfoGaussianParams do, rather than the covariance.
template<GaussianForm G>
constexpr bool Emrys::isSqrtForm = G::IsSqrtForm
 Whether the GaussianForm G holds a triangular root, as SqrtGaussianParams and SqrtInfoGaussianParams do, rather than a whole matrix.

Detailed Description

The third layer (decisions.md [layered-headers]): the distributions, each stored as parameters and evaluated through a density, and what is computed from them.

Parameters and densities. A distribution whose values can fail to define it, such as a Gaussian whose covariance is not positive definite, has two types [params-and-density]: its parameters, which hold the values and change step by step, and its density, which evaluates it. The split exists so that the expensive work is done once and the cheap work many times. Evaluating a Gaussian's density needs a Cholesky factorization of its covariance, whose cost is cubic in the dimension, while each evaluation after that is a triangular solve, whose cost is quadratic. A filter changes a covariance once in a step but may evaluate it many times in that step: a particle filter's update evaluates one measurement noise at the residual of every particle, and a Gaussian mixture evaluates each of its components at every value. So GaussianParams holds the mean and covariance and caches their factorization; toDensity() factorizes only if the covariance has changed since the last factorization, and returns a Gaussian, which borrows that factorization and copies nothing:

auto const cov = Eigen::Matrix2d{{1.0, 0.2}, {0.2, 0.8}};
auto noise = GaussianParams<Linear<2>>{Eigen::Vector2d::Zero(), cov};
auto const density = noise.toDensity(); // factorizes, or fails with a GaussianError
if (!density)
{
return;
}
for (Eigen::Index j = 0; j < residuals.cols(); ++j)
{
logLikelihoods(j) = density->logDensity(residuals.col(j)); // a triangular solve each
}
noise.setCovariance(widened); // density must not be read again; the next toDensity() factorizes
Eigen::Array< typename Derived::Scalar, Eigen::Dynamic, 1 > logLikelihoods(M const &measurement, Space const &space, Eigen::MatrixBase< Derived > const &states)
Definition Likelihood.h:408

The split also puts the check of the values in one place. Parameters that fail to define a distribution fail in toDensity(), once, as a std::expected, so logDensity() returns a plain scalar and a loop over particles or components has no error to check. A density writes nothing, so any number of threads may evaluate one at once (see below). In exchange, a density must not outlive its parameters, and reading it after they have changed is a programmer error that EMRYS_FILTER_ASSERT catches [view-stamp].

Two cases the check can't see, since the stamp it reads is gone. Hold a density by value: the std::expected that toDensity() returns is a temporary, and a reference into it dangles at the end of the statement. And a density of a component inside a container, a mixture's or a hybrid's, must not be read after the container grows, which may move the component it borrows; only AddressSanitizer catches either.

auto const density = noise.toDensity().value(); // a Gaussian, held by value
auto const & dangling = noise.toDensity().value(); // dangles at the semicolon
auto const first = mixture[0].component.toDensity().value();
mixture.add(0.0, moments); // may move the components; first must not be read again

The split also lets values be written one at a time where the check is of all of them together. A categorical distribution's weights must not all be zero, and no single write makes or breaks that: filling a histogram, setting a weight by name, or ruling a value out passes through states that would fail. CategoricalParams takes those writes unchecked, and its toDensity() checks the weights once and returns the Categorical that reads the probabilities.

A distribution whose values are always valid, such as Uniform, Gamma, StudentT, or Product, has nothing to cache, so it is one type: it checks its values when it is built, as StudentT::create() does, and is its own parameters and its own density. Params<D> and Density

(Params.h) map each type to the other, and a type of the first kind to itself. Filters, mixtures, and hybrids are named by the density and store its parameters: KalmanFilter<Gaussian<State>, Model> holds a GaussianParams, which each step changes in place, and its state's toDensity() gives the Gaussian. Generic code is written against the density, since every distribution has one, and the HasLogDensity concept (Product.h) says what a continuous density can do.

A statistic that reads the components is the density's: a mixture's or a hybrid's moments and collapse, and a Rao-Blackwellized state's collapse. It needs no factorization to compute, but only the factorization checks that each component is a distribution, so on the parameters it could describe none. One that reads only the weights, such as MixtureParams::ess(), is on the parameters too, a std::expected of the weights' error (decisions.md [params-and-density]).

The headers. Params.h pairs parameters with their densities. Moments.h holds the mean and covariance that every distribution is matched to, SampleSet.h a matrix of samples, and Roots.h the square roots of a covariance by the axes and repairs of Emrys::roots. The Gaussian (Gaussian.h) comes first, with its draws (Sampling.h) and its square-root and information forms SqrtGaussian, InfoGaussian, and SqrtInfoGaussian, which GaussianForm.h ties together [gaussian-forms]. The distributions that are their own parameters are Uniform, Gamma, StudentT, and Product. CategoricalParams and Categorical are the distribution over a discrete space [discrete-spaces], and ContinuousTimeMarkovChain.h moves one over an interval [emissions]. The containers of weighted elements share the statistics in Statistics.h and, where the elements are Gaussians, the Component concept (Component.h, [component-first]): GaussianMixture (Mixture.h), with uniformComponents() giving, one at a time, the components that approximate a Uniform, or the Uniform factors of a Product, to fill one (UniformMixture.h, [uniform-mixtures]), HybridGaussian (Hybrid.h, [imm]), and ParticleSet with its KernelDensity. Fitting.h fits a mixture by expectation-maximization; Upkeep.h holds the actions a caller applies to a state between steps [upkeep]; Divergence.h compares two distributions [divergences]; and Conditionals.h, GridGaussian.h, and ParticleGaussian.h are the Rao-Blackwellized states [rao-blackwellized-core], [rb-particle-filter]. Read Params.h first, and Models next.

Sharing between threads. Parameters are for changing step by step, not for sharing. Their const members fill the cache that evaluation needs, so const does not make them safe to read from several threads at once [execution-policies]: factorize(), toDensity(), and the accessors that need a factorization, such as GaussianParams::precision(), write the cache the first time after a change, and the square-root and information forms' toDensity() writes it each time. What threads should share is what toDensity() returns: a density writes nothing, so any number of threads may evaluate one at once, while its parameters stay alive and unchanged and nothing calls their const members that write the cache. Code that needs only the mean and covariance shares a copy of the Moments instead, which owns its values and needs neither.

What a view's check catches. A view's check of its parameters detects a change after the fact and prevents nothing: it blocks no mutator and makes nothing wait. It records the parameters' modification stamp when the view is made, and reading the view after the parameters have changed is a programmer error that EMRYS_FILTER_ASSERT catches. The stamp is a plain counter, so changing parameters on one thread while another reads a view of them is a data race that no check catches.

The views differ in what they tolerate. Parameters keep two counters: every mutator advances the first, and a change of size or structure (a resize, an insertion or removal, a resample, an assignment, a move from) advances the second too. A density reads the cached factorization or bandwidth, so it checks the first and fails after any change. A marginal of parameters reads their values by indices resolved when it was made, so it checks only the second: it sees new values, and fails after a change of size or structure. A marginal of a view holds a copy of the view and fails as the view would. An element of a mixture's or a hybrid's marginal reads its component through the range's indices, so it must not outlive the range. A copy of the parameters is new parameters, and changing it leaves the views of the original alone.

Marginals and conditionals. Every continuous distribution has marginal<Path>() and conditional<GivenPath>(values) by tag path [tag-addressing]. A marginal reads its source wherever it can without computing, and copy() gives parameters [element-marginals]: the Gaussian's is a GaussianMarginal view, and a mixture's, a hybrid's, or a particle set's a range over the elements' marginals. A marginal that must compute is a value: the square-root and information forms', a categorical's over an axis, and those of the distributions that are their own parameters. A conditional is always a value. One whose type has weights (a mixture's, a particle set's, a categorical's) leaves them unnormalized, so its total weight is the source's times the density of the given values; a single Gaussian returns that evidence from conditionalWithEvidence() [conditional-evidence]. A KernelDensity only evaluates: condition the ParticleSet, whose conditional stores the exact conditional bandwidth.

Random draws. A density draws, and parameters don't: drawSamples() and drawSample(), with their WithLogDensity forms, take the density and the caller's generator [random-draws]. The draws go through std::normal_distribution and its siblings, whose algorithms the standard leaves to the implementation, so a seed gives the same draws under one standard library and other draws under another. drawSample() takes its own draws from the generator at each call, so a stream of single draws is not the sequence drawSamples() gives from the same seed.

Typedef Documentation

◆ ConstSampleSetMap

template<typename Space, typename Scalar = double>
using Emrys::ConstSampleSetMap = Eigen::Map<SampleSet<Space, Scalar> const>

A read-only view of samples in Space, one per column, over memory it does not own, laid out as a SampleSet is: what the containers return for their states, means, and centers.

Template Parameters
Spacespace of the samples
Scalarscalar type, double by default

◆ Density

template<typename P>
using Emrys::Density = typename DensityOf<P>::type

The density of the parameters P: Gaussian for GaussianParams, and P itself for a type that is its own parameters (decisions.md [params-and-density]).

Deduction guides use it to name a filter or mixture by the density when they are given its parameters.

◆ GaussianError

Reasons a Gaussian, in any of its forms (decisions.md [gaussian-forms]), can fail to give a density, a mean, or one of its matrices, and a root of a covariance can fail to be taken: NotPositiveDefinite, Singular, or NonFinite of NumericError.

See also
GaussianParams::toDensity(), GaussianForm, roots::squareRoot()

◆ GaussianMixture

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::GaussianMixture = Mixture<Gaussian<Space_, Scalar_>, Allocator_>

The Mixture of a GaussianMixtureParams, the spelling for the common case (decisions.md [component-first]).

Template Parameters
Space_space of the components (see Spaces)
Scalar_scalar type, double by default
Allocator_the parameters' allocator (see Allocation)

◆ GaussianMixtureParams

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::GaussianMixtureParams = MixtureParams<Gaussian<Space_, Scalar_>, Allocator_>

A Mixture of Gaussians in covariance form, the spelling for the common case (decisions.md [component-first]): \( \sum_i w_i \, \mathcal{N}(x; \mu_i, \Sigma_i) \).

Template Parameters
Space_space of the components (see Spaces)
Scalar_scalar type, double by default
Allocator_allocator for the entries and scratch (see Allocation)

◆ HybridGaussian

template<Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::HybridGaussian = Hybrid<Gaussian<Space_, Scalar_>, ModeSpace_, Allocator_>

The Hybrid of Gaussians in covariance form, the spelling for the common case (decisions.md [component-first]): \( p(x, m) = P(m) \, \mathcal{N}(x; \mu_m, \Sigma_m) \), the density of an ImmFilter's state, and the name a mixture of hybrids takes as its component.

Template Parameters
Space_the continuous state space (see Spaces)
ModeSpace_the discrete mode space (see Discrete spaces)
Scalar_scalar type, double by default
Allocator_allocator for the Gaussians (see Allocation)

◆ HybridGaussianParams

template<Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
using Emrys::HybridGaussianParams = HybridParams<Gaussian<Space_, Scalar_>, ModeSpace_, Allocator_>

The HybridParams of Gaussians in covariance form: the parameters of a HybridGaussian, an ImmFilter's state.

Template Parameters
Space_the continuous state space (see Spaces)
ModeSpace_the discrete mode space (see Discrete spaces)
Scalar_scalar type, double by default
Allocator_allocator for the Gaussians (see Allocation)

◆ InfoGaussian

template<Space Space_, RealScalar Scalar_ = double>
using Emrys::InfoGaussian = FormGaussian<InfoGaussianParams<Space_, Scalar_>>

The Gaussian in information form, which evaluates its density: what InfoGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).

It reads its parameters' cached factorization and must not outlive them [view-stamp].

Template Parameters
Space_the state space (see Spaces)
Scalar_scalar type, double by default

◆ RootMatrix

template<typename Derived>
using Emrys::roots::RootMatrix = internal::SquareMatrixOf<Derived>

The type of a root of the covariance or factor Derived: square, with a row and a column per row of it and its bounds, so that a bounded matrix allocates nothing [allocation].

What axes of the user's own return.

◆ SampleSet

template<typename Space, typename Scalar = double>
using Emrys::SampleSet
Initial value:
Eigen::Matrix<
Scalar,
Eigen::Dynamic,
(maxValueDimensionAtCompileTime<Space> == 1 ? Eigen::RowMajor : Eigen::ColMajor),
Eigen::Dynamic>
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

A matrix whose columns are samples in Space (see Spaces), with the space's size and storage bound.

It is a plain Eigen matrix, so the space is not part of its type and the samples are not normalized by it.

Template Parameters
Spacespace of the samples; plain vectors of dimension N are Linear<N>
Scalarscalar type, double by default

The number of samples is not bounded, so a SampleSet allocates its storage from Eigen's heap, which takes no allocator. Where that storage must come from an allocator or a buffer of one's own, as on a system with no heap, use a SampleSetMap over it: the containers keep their samples that way and return them as maps [allocation], and drawSample() takes one sample at a time.

Eigen requires a single-row matrix to be row-major, so one-dimensional sample sets are stored row-major; all others are column-major.

◆ SampleSetMap

template<typename Space, typename Scalar = double>
using Emrys::SampleSetMap = Eigen::Map<SampleSet<Space, Scalar>>

A writable view of samples in Space, one per column, over memory it does not own, laid out as a SampleSet is: what to wrap a buffer from an allocator in, so that nothing is taken from the heap.

Template Parameters
Spacespace of the samples
Scalarscalar type, double by default

◆ SqrtGaussian

template<Space Space_, RealScalar Scalar_ = double>
using Emrys::SqrtGaussian = FormGaussian<SqrtGaussianParams<Space_, Scalar_>>

The Gaussian in square-root form, which evaluates its density: what SqrtGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).

It reads its parameters' cached factorization and must not outlive them [view-stamp].

Template Parameters
Space_the state space (see Spaces)
Scalar_scalar type, double by default

◆ SqrtInfoGaussian

template<Space Space_, RealScalar Scalar_ = double>
using Emrys::SqrtInfoGaussian = FormGaussian<SqrtInfoGaussianParams<Space_, Scalar_>>

The Gaussian in square-root information form, which evaluates its density: what SqrtInfoGaussianParams::toDensity() returns (decisions.md [gaussian-forms], [params-and-density]).

It reads its parameters' cached factorization and must not outlive them [view-stamp].

Template Parameters
Space_the state space (see Spaces)
Scalar_scalar type, double by default

Enumeration Type Documentation

◆ ChainError

enum class Emrys::ChainError
strong

Reasons a Markov chain has no single stationary distribution.

See also
stationary()
Enumerator
Reducible 

some value can't be reached from some other, so the chain is not irreducible

◆ FitError

enum class Emrys::FitError
strong

Reasons fitMixture() can fail.

Enumerator
Degenerate 

the source has no spread in some dimension, e.g. every particle has the same state

InvalidWeights 

the particles' weights cannot be normalized (see ParticleSet::logTotalWeight())

◆ GammaError

enum class Emrys::GammaError
strong

Reasons a shape and scale fail to define a Gamma.

Enumerator
NotPositive 

a shape or scale is zero or negative

NonFinite 

a shape or scale is NaN or infinite

◆ MomentsError

enum class Emrys::MomentsError
strong

Reasons a distribution's moments() can fail.

Enumerator
Infinite 

the distribution has no finite mean or covariance, such as a Student-t with \( \nu \le 2 \)

◆ StudentTError

enum class Emrys::StudentTError
strong

Reasons a location, scale matrix, and degrees of freedom fail to define a StudentT.

Enumerator
NotPositiveDefinite 

the scale matrix is not positive definite

NonFiniteScale 

the scale matrix is not finite

NotPositiveDegreesOfFreedom 

the degrees of freedom are zero or negative

NonFiniteDegreesOfFreedom 

the degrees of freedom are NaN or infinite

◆ UniformError

enum class Emrys::UniformError
strong

Reasons bounds fail to define a Uniform.

Enumerator
Empty 

an upper bound is not above its lower bound

NonFinite 

a bound is NaN or infinite

WiderThanPeriod 

an interval on a Periodic coordinate spans more than one period

Function Documentation

◆ along()

template<typename Derived, typename... Fallbacks>
auto Emrys::roots::along ( Eigen::MatrixBase< Derived > const & direction,
Fallbacks... fallbacks )
nodiscard
Returns
axes along the direction direction, a column vector in the covariance's coordinates (Along), followed by fallbacks when it fails: along(d, pivoted()) on a state with a block known exactly

◆ cholesky()

template<typename... Fallbacks>
auto Emrys::roots::cholesky ( Fallbacks... fallbacks)
nodiscardconstexpr
Returns
Cholesky axes, followed by fallbacks when it fails (WithFallbacks): cholesky(), which can fail, or cholesky(pivoted()), the default, which cannot

◆ drawParticleGaussian()

template<typename P, typename Covariance = SharedCovariance, typename S, typename Scalar, std::uniform_random_bit_generator G, typename Allocator = DefaultAllocator>
auto Emrys::drawParticleGaussian ( GaussianParams< S, Scalar > const & joint,
Eigen::Index count,
G & rng,
Covariance = {},
Allocator const & allocator = {} )
nodiscard
Returns
count equally weighted particles of the block named by the path P drawn from the Gaussian joint over the whole state with rng, each with the Gaussian of the rest given its value: the Rao-Blackwellized form of joint. Those Gaussians share one covariance, which a PerPointCovariance state copies to each. The state allocates through allocator.

◆ drawSample() [1/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Eigen::Index Emrys::drawSample ( Categorical< Space, Scalar > const & distribution,
G & rng )
nodiscard
Returns
one draw from distribution, a value's flat index: the stream of draws that drawSample() of a Gaussian is. It compares one uniform draw with the running sum of the probabilities, since std::discrete_distribution copies them onto the heap, so it allocates nothing, and is not the sequence drawSamples() gives from the same generator.

◆ drawSample() [2/10]

template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
Moments< BlockSpace, typenameF::Scalar >::VectorType Emrys::drawSample ( EachRepetition< F, BlockSpace > const & each,
G & rng )
nodiscard
Returns
one draw from each, the factor's drawSample() at each repetition, in order.

◆ drawSample() [3/10]

template<typename Params_, std::uniform_random_bit_generator G>
Moments< typenameParams_::SpaceType, typenameParams_::Scalar >::VectorType Emrys::drawSample ( FormGaussian< Params_ > const & gaussian,
G & rng )
nodiscard
Returns
one draw from gaussian, \( \mu \boxplus A z \) as drawSamples() draws each, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is.

◆ drawSample() [4/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( Gamma< Space, Scalar > const & gamma,
G & rng )
nodiscard
Returns
one draw from gamma, by std::gamma_distribution on each coordinate, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is. It makes each coordinate's distribution afresh, where drawSamples() keeps one per coordinate, with whatever state it carries, from draw to draw.

◆ drawSample() [5/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( Gaussian< Space, Scalar > const & gaussian,
G & rng )
nodiscard
Returns
one draw from gaussian, \( \mu \boxplus L z \) as drawSamples() draws each, in a vector sized by the space, so that a bounded space allocates nothing.

Called again and again, it is a stream of independent draws for code that keeps each one where it chooses, as on a system with no heap. Each call takes its own normal draws from rng, so a stream of them is not the sequence drawSamples() gives from the same generator.

See also
drawSamples()

◆ drawSample() [6/10]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( KernelDensity< Space, Scalar, Allocator > const & kde,
G & rng )
nodiscard
Returns
one draw from kde, a particle picked in proportion to its weight plus kernel noise \( L z \), in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is. Its draws are independent, as resamplers::Multinomial makes those of drawSamples(); a lower-variance resampler spreads a batch over the particles, which one draw at a time cannot.

◆ drawSample() [7/10]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( Mixture< Gaussian< Space, Scalar >, Allocator > const & mixture,
G & rng )
nodiscard
Returns
one draw from mixture, a component picked in proportion to its weight and then a draw from it, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is. Its draws are independent, as resamplers::Multinomial makes those of drawSamples(); a lower-variance resampler spreads a batch over the components, which one draw at a time cannot.

◆ drawSample() [8/10]

template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( Product< Space, Scalar, Factors_... > const & product,
G & rng )
nodiscard
Returns
one draw from product, each factor's drawSample() in its coordinates, factor by factor, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is.

◆ drawSample() [9/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( StudentT< Space, Scalar > const & t,
G & rng )
nodiscard
Returns
one draw from t, \( \mu \boxplus L z \sqrt{\nu / u} \) as drawSamples() draws each, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is. It draws the normals and then the chi-squared, where drawSamples() draws every normal first.

◆ drawSample() [10/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
Moments< Space, Scalar >::VectorType Emrys::drawSample ( Uniform< Space, Scalar > const & uniform,
G & rng )
nodiscard
Returns
one draw from uniform, \( \ell + w \circ u \) as drawSamples() draws each, in a vector sized by the space: the stream of draws that drawSample() of a Gaussian is. Its coordinates take the uniform draws in the order drawSamples() gives each column.

◆ drawSamples() [1/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
std::vector< Eigen::Index > Emrys::drawSamples ( Categorical< Space, Scalar > const & distribution,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from distribution, each a value's flat index, by std::discrete_distribution over the probabilities

◆ drawSamples() [2/10]

template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SampleSet< BlockSpace, typename F::Scalar > Emrys::drawSamples ( EachRepetition< F, BlockSpace > const & each,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from each, one per column: the factor's draws at each repetition, repetition by repetition.

◆ drawSamples() [3/10]

template<typename Params_, std::uniform_random_bit_generator G>
SampleSet< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSamples ( FormGaussian< Params_ > const & gaussian,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gaussian, one per column: \( \mu \boxplus A z \) with \( z \sim \mathcal{N}(0, I) \) and \( A \) the root of FormGaussian::colorNormals(), as drawSamples() of a Gaussian draws with its Cholesky factor.

◆ drawSamples() [4/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples ( Gamma< Space, Scalar > const & gamma,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gamma, one per column, by std::gamma_distribution on each coordinate.
See also
drawSamplesWithLogDensity(Gamma const &, Eigen::Index, G &)

◆ drawSamples() [5/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples ( Gaussian< Space, Scalar > const & gaussian,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gaussian, one per column.

Each draw is \( \mu \boxplus L z \) with \( z \sim \mathcal{N}(0, I) \) and \( L \) the Cholesky factor of the covariance: the standard affine transformation of standard normals, with the space's \( \boxplus \) in place of addition.

See also
drawSamplesWithLogDensity()

◆ drawSamples() [6/10]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SampleSet< Space, Scalar > Emrys::drawSamples ( KernelDensity< Space, Scalar, Allocator > const & kde,
Eigen::Index n,
G & rng,
R const & resampler = {} )
nodiscard
Returns
n draws from kde, one per column.

Each draw picks a particle in proportion to its weight using resampler, then adds kernel noise \( L z \) with \( z \sim \mathcal{N}(0, I) \) and \( H = L L^T \). The default resamplers::Multinomial makes the draws independent; a lower-variance resampler such as resamplers::Systematic spreads them more evenly over the particles, as in the regularized particle filter of Musso, Oudjane, and Le Gland (2001).

See also
drawSamplesWithLogDensity(KernelDensity const &, Eigen::Index, G &, R const &), Resamplers

◆ drawSamples() [7/10]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SampleSet< Space, Scalar > Emrys::drawSamples ( Mixture< Gaussian< Space, Scalar >, Allocator > const & mixture,
Eigen::Index n,
G & rng,
R const & resampler = {} )
nodiscard
Returns
n draws from mixture, one per column.

Each draw picks a component in proportion to its weight using resampler, then draws \( \mu_c \boxplus L_c z \) from it, with \( z \sim \mathcal{N}(0, I) \) and \( \Sigma_c = L_c L_c^T \): sampling a mixture by composition. The default resamplers::Multinomial makes the draws independent; a lower-variance resampler such as resamplers::Systematic gives each component a count closer to its expected share.

See also
drawSamplesWithLogDensity(GaussianMixture const &, Eigen::Index, G &, R const &), Resamplers

◆ drawSamples() [8/10]

template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples ( Product< Space, Scalar, Factors_... > const & product,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from product, one per column: each factor's draws in its coordinates, factor by factor.
See also
drawSamplesWithLogDensity(Product const &, Eigen::Index, G &)

◆ drawSamples() [9/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples ( StudentT< Space, Scalar > const & t,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from t, one per column: \( \mu \boxplus L z \sqrt{\nu / u} \) with \( z \sim \mathcal{N}(0, I) \) and \( u \sim \chi^2_\nu \), normalized in the space.
See also
drawSamplesWithLogDensity(StudentT const &, Eigen::Index, G &)

◆ drawSamples() [10/10]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleSet< Space, Scalar > Emrys::drawSamples ( Uniform< Space, Scalar > const & uniform,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from uniform, one per column: \( \ell + w \circ u \) with \( u \) uniform on [0, 1), normalized in the space.
See also
drawSamplesWithLogDensity(Uniform const &, Eigen::Index, G &)

◆ drawSamplesWithLogDensity() [1/9]

template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SamplesWithLogDensity< BlockSpace, typename F::Scalar > Emrys::drawSamplesWithLogDensity ( EachRepetition< F, BlockSpace > const & each,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from each, one per column, with the log-density at each: the sum of the factor's log-densities at its draws.

◆ drawSamplesWithLogDensity() [2/9]

template<typename Params_, std::uniform_random_bit_generator G>
SamplesWithLogDensity< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSamplesWithLogDensity ( FormGaussian< Params_ > const & gaussian,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gaussian, one per column, as drawSamples() draws them, with the log-density of gaussian at each.

The log-densities cost almost nothing extra in a linear space: the whitened residual of \( x = \mu + A z \) is \( z \), so the squared Mahalanobis distance is \( \|z\|^2 \). In other spaces each is FormGaussian::logDensity() of the stored sample, as for a Gaussian (see drawSamplesWithLogDensity(Gaussian const &, Eigen::Index, G &)).

◆ drawSamplesWithLogDensity() [3/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( Gamma< Space, Scalar > const & gamma,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gamma, one per column, with the log-density at each.
See also
drawSamples(Gamma const &, Eigen::Index, G &)

◆ drawSamplesWithLogDensity() [4/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( Gaussian< Space, Scalar > const & gaussian,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from gaussian, one per column, with the log-density of gaussian at each.

The log-densities cost almost nothing extra in a linear space: for \( x = \mu + L z \) the squared Mahalanobis distance is \( \|z\|^2 \). In other spaces each is Gaussian::logDensity() of the stored sample, so a draw that wraps far around a periodic coordinate gets the nearest-image density, matching logDensity().

See also
drawSamples()

◆ drawSamplesWithLogDensity() [5/9]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( KernelDensity< Space, Scalar, Allocator > const & kde,
Eigen::Index n,
G & rng,
R const & resampler = {} )
nodiscard
Returns
n draws from kde, one per column, with the log-density of kde at each.

Draws exactly as drawSamples() does. Unlike the Gaussian case the log-densities are not free: each costs a full KernelDensity::logDensity() evaluation, so the total is \( O(n \cdot \mathrm{size}() \cdot d^2) \).

See also
drawSamples(KernelDensity const &, Eigen::Index, G &, R const &)

◆ drawSamplesWithLogDensity() [6/9]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G, typename R = resamplers::Multinomial>
requires Resampler<R, Scalar, G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( Mixture< Gaussian< Space, Scalar >, Allocator > const & mixture,
Eigen::Index n,
G & rng,
R const & resampler = {} )
nodiscard
Returns
n draws from mixture, one per column, with the log-density of mixture at each.

Draws exactly as drawSamples() does. Each log-density is a full Mixture::logDensity() evaluation, so the total is \( O(n \cdot \mathrm{size}() \cdot d^2) \).

See also
drawSamples(GaussianMixture const &, Eigen::Index, G &, R const &)

◆ drawSamplesWithLogDensity() [7/9]

template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( Product< Space, Scalar, Factors_... > const & product,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from product, one per column, with the log-density at each: the sum of the factors' log-densities at their draws.
See also
drawSamples(Product const &, Eigen::Index, G &)

◆ drawSamplesWithLogDensity() [8/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( StudentT< Space, Scalar > const & t,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from t, one per column, with the log-density at each.

In a linear space the log-densities cost almost nothing extra: the squared Mahalanobis distance of a draw is \( \|z\|^2 \nu / u \). In other spaces each is logDensity() of the stored sample, the nearest-image density.

See also
drawSamples(StudentT const &, Eigen::Index, G &)

◆ drawSamplesWithLogDensity() [9/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SamplesWithLogDensity< Space, Scalar > Emrys::drawSamplesWithLogDensity ( Uniform< Space, Scalar > const & uniform,
Eigen::Index n,
G & rng )
nodiscard
Returns
n independent draws from uniform, one per column, with the log-density at each, which is the same everywhere in the box.
See also
drawSamples(Uniform const &, Eigen::Index, G &)

◆ drawSampleWithLogDensity() [1/9]

template<typename F, typename BlockSpace, std::uniform_random_bit_generator G>
SampleWithLogDensity< BlockSpace, typename F::Scalar > Emrys::drawSampleWithLogDensity ( EachRepetition< F, BlockSpace > const & each,
G & rng )
nodiscard
Returns
one draw from each, the factor's drawSampleWithLogDensity() at each repetition, in order, with the sum of their log-densities.

◆ drawSampleWithLogDensity() [2/9]

template<typename Params_, std::uniform_random_bit_generator G>
SampleWithLogDensity< typename Params_::SpaceType, typename Params_::Scalar > Emrys::drawSampleWithLogDensity ( FormGaussian< Params_ > const & gaussian,
G & rng )
nodiscard
Returns
one draw from gaussian, as drawSample() draws it, with the log-density of gaussian at it, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is, with the log-density computed as drawSamplesWithLogDensity() computes it.

◆ drawSampleWithLogDensity() [3/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( Gamma< Space, Scalar > const & gamma,
G & rng )
nodiscard
Returns
one draw from gamma, as drawSample() draws it, with the log-density at it, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is.

◆ drawSampleWithLogDensity() [4/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( Gaussian< Space, Scalar > const & gaussian,
G & rng )
nodiscard
Returns
one draw from gaussian, as drawSample() draws it, with the log-density of gaussian at it, so that a bounded space allocates nothing: the stream of draws for code that needs each one's density, such as an importance sampler on a system with no heap.

The log-density costs almost nothing extra in a linear space, \( \|z\|^2 \) being the squared Mahalanobis distance of \( \mu + L z \); in other spaces it is Gaussian::logDensity() of the draw, as drawSamplesWithLogDensity() computes it.

See also
drawSample(), drawSamplesWithLogDensity()

◆ drawSampleWithLogDensity() [5/9]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( KernelDensity< Space, Scalar, Allocator > const & kde,
G & rng )
nodiscard
Returns
one draw from kde, as drawSample() draws it, with the log-density of kde at it, a full KernelDensity::logDensity() evaluation, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is.

◆ drawSampleWithLogDensity() [6/9]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( Mixture< Gaussian< Space, Scalar >, Allocator > const & mixture,
G & rng )
nodiscard
Returns
one draw from mixture, as drawSample() draws it, with the log-density of mixture at it, a full Mixture::logDensity() evaluation, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is.

◆ drawSampleWithLogDensity() [7/9]

template<typename Scalar, typename Space, typename... Factors_, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( Product< Space, Scalar, Factors_... > const & product,
G & rng )
nodiscard
Returns
one draw from product, each factor's drawSampleWithLogDensity() in its coordinates, factor by factor, with the sum of their log-densities, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is.

◆ drawSampleWithLogDensity() [8/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( StudentT< Space, Scalar > const & t,
G & rng )
nodiscard
Returns
one draw from t, as drawSample() draws it, with the log-density at it, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is, with the log-density computed as drawSamplesWithLogDensity() computes it.

◆ drawSampleWithLogDensity() [9/9]

template<typename Scalar, typename Space, std::uniform_random_bit_generator G>
SampleWithLogDensity< Space, Scalar > Emrys::drawSampleWithLogDensity ( Uniform< Space, Scalar > const & uniform,
G & rng )
nodiscard
Returns
one draw from uniform, as drawSample() draws it, with the log-density at it, the same everywhere in the box, in a vector sized by the space: the stream of draws that drawSampleWithLogDensity() of a Gaussian is.

◆ fitMixture() [1/4]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture ( GaussianMixture< Space, Scalar, Allocator > const & mixture,
Eigen::Index k,
G & rng,
FitOptions< Scalar > const & options = {} )
nodiscard
Returns
a mixture of at most k Gaussians fitted to mixture by hierarchical EM, with the mixture's allocator.

Reduces the mixture without sampling: each component is a weighted point carrying its covariance. Seeds by weighted k-means++ over the component means, so stacked components are not seeded twice. The result is in the mixture's space. Costs O(iterations · size() · k · d³), with no pairwise pass over the components.

Returns
the fit, or FitError::Degenerate if the mixture has no spread in some dimension

◆ fitMixture() [2/4]

template<ExecutionPolicy P, typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture ( P && policy,
ParticleSet< Space, Scalar, Allocator > const & particles,
Eigen::Index k,
G & rng,
FitOptions< Scalar > const & options = {} )
nodiscard

fitMixture() of particles under policy: each E-step is a for-each over the particles, and each M-step's moments are reductions over them, which match Sequential's to rounding (see Execution policies).

The seeding is sequential, from rng as Sequential draws.

◆ fitMixture() [3/4]

template<typename Scalar, typename Space, typename Allocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture ( ParticleSet< Space, Scalar, Allocator > const & particles,
Eigen::Index k,
G & rng,
FitOptions< Scalar > const & options = {} )
nodiscard
Returns
a mixture of at most k Gaussians fitted to particles by weighted EM, with the particles' allocator.

Seeds by weighted k-means++ over the particles, using the Mahalanobis distance under the particles' covariance, so duplicate particles are not seeded twice. Fewer than k components result if fewer distinct particles exist or components die (see FitOptions::minLogWeight). The result is in the particles' space. Costs O(iterations · size() · k · d²).

Returns
the fit; FitError::Degenerate if the particles have no spread in some dimension; or FitError::InvalidWeights if their weights cannot be normalized

◆ fitMixture() [4/4]

template<typename Scalar, typename Space, typename Allocator, typename SeedAllocator, std::uniform_random_bit_generator G>
std::expected< MixtureFit< Space, Scalar, Allocator >, FitError > Emrys::fitMixture ( ParticleSet< Space, Scalar, Allocator > const & particles,
GaussianMixture< Space, Scalar, SeedAllocator > const & seedsFrom,
Eigen::Index k,
G & rng,
FitOptions< Scalar > const & options = {} )
nodiscard
Returns
a mixture of at most k Gaussians fitted to particles by weighted EM, seeded by weighted k-means++ over the component means of seedsFrom, which must be in the same space.

Useful when the particles were drawn from seedsFrom: its components summarize the particles and are far fewer, so seeding is cheaper and starts EM closer to the answer. Fails as fitMixture(ParticleSet const &, Eigen::Index, G &, FitOptions const &) does.

◆ multiply() [1/2]

template<Space Space_, RealScalar Scalar_>
InfoGaussianParams< Space_, Scalar_ > Emrys::multiply ( InfoGaussianParams< Space_, Scalar_ > const & first,
InfoGaussianParams< Space_, Scalar_ > const & second )
nodiscard
Returns
the normalized product of the densities first and second, about first's reference: second is moved there (InfoGaussianParams::setReference()) and their precisions and information vectors are added. This is how independent information about one state combines, from two sensors, two factors of a graph, or a prior and a likelihood.

◆ multiply() [2/2]

template<Space Space_, RealScalar Scalar_>
SqrtInfoGaussianParams< Space_, Scalar_ > Emrys::multiply ( SqrtInfoGaussianParams< Space_, Scalar_ > const & first,
SqrtInfoGaussianParams< Space_, Scalar_ > const & second )
nodiscard
Returns
the normalized product of the densities first and second, about first's reference: second is moved there and the two data arrays are stacked and triangularized,

\[ Q^T \begin{bmatrix} R_1 & r_1 \\ R_2 & r_2 \end{bmatrix} = \begin{bmatrix} R & r \\ 0 & e \end{bmatrix}, \]

which gives \( R^T R = R_1^T R_1 + R_2^T R_2 \) without forming either precision. This is the measurement update of Bierman (1977) (Ke et al. (2024), §II), with the second factor as the whitened measurement; \( e \), the residual, is discarded. The stacked array lives in a buffer sized by the difference dimension, so a bounded space allocates nothing.

◆ particleGaussian() [1/2]

template<typename P, Space S, typename Scalar, typename Allocator, typename Covariance = SharedCovariance>
auto Emrys::particleGaussian ( S space,
ParticleSet< typename internal::BlockSplit< S, P >::PinnedSpace, Scalar, Allocator > particles,
GaussianParams< typename internal::BlockSplit< S, P >::RestSpace, Scalar > const & conditional,
Covariance covariance = {} )
nodiscard
Returns
the ParticleGaussianParams with particles of the block named by the path P of a state in space, each with conditional as its Gaussian over the rest, its covariance shared or per particle as Covariance says

◆ particleGaussian() [2/2]

template<typename P, Space S, typename Scalar, typename Allocator, typename Component, typename ModeSpace, typename HybridAllocator>
auto Emrys::particleGaussian ( S space,
ParticleSet< typename internal::BlockSplit< S, P >::PinnedSpace, Scalar, Allocator > particles,
HybridParams< Component, ModeSpace, HybridAllocator > const & conditional )
nodiscard
Returns
the ParticleGaussianParams with particles of the block named by the path P of a state in space, each with the hybrid conditional over the rest, an IMM's state, and so with PerPointCovariance

◆ pivoted()

template<typename... Fallbacks>
auto Emrys::roots::pivoted ( Fallbacks... fallbacks)
nodiscardconstexpr
Returns
Pivoted axes, which cannot fail and so take no fallback

◆ pointGrid() [1/2]

template<typename P, Space S, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid ( S space,
Eigen::MatrixBase< Derived > const & centers,
std::optional< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType > cellCovariance = {},
Allocator const & allocator = {} )
nodiscard
Returns
points for the block named by the path P of a state in space at centers, one per column, with cells (PointCells<P>) numbered in column order, and each cell's covariance about its center cellCovariance (none by default), stored through allocator

◆ pointGrid() [2/2]

template<typename P, Space S, typename Derived, typename Allocator = DefaultAllocator>
auto Emrys::pointGrid ( S space,
Eigen::MatrixBase< Derived > const & centers,
std::span< typename Moments< internal::PathTag< P >, typename Derived::Scalar >::MatrixType const > cellCovariances,
Allocator const & allocator = {} )
nodiscard
Returns
points for the block named by the path P of a state in space at centers, one per column, with cells (PointCells<P>) numbered in column order, and cellCovariances, each cell's covariance about its center, in the same order. The grid needs a PerPointCovariance filter.

◆ predict() [1/2]

template<typename Scalar, typename Space>
CategoricalParams< Space, Scalar > Emrys::predict ( CategoricalParams< Space, Scalar > const & prior,
ContinuousTimeMarkovChain< Space, Scalar > const & chain,
TimeStep< Scalar > auto const & dt )
nodiscard
Returns
prior moved over an interval of dt by chain: \( p' = p\, e^{Q \Delta t} \)

◆ predict() [2/2]

template<typename Scalar, typename Space>
CategoricalParams< Space, Scalar > Emrys::predict ( CategoricalParams< Space, Scalar > const & prior,
MarkovChain< Space, Scalar > const & chain )
nodiscard
Returns
prior moved one step by chain: \( w'_j = \sum_i w_i \Pi_{ij} \), the Chapman-Kolmogorov step of a discrete chain. The rows of \( \Pi \) sum to one, so the weights keep their total, and weights that fail to define a distribution still fail to.

◆ principal()

template<typename... Fallbacks>
auto Emrys::roots::principal ( Fallbacks... fallbacks)
nodiscardconstexpr
Returns
Principal axes, which cannot fail and so take no fallback

◆ regularGrid() [1/2]

template<typename P, Space S, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid ( S space,
Eigen::MatrixBase< FirstDerived > const & first,
Eigen::MatrixBase< SpacingDerived > const & spacing,
std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const & counts,
std::optional< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType > cellCovariance = {},
Allocator const & allocator = {} )
nodiscard
Returns
points on a regular grid for the block named by the path P of a state in space: counts[i] points along axis i, the first at first and the rest spacing apart, with each cell's covariance about its center cellCovariance (none by default). The cells are GridCells<P>, so the probability of each axis is a marginal (marginal<GridAxis<Position, 0>>()). A GridGaussian over the grid allocates through allocator.

◆ regularGrid() [2/2]

template<typename P, Space S, typename FirstDerived, typename SpacingDerived, typename Allocator = DefaultAllocator>
auto Emrys::regularGrid ( S space,
Eigen::MatrixBase< FirstDerived > const & first,
Eigen::MatrixBase< SpacingDerived > const & spacing,
std::array< Eigen::Index, std::size_t(internal::PathTag< P >::FixedValueDimension)> const & counts,
std::span< typename Moments< internal::PathTag< P >, typename FirstDerived::Scalar >::MatrixType const > cellCovariances,
Allocator const & allocator = {} )
nodiscard

regularGrid() with cellCovariances, each cell's covariance about its center in flat-index order, as on a latitude-longitude grid whose cells narrow toward the poles.

The grid needs a PerPointCovariance filter, and can't be subdivided.

◆ ridge()

template<double Relative = 1.0, double Absolute = 0.0>
Ridge< Relative, Absolute > Emrys::roots::ridge ( )
nodiscardconstexpr
Returns
the ridge repair with the margins Relative and Absolute (Ridge): ridge() is the ridge of decisions.md [covariance-repair], and ridge<1.0, 1e-12>() also repairs a zero block

◆ silvermanBandwidth()

template<typename Scalar, typename Space, typename Allocator>
std::expected< typename ParticleSet< Space, Scalar, Allocator >::MatrixType, WeightError > Emrys::silvermanBandwidth ( ParticleSet< Space, Scalar, Allocator > const & particles)
nodiscard
Returns
Silverman's rule-of-thumb bandwidth

\[ H = \left(\frac{4}{N_\mathrm{eff}\,(d + 2)}\right)^{2/(d+4)} \Sigma, \]

where \( \Sigma \) is the particles' weighted covariance, \( d \) their dimension, and \( N_\mathrm{eff} \) their effective sample size; or a WeightError if the weights cannot be normalized.

The normal reference rule of Silverman (1986), as given in Multivariate KDE, for a Gaussian kernel with the data's covariance as its shape, with the effective sample size in place of the sample count for weighted particles. Near-optimal for roughly Gaussian particle clouds; scale it down for multimodal ones.

◆ squareRoot()

template<Axes A, typename Derived>
auto Emrys::roots::squareRoot ( A const & axes,
Eigen::MatrixBase< Derived > const & cov )
nodiscard
Returns
a root \( S \), \( S S^T = P \), of the covariance cov, of which only the lower triangle is read, by axes (Axes): the root, or, when axes can fail, a std::expected of it with the GaussianError of the last entry tried. Square with cov's rows and its bounds, so that a bounded covariance allocates nothing.
auto const s = roots::squareRoot(roots::cholesky(roots::pivoted()), cov); // a matrix
auto const t = roots::squareRoot(roots::cholesky(), cov); // a std::expected
constexpr auto cholesky(Fallbacks... fallbacks)
Definition Roots.h:1174
auto squareRoot(A const &axes, Eigen::MatrixBase< Derived > const &cov)
Definition Roots.h:1271
constexpr auto pivoted(Fallbacks... fallbacks)
Definition Roots.h:1184
See also
squareRootWithReport()

◆ squareRootWithReport()

template<Axes A, typename Derived>
auto Emrys::roots::squareRootWithReport ( A const & axes,
Eigen::MatrixBase< Derived > const & cov )
nodiscard
Returns
the root of squareRoot() with a report of what axes did (RootWithReport): the pivots or eigenvalues clamped, the ridge added, or a report of the user's own, and for a fallback list which entry succeeded. When axes can fail, a std::expected of it, whose error is a RootFailure with the error and each entry's report. Transforms and filters carry no reports: a caller diagnosing one calls this on the same covariance with the same axes.

◆ stationary() [1/2]

template<typename Scalar, typename Space>
std::expected< CategoricalParams< Space, Scalar >, ChainError > Emrys::stationary ( ContinuousTimeMarkovChain< Space, Scalar > const & chain)
nodiscard
Returns
the stationary distribution of chain, the probabilities \( \pi \) that no interval changes, \( \pi Q = 0 \), and the stationary distribution of its transition over any interval: the prior for a mode that has run long before the first measurement. It exists and is unique when every value can be reached from every other, and otherwise is ChainError::Reducible. It is computed as the discrete chain's is, by the algorithm of Grassmann, Taksar, and Heyman (1985), which reads only the rates off the diagonal.

◆ stationary() [2/2]

template<typename Scalar, typename Space>
std::expected< CategoricalParams< Space, Scalar >, ChainError > Emrys::stationary ( MarkovChain< Space, Scalar > const & chain)
nodiscard
Returns
the stationary distribution of chain, the probabilities \( \pi \) that one step leaves as they are, \( \pi \Pi = \pi \): the distribution the chain settles into from any start, and the prior for a mode that has run long before the first measurement. It exists and is unique when every value can be reached from every other, and otherwise is ChainError::Reducible. It is computed by the algorithm of Grassmann, Taksar, and Heyman (1985), which keeps every digit when the chain stays a long time at each value, as \( \pi (\Pi - I) = 0 \) solved directly doesn't.

◆ symmetric()

template<typename... Fallbacks>
auto Emrys::roots::symmetric ( Fallbacks... fallbacks)
nodiscardconstexpr
Returns
Symmetric axes, which cannot fail and so take no fallback

◆ toGaussian()

template<GaussianForm G>
std::expected< GaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toGaussian ( G const & form)
nodiscard
Returns
form in the covariance form: its mean and covariance() in a Gaussian in the same space, or the GaussianError of either.

An information form's covariance lives in the differences at its reference, a Gaussian's at its mean, so on a space with a reset Jacobian the covariance is carried from the one to the other by resetCovariance() (decisions.md [covariance-reset]); where the reset is the identity, as on a space of plain, periodic, and bounded blocks, nothing moves.

See also
toSqrt(), toInfo(), toSqrtInfo()

◆ toInfo()

template<GaussianForm G>
std::expected< InfoGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toInfo ( G const & form)
nodiscard
Returns
form in the information form, or the GaussianError of the accessors it reads.

A covariance form gives an InfoGaussianParams about its mean, with \( \eta = 0 \) and its precision(). An information form keeps its reference and gives its precision() and its infoVector().

See also
toGaussian(), toSqrt(), toSqrtInfo()

◆ toSqrt()

template<GaussianForm G>
std::expected< SqrtGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toSqrt ( G const & form)
nodiscard
Returns
form in the square-root form: its mean and a lower-triangular root of its covariance in a SqrtGaussianParams in the same space, or the GaussianError of either.

The root is covarianceRoot() itself in the covariance forms, which have it lower triangular already. An information form gives \( R^{-1} \), upper triangular, which triangularize() turns into the lower-triangular root of the same covariance without forming it; and since that covariance lives at the form's reference, on a space with a reset Jacobian \( G \) the root is carried to the mean as \( \mathrm{tri}(G S) \) (decisions.md [covariance-reset], as toGaussian() carries the covariance).

See also
toGaussian(), toInfo(), toSqrtInfo()

◆ toSqrtInfo()

template<GaussianForm G>
std::expected< SqrtInfoGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > Emrys::toSqrtInfo ( G const & form)
nodiscard
Returns
form in the square-root information form, or the GaussianError of the accessors it reads.

A covariance form gives the form about its mean with \( r = 0 \) and \( R \) from triangularizing its precisionRoot(), which is lower triangular there. InfoGaussianParams keeps its reference and gives its upper-triangular precisionRoot() and \( r = R^{-T} \eta \), so it fails while its precision is singular, though the target form could hold that.

See also
toGaussian(), toSqrt(), toInfo()

◆ uniformComponents() [1/2]

template<Space S, RealScalar Scalar, typename... Factors, typename CountsDerived>
requires std::integral<typename CountsDerived::Scalar>
UniformGrid< S, Scalar > Emrys::uniformComponents ( Product< S, Scalar, Factors... > const & product,
Eigen::DenseBase< CountsDerived > const & counts,
std::type_identity_t< Scalar > relativeWidth = Scalar(0.6) )
nodiscard
Returns
the components, one at a time, of a mixture in product's space that is uniform over the blocks of its Uniform factors and Gaussian over the rest: the Uniform factors' coordinates gridded as uniformComponents(Uniform const &, Eigen::DenseBase const &, Scalar) grids a Uniform's, and every component given each Gaussian factor's mean and covariance on its block.

A state that starts somewhere in a box with a velocity known to a Gaussian:

prior.assign(uniformComponents(Product{State{}, on<Position>(box), on<Velocity>(velocity)}, Eigen::Array2i{8, 8}));
MixtureParams< Gaussian< Space_, Scalar_ >, Allocator_ > GaussianMixtureParams
A Mixture of Gaussians in covariance form, the spelling for the common case (decisions....
Definition Mixture.h:2072
UniformGrid< S, Scalar > uniformComponents(Uniform< S, Scalar > const &uniform, Eigen::DenseBase< CountsDerived > const &counts, std::type_identity_t< Scalar > relativeWidth=Scalar(0.6))
Definition UniformMixture.h:362
auto on(Model const &model, Renames const &...)
Definition Placement.h:1067

The factors are Uniform factors placed with on<Path>(), and GaussianParams factors placed with on<Path>() or onEach<Path>(). counts holds one count per coordinate of the Uniform factors, in the order of the space's coordinates, and the first of them varies fastest. The blocks are independent in every component, as they are in product.

See also
uniformComponents(Product const &, Eigen::Index, Scalar), UniformGrid, Product

◆ uniformComponents() [2/2]

template<Space S, RealScalar Scalar, typename CountsDerived>
requires std::integral<typename CountsDerived::Scalar>
UniformGrid< S, Scalar > Emrys::uniformComponents ( Uniform< S, Scalar > const & uniform,
Eigen::DenseBase< CountsDerived > const & counts,
std::type_identity_t< Scalar > relativeWidth = Scalar(0.6) )
nodiscard
Returns
the components that approximate uniform, one at a time: counts(i) along coordinate i, \( \prod_i N_i \) in all, with equal weights, which GaussianMixtureParams::assign() puts in a mixture.

Coordinate \( i \)'s interval, from \( \ell_i \) with width \( w_i \), is cut into \( N_i \) cells of width \( s_i = w_i / N_i \), and a component sits at the center of each cell, \( \ell_i + (j + \tfrac12) s_i \), normalized in the mixture's space. Every component has the covariance \( \mathrm{diag}(c^2 s_i^2) \), where \( c \) is relativeWidth.

The width trades flatness against moments. By Poisson summation, along one coordinate the components sum to \( 1 / w \) times \( 1 + 2 \sum_{m \ge 1} e^{-2 \pi^2 c^2 m^2} \cos(2 \pi m u) \), where \( u \) is the offset from a center in cells, so the relative ripple inside the box is about \( \pm 2 e^{-2 \pi^2 c^2} \) per coordinate:

\( c \) ripple
\( 1 / \sqrt{12} \approx 0.29 \) \( \pm 39\% \) matches the moments
0.5 \( \pm 1.4\% \)
0.6 \( \pm 0.16\% \) the default
0.7 \( \pm 0.01\% \)

With \( c = 1 / \sqrt{12} \) the mixture's mean and covariance are the box's: the centers spread \( (N_i^2 - 1) s_i^2 / 12 \) and each component adds \( s_i^2 / 12 \), together \( w_i^2 / 12 \). A wider component flattens the density but adds \( c^2 s_i^2 \) to the variance in place of \( s_i^2 / 12 \). Near a face of the box the density falls to about half its interior value over a distance of a few \( c s_i \), whatever the width.

A Periodic coordinate's interval over a whole period has no faces: the components wrap round and the density only ripples. Each component's density is not wrapped, though (a Gaussian in the tangent space), so keep at least six components per period, which leaves every component's mass beyond half a period below \( 10^{-6} \) at the default width.

The components are in uniform's space.

See also
UniformGrid, uniformComponents(Uniform const &, Eigen::Index, Scalar), uniformComponents(Product const &, Eigen::DenseBase const &, Scalar), Uniform

◆ withFallbacks()

template<typename Head, typename First, typename... Rest>
WithFallbacks< Head, First, Rest... > Emrys::roots::withFallbacks ( Head axes,
First first,
Rest... rest )
nodiscardconstexpr
Returns
the axes axes, which can fail, followed by fallbacks (WithFallbacks): what the library's factories do for their own axes, for axes of the user's own, withFallbacks(MyAxes{}, ridge(), pivoted())

Variable Documentation

◆ isInfoForm

template<GaussianForm G>
bool Emrys::isInfoForm = G::IsInfoForm
inlineconstexpr

Whether the GaussianForm G holds the precision, as InfoGaussianParams and SqrtInfoGaussianParams do, rather than the covariance.

Its roots are then upper triangular, and its mean is a solve that fails while the precision is singular.