You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The nightly PyAutoHeart workspace-validation.yml run is RED on a single cell, run_scripts (3.12, autolens, guides), because autolens_workspace/scripts/guides/modeling/advanced/expectation_propagation.py crashes during expectation propagation with autofit.exc.MessageException: NormalMessage sigma cannot be negative. It is stochastic/unseeded (sigma=-0.016 on 2026-07-13, sigma=-0.17 on 2026-07-11), so the negative width is produced inside the EP message-passing algebra, not by a fixed model mistake. The fix belongs in the PyAutoFit library — the user-facing guide must keep exercising the real EP path (no seeding / no autoimmunity).
Plan
Reproduce the crash locally with a fixed seed that forces the negative-variance EP branch; capture the exact frame constructing a strict NormalMessage from a negative-precision/variance message.
Determine whether (a) the EP path should route that construction through NaturalNormal / update_invalid so a transient negative-variance cavity is tolerated or damped, or (b) the projection/inversion feeding sigma has a sign/validity bug.
Implement the minimal library fix in autofit/graphical/expectation_propagation and/or autofit/messages/normal.py; keep the strict assert_sigma_non_negative guard intact for the genuine prior-passing misuse it was added for.
Correct the now-misleading RelativeWidthModifier hint in the exception text (that path already abs()-guards and cannot emit a negative sigma).
Add a regression test under test_autofit/graphical/ driving an EP update through a negative-variance cavity without raising.
Validate: full test_autofit/ green (3.12/3.13), smoke the EP guide script, Heart readiness. The guide script is not modified.
Detailed implementation plan
Affected Repositories
PyAutoFit (primary)
Branch Survey
Repository
Current Branch
Dirty?
./PyAutoFit
main
clean
Suggested branch:feature/ep-negative-sigma-crash
Root cause (grounded)
The guard assert_sigma_non_negative (autofit/messages/normal.py:45) rejects sigma < 0 at strict NormalMessage.__init__ (normal.py:110). It was added deliberately for the prior-passing misuse case and is load-bearing there — do not delete it.
Its error hint blames RelativeWidthModifier, but that is stale for this path: RelativeWidthModifier.__call__ already returns value * abs(mean) (autofit/mapper/prior/width_modifier.py:110, Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331 D5), so it cannot emit a negative sigma.
EP legitimately produces intermediate messages with negative/infinite variance (cavity division of Gaussians). The correct vehicle already exists: NaturalNormal (normal.py:508), which permits eta2 in (-inf, 0) and bypasses the guard via AbstractMessage.__init__. The bug is that somewhere on the EP/declarative path a strict NormalMessage is built from a negative-variance state where a NaturalNormal should be used (or the projection/inversion that yields the passed sigma has a sign/validity bug).
Implementation Steps
Reproduce: run the EP guide (or a minimal EP factor-graph) under a seed forcing a negative-variance cavity; capture the traceback frame that calls strict NormalMessage(mean, sigma).
Inspect autofit/graphical/expectation_propagation/ep_mean_field.py (cavity prod/division ~L196-222, rescale ~L447) and factor_optimiser.py (calc_exact_update/calc_exact_projection).
Route the offending construction through NaturalNormal / AbstractMessage.update_invalid (abstract.py:346), or correct the inversion sign — narrowest change that unblocks EP without weakening the prior-passing guard.
Fix the misleading RelativeWidthModifier hint in the exception at normal.py:48.
Add a regression test in test_autofit/graphical/ that drives an EP update through a negative-variance cavity without raising; keep an assertion that strict NormalMessage(sigma<0) still raises for the prior-passing case.
Run python -m pytest test_autofit/ (3.12 + 3.13); smoke the EP guide script; confirm Heart readiness.
Key Files
autofit/messages/normal.py — strict NormalMessage guard (L45/L110) vs NaturalNormal (L508); exception hint (L48).
Preserve the strict sigma<0 guard for prior passing; only tolerate/damp negative-variance messages on the EP natural-parameter seam. Keep the change minimal.
Evidence
PyAutoHeart workspace-validation runs 29227574734 (2026-07-13) and 29153442364 (2026-07-11). Related history: #1331 / #1348 (sigma<=0 semantics, point-mass idiom).
The nightly PyAutoHeart workspace-validation.yml run is RED on run_scripts (3.12, autolens, guides) because the EP guide script crashes with NormalMessage sigma cannot be negative (sigma=-0.016 on 2026-07-13, sigma=-0.17 on 2026-07-11 — stochastic/unseeded). Root cause: the sigma<0 guard (normal.py:45) is load-bearing for prior passing, but RelativeWidthModifier already abs()-guards, so the EP crash comes from the message-passing algebra producing a negative-variance message that is wrapped as a strict NormalMessage instead of NaturalNormal. Fix in the PyAutoFit library (graphical + messages/normal.py), not the workspace guide (no autoimmunity). Fix the stale RelativeWidthModifier hint; add an EP regression test.
Overview
The nightly PyAutoHeart
workspace-validation.ymlrun is RED on a single cell,run_scripts (3.12, autolens, guides), becauseautolens_workspace/scripts/guides/modeling/advanced/expectation_propagation.pycrashes during expectation propagation withautofit.exc.MessageException: NormalMessage sigma cannot be negative. It is stochastic/unseeded (sigma=-0.016on 2026-07-13,sigma=-0.17on 2026-07-11), so the negative width is produced inside the EP message-passing algebra, not by a fixed model mistake. The fix belongs in the PyAutoFit library — the user-facing guide must keep exercising the real EP path (no seeding / no autoimmunity).Plan
NormalMessagefrom a negative-precision/variance message.NaturalNormal/update_invalidso a transient negative-variance cavity is tolerated or damped, or (b) the projection/inversion feedingsigmahas a sign/validity bug.autofit/graphical/expectation_propagationand/orautofit/messages/normal.py; keep the strictassert_sigma_non_negativeguard intact for the genuine prior-passing misuse it was added for.RelativeWidthModifierhint in the exception text (that path alreadyabs()-guards and cannot emit a negative sigma).test_autofit/graphical/driving an EP update through a negative-variance cavity without raising.test_autofit/green (3.12/3.13), smoke the EP guide script, Heart readiness. The guide script is not modified.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/ep-negative-sigma-crashRoot cause (grounded)
assert_sigma_non_negative(autofit/messages/normal.py:45) rejectssigma < 0at strictNormalMessage.__init__(normal.py:110). It was added deliberately for the prior-passing misuse case and is load-bearing there — do not delete it.RelativeWidthModifier, but that is stale for this path:RelativeWidthModifier.__call__already returnsvalue * abs(mean)(autofit/mapper/prior/width_modifier.py:110, Priors & messages: 9 confirmed bugs — guidance wanted on 5 decisions #1331 D5), so it cannot emit a negative sigma.NaturalNormal(normal.py:508), which permitseta2 in (-inf, 0)and bypasses the guard viaAbstractMessage.__init__. The bug is that somewhere on the EP/declarative path a strictNormalMessageis built from a negative-variance state where aNaturalNormalshould be used (or the projection/inversion that yields the passedsigmahas a sign/validity bug).Implementation Steps
NormalMessage(mean, sigma).autofit/graphical/expectation_propagation/ep_mean_field.py(cavityprod/division ~L196-222,rescale~L447) andfactor_optimiser.py(calc_exact_update/calc_exact_projection).NaturalNormal/AbstractMessage.update_invalid(abstract.py:346), or correct the inversion sign — narrowest change that unblocks EP without weakening the prior-passing guard.RelativeWidthModifierhint in the exception atnormal.py:48.test_autofit/graphical/that drives an EP update through a negative-variance cavity without raising; keep an assertion that strictNormalMessage(sigma<0)still raises for the prior-passing case.python -m pytest test_autofit/(3.12 + 3.13); smoke the EP guide script; confirm Heart readiness.Key Files
autofit/messages/normal.py— strictNormalMessageguard (L45/L110) vsNaturalNormal(L508); exception hint (L48).autofit/graphical/expectation_propagation/ep_mean_field.py— cavity build / division / rescale.autofit/graphical/expectation_propagation/factor_optimiser.py— exact update/projection.autofit/messages/abstract.py—update_invalid(L346),from_natural_parameters(L173),project(L266).test_autofit/graphical/— new regression test.Trade-off
Preserve the strict
sigma<0guard for prior passing; only tolerate/damp negative-variance messages on the EP natural-parameter seam. Keep the change minimal.Evidence
PyAutoHeart workspace-validation runs 29227574734 (2026-07-13) and 29153442364 (2026-07-11). Related history: #1331 / #1348 (sigma<=0 semantics, point-mass idiom).
Original Prompt
Click to expand starting prompt
Type: bug · Target: autofit · Repo: PyAutoFit · Difficulty: medium · Autonomy: safe
The nightly PyAutoHeart workspace-validation.yml run is RED on
run_scripts (3.12, autolens, guides)because the EP guide script crashes withNormalMessage sigma cannot be negative(sigma=-0.016 on 2026-07-13, sigma=-0.17 on 2026-07-11 — stochastic/unseeded). Root cause: the sigma<0 guard (normal.py:45) is load-bearing for prior passing, but RelativeWidthModifier already abs()-guards, so the EP crash comes from the message-passing algebra producing a negative-variance message that is wrapped as a strict NormalMessage instead of NaturalNormal. Fix in the PyAutoFit library (graphical + messages/normal.py), not the workspace guide (no autoimmunity). Fix the stale RelativeWidthModifier hint; add an EP regression test.