Skip to content

feat: re-mainline af.NSS as a first-class search on mainline blackjax ≥1.6 - #1492

Merged
Jammy2211 merged 2 commits into
mainfrom
feature/nss-remainline-mainline-blackjax
Aug 18, 2026
Merged

feat: re-mainline af.NSS as a first-class search on mainline blackjax ≥1.6#1492
Jammy2211 merged 2 commits into
mainfrom
feature/nss-remainline-mainline-blackjax

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Closes #1491. Restores the af.NSS nested slice sampler removed in #1356/#1357. The removal reason — unshippable git-fork pins (handley-lab/blackjax + yallup/nss) — is gone: nested sampling merged into mainline blackjax 1.6 (current 1.6.2), so this is now a plain-dependency search, exactly the condition the stash README's re-mainlining checklist was waiting for.

What this restores

autofit/non_linear/search/nest/nss/ (search + samples + the chunked GPU-memory builders) and test_autofit/non_linear/search/nest/nss/, verbatim from the autofit_workspace_developer/searches/nss/ stash, with the mainline port:

  • Imports: from nss.ns import log_weights, finaliseblackjax.ns.utils; the import guard now checks blackjax >= 1.6 instead of the fork packages.
  • Eval counter: fork SliceInfo.num_steps → mainline num_expansions (+ num_shrink, unchanged).
  • Chunked path: mainline build_kernel has no update_strategy= kwarg (the fork's seam), so _chunked_nss.py recomposes the kernel from mainline public helpers (build_slice_kernel / slice_constrained_step / build_adaptive_kernel / live_covariance). _chunked_update.py needed no logic change — its body is byte-equivalent to mainline's update_with_mcmc_take_last bar the final vmap→lax.map swap.
  • Wiring: NSS re-exported from autofit/__init__.py; pyproject.toml optional-extra blackjax floor bumped >=1.2.0>=1.6.2 (no cap existed).
  • Fork-era install prose removed from docstrings; tests get one ImportError match-string update.

Validation (CPU, from the checkout)

  • 17/17 NSS unit tests pass (test_autofit/non_linear/search/nest/nss/).
  • End-to-end toy through search.fit (2D Gaussian × uniform box, analytic logZ = −4.605): logZ = −4.558 ± 0.078, posterior median (1.008, −0.990) vs truth (1, −1).
  • Chunked ≡ unchunked: chunk_size=7 produces bit-identical logZ / evals / ESS to the unchunked path at fixed seed — the strongest parity check for the recomposed builder.

Context

Requested by the human 2026-08-18 as part of the inference programme (autolens_profiling results/notes/inference/PROGRAMME.md); the programme's Gate A still decides whether NSS becomes the GPU nested-sampling baseline — this PR only restores the search. Follow-ups tracked separately: the workspace tutorial section (stash checklist item 5) and the Phase 2 NSS re-benchmarking campaign.

🤖 Generated with Claude Code

https://claude.ai/code/session_018dV9h5h76hZ6trGZKWJFHe


Generated by Claude Code

claude added 2 commits August 18, 2026 16:28
… >=1.6

Restores the NSS nested slice sampler removed in #1356/#1357 (the removal
reason -- unshippable git-fork pins -- is gone: nested sampling merged into
mainline blackjax in release 1.6). Implementation restored verbatim from the
autofit_workspace_developer/searches/nss/ stash with the mainline port:

- from nss.ns import log_weights, finalise -> blackjax.ns.utils; the
  import guard now checks blackjax >= 1.6 instead of the fork packages.
- SliceInfo eval counter: fork num_steps -> mainline num_expansions.
- Chunked GPU-memory path recomposed from mainline public helpers
  (build_slice_kernel / slice_constrained_step / build_adaptive_kernel /
  live_covariance) since mainline build_kernel has no update_strategy
  kwarg; _chunked_update.py unchanged (already byte-equivalent to
  mainline's update_with_mcmc_take_last bar the vmap->lax.map swap).
- Tests restored verbatim (one ImportError match-string update); NSS
  re-exported from autofit/__init__.py; optional extra blackjax floor
  bumped 1.2.0 -> 1.6.2 (no cap existed).

Validation (CPU): 17/17 nss tests pass from the checkout; end-to-end 2D
analytic toy through search.fit gives logZ -4.558 +/- 0.078 vs analytic
-4.605 with truth recovered, and the chunked path is bit-identical to
unchunked at fixed seed (same logZ/evals/ESS).

Closes #1491.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dV9h5h76hZ6trGZKWJFHe
af.NSS samples through inline JAX closures, never through Fitness -- its
Fitness exists only for AbstractNest.perform_update post-fit work, so
forwarding iterations_per_quick_update there would wire the cadence to a
dead path. Quick updates fire through the search's own outer loop
(_fire_quick_update), so the announced cadence is real. The wiring test
postdates the search's removal, which is why the restored stash tripped it.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dV9h5h76hZ6trGZKWJFHe
@Jammy2211
Jammy2211 merged commit 401e666 into main Aug 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: re-mainline af.NSS as a first-class search on mainline blackjax ≥1.6

2 participants