This release is a pre-release and may not be stable for production use.
Stochastic Program IR
Status: v0.1 alpha. The public API is still allowed to change.
Stochastic Program IR is a small, immutable random-variable algebra for writing forward-sampling programs that read like ordinary mathematical array code. Named plates replace positional shape reasoning; explicit reductions replace hidden contractions; staged materialization replaces mutable RNG state. Features whose semantics cannot be understood locally—especially arbitrary indexing—are intentionally excluded.
The project is designed for simulations, generators, and agent-authored stochastic programs where probabilistic structure should remain easy to read, compare, and validate. It performs forward sampling only; it is not a Bayesian inference framework.
Why an IR?
“IR” describes the immutable expression graph that the API constructs. The graph preserves:
- which values are sampled and which operations are deterministic;
- which distribution output plates receive conditionally independent draws;
- where existing values are broadcast over new plates;
- which named plates are preserved, checked, or reduced;
- which sampling phase owns each unresolved distribution;
- structural equality independently from resolved stochastic sharing; and
- partially materialized values without mutable runtime sessions.
The name does not imply that v0.1 includes serialization, optimization passes, compilation, or multiple numeric backends.
Installation
Stochastic Program IR requires Python 3.10 or newer:
pip install stoch-ir
The public API is still in alpha. Pin the exact prerelease when reproducibility matters:
pip install "stoch-ir==0.1.0a1"
Quick start
from stoch_ir import Normal, sampling_phase, softplus
with sampling_phase("latent"):
weights = Normal(
0.0,
1.0,
plates="layer",
rng_label="weights",
)
with sampling_phase("observation"):
activations = Normal(
mu=weights,
sigma=softplus(weights) + 0.1,
plates=("layer", "batch"),
rng_label="activations",
)
layer_score = activations.mean("batch").check_plates("layer")
The distribution's plates= argument is its complete output layout. Its
parameters may use any subset of that layout, so weights is shared across
"batch" while activations receives a conditionally independent draw at
every ("layer", "batch") coordinate.
The same graph can be realized in stages:
sizes = {"layer": 8, "batch": 32}
fixed_latent = layer_score.materialize(
phases=("latent",),
seed=100,
plate_sizes=sizes,
)
sample_a = fixed_latent.realize(seed=200)
sample_b = fixed_latent.realize(seed=201)
fixed_latent is an opaque immutable checkpoint. Its latent draws have become
constants, while its observation draws remain symbolic. Branching from that
checkpoint reuses the latent values and resamples only the remaining
uncertainty.
Explicit contractions
Named alignment makes familiar array operations readable without positional axis bookkeeping. For example, a matrix product is elementwise multiplication followed by an explicit reduction:
from stoch_ir import Normal
# left varies over {"row", "inner"}
left = Normal(0.0, 1.0, plates=("row", "inner"))
# right varies over {"inner", "col"}
right = Normal(0.0, 1.0, plates=("inner", "col"))
product = (left * right).sum("inner").check_plates("row", "col")
This replaces an implicit left @ right contraction with source code that
names the contracted plate. The missing @ operator is therefore not a
capability gap in v0.1: the primitive expression is more explicit about the
stochastic and array structure.
Distributions and concrete inputs
v0.1 includes normal, arbitrary-bound continuous uniform, and Bernoulli draws:
from stoch_ir import Bernoulli, Uniform, sampling_phase
with sampling_phase("probability"):
probability = Uniform(plates="group")
with sampling_phase("trial"):
trial = Bernoulli(
probability,
plates=("group", "trial"),
)
rate = trial.mean("trial").check_plates("group")
Existing NumPy values enter through one explicit boundary:
import numpy as np
from stoch_ir import constant
offset = constant(
np.array([0.1, 0.2], dtype=np.float32),
plates=("group",),
)
constant infers Boolean, integer, or floating metadata and stores values
canonically as np.bool_, np.int64, or np.float64. Complex, object, string,
and unnamed multidimensional values are rejected. Declared plate order follows
the input array axes; storage is transposed when necessary into canonical
lexicographic order. A bare string such as plates="group" denotes one plate.
Integer inputs and operation results outside the canonical np.int64 range
are rejected rather than silently wrapped.
Plate algebra
Plate names are strings. Sizes are supplied only when a graph is materialized. The public operations are deliberately small:
- distribution
plates=declares the complete conditionally independent sampling layout; add_plates(*new, expect=None)broadcasts an existing value over new plates;check_plates(*expected)validates the complete plate set;reduce_plates(*plates, reduction=REDUCTION)explicitly contracts plates with a required reduction argument; andmean,sum,max,min,prod, andlogsumexpprovide named convenience reductions.
expr.plates returns the canonical lexicographic tuple used to align concrete
array axes. Contract methods accept plate names in any order.
Structural and stochastic equality
Expression equality compares exact computation structure—not numerical, algebraic, or absolute probabilistic equivalence. It intentionally ignores object aliasing and unresolved randomness:
from stoch_ir import Normal, sampling_phase
with sampling_phase("draw"):
x = Normal(0.0, 1.0)
shared = x + x
independent = Normal(0.0, 1.0) + Normal(0.0, 1.0)
assert shared == independent
Graph-derived node entropy is resolved only during materialization. The
resulting checkpoints therefore expose stochastically_equal, which also
checks stochastic sharing and resolved RNG state:
shared_checkpoint = shared.materialize(seed=1, phases=())
independent_checkpoint = independent.materialize(seed=1, phases=())
assert not shared_checkpoint.stochastically_equal(independent_checkpoint)
This compares unresolved stochastic provenance in the checkpoints. Once draws are materialized into constants, their historical RNG provenance is intentionally discarded and equality compares the resulting values.
An rng_label supplements graph-derived entropy but never replaces it or opts
distinct nodes into shared randomness.
Intentional v0.1 boundaries
The project intentionally excludes arbitrary indexing, positional-axis operations, hidden contractions, mutable RNG sessions, probabilistic inference, autodiff, JIT compilation, serialization, graph optimization, custom nodes or reductions, and alternate numeric backends.
v0.1 uses NumPy internally. Conversion to other array libraries belongs at the API boundary.
Documentation and development
- Documentation site
- Getting started
- v0.1 specification
- Public API contract
- Hashing and materialization architecture
- Contributor guide
- Changelog
The package ships inline annotations with py.typed. CI checks Ruff, ty, tests
on Python 3.10, 3.11, and the latest supported Python, with warnings treated as
errors and a 95% branch-coverage floor. It also checks built-wheel imports and
the documentation site.
License
Stochastic Program IR is distributed under the BSD 3-Clause License.
Metadata
Release files for stoch-ir 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| stoch_ir-0.1.0a1.tar.gz | 28.9 kB | With provenance | Details for stoch_ir-0.1.0a1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| stoch_ir-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details for stoch_ir-0.1.0a1-py3-none-any.whl |
Total release size: 71.9 kB
Release files / stoch_ir-0.1.0a1.tar.gz
| Download URL | stoch_ir-0.1.0a1.tar.gz |
|---|---|
| Size | 28.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
220630b53f3880428b99c541e7e34f3db24690617c7e2562c6529717634a64fa
|
|
BLAKE2b-256 checksum How to use checksums |
7be2d2c4ec4fb90bf93477d66f0bd49b1dea8dc41fad297517e6d176b5156e17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logRelease files / stoch_ir-0.1.0a1-py3-none-any.whl
| Download URL | stoch_ir-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 43.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d88d753bf3b71b5b06f5b7f1ad266575e1dafd9177685ab7027e8059dae802a5
|
|
BLAKE2b-256 checksum How to use checksums |
b2085f45ae0d5d2ec21b7b71b306dc397ce82a0f63ba0c5d9a4ec5d055576d37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logSecurity for stoch-ir 0.1.0a1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for stoch_ir-0.1.0a1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.