Overview
The interferometer analysis crashes the whole non-linear search when a sampled model produces a non-positive-definite inversion matrix. AnalysisInterferometer.log_likelihood_function returns the fit's figure_of_merit unwrapped, so a numpy.linalg.LinAlgError: Matrix is not positive definite from the Cholesky log-det term (PyAutoArray/autoarray/inversion/inversion/abstract.py:743) propagates through Nautilus's multiprocessing pool and kills the search (~38 s). The imaging analysis already guards this; interferometer does not. Surfaced on the 2026-07-13 release-validation tail (resolves item G, PyAutoHeart#72).
This is NOT jax-0.10.2 numerical drift (the original hypothesis). It is a NumPy/JAX backend divergence: the release profile runs interferometer/model_fit.py with PYAUTO_DISABLE_JAX=1 (NumPy path), where np.linalg.cholesky raises on a non-PD matrix; the JAX path returns NaN, which the fitness resamples — so JAX silently rejects the same pathological point that NumPy crashes on. Reproduced locally on jax 0.10.2: crashes with PYAUTO_DISABLE_JAX=1, completes cleanly without it.
Plan
- Mirror the imaging analysis's NumPy-path guard in the interferometer analysis so a non-PD inversion at a sampled model resamples instead of crashing.
- Split
log_likelihood_function on self._use_jax: JAX path returns unwrapped (must stay exception-free for tracing); NumPy path wraps the fit in try/except Exception → raise af.exc.FitException (caught by autofit/non_linear/fitness.py → resample_figure_of_merit).
- Verify whether the point-source analysis has the same missing guard; align only if it shares the unwrapped figure_of_merit path.
- Validate: NumPy-path
interferometer/model_fit.py completes (bad point resampled) instead of LinAlgError; JAX path unchanged; PyAutoLens unit suite green.
Detailed implementation plan
Affected Repositories
- PyAutoLens (primary — the fix)
- autolens_workspace_test (repro / validation only; no edit expected)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoLens |
main |
clean |
| ./autolens_workspace_test |
main |
clean |
Suggested branch: feature/interferometer-analysis-fitexception
Implementation Steps
autolens/interferometer/model/analysis.py — log_likelihood_function (~L166–173): replace the direct return (fit… - penalty) with the imaging pattern from autolens/imaging/model/analysis.py:132-144:
log_likelihood_penalty = self.log_likelihood_penalty_from(instance=instance)
if self._use_jax:
return (self.fit_from(instance=instance, preloads=shared).figure_of_merit
- log_likelihood_penalty)
try:
return (self.fit_from(instance=instance, preloads=shared).figure_of_merit
- log_likelihood_penalty)
except Exception:
raise af.exc.FitException
(af is already imported at analysis.py:22.)
autolens/point/model/analysis.py — inspect log_likelihood_function (L91–160); align to the same guard only if it returns an unwrapped NumPy-path figure_of_merit.
- Add/mirror a unit test asserting a non-PD interferometer inversion raises
FitException on the NumPy path, if an imaging analogue exists to mirror.
Testing
- Repro (must now pass): wipe
output/build/model_fit/interferometer, then
PYAUTO_TEST_MODE=0 PYAUTO_SKIP_WORKSPACE_VERSION_CHECK=1 PYAUTO_DISABLE_JAX=1 JAX_ENABLE_X64=True python scripts/interferometer/model_fit.py → completes instead of LinAlgError.
- JAX path unchanged: same script with no env → still completes.
- Unit:
pytest test_autolens/interferometer/ (NumPy-only).
- Trade-off: catching broad
Exception → FitException is the accepted sibling (imaging) pattern; real bugs still surface on the unwrapped JAX path.
Key Files
autolens/interferometer/model/analysis.py — the fix (missing _use_jax split + try/except).
autolens/imaging/model/analysis.py:132-144 — the reference pattern to mirror.
PyAutoArray/autoarray/inversion/inversion/abstract.py:743 — where the raw LinAlgError originates (Cholesky log-det of the regularization matrix).
autofit/non_linear/fitness.py:235,239 — where FitException / NaN become resample_figure_of_merit.
Original Prompt
Click to expand starting prompt
interferometer/model_fit crashes with numpy.linalg.LinAlgError: Matrix is not positive definite on the 2026-07-13 release-validation tail (PyAutoHeart#72), under the release profile (PYAUTO_TEST_MODE=0). Confirmed diagnosis (2026-07-14): the release profile runs the script with PYAUTO_DISABLE_JAX=1 (NumPy path); np.linalg.cholesky raises on a non-PD regularization matrix at a sampled model, whereas the JAX path returns NaN and resamples. The interferometer analysis lacks the NumPy-path try/except → FitException guard that the imaging analysis has (imaging/model/analysis.py:132-144). Fix: mirror the imaging guard in interferometer/model/analysis.py; verify point_source. NOT jax-0.10.2 drift.
Overview
The interferometer analysis crashes the whole non-linear search when a sampled model produces a non-positive-definite inversion matrix.
AnalysisInterferometer.log_likelihood_functionreturns the fit'sfigure_of_meritunwrapped, so anumpy.linalg.LinAlgError: Matrix is not positive definitefrom the Cholesky log-det term (PyAutoArray/autoarray/inversion/inversion/abstract.py:743) propagates through Nautilus's multiprocessing pool and kills the search (~38 s). The imaging analysis already guards this; interferometer does not. Surfaced on the 2026-07-13 release-validation tail (resolves item G, PyAutoHeart#72).This is NOT jax-0.10.2 numerical drift (the original hypothesis). It is a NumPy/JAX backend divergence: the release profile runs
interferometer/model_fit.pywithPYAUTO_DISABLE_JAX=1(NumPy path), wherenp.linalg.choleskyraises on a non-PD matrix; the JAX path returns NaN, which the fitness resamples — so JAX silently rejects the same pathological point that NumPy crashes on. Reproduced locally on jax 0.10.2: crashes withPYAUTO_DISABLE_JAX=1, completes cleanly without it.Plan
log_likelihood_functiononself._use_jax: JAX path returns unwrapped (must stay exception-free for tracing); NumPy path wraps the fit intry/except Exception → raise af.exc.FitException(caught byautofit/non_linear/fitness.py→resample_figure_of_merit).interferometer/model_fit.pycompletes (bad point resampled) instead ofLinAlgError; JAX path unchanged; PyAutoLens unit suite green.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/interferometer-analysis-fitexceptionImplementation Steps
autolens/interferometer/model/analysis.py—log_likelihood_function(~L166–173): replace the directreturn (fit… - penalty)with the imaging pattern fromautolens/imaging/model/analysis.py:132-144:afis already imported at analysis.py:22.)autolens/point/model/analysis.py— inspectlog_likelihood_function(L91–160); align to the same guard only if it returns an unwrapped NumPy-path figure_of_merit.FitExceptionon the NumPy path, if an imaging analogue exists to mirror.Testing
output/build/model_fit/interferometer, thenPYAUTO_TEST_MODE=0 PYAUTO_SKIP_WORKSPACE_VERSION_CHECK=1 PYAUTO_DISABLE_JAX=1 JAX_ENABLE_X64=True python scripts/interferometer/model_fit.py→ completes instead ofLinAlgError.pytest test_autolens/interferometer/(NumPy-only).Exception → FitExceptionis the accepted sibling (imaging) pattern; real bugs still surface on the unwrapped JAX path.Key Files
autolens/interferometer/model/analysis.py— the fix (missing_use_jaxsplit + try/except).autolens/imaging/model/analysis.py:132-144— the reference pattern to mirror.PyAutoArray/autoarray/inversion/inversion/abstract.py:743— where the rawLinAlgErrororiginates (Cholesky log-det of the regularization matrix).autofit/non_linear/fitness.py:235,239— whereFitException/ NaN becomeresample_figure_of_merit.Original Prompt
Click to expand starting prompt
interferometer/model_fit crashes with
numpy.linalg.LinAlgError: Matrix is not positive definiteon the 2026-07-13 release-validation tail (PyAutoHeart#72), under the release profile (PYAUTO_TEST_MODE=0). Confirmed diagnosis (2026-07-14): the release profile runs the script withPYAUTO_DISABLE_JAX=1(NumPy path);np.linalg.choleskyraises on a non-PD regularization matrix at a sampled model, whereas the JAX path returns NaN and resamples. The interferometer analysis lacks the NumPy-pathtry/except → FitExceptionguard that the imaging analysis has (imaging/model/analysis.py:132-144). Fix: mirror the imaging guard ininterferometer/model/analysis.py; verify point_source. NOT jax-0.10.2 drift.