Structure and inference routes
A plan is the compiler's answer together with its evidence: which latents share a block, which route each block takes, what was measured to justify it, and how the blocks run together. This page reads one line by line.
How to read a plan
This is the plan for a model whose prediction is affine in x once nu is fixed. The table summarizes it; open the printed plan underneath to follow the paragraphs below.
| Block | Latents | Route | Why |
|---|---|---|---|
| 0 | x | GCR exact | structurally certified; numerical check 3 scales x 3 at-points (max 0.00e+00) |
| 1 | nu | NUTS | outside the exact block ['x']: sampled by NUTS, and the exact block is solved CONDITIONAL on them, once per sweep |
| Execution | HMCGibbs(inner=NUTS, gibbs_sites=['x']); noise_std rebuilt every sweep | ||
Printed plan
block 0 {x} GCR exact structurally certified; numerical check 3 scales x 3 at-points (max 0.00e+00)
kappa=72.652432 -> tol=1.3764164e-05, guard hoisted out of the sweep
exact block ['x']: sigma does not move with the block (0.000e+00 relative,
rtol=1.0e-08), so the covariance is fixed and one Wiener solve is exact; the
linearity check held ['nu'] at their prior centre rather than drawing them --
they are not Gaussian, so their prior has no draw this module will take; the
kappa sweep held ['nu'] at their prior centre rather than moving them -- they
are not Gaussian, so this module has no prior width to sweep them by, and the
interval is not an interval in them
block 1 {nu} NUTS
outside the exact block ['x']: sampled by NUTS, and the exact block is solved
CONDITIONAL on them, once per sweep
execution: HMCGibbs(inner=NUTS, gibbs_sites=['x']); noise_std rebuilt every sweepoverview_plan.py. Condition numbers and tolerances in the printout depend on the BLAS; block membership and routes are re-checked by the test suite. Full record.A plan prints one head line per block, its evidence indented under it, and one execution line for the whole graph.
- The head line names the block's index, its members and the route. Next to the route is the basis for it:
structurally certifiedwhen an analysis of the traced computation proved the block affine over its whole valid domain, ornumerically validated (global affinity unproved)when only the probes passed. It is followed by the size of the probe, as scales × points, and the worst departure measured over them. - The conditioning line reports
kappaand thetolderived from it, then says whether the solver's own convergence guard can run. - The indented paragraph states what the checks held fixed and why, in the classifier's words. In the plan above it records that the noise does not move with the block, and that the non-Gaussian
nuwas held at its prior centre because it has no prior draw for this module to take. - The execution line says what will actually be run: independent exact draws, NUTS, or the combination of the two with the exact block solved once per sweep.
Condition number and tolerance
An exact block is solved iteratively, so the plan states the accuracy that solve is asked for. kappa is an upper bound on the block's conditioning and tol is derived from it, as the convergence target divided by that bound. The target is a relative error of 10−3. The pair is printed to eight significant digits because it is meant to be checked: three digits cannot round-trip the division.
The bound is an upper bound and a loose one, so a block whose printed kappa is large may still be solved accurately. That is why the plan prints the number instead of refusing on it.
Two further clauses can appear on that line. guard hoisted out of the sweep means the block is solved inside a compiled Gibbs sweep, where the solver's concrete-valued convergence guard cannot run, so tol carries the discipline alone. guard reachable, off by default means the graph is solved outside any trace and the guard can be switched on. A third replaces them when the requested tol is below what the current precision can deliver: the plan says the tolerance is unattainable at this dtype, and prints the product that establishes it. See installation and precision.
Which structure takes which route
Core concepts lists the five methods a block can carry. This table reads the same decision from the model's side.
| Structure | Route | Boundary |
|---|---|---|
| Linear-Gaussian with an eligible covariance | Wiener solve and constrained realization | Conditioning and precision checks still apply. |
| A supported log-linear form | The same solve in log space | The transformation and the noise law must justify it. |
| Conditionally Gaussian affine groups | Exact conditional updates inside a chain | Each update is exact; the joint draws stay correlated. |
| An eliminable exact block | Collapse the block and sample the residual target | Reconstruction and target semantics must stay explicit. |
| A general differentiable model | NumPyro NUTS | Geometry and diagnostics decide practical reliability. |
| An explicit proposal schedule | GLS, log-linear or Gauss–Newton proposals | The Metropolis correction is the default; disabling it changes the approximation class. |
Affinity is a joint claim
A model such as a * b is affine in a with b held fixed, and affine in b with a held fixed. It is not jointly affine in both. The compiler certifies whole candidate groups with the complementary latents kept symbolic, then checks the prior and covariance requirements. This distinction controls whether several conditional Gaussian updates can be scheduled, whether a whole-graph exact posterior exists, and whether analytic evidence is admissible. A conditional certificate is not a whole-graph claim.
When a premise fails
A failed premise does not stop the plan. The block takes a general route and the plan records what was measured: the Overview shows a false affinity declaration refused with its departures, and a model with no exact block at all compiles to NUTS with the reason on the block's own line. In the typed protocol the same judgement is returned as a Refusal rather than printed.
Inspect both compile and execution products
The compact API returns a runtime InferencePlan. The typed API returns a planned task with its analysis and a serializable plan record, or a Refusal. The run that follows records backend, budget, termination and approximation class.
Backend options are bounded inputs, not arbitrary dictionaries. An unsupported control is refused rather than ignored. See sampling policies for initialization and stopping.
Compatibility entry points
compile, InferencePlan.sample, InferencePlan.estimate, fit and their runtime result objects remain useful compact interfaces. Prefer typed Tasks and Results when storing or coordinating work. Their coexistence does not imply identical return types.
Reference: compile_task, execute_task, factor_partition, fit.