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:
ABCDraws 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:
- abstractmethod sample(size=None, *, batched=True)[source]
Draw observations.
Combinator samplers (mixture/sequence/…) accept
batched. Withbatched=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 independentRandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path.batched=Falseforces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.
- class ConditionalSampler[source]
Bases:
ABCSampler mixin for conditional draws: sample_given(x) draws from P(. | x).
- abstractmethod sample_given(x)[source]
- class DistributionEnumerator(dist)[source]
Bases:
ABCLazy 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).
- 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.95gives a 95%-coverage support set – the discrete analogue of nucleus sampling). Accumulation stops as soon as the cumulative probability reachesp.max_itemscaps 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.0on an infinite support therefore requiresmax_items.
- 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.
- rank(value)[source]
Rank and cumulative probability of
valuein the descending-probability order.Returns a
DensityRankResultwith.rank(0-based count of strictly-more-probable outcomes;Noneif 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 ofrank().Returns a
CountDPSeekResultcarrying 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
indexwith 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’stropical_displacement_bitsand divides out the component over-count, so the returnedMarginalSeekResult[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 withseek().- Parameters:
index (int)
- cumulative(value)[source]
G(value) = P(p(Y) >= p(value))– total mass of outcomes at least as probable asvalue.- Parameters:
value (Any)
- nucleus_size(p)[source]
Size of
top_p()(the minimal>= p-mass set) WITHOUT materializing it.Returns a
CountDPTopPResultwith 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 structuralstart.Yields the same stream as iterating a fresh enumerator but beginning at index
start(and ending beforestopif given). A fresh underlying enumeration is used, so this does not consumeself. (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.)
- class ParameterEstimator[source]
-
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.
- classmethod from_dict(payload)[source]
Reconstruct an estimator from
to_dictoutput.
- to_json(**kwargs)[source]
Serialize this estimator as safe strict JSON.
- classmethod from_json(text)[source]
Deserialize an estimator from
to_jsonoutput.- 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 toFalseso stacked/generated kernels fall back to the host accumulator, keeping every backend’s fixed point identical.- Return type:
- 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:
Nonegives maximum likelihood, a conjugate prior gives the Bayesian posterior update insideestimate. The default reads thepriorattribute (Nonewhen 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 is0.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:
- class StatisticAccumulator[source]
-
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.
- initialize(x, weight, rng)[source]
- Parameters:
x (Any)
weight (float)
rng (RandomState)
- 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_dictunder its merge key.The structural default implements the common single-key pattern: store the accumulator under
self.keysthe first time the key is seen, elsecombineinto 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. AkeysofNone(the default) is a no-op.
- 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:
weights (ndarray)
rng (RandomState)
- Return type:
None
- abstractmethod acc_to_encoder()[source]
- Return type:
DataSequenceEncoder
- class StatisticAccumulatorFactory[source]
Bases:
ABCFactory whose make() returns a fresh, zeroed accumulator for one estimator.
- abstractmethod make()[source]
- Return type:
SequenceEncodableStatisticAccumulator
- class DataSequenceEncoder[source]
Bases:
ABCEncodes 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.
- class Enumerable[source]
Bases:
PredicateCapabilityIts support can be iterated in descending-probability order (
enumerator()works).
- class FiniteSupport[source]
Bases:
PredicateCapabilityHas a finite number of distinct support points (
support_size()is an int).
- class RankableByIndex[source]
Bases:
PredicateCapabilitySupports 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 ==> rankableis 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.)
- class ExponentialFamily[source]
Bases:
PredicateCapabilityDeclares an exponential-family form (generated stacked kernels + conjugate estimation).
- class ConjugateUpdatable[source]
Bases:
PredicateCapabilityHas a closed-form conjugate Bayesian update (the top tier of the inference ladder).
supports(x, ConjugateUpdatable)is True iffconjugate_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 singleconjugate_posteriorregistry.
- class Conditionable(*args, **kwargs)[source]
Bases:
ProtocolSupports conditioning on a subset of coordinates:
condition(observed) -> distribution.
- class Marginalizable(*args, **kwargs)[source]
Bases:
ProtocolSupports marginalising to a subset of coordinates:
marginal(keep) -> distribution.
- class LatentStructured(*args, **kwargs)[source]
Bases:
ProtocolExposes an explicit latent posterior q(z|x):
latent_posterior(x) -> LatentPosterior.
- class PosteriorPredictive(*args, **kwargs)[source]
Bases:
ProtocolCan draw/score new data conditioned on an observation’s inferred latent state.
- class TemporalPointProcess(*args, **kwargs)[source]
Bases:
ProtocolAn 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]
- class SetValued[source]
Bases:
PredicateCapabilityA distribution over sets with forced/required membership (
required/num_required).
- class Neutral[source]
Bases:
PredicateCapabilityThe identity / no-op element of a combinator (a Null distribution, accumulator, or encoder).
- class Transform(*args, **kwargs)[source]
Bases:
ProtocolAn invertible change of variables with a tractable Jacobian (combinator/transform.py).
- class EngineResidentEStep(*args, **kwargs)[source]
Bases:
ProtocolAn accumulator that can run its E-step on the active compute engine without leaving it.
- class SupportsBackendScoring(*args, **kwargs)[source]
Bases:
ProtocolA distribution that can score a batch directly on the active engine (
backend_seq_log_density).
- class SupportsBackendComponentScoring(*args, **kwargs)[source]
Bases:
ProtocolA distribution that exposes per-component engine scoring (
backend_seq_component_log_density).