Implementation Correspondence and Limits¶
This page records the implementation-correspondence claim (ICC): the compiler should construct the runtime object described by the semantics pages for each supported QVR phrase. The ICC is a specification tested on representative cases. It is not a mechanized adequacy theorem for the whole language.
1. What the compiler returns¶
Compiler resolves a parsed module into an environment of objects, morphisms, programs, deductions, structural components, and exports. A successful compilation does not always return one Program, and Program.forward does not in general return a probability distribution. Depending on the compiled artifact, evaluation may return a tensor, a sample, a dictionary of returned values, or another runtime wrapper.
Thus correspondence must be stated per artifact:
| Phrase | Runtime object | Evidence-bearing operation |
|---|---|---|
object |
SetObject or ContinuousSpace |
structural equality, shape, membership where implemented |
discrete morphism |
Morphism |
.tensor |
| family morphism | ContinuousMorphism |
.rsample, .log_prob |
program |
MonadicProgram or compiled program wrapper |
sampling and .log_joint |
deduction |
DeductionSystem |
agenda/chart evaluation |
| structural declaration | encoder, decoder, signature, or loss object | component-specific method |
2. Direct correspondences¶
Several clauses are close enough to their implementations to check pointwise.
First, object resolution is a structural walk over ObjectExpr. Nested products and coproducts are flattened without reordering components. Continuous constructors dispatch through the compiler's constructor table.
Second, a discrete latent morphism stores a raw parameter and exposes sigmoid(raw) as its tensor. An observed morphism exposes its supplied tensor. Composition calls the active composition rule's tensor_op and join; tensor product applies tensor_op pointwise.
Third, the expression combinators have distinct operational contracts:
| Combinator | Current implementation |
|---|---|
.marginalize(X, ...) |
reduces named codomain axes with the active algebra's join |
fan(f, g, ...) |
feeds one input to each component and concatenates outputs |
repeat(f, n) |
sequentially composes the same instance, sharing parameters |
stack(f, n) |
sequentially composes deep copies, giving each layer independent parameters |
scan(cell) |
iterates a continuous cell A * H -> H over an implicit time axis and returns the final state |
These last two distinctions matter: stack is not tensor power, and scan is not .trace.
3. Probabilistic composition¶
Sampling from f >> g is ancestral: sample the intermediate value with f.rsample, then pass it to g.rsample. This produces samples from the composite kernel when the component samplers implement their declared kernels.
Density evaluation is different. SampledComposition.log_prob draws a fixed number of intermediate samples, evaluates the second density, and combines the values with logsumexp - log(n). The density-scale average is a Monte Carlo estimator of the integral; taking its logarithm introduces finite-sample bias. The default sample count is 100. Thus the returned log density is an approximation, not pointwise equality with the ChapmanāKolmogorov integral.
ScanMorphism.log_prob currently returns zeros for the final state, while log_joint(x, hidden_states) scores a supplied full hidden trajectory. A semantics that requires the marginal density of the final recurrent state is thus not implemented by log_prob.
4. Programs and data¶
Program statements preserve their leading-keyword distinction:
sampleintroduces a random value;observeadds a family log density at supplied data;letbinds deterministic tensor arithmetic;scoreadds an explicitly computed scalar to the log joint;marginalizeintroduces a scoped latent and removes it from the outer scope;returnselects the program result.
from_data("key") is resolved through data bound to the compiler before expression compilation. It should not be described as a learnable value or as an unbound runtime lookup.
5. What the tests establish¶
The repository contains focused evidence rather than one exhaustive theorem:
- compiler and DSL tests exercise parsing, resolution, typing errors, expression composition, contractions, programs, and structural declarations;
tests/test_program_theory.pychecks extraction and validation of program-shape schemas;tests/test_model_roundtrips.pychecks JSON round trips fordx.Modelvalues;tests/transpile/test_structural.py,test_lens_laws.py,test_external_syntax.py, andtest_numeric_equivalence.pytest the separate transpilation pipeline described in Transpilation correctness.
Passing these tests supports the covered cases. It does not establish equality for every phrase, algebra, distribution parameterization, backend, input, or floating-point value.
6. Conditions and open gaps¶
The ICC must be qualified in five places.
- Categorical equations that use distributivity, arbitrary joins, or compact closure require those laws of the active algebra. The
Algebraclass does not prove them. - Floating-point operations may differ from exact real arithmetic, especially near support boundaries and saturated reductions.
- Monte Carlo density calculations are approximate at finite sample counts.
- Family registries state support and parameter maps operationally; registry membership alone does not prove measurability, normalization, or equivalence to an external library.
- Schema extraction records program shape. Equality of extracted schemas is not equality of program behavior or parameter values.
These limits identify concrete work: add property tests for each claimed algebraic law, compare probabilistic compositions against analytic cases, and connect each declarative typing rule to a compiler test. Until then, the semantics pages should distinguish implemented behavior, test evidence, and conditional mathematical interpretation.