fix(graphical): EP statistics fix batch — F1/F2/F4/F8 from #1332#1351
Merged
Conversation
- F1/F7(a): MeanField.__truediv__/__pow__ passed log_norm positionally into the plates ctor slot — evidence silently dropped and a float stored in _plates. log_norm now passed by keyword; the per-variable- exponent __pow__ branch sets log_norm=0.0 (no meaningful scalar aggregate exists; the old self.log_norm * other.log_norm was meaningless even in the right slot). - F2 (+extended): GammaMessage.kl and BetaMessage.kl computed the reverse direction KL(dist||self); both now follow the family-wide contract self.kl(other) = KL(self||other) (matching Normal / TruncatedNormal), so EPHistory.kl_divergence no longer sums KLs measured in opposite directions on mixed graphs. Certified per family by a Monte-Carlo direction property test. - F4: AbstractMessage.update_invalid scalar branch empirically verified correct — the "fairly certain this would not work" TODO was a stale false alarm; replaced with an explanatory comment and pinned by unit tests on both branches. - F8: dead/suspect quasi-Newton variants deleted from laplace/newton.py (diag_sr1_update_ unused; diag_sr1_bfgs_update returned None; bfgs1_update sign-disputed vs the exported bfgs_update). Adds test_ep_statistics_fixes.py (9 tests). Full suite: 1465 passed / 14 skipped / 1 pre-existing flake (test_full_hierachical — fails on clean main with this batch fully stashed; filed as PyAutoMind/bug/autofit/hierarchical_ep_test_flaky.md). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 10, 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.
Summary
Executes the remainder of the #1332 EP statistics audit's recommended fix batch (tracker #1350), now that the #1331 decision hub is resolved (#1345, #1348) and F3/F10 (#1349), F5 (#1334), F7(c) (#1345) have landed. Two real statistical repairs —
MeanFieldevidence bookkeeping through__truediv__/__pow__(F1/F7a:log_normwas silently dropped into theplatesctor slot) and the Gamma/Beta KL direction (F2: both computedKL(other‖self)while Normal/TruncatedNormal computeKL(self‖other), soEPHistory.kl_divergencesummed opposite-direction KLs on mixed graphs) — plus one exoneration (F4: the self-flaggedupdate_invalidscalar branch is empirically correct; stale TODO replaced and both branches pinned by tests) and one deletion (F8: three dead/suspect quasi-Newton variants).API Changes
Behaviour fixes on EP internals; three never-exported module functions removed.
GammaMessage.kl/BetaMessage.klnow returnKL(self‖other)(family-wide contract) — EP convergence metrics on graphs with Gamma/Beta variables change value (correctly).MeanField.__truediv__/__pow__now propagatelog_norm, soEPMeanField.log_evidencethrough these operators is no longer silently zeroed (one leg of F7's "evidence bookkeeping broken"; F7(b) — where sampler per-factor evidence is recorded — remains a parked design decision).See full details below.
Test Plan
test_autofit/suite: 1465 passed / 14 skipped / 1 pre-existing flake —test_full_hierachicalfails on cleanmainwith this batch fully stashed (bisect-proven ×3: clean, F1-reverted, F2-reverted); filed asPyAutoMind/bug/autofit/hierarchical_ep_test_flaky.mdtest_ep_statistics_fixes.py— 9 tests: log_norm/plates round-trip through__truediv__/__pow__(scalar + MeanField exponent), Monte-Carlo KL direction property test per family (Normal/Gamma/Beta, asymmetric cases, reverse direction asserted different),update_invalidscalar + array branches, dead-variant removalep_parity.py/ep_deterministic.py/ep_exact.pyall PASS against this branchValidation checklist (--auto run — plan on the issue)
Full API Changes (for automation & release notes)
Removed
autofit.graphical.laplace.newton.diag_sr1_update_— never referencedautofit.graphical.laplace.newton.diag_sr1_bfgs_update— computed locals then implicitly returnedNone(would have nuked optimiser state if wired in)autofit.graphical.laplace.newton.bfgs1_update— disagreed with the exportedbfgs_updateon they_ksign and carried a stray minus ond_k^T B d_k(None were exported via
autofit.graphical; the verifiedbfgs_update/sr1_update/full_*variants are unchanged.)Changed Behaviour
MeanField.__truediv__—log_normnow correctlyself.log_norm - other.log_norm(previously silently 0.0 with the value stored as a float in_plates)MeanField.__pow__(scalar) —log_norm = self.log_norm * exponentin the right slot; (MeanField exponent) —log_norm = 0.0with rationale comment (the previousself.log_norm * other.log_normwas not a meaningful quantity)GammaMessage.kl(dist)/BetaMessage.kl(dist)— nowKL(self‖dist); previouslyKL(dist‖self). Convergence metric values on mixed-family EP graphs change; the EP fixed point itself is unaffected (KL is only used for history/convergence checks)Migration
🤖 Generated with Claude Code