mixle.contracts module

mixle.contracts — every contract (ABC / Protocol) in one import.

The capability vocabulary was correct but spread across several modules (capability, pdist, relations, engines.base, planner, utils.em, doe._contracts). This module gathers them so the whole contract surface has one home:

from mixle.contracts import Distribution, Enumerable, Conditionable, Relation, ComputeEngine, Surrogate, EMStrategy

The light contracts (the object cast + the capability protocols) are imported eagerly; the heavier subsystem roles are resolved lazily (PEP 562 __getattr__) so this stays a cheap leaf import with no cycles. See docs/ARCHITECTURE.md.

Distribution

alias of SequenceEncodableProbabilityDistribution

class DistributionSampler(dist, seed=None, *, rng=None)[source]

Bases: ABC

Draws iid observations from a distribution using a seeded RandomState.

sample(size=None) returns a single observation of the distribution’s data type; sample(size=n) returns a length-n collection of observations.

Parameters:
  • dist (SequenceEncodableProbabilityDistribution)

  • seed (int | None)

  • rng (RandomState | None)

new_seed()[source]

Return a fresh random seed drawn from this sampler’s RandomState.

Return type:

int

abstractmethod sample(size=None, *, batched=True)[source]

Draw observations.

Combinator samplers (mixture/sequence/…) accept batched. With batched=True (the default) each child stream is drawn in one vectorized call instead of a per-draw Python loop – far faster. Because every child sampler owns an independent RandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path. batched=False forces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.

Parameters:
Return type:

Any

class ConditionalSampler[source]

Bases: ABC

Sampler mixin for conditional draws: sample_given(x) draws from P(. | x).

abstractmethod sample_given(x)[source]
class DistributionEnumerator(dist)[source]

Bases: ABC

Lazy iterator over the support of dist in non-increasing probability order.

Yields (value, log_prob) pairs, possibly infinitely many. Contract:
  • Each support value is yielded exactly once (deduplication is the enumerator’s responsibility).

  • log_prob equals dist.log_density(value) up to float round-off (~1e-10), and the sequence of log_probs is non-increasing up to the same tolerance.

  • Values with zero probability are skipped, never yielded.

  • Ties are broken deterministically by insertion order; no further guarantee.

Parameters:

dist (SequenceEncodableProbabilityDistribution)

top_k(k)[source]

Return the k most probable (value, log_prob) pairs (fewer if the support is smaller).

Parameters:

k (int)

Return type:

list[tuple[Any, float]]

top_p(p, max_items=None)[source]

Return the smallest descending-probability prefix whose total probability reaches p.

The nucleus / minimal high-probability set: because values are yielded in non-increasing probability order, the returned prefix is a minimum-size set of outcomes whose summed mass is >= p (e.g. p=0.95 gives a 95%-coverage support set – the discrete analogue of nucleus sampling). Accumulation stops as soon as the cumulative probability reaches p.

max_items caps how many values are pulled so an infinite or heavy-tailed support cannot run away; if the cap is hit before the threshold, the (sub-threshold) prefix gathered so far is returned. p >= 1.0 on an infinite support therefore requires max_items.

Parameters:
  • p (float) – Target cumulative probability; p <= 0 returns the empty set.

  • max_items (Optional[int]) – Hard cap on the number of values pulled.

Returns:

List of (value, log_prob) pairs in non-increasing probability order.

Return type:

list[tuple[Any, float]]

quantized_index(max_bits, bin_width_bits=1.0)[source]

Precompute a bounded bit-quantized index over this enumeration.

The index groups values by floor((-log2 p(x)) / bin_width_bits), includes only values with -log2 p(x) <= max_bits, and returns exact log probabilities for indexed values. Building the index consumes this enumerator.

Parameters:
  • max_bits (float) – Maximum information content in bits to index.

  • bin_width_bits (float) – Width of each quantized probability bin in bits.

Returns:

mixle.enumeration.algorithms.QuantizedEnumerationIndex.

rank(value)[source]

Rank and cumulative probability of value in the descending-probability order.

Returns a DensityRankResult with .rank (0-based count of strictly-more-probable outcomes; None if only the sampling estimate was used) and .cumulative_probability (G(value) = P(p(Y) >= p(value))). Exact head enumeration where the support is countable, with a Monte-Carlo fallback for the deep tail.

Parameters:

value (Any)

seek(index)[source]

The value at descending-probability index (0-based) – the inverse of rank().

Returns a CountDPSeekResult carrying the value and a provable [rank_lower, rank_upper] bracket. Uses the structural count-DP for decomposable families, so arbitrarily deep indices are reachable without enumerating the prefix.

Parameters:

index (int)

seek_certified(index)[source]

The value at descending index with a GUARANTEED bracket on its TRUE marginal rank.

Unlike seek() – whose bracket bounds only the tropical rank for a marginal family (mixture/HMM) – this widens the rank window by the family’s tropical_displacement_bits and divides out the component over-count, so the returned MarginalSeekResult [true_rank_lower, true_rank_upper] provably contains #{u : log p(u) > log p(value)}. It pins the rank exactly (.exact) for decomposable / provably-disjoint families and for shallow indices, and otherwise returns the honest provable envelope. For a decomposable family it agrees with seek().

Parameters:

index (int)

cumulative(value)[source]

G(value) = P(p(Y) >= p(value)) – total mass of outcomes at least as probable as value.

Parameters:

value (Any)

nucleus_size(p)[source]

Size of top_p() (the minimal >= p-mass set) WITHOUT materializing it.

Returns a CountDPTopPResult with a provable size bracket, from the structural count-DP – usable when the nucleus is far too large to list.

Parameters:

p (float)

from_index(start, stop=None)[source]

Iterate (value, log_prob) in descending-probability order starting at structural start.

Yields the same stream as iterating a fresh enumerator but beginning at index start (and ending before stop if given). A fresh underlying enumeration is used, so this does not consume self. (Decomposable families admit a direct structural jump via the count-budget index; the current implementation skips the best-first prefix – the structural fast path is a WS-3 performance follow-up.)

Parameters:
  • start (int)

  • stop (int | None)

class ParameterEstimator[source]

Bases: ABC, Generic[SS]

Estimates a distribution from accumulated sufficient statistics.

accumulator_factory() supplies accumulators that gather sufficient statistics of type SS, and estimate(nobs, suff_stat) maps those statistics (plus optional regularization configured on the estimator) to a new distribution.

to_dict()[source]

Return a safe JSON-compatible representation of this estimator.

Return type:

dict[str, Any]

classmethod from_dict(payload)[source]

Reconstruct an estimator from to_dict output.

Parameters:

payload (dict[str, Any])

Return type:

ParameterEstimator

to_json(**kwargs)[source]

Serialize this estimator as safe strict JSON.

Parameters:

kwargs (Any)

Return type:

str

classmethod from_json(text)[source]

Deserialize an estimator from to_json output.

Parameters:

text (str)

Return type:

ParameterEstimator

abstractmethod estimate(nobs, suff_stat)[source]
Parameters:
  • nobs (float | None)

  • suff_stat (SS)

Return type:

SequenceEncodableProbabilityDistribution

abstractmethod accumulator_factory()[source]
Return type:

StatisticAccumulatorFactory

resident_accumulation_supported()[source]

Return whether engine-resident (fixed-width) sufficient statistics suffice for estimate.

Most exponential-family M-steps consume only the resident sufficient statistics, so the default is True. Estimators whose M-step needs more than that (e.g. a full count histogram for the negative-binomial dispersion solve) override this to False so stacked/generated kernels fall back to the host accumulator, keeping every backend’s fixed point identical.

Return type:

bool

get_prior()[source]

Return the parameter prior configured on this estimator, if any.

The unified estimation contract treats the prior as the single regularization concept: None gives maximum likelihood, a conjugate prior gives the Bayesian posterior update inside estimate. The default reads the prior attribute (None when unset).

Return type:

ProbabilityDistribution | None

model_log_density(model)[source]

Return the prior log-density of model’s parameters (the ELBO global term).

Used by the variational/MAP objective in fit. The default is 0.0 (no prior); conjugate estimators override this to evaluate their prior at the model’s parameters, mapping to the prior’s parameterization first.

Parameters:

model (ProbabilityDistribution)

Return type:

float

class StatisticAccumulator[source]

Bases: ABC, Generic[SS]

Accumulates weighted sufficient statistics of type SS from observations.

update(x, weight, estimate) adds one observation (estimate is the previous model, used for E-step posteriors; it may be None during initialization). Accumulators merge across partitions via combine(suff_stat) / value() / from_value(), and key_merge / key_replace pool statistics shared across model components through a stats_dict keyed by the accumulator’s key.

update(x, weight, estimate)[source]
Parameters:
Return type:

None

initialize(x, weight, rng)[source]
Parameters:
Return type:

None

abstractmethod combine(suff_stat)[source]
Parameters:

suff_stat (SS)

Return type:

StatisticAccumulator

abstractmethod value()[source]
Return type:

SS

abstractmethod from_value(x)[source]
Parameters:

x (SS)

Return type:

SequenceEncodableStatisticAccumulator

scale(c)[source]

Scale linear sufficient statistics in-place by c.

The structural default is correct for ordinary weighted sums, nested tuples/lists/dicts, and numeric arrays. Families whose value() payload includes non-linear metadata such as support bounds must override this method and leave that metadata unscaled.

Parameters:

c (float)

Return type:

StatisticAccumulator

key_merge(stats_dict)[source]

Pool this accumulator’s statistics into stats_dict under its merge key.

The structural default implements the common single-key pattern: store the accumulator under self.keys the first time the key is seen, else combine into the one already there. Accumulators with several named keys (e.g. an HMM’s init/trans/state keys) or a non-accumulator stats payload override this. A keys of None (the default) is a no-op.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

key_replace(stats_dict)[source]

Replace this accumulator’s statistics from the pooled stats_dict entry (see key_merge).

Parameters:

stats_dict (dict[str, Any])

Return type:

None

class SequenceEncodableStatisticAccumulator[source]

Bases: StatisticAccumulator[SS]

StatisticAccumulator with vectorized updates on encoded data sequences.

seq_update / seq_initialize consume the output of the matching DataSequenceEncoder’s seq_encode() (obtained via acc_to_encoder()) together with a per-observation weight vector.

get_seq_lambda()[source]
abstractmethod seq_update(x, weights, estimate)[source]
Parameters:

weights (ndarray)

Return type:

None

abstractmethod seq_initialize(x, weights, rng)[source]
Parameters:
Return type:

None

abstractmethod acc_to_encoder()[source]
Return type:

DataSequenceEncoder

class StatisticAccumulatorFactory[source]

Bases: ABC

Factory whose make() returns a fresh, zeroed accumulator for one estimator.

abstractmethod make()[source]
Return type:

SequenceEncodableStatisticAccumulator

class DataSequenceEncoder[source]

Bases: ABC

Encodes an iid data sequence into the vectorized form used by seq_* methods.

seq_encode(x) transforms a sequence of observations into the encoding consumed by seq_log_density / seq_update / seq_initialize. Encoders must define __eq__ (so equivalent encoders are interchangeable when batching) and a readable __str__.

seq_encode(x)[source]

Encode the iid observation sequence x for vectorized evaluation.

Parameters:

x (Any)

Return type:

Any

nbytes(x)[source]

Return the approximate in-memory byte size of an encoded payload.

Parameters:

x (Any)

Return type:

int

class Enumerable[source]

Bases: PredicateCapability

Its support can be iterated in descending-probability order (enumerator() works).

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class FiniteSupport[source]

Bases: PredicateCapability

Has a finite number of distinct support points (support_size() is an int).

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class RankableByIndex[source]

Bases: PredicateCapability

Supports random access by integer rank (unranking) via the count-budget seek index.

Finite-support enumerables are rankable by index through the count-DP semiring; the implication edge finite ==> enumerable ==> rankable is exactly this composition. (Decomposable combinators over infinite-but-countable children are also rankable structurally; this conservative check covers the finite-leaf case used by the dispatch layers.)

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class ExponentialFamily[source]

Bases: PredicateCapability

Declares an exponential-family form (generated stacked kernels + conjugate estimation).

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class ConjugateUpdatable[source]

Bases: PredicateCapability

Has a closed-form conjugate Bayesian update (the top tier of the inference ladder).

supports(x, ConjugateUpdatable) is True iff conjugate_posterior(x, data) returns an exact closed-form posterior; otherwise Bayesian inference falls back to the numerical fitters (MAP / Laplace / MCMC / VI). Detection is the single conjugate_posterior registry.

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class Conditionable(*args, **kwargs)[source]

Bases: Protocol

Supports conditioning on a subset of coordinates: condition(observed) -> distribution.

condition(observed)[source]
Parameters:

observed (dict[int, float])

Return type:

Any

class Marginalizable(*args, **kwargs)[source]

Bases: Protocol

Supports marginalising to a subset of coordinates: marginal(keep) -> distribution.

marginal(keep)[source]
Parameters:

keep (Any)

Return type:

Any

class LatentStructured(*args, **kwargs)[source]

Bases: Protocol

Exposes an explicit latent posterior q(z|x): latent_posterior(x) -> LatentPosterior.

latent_posterior(x)[source]
Parameters:

x (Any)

Return type:

Any

class PosteriorPredictive(*args, **kwargs)[source]

Bases: Protocol

Can draw/score new data conditioned on an observation’s inferred latent state.

posterior_predictive(*args, **kwargs)[source]
Parameters:
Return type:

Any

class TemporalPointProcess(*args, **kwargs)[source]

Bases: Protocol

An event-time point process exposing its conditional intensity and compensator.

intensity(t, times, marks=None) is the conditional rate lambda(t) given the history; the univariate Hawkes / inhomogeneous-Poisson leaves return a float, the multivariate variant a per-mark vector. expected_count(t_start, t_end, times, marks=None) is the integrated intensity (compensator) over the window. (Birth-death is a population process, not an intensity-based point process, and is intentionally excluded.)

intensity(t, times, marks=None)[source]
Parameters:
Return type:

Any

expected_count(t_start, t_end, times, marks=None)[source]
Parameters:
Return type:

Any

class SetValued[source]

Bases: PredicateCapability

A distribution over sets with forced/required membership (required / num_required).

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class Neutral[source]

Bases: PredicateCapability

The identity / no-op element of a combinator (a Null distribution, accumulator, or encoder).

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool

class Transform(*args, **kwargs)[source]

Bases: Protocol

An invertible change of variables with a tractable Jacobian (combinator/transform.py).

forward(x)[source]
Parameters:

x (Any)

Return type:

Any

inverse(y)[source]
Parameters:

y (Any)

Return type:

Any

log_abs_det_inverse_jacobian(y)[source]
Parameters:

y (Any)

Return type:

float

class EngineResidentEStep(*args, **kwargs)[source]

Bases: Protocol

An accumulator that can run its E-step on the active compute engine without leaving it.

seq_update_engine(enc, weights, estimate, engine)[source]
Parameters:
Return type:

None

class SupportsBackendScoring(*args, **kwargs)[source]

Bases: Protocol

A distribution that can score a batch directly on the active engine (backend_seq_log_density).

backend_seq_log_density(x, engine)[source]
Parameters:
Return type:

Any

class SupportsBackendComponentScoring(*args, **kwargs)[source]

Bases: Protocol

A distribution that exposes per-component engine scoring (backend_seq_component_log_density).

backend_seq_component_log_density(x, engine)[source]
Parameters:
Return type:

Any

class SupportsStackedBackend(*args, **kwargs)[source]

Bases: Protocol

A component type that can score/parameterise a homogeneous stack on the engine.

backend_stacked_params(dists, engine)[source]
Parameters:
Return type:

Any

backend_stacked_log_density(x, params, engine)[source]
Parameters:
Return type:

Any

class PredicateCapability[source]

Bases: object

Base for capabilities determined by inspecting the object rather than a method name.

classmethod check(obj)[source]
Parameters:

obj (Any)

Return type:

bool