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 dist over the variable indices scope (an int or a tuple).

Parameters:
Return type:

_Node

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); w are mixing weights.

Parameters:
Return type:

_Node

class ProbabilisticCircuitDistribution(root, num_vars, lns_step=None)[source]

Bases: SequenceEncodableProbabilityDistribution

A sum-product network density; build with leaf()/prod()/summ() then pass the root.

Parameters:
  • root (_Node)

  • num_vars (int)

  • lns_step (float | None)

log_density(x)[source]

Return the log-density of one full observation by an upward circuit pass.

Parameters:

x (Any)

Return type:

float

seq_log_density(x)[source]

Return vectorized log-densities for encoded observations.

Parameters:

x (Any)

Return type:

ndarray

dist_to_encoder()[source]

Return the encoder that projects observations into each leaf scope.

Return type:

ProbabilisticCircuitEncoder

sampler(seed=None)[source]

Return an ancestral sampler for this fixed circuit.

Parameters:

seed (int | None)

Return type:

ProbabilisticCircuitSampler

estimator(pseudo_count=None)[source]

Return an EM estimator for this fixed circuit structure.

Parameters:

pseudo_count (float | None)

Return type:

Any

with_params(new_nodes, new_leaf_dists)[source]

A new circuit with the same structure but re-estimated sum-weights / leaf parameters (M-step output).

Parameters:
Return type:

ProbabilisticCircuitDistribution

class ProbabilisticCircuitEncoder(leaf_dists, leaf_scope)[source]

Bases: DataSequenceEncoder

Encode each leaf’s projected columns once with the leaf’s own encoder (shared across EM iterations).

Parameters:
seq_encode(x)[source]

Encode a batch for every leaf distribution using its projected scope.

Parameters:

x (Any)

Return type:

dict[int, Any]

class ProbabilisticCircuitSampler(dist, seed=None)[source]

Bases: DistributionSampler

Ancestral 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 one observation or size iid observations from the circuit.

Parameters:

size (int | None)

Return type:

Any

class ProbabilisticCircuitAccumulator(nodes, leaf_scope, leaf_estimators)[source]

Bases: SequenceEncodableStatisticAccumulator

E-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 then exp(lc[sum] + value[child] + log_w - value[sum]) (its expected count), and a leaf’s responsibility is exp(lc[leaf]) (the weight for its sufficient statistic).

Parameters:
seq_update(enc, weights, estimate)[source]

Update circuit-flow responsibilities and leaf sufficient statistics.

Parameters:
  • enc (dict[int, Any])

  • weights (Any)

  • estimate (ProbabilisticCircuitDistribution)

Return type:

None

update(x, weight, estimate)[source]

Update from one weighted observation.

Parameters:
  • x (Any)

  • weight (float)

  • estimate (ProbabilisticCircuitDistribution)

Return type:

None

initialize(x, weight, rng)[source]

Initialize sum counts and leaf statistics from one weighted observation.

Parameters:
Return type:

None

seq_initialize(enc, weights, rng)[source]

Initialize sum counts and leaf statistics from encoded observations.

Parameters:
Return type:

None

combine(suff_stat)[source]

Merge sum-node expected counts and leaf accumulator values.

Parameters:

suff_stat (Any)

Return type:

ProbabilisticCircuitAccumulator

value()[source]

Return sum-node expected counts and leaf sufficient statistics.

Return type:

Any

from_value(x)[source]

Restore sum-node and leaf sufficient statistics from value output.

Parameters:

x (Any)

Return type:

ProbabilisticCircuitAccumulator

scale(c)[source]

Scale sum-node and leaf sufficient statistics by a constant.

Parameters:

c (float)

Return type:

ProbabilisticCircuitAccumulator

key_merge(stats_dict)[source]

Delegate keyed merges to the leaf accumulators.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

key_replace(stats_dict)[source]

Delegate keyed replacements to the leaf accumulators.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

acc_to_encoder()[source]

Return an encoder based on the current leaf accumulator estimates.

Return type:

ProbabilisticCircuitEncoder

class ProbabilisticCircuitAccumulatorFactory(nodes, leaf_scope, leaf_estimators)[source]

Bases: StatisticAccumulatorFactory

Create accumulators for fixed-structure probabilistic-circuit EM.

Parameters:
make()[source]

Create an empty probabilistic-circuit accumulator.

Return type:

ProbabilisticCircuitAccumulator

class ProbabilisticCircuitEstimator(dist, pseudo_count=None)[source]

Bases: ParameterEstimator

Fits 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 a factory for circuit-flow sufficient-statistic accumulators.

Return type:

ProbabilisticCircuitAccumulatorFactory

estimate(nobs, suff_stat)[source]

Estimate sum-node weights and leaf distributions from accumulated circuit flows.

Parameters:
Return type:

ProbabilisticCircuitDistribution