Repository navigation
Description
Overview
Two seeds of the 200-seed N=5 analytic_gaussian ensemble (RAL job 342413, autofit 2026.8.17.1; PyAutoCortex ruling R-20260910-04) emitted, repeatedly, RuntimeWarning: invalid value encountered in add from EPMeanField.log_evidence (autofit/graphical/expectation_propagation/ep_mean_field.py:336): 7 times on seed 25, 19 on seed 172. Both seeds' parity results are otherwise fine and neither is in the stale-factor set, so the evidence accumulator goes non-finite on healthy-looking runs, and only SLURM's .err capture caught it. This task finds which term is non-finite and why, decides whether the readout is biased or merely NaN, and makes the library report it once by name instead of warn-and-sum. Reporting only: no change to the EP update maths, projections or messages (the human's 2026-10-23 instruction: EP is trusted).
Second of the three wave-1 ruling findings of the graphical-ep campaign (PyAutoInsight tasks/ep_campaign_state_2026-10-23.md); the first shipped as PyAutoFit#1711/#1712.
Plan
- Reproduce seeds 25 and 172 (
--columns ep) on current main from a scratch copy of the science scripts (/mnt/c/Users/Jammy/Science/active/analytic_gaussian; the prompt predates theactive/layout), under-W error::RuntimeWarningto get the traceback at the first non-finite term; dump per-variable and per-factor evidence terms on that sweep. - Diagnose the term (degenerate message, inf−inf between log partitions, NaN sampler logz) and whether the final posterior is affected (compare against
results/ens_n5/seed_0025.json). - Library:
log_evidencedetects non-finite terms before summing, warns once per run naming the variable/factor, returns NaN explicitly without numpy warning spam;diagnosticsrecords the names inep_diagnostics.results;EPHistory.evidence_divergencereturns inf for a NaN so it can never claim convergence. If the root cause is a degenerate message from an accepted projection, report it as new scope rather than touching the projection. - Unit test (red before, green after): no RuntimeWarning, one named warning, NaN evidence, inf divergence.
- Workspace regression in
autofit_workspace_test/scripts/graphical/analytic_gaussian.py: noRuntimeWarningfromep_mean_fieldand finite final evidence on seed 0 (seed 25 only if ≤ 60 s). - Ship library first, then workspace; ledger lines in Insight (companion state file) and Cortex (analytic_gaussian Log).
Tier: glance — merge mode: auto-merge on green if the Witness passes, post-merge summary.
Detailed implementation plan
Affected Repositories
- PyAutoFit (primary)
- autofit_workspace_test (regression)
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./fit/PyAutoFit | main (abb8bfa) | clean |
| ./fit/autofit_workspace_test | main (97cb781) | clean |
Suggested branch: feature/ep-evidence-nonfinite — worktree ~/Code/PyAutoLabs-wt/ep-evidence-nonfinite/
Implementation Steps
- Repro: scratch copy of
scripts/+config/;python3 -W error::RuntimeWarning scripts/ensemble_seed.py --seed 25 --columns ep(and 172) with the worktree PyAutoFit on PYTHONPATH,NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib; then a normal run withEPMeanField.log_evidencemonkeypatched to log each term (variable name, message mean/variance/limits, factorlog_norm). Never write into the science checkout'sresults/. - Library (
autofit/graphical/expectation_propagation/):ep_mean_field.pylog_evidence(~lines 310–336) — per-term dicts,np.isfinitescan, onelogger.warningper instance naming variables/factors,np.errstate(invalid="ignore")around the sum, explicitfloat("nan");diagnostics.py(~131) — recordevidence_nonfinite: <names>inep_diagnostics.results;history.pyevidence_divergence(~152) — NaN → inf. - Tests in
test_autofit/graphical/functionality/(newtest_evidence_nonfinite.pyor intest_history.py): build anEPMeanFieldfrom a tiny graph, inject a non-finitelog_norm/ degenerate message; assert no RuntimeWarning, one named warning, NaN evidence, inf divergence.pytest test_autofit/graphical -q -x, then the full suite. - Workspace:
scripts/graphical/analytic_gaussian.py—warnings.catch_warnings(record=True)around the EP column, assert noRuntimeWarningwhose filename ends inep_mean_field.py, assertnp.isfiniteon the finallog_evidence; seed 25 leg only if ≤ 60 s. - Ledgers: append a 2026-10-23 row to the findings follow-ups table in PyAutoInsight
tasks/ep_campaign_state_2026-10-23.md(render with the worktree's ownbin/pyauto-insight board+PYAUTO_BRAIN), and a Log note in PyAutoCortexprojects/analytic_gaussian.md.
Key Files
autofit/graphical/expectation_propagation/ep_mean_field.py—variable_evidence,factor_evidence,log_evidenceautofit/messages/abstract.py:380—log_normalisation(read only)autofit/graphical/expectation_propagation/history.py—evidence_divergence,evidencesautofit/graphical/expectation_propagation/diagnostics.py— results fileautofit_workspace_test/scripts/graphical/analytic_gaussian.py— regression
Witness
python3 scripts/ensemble_seed.py --seed 25 --columns ep and the same for seed 172 complete with no RuntimeWarning from ep_mean_field.py, and the EP evidence they record is finite — or the non-finite term is raised/logged with the variable named rather than warned-and-summed, with a regression in autofit_workspace_test/scripts/graphical/ asserting the EP evidence of a converged fit is finite.
Lineage
PyAutoCortex ruling R-20260910-04; PyAutoFit#1405; PyAutoFit#1711/#1712 (sibling finding); Mind prompt draft/bug/autofit/nan_in_ep_evidence_accumulation_invalid_value.md.
Original Prompt
Click to expand starting prompt
NaN in EP evidence accumulation: invalid value encountered in add in ep_mean_field.py on analytic_gaussian seeds 25 and 172
Type: bug
Target: PyAutoFit
Repos:
- PyAutoFit
- autofit_workspace_test
Themes: - graphical-ep
Difficulty: medium
Autonomy: supervised
Priority: medium
Status: formalised
Consequence: glance
Witness:python3 scripts/ensemble_seed.py --seed 25 --columns epand the same for seed 172 complete with noRuntimeWarningfromep_mean_field.py, and the EP evidence they record is finite — or the non-finite term is raised/logged with the variable named rather than warned-and-summed, with a regression inautofit_workspace_test/scripts/graphical/asserting the EP evidence of a converged fit is finite.
Review-minutes: 3
Unattended: ready
Epic: graphical-ep
Filed: 2026-09-10
Why
Two seeds of the 200-seed N=5 ensemble behind
PyAutoCortex/tasks/analytic_gaussian/ensemble_parity.md (RAL job 342413_[0-199],
autofit 2026.8.17.1) emitted a numpy warning from the EP evidence accumulator, repeatedly.
Verbatim from hpc/batch_cpu/error/error.342413_25.err (line 1, repeated 7x in that file and
10x in error.342413_172.err):
/mnt/ral/jnightin/PyAuto/PyAutoFit/autofit/graphical/expectation_propagation/ep_mean_field.py:336: RuntimeWarning: invalid value encountered in add
return factor_evidence + sum(variable_evidence.values())
invalid value encountered in add is numpy's NaN-producing-add: at least one term of
factor_evidence or of variable_evidence.values() is non-finite (NaN, or a ±inf pair), and
the library warns and keeps going, folding the result into the EP evidence readout.
This is a separate symptom from the zero-SUCCESS stale-factor finding of the same ruling:
neither seed 25 nor seed 172 appears in that finding's 19 stale seed-legs, and both seeds'
parity results are otherwise fine — they are not among the outliers on any row. So the evidence
accumulator is going non-finite on runs that otherwise look healthy, which is exactly the case a
warning is least likely to be noticed in.
Ruled 2026-09-10 as PyAutoCortex/rulings/2026/09/R-20260910-04.md (accept with findings).
Repro
Science project analytic_gaussian at /mnt/c/Users/Jammy/Science/analytic_gaussian
(git main, no remote), results committed at b44390d:
cd /mnt/c/Users/Jammy/Science/analytic_gaussian
python3 scripts/ensemble_seed.py --seed 25 --columns ep
python3 scripts/ensemble_seed.py --seed 172 --columns ep
Run them with python3 -W error::RuntimeWarning (or np.seterr(invalid="raise")) to get the
traceback at the moment the term goes non-finite. The witness scripts are borrowed verbatim from
autofit_workspace_test/scripts/graphical/analytic_{reference,ep_minimal,autofit}.py @ 165a19e;
the per-seed sidecars are results/ens_n5/seed_0025.json and seed_0172.json.
Ask
- Where does the non-finite variable evidence come from? Which variable's
variable_evidenceentry is NaN/inf, and what makes it so — a degenerate (zero- or
negative-variance) message, a log of a non-positive normalisation, an inf−inf cancellation? - Should this warn and continue at all? Decide between guarding it (skip / clamp the term
with a named reason), raising it (a non-finite evidence is a broken fit and should say so), or
logging it with the offending variable named. Warn-and-sum is the one option that leaves no
usable trace in a batch run — the only reason it was caught here is that SLURM kept the
.errfiles. - Does it bias the EP evidence readout? If the accumulated evidence is used for
convergence, model comparison or the reportedlog_evidence, a silently-NaN term is a
correctness problem, not cosmetic. Say which, with the evidence for it. - Add the regression named in the Witness above.
Lineage
PyAutoCortex/rulings/2026/09/R-20260910-04.md— the ruling that surfaced it- PyAutoFit#1405 — the open Laplace-on-scatter collapse basin (leg B's known bias); this is not
that, but the same EP path
🤖 Generated with Claude Code
Activity
Jammy2211 commentedon Oct 23, 2026
Library PR Created
PyAutoFit PR #1714 (
feature/ep-evidence-nonfinite, commit 42548b3, label pending-release).Diagnosis: reproduces on main under the default mode projection (not under moments). The scatter
sigma's variable evidence goes +inf on sweep 4 (step 39 on seed 25, step 40 on seed 172) because one HierarchicalFactor member sends it an acceptedTruncatedNormalMessagewith mean −7374.18, sigma 384.36 on [0, 100] (support ~19 sigma into the tail);TruncatedNormalMessage.log_partitioncomputeslog(Φ(b) − Φ(a))directly, which underflows to −inf (true log Z ≈ −187.93, full log-partition ≈ 2.07 vialog_ndtr). Every adjacent factor term becomes −inf and the sum NaN. Posterior rows bit-identical to the committed sidecars;evidence_tolis None so stopping is KL-only; a NaN divergence already failed every comparison. Readout only.Shipped (reporting only): named once-per-fit warning +
evidence_nonfinite:diagnostics line + explicit NaN,evidence_divergenceinf on NaN. No message arithmetic, projection or optimiser change. The tail-stablelog_partitioncure is message maths and is filed asPyAutoMind/draft/bug/autofit/truncated_normal_log_partition_tail_underflow.md(judge tier, human decision).Tests: 7 new (6 red before),
test_autofit/graphical329 passed, full suite serial 3890 passed / 1 skipped / 1 xfailed. Heart YELLOW at ship (manifest drift; PyAutoLens release validation stale), the same two reasons the human acknowledged earlier today.Next: autofit_workspace_test regression PR (seed-0 legs assert no
ep_mean_fieldRuntimeWarning + finite evidence; new seed-25 mode leg, 3 s, asserts the term is named).Jammy2211 commentedon Oct 23, 2026
CI on #1714 (sha 42548b3): docs + generated-search-docs + unittest 3.12 + unittest 3.13 all success; unittest-nojax failed on one unrelated test —
test_autofit/non_linear/search/test_start_points.py::test_plot_false_skips_the_plot,InitializerException: The initial samples all have the same figure of merit(1 failed, 3572 passed, 180 skipped). The test drawsn=2unseeded start points (InitializerBallwithnp.random.default_rng()) on flat data and raises when the two figures of merit coincide; it passes 3/3 locally under a nojax emulation on this head, main's nojax leg was green on 39970496109 an hour earlier, and the EP evidence change is not on its path. Filed asPyAutoMind/draft/bug/autofit/start_points_test_unseeded_identical_figures_of_merit_flake.md. Workspace PR autofit_workspace_test#116 is green (smoke 3.12/3.13) and waits on the library-first gate.Per the merge rules a re-run of a red leg is the human's call:
gh run rerun 39976190947 --failed -R PyAutoLabs/PyAutoFit.Merge pull request #1714 from PyAutoLabs/feature/ep-evidence-nonfinite
Jammy2211 commentedon Oct 23, 2026
Shipped — 2026-10-23
PRs
Upstream PR
#1714 (merged 919ebd4, pending-release)
Summary
The NaN evidence on seeds 25/172 is a readout defect: an accepted truncated-normal message on the scatter sigma sits ~19 sigma into its tail, its
log_partitionunderflows to −inf, the variable's evidence goes +inf and the sum NaN, while the posterior stays bit-identical. The library now names the non-finite term once per fit (log +ep_diagnostics.results), returns an explicit NaN without numpy warnings, andevidence_divergenceis inf on a NaN. The workspace script asserts finite evidence and noep_mean_fieldRuntimeWarning on seed 0, and that the term is named on seed 25 under the mode projection.Session Notes
log_partitionvialog_ndtr— is message maths and is filed for the human:PyAutoMind/draft/bug/autofit/truncated_normal_log_partition_tail_underflow.md.draft/bug/autofit/start_points_test_unseeded_identical_figures_of_merit_flake.md.git revert 919ebd452on PyAutoFit main and the DOC: module not found #116 merge commit on autofit_workspace_test main.