v0.1 Implementation Plan¶
This plan tracks the incremental v0.1 implementation. It intentionally contains no placeholder integrations or speculative extension points: every listed component is needed for the acceptance behavior.
Deliverable 1: immutable graph core¶
Build the six IR node families and scalar-to-constant coercion.
Required work:
immutable expression/node representation;
child traversal and DAG sharing;
operator overloads for
+,-,*,/, and//;unary nodes for
exp,log,softplus, and absolute value;distribution nodes for
Normal,Uniform, andBernoulli;alias-agnostic structural equality;
cycle validation.
Acceptance checks:
constructing expressions performs no sampling;
attempts to mutate nodes fail;
equivalent separately built DAGs compare equal;
shared-node and duplicate-node graphs compare structurally equal when their computation trees are otherwise equivalent;
resolved checkpoints distinguish stochastic aliasing, node entropy, and bound sampling-seed differences.
Deliverable 2: plate algebra and value alignment¶
Implement named plate inference, contracts, reductions, and the minimal concrete alignment required by the backend boundary.
Required work:
platesand canonical lexicographicplate_layoutinference;add_plates(*plates, expect=None);check_plates(*plates);reduce_platesplus the six convenience reduction methods;strictly positive materialization-time plate sizes;
alignment of concrete values by named plate order;
complete output plate declarations on distribution nodes;
deterministic broadcasting through
AddPlates;the public plate error hierarchy.
Acceptance checks:
duplicate plate introduction fails;
an incorrect
expectfails before graph transformation;check_platesreturns the same object;reducing a missing plate fails;
Normal(row_value, col_value)aligns to logical(row, col);distribution output plates create conditionally independent draws;
distribution output plates must contain every parameter plate;
adding a plate to any expression broadcasts its existing value.
Concrete-value work:
expose
constant(value, *, plates=(), dtype=None);infer supported Boolean, integer, and floating inputs;
canonicalize storage to
np.bool_,np.int64, ornp.float64;transpose declared input axes into canonical plate order;
derive and enforce four-state support after coercion;
reject unsupported kinds and rank/layout mismatches at the boundary.
Deliverable 3: phase annotation¶
Implement distribution-only sampling phases.
Required work:
a context-local current phase;
nested
sampling_phaserestoration;phase capture by distribution constructors only;
recursive
pending_phasesintrospection;unphased distribution nodes with no phase barrier.
Acceptance checks:
deterministic nodes created inside a phase do not acquire a phase;
nested contexts assign the innermost phase and restore the outer phase;
pending phases reflect only reachable, unmaterialized distributions.
Deliverable 4: graph-aware RNG derivation and NumPy execution¶
Implement deterministic graph-key resolution and concrete NumPy sampling.
Required work:
stable seed normalization;
a stochastic-only graph projection;
dependency hashes, direct-consumer hashes, repeated-use multiplicities, and symmetric-node enumeration;
compressed projected edges for repeated stochastic consumption;
optional
rng_labelentropy mixed after the graph hash;node-entropy resolution coupled to initial materialization;
one run seed selected per materialization invocation;
phase-enabled sampling seeds bound immediately, even while dependencies are blocked;
NumPy sampling for the implemented distributions;
concrete deterministic arithmetic, transforms, and reductions.
Uniform must support arbitrary symbolic bounds with unit defaults and
elementwise low < high validation. Bernoulli must accept symbolic
probabilities, validate 0 <= p <= 1, and return canonical Boolean values.
Acceptance checks:
the same graph and seed reproduce exactly;
different seeds alter pending stochastic nodes;
unrelated graph construction does not perturb a result;
labels never override graph structure or couple distinct nodes;
separately allocated symmetric nodes receive distinct default keys;
aliases of one node share one resolved entropy identity and sampled value.
Deliverable 5: immutable partial materialization¶
Implement staged graph rewriting and value extraction.
Required work:
materialize(phases=..., seed=..., plate_sizes=...);an opaque, non-composable
SamplingCheckpoint;monotonic phase-barrier removal;
dependency-blocked enabled nodes that resume on a later pass;
node-owned exact dependency rewriting through a private reconstruction hook;
distribution-to-constant replacement;
eager constant folding for deterministic downstream nodes;
unchanged subgraph sharing;
checkpoint
materializeandrealize;checkpoint-only
stochastically_equal;materialization error reporting.
Acceptance checks:
the source graph remains unchanged;
materializing one phase leaves other distributions symbolic;
enabling a downstream phase before its dependency retains the permission;
later enabling the dependency finishes all newly ready enabled work;
two branches share embedded early-phase constants;
later-phase seeds can vary independently;
value extraction fails while stochastic nodes remain.
deterministic raw expressions can realize without a checkpoint;
checkpoint
value()extracts only an already constant root.
Deliverable 6: product validation suite and examples¶
Validate the authoring experience rather than only line coverage.
Required work:
one small hierarchical model example;
one row/column plate-alignment example;
one fixed-latent/repeated-observation example;
expected-graph fixtures suitable for testing generated code;
error-message snapshots for common plate mistakes;
README examples converted to executable tests.
a public-import-only static typing fixture;
branch coverage of at least 95%;
a fixed v0.1 graph-digest fixture and cross-
PYTHONHASHSEEDsubprocess check;wheel validation proving that
py.typedand inline annotations ship without.pyifiles.
The release candidate is acceptable only if each example is shorter or materially more explicit about stochastic structure than its equivalent imperative NumPy program.
Test matrix¶
Concern |
Required cases |
|---|---|
Equality |
equal structures, different args, allocation-order independence, shared vs duplicated stochastic node |
Plates |
add, duplicate add, exact check, failed expectation, ordered union, each reduction |
Alignment |
scalar/scalar, row/scalar, row/col, reduced row/col |
Phases |
named, unphased, nested context, blocked enabled phase, enable all |
RNG |
same seed, different seed, unrelated construction, label mixing, repeated projected edge, symmetric enumeration, blocked-node seed persistence |
Materialization |
none eligible, some eligible, all eligible, immutable source, branch reuse |
Errors |
invalid plate, missing size, numeric sampling failure, premature value extraction |
Release deliverables¶
The v0.1 release must contain:
the typed public runtime interfaces;
inline annotations and
py.typed, with no shipped stub files;NumPy concrete propagation and distribution sampling;
full implementations of the six node families;
plate-aware deterministic evaluation and the six reductions;
phase contexts and partial materialization;
structural and checkpoint stochastic equality;
tests for the matrix above;
the realistic end-to-end examples;
package metadata and generated API documentation.
Python 3.10/latest-supported CI for Ruff, ty, tests, coverage, wheel build, wheel inspection, and installed-package smoke tests.
Deferred work¶
Do not begin the following during v0.1 unless the core acceptance work proves impossible without it:
custom extension registries;
JAX or PyTorch support;
serialization or visualization;
optimizers, compilers, tracing, or autodiff;
inference or observations;
custom reduction callables;
rich tensor indexing or dynamic plates;
public graph visitor or rewrite APIs.
Locked implementation decisions¶
optional
rng_labelsupplements graph-derived entropy and never overrides it;exact concrete values use NumPy arrays;
PlateLayoutis canonicalized lexicographically;unphased distributions remain expressible and have no phase barrier;
a public backend protocol is deferred;
distribution constructors retain their natural parameters (for example,
Normal(mu, sigma)) rather than lowering to standardized distributions;public generic reductions use the immutable singleton objects in
stoch_ir.reductions;concrete NumPy storage always matches authoritative
ValueMeta.dtype;custom-node execution support and public graph rewrite APIs are deferred.