mixle.stats.latent.probabilistic_circuit module¶
Probabilistic circuits (sum-product networks) – a tractable deep model that scores in integer log-space.
A probabilistic circuit is a DAG of sum nodes (mixtures, with weights), product nodes (independent
factorizations over disjoint variable scopes), and leaf distributions over a scope. When it is
decomposable (a product’s children have pairwise-disjoint scopes) and smooth (a sum’s children share
one scope) the density is exact and inference is linear in the circuit size – the appeal over an
intractable deep net. Every node is a sum or a product of probabilities, so the whole forward pass runs in
mixle’s logarithmic number system: products become integer ADDs, sums become integer logsumexp (the
compiled max+LUT kernel), and leaf log-densities are quantized – a transcendental-free deep forward pass.
This is the model class where the LNS is a complete fit (not just the normalizer). v1 takes a
user-supplied structure (build it with leaf() / prod() / summ()) and learns the per-leaf
parameters and per-sum log-weights by EM; structure learning is a later phase that emits the same DAG.
- leaf(scope, dist)[source]
A leaf node: an existing mixle
distover the variable indicesscope(an int or a tuple).
- prod(children)[source]
A product node over children with PAIRWISE-DISJOINT scopes (the decomposability requirement).
- Parameters:
children (list[_Node])
- Return type:
_Node
- summ(children, w=None)[source]
A sum (mixture) node over children that share ONE scope (smoothness);
ware mixing weights.
- class ProbabilisticCircuitDistribution(root, num_vars, lns_step=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA sum-product network density; build with
leaf()/prod()/summ()then pass the root.- log_density(x)[source]
Return the log-density or log-mass at a single observation.
- seq_log_density(x)[source]
Return vectorized log-density values for sequence-encoded observations.
- dist_to_encoder()[source]
Return the data encoder used by this distribution for vectorized methods.
- Return type:
ProbabilisticCircuitEncoder
- sampler(seed=None)[source]
Return a sampler for drawing observations from this distribution.
- Parameters:
seed (int | None)
- Return type:
ProbabilisticCircuitSampler
- estimator(pseudo_count=None)[source]
Return an estimator for fitting this distribution from data.
- class ProbabilisticCircuitEncoder(leaf_dists, leaf_scope)[source]
Bases:
DataSequenceEncoderEncode each leaf’s projected columns once with the leaf’s own encoder (shared across EM iterations).
- class ProbabilisticCircuitSampler(dist, seed=None)[source]
Bases:
DistributionSamplerAncestral top-down sampling: a sum draws one child by its weights, a product recurses into all.
- Parameters:
dist (ProbabilisticCircuitDistribution)
seed (int | None)
- sample(size=None)[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 ProbabilisticCircuitAccumulator(nodes, leaf_scope, leaf_estimators)[source]
Bases:
SequenceEncodableStatisticAccumulatorE-step sufficient statistics: per-sum-node expected child counts + per-leaf weighted statistics.
The E-step is the circuit FLOW (Peharz et al. EM-for-SPNs): an upward forward gives each node’s log-value, a downward pass gives each node’s log-context
lc= derivative of the root log-density w.r.t. that node (the posterior the node is active). A sum node’s per-child responsibility is thenexp(lc[sum] + value[child] + log_w - value[sum])(its expected count), and a leaf’s responsibility isexp(lc[leaf])(the weight for its sufficient statistic).- seq_update(enc, weights, estimate)[source]
- update(x, weight, estimate)[source]
- initialize(x, weight, rng)[source]
- Parameters:
x (Any)
weight (float)
rng (RandomState)
- Return type:
None
- seq_initialize(enc, weights, rng)[source]
- Parameters:
weights (Any)
rng (RandomState)
- Return type:
None
- 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:
ProbabilisticCircuitAccumulator
- 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.
- key_replace(stats_dict)[source]
Replace this accumulator’s statistics from the pooled
stats_dictentry (see key_merge).
- acc_to_encoder()[source]
- Return type:
ProbabilisticCircuitEncoder
- class ProbabilisticCircuitAccumulatorFactory(nodes, leaf_scope, leaf_estimators)[source]
Bases:
StatisticAccumulatorFactory- make()[source]
- Return type:
ProbabilisticCircuitAccumulator
- class ProbabilisticCircuitEstimator(dist, pseudo_count=None)[source]
Bases:
ParameterEstimatorFits a fixed-structure circuit by EM: renormalize each sum node’s weights to its expected child counts, and re-estimate each leaf from its responsibility-weighted sufficient statistic.
- Parameters:
dist (ProbabilisticCircuitDistribution)
pseudo_count (float | None)
- accumulator_factory()[source]
- Return type:
ProbabilisticCircuitAccumulatorFactory