test: property-based correctness sweep over every Prior subclass - #1499
Merged
Conversation
Adds test_autofit/mapper/prior/test_prior_properties.py — 134 parametrised tests locking five properties over every concrete Prior family: - P1 value_for is the inverse CDF (cdf round-trip to 1e-6) - P2 the normalised prior density integrates to 1, three ways: the log_prior_from_value + log_normalisation() contract (#1331 Option A), the message physical-density path, and the generic exponential-family pdf for direct messages — now including TruncatedNormalMessage, the exclusion that let the #1331-04 log-partition bug survive - P3 log_prior gradient matches the density gradient by central finite differences (the #1266 sign-convention canary) - P4 with_limits constructs for every family with documented semantics (hard limits hit exactly; Gaussian families centre between limits) - P5 from_mode(m, V) reproduces mean and variance at V != 1 discriminating points for Normal and Gamma (#1331-D3 invariant) TransformedMessage physical densities are asserted via factor() because the generic logpdf path omits the transform Jacobian — filed as #1498. Also adds the LinearShiftTransform class docstring (bug/priors/11 s2): shift/scale are physical-space parameters; the stored parent Jacobian is deliberately 1/scale because transform() runs physical -> base.
This was referenced Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1497. Phase 3 of the priors/messages census (hub #1331): the general property sweep that locks the nine shipped fixes in as class-wide invariants rather than pointwise regressions.
What this adds
test_autofit/mapper/prior/test_prior_properties.py— 134 parametrised tests, five properties over every concretePriorfamily (Uniform, LogUniform, Gaussian, LogGaussian, TruncatedGaussian; two parameterisations each):cdf(value_for(u)) ≈ uto 1e-6 across the unit interval.exp(log_prior_from_value + log_normalisation())integrates to 1 (locks the Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331 Option A drop-constants contract); the message physical-density path integrates to 1; the generic exponential-familypdfintegrates to 1 for direct messages — now includingTruncatedNormalMessage, the exact exclusion that let the Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331-04 log-partition bug survive.log_prior_from_valueand of the physical log density agree (constants cancel) — the check that would have caught the fix: log_prior_from_value sign-convention bug across Prior subclasses #1266 LogUniform sign bug.with_limits: constructs for every family (the Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331-01 crash class); hard-limit families hit the requested limits at the unit-cube edges; Gaussian families centre between limits with sigma equal to their separation.from_mode:NormalMessage/GammaMessagereproduce mean and variance at V≠1 discriminating points (locks the Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331-D3 invariant; V=1 points cannot discriminate the historical inverted formula).autofit/messages/transform.py— theLinearShiftTransformclass docstring (the remaining half of the census's C6/bug/priors/11; the composition-order half shipped in #1334):shift/scaleare physical-space parameters and the stored parent Jacobian is deliberately1/scalebecausetransform()runs physical → base.New finding, filed separately
While implementing P2:
TransformedMessage.logpdf/pdfomit the transform Jacobian — the generic path returns the base-space density at physical coordinates (UniformPrior(0,1).message.pdfintegrates to 0.282 = 1/(2√π), not 1.0), whilefactor()is correct. Filed as #1498 with full reproduction; the tests here assert the physical density viafactor()for transformed messages and cite #1498 at the site, so they can be tightened once it is adjudicated.Validation
test_autofit/mapper/prior/+test_autofit/messages/+test_autofit/graphical/functionality/test_messages.py: 477 passed; the 5 failures present are identical on cleanmainin this environment (jax API drift intest_jax_trace.py/test_beta, unrelated — the new module is NumPy-only per the house rule).mainbefore being committed as assertions.🤖 Generated with Claude Code
https://claude.ai/code/session_016KANrjyrdj7pLXC7sKbhJo
Generated by Claude Code