Tags: dek3rr/hamon
Tags
feat!: NRPT autotuning as the primary interface (0.7.0) (#44) * feat!: complete NRPT autotuning as the primary interface (0.7.0) Make full autotuning the main way to use hamon and unify the tuner names. BREAKING — rename the NRPT tuners to a coherent tune_* family: nrpt_adaptive -> tune_schedule discover_chain_count -> tune_chains discover_gibbs_steps -> tune_exploration (nrpt and optimize_schedule unchanged; no deprecated aliases.) New one-call autotuning: - autotune(...) -> NRPTPlan runs the dependency-ordered, cheap->expensive recipe: tune_chains at n_expl=1 -> tune_exploration at fixed N reusing the schedule (it is invariant to n_expl, so N is never re-discovered) -> a schedule polish that also leaves a warm cold-chain state. - NRPTPlan.sample(key, n) draws cheaply and repeatably without re-tuning. - autosample(...) is the one-shot (samples, AutotuneReport) convenience. - The persistent compile cache is enabled by default (compile_cache=, exposed as hamon.enable_persistent_compile_cache) to amortize the multi-probe recompiles. tune_exploration gains a fixed_schedule path (production-only probes, no re-tuning) used by autotune. sample_nodes pins the output column order. BREAKING — ising_sample now autotunes gibbs_steps_per_round via autosample; its gibbs_steps_per_round and n_draw_chains params are removed, max_chains is added, and the diagnostics dict gains gibbs_steps_per_round/report and drops converged_reason/acceptance_rate/health. Compile guard (per the profiling playbook): the rename is identifiers only, so the core paths stay bit-identical — bench NRPT_NOOBS=938b8b504fb1ea4a and OBS_OUT=f3bbd537da9adea2 unchanged with traces=1 / fori_loop-reuse traces=0. ising_sample's SAMP checksum changes by design (it now tunes n_expl; on GPU it picks n_expl=8). Full CPU suite 360 passed + GPU smoke 3/3, ruff + pyright clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: refresh guides and notebooks for autotuning as the primary interface - index/getting-started: lead with autosample/autotune; fix the stale 3-tuple unpacks in the manual nrpt/tune_schedule examples (both return 2-tuples). - concepts: add "Local exploration" and "Autotuning" sections explaining n_expl and how autotune composes the three searches in dependency order. - architecture: add the autotuning-orchestration section (schedule reuse, measured-wall-time exploration, persistent compile cache). - 05_parallel_tempering: add an autosample showcase cell up front (validated to run) framing the rest of the notebook as "what it does under the hood". - 02_the_ising_model: replace the dropped diagnostics['converged_reason'] key (ising_sample now returns gibbs_steps_per_round instead). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(autotune): report round-trip count and measure efficiency over a real production window The AutotuneReport's round-trip diagnostics were taken from the final polish run sized at rounds_per_probe, which is far too short for the rate to be representative — a round trip needs >= ~2N rounds, so at N=19 a 200-round window reported tau_obs=0.005 / efficiency=8% when the tuned config actually achieves ~30% (matching equivalent manual runs). - Add an n_rounds production argument (default 1000) for the final run, decoupled from the cheap per-probe budget. It equilibrates the warm cold state and is the window the round-trip rate/efficiency are measured over. - Surface total_round_trips and production_rounds on AutotuneReport and in summary() (e.g. "round trips: 19 over 1000 rounds ... efficiency=0.296"). Verified on a 16x16 ferromagnet: efficiency 0.08 -> 0.30 (now consistent with manual tuning), round-trip count printed. pyright clean; autotune + ising tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(05): match autosample budgets to the manual pipeline for a fair comparison Set n_tune=8, rounds_per_probe=200, n_rounds=2500 in the autosample showcase cell so its reported round-trip efficiency is directly comparable to the manual pipeline at the end of the notebook. With those matched, the remaining gap is purely the autotuned n_expl=2 (best ESS/compute on CPU) vs the manual fixed n_expl=5 — higher per-round efficiency but ~2x more compute per round, so per-compute the autotuned choice still wins. Added a markdown note explaining this. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(05): set manual pipeline budgets to autotune defaults for a fair comparison Reverses the previous approach: instead of inflating the autosample showcase to the manual run's budgets, put both at autotune's defaults. The autosample cell now uses defaults (n_tune=4, rounds_per_probe=400, n_rounds=1000), and the manual comparison/pipeline cells (the Naive/Opt table and "put it all together") are set to the same budgets (n_tune 5->4, rounds_per_tune 200->400, production rounds ->1000). The only deliberate remaining difference is gibbs_steps_per_round, which autotune calibrates to the device (~2 on CPU) while the manual run fixes 5 — higher per-round efficiency but ~2x more compute per round. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(nrpt): split tuners and autotune out of nrpt.py nrpt.py had grown to ~2250 lines. Split it along its one-directional dependency (core <- tuning <- autotune), keeping the performance-critical jitted core in nrpt.py: - hamon/tuning.py: tune_schedule, tune_chains, tune_exploration + private helpers. Host-side orchestration that calls the jitted nrpt. - hamon/autotune.py: autotune, autosample, NRPTPlan, AutotuneReport. nrpt.py keeps the compiled round loop (_nrpt_rounds + builders), nrpt(), optimize_schedule, the jitted stat helpers, _resolve_run_inputs, and _ChainSource. _nrpt_rounds and _nrpt_rounds_trace_count stay put so the bench and trace-count tests are unaffected. Result: nrpt.py 2253 -> 939 lines; tuning.py 964; autotune.py 406. Public hamon.* API unchanged (names re-exported from their new homes); test/bench imports of the tuners updated to hamon.tuning. Performance-neutral by construction (JIT caches key on the function object, not the module; the hot loop is entirely inside the unchanged compiled _nrpt_rounds). Verified: bench NRPT_NOOBS=938b8b504fb1ea4a and OBS_OUT=f3bbd537da9adea2 bit-identical with traces=1; full CPU suite 360 passed + GPU smoke 3/3; ruff + pyright clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(examples): refresh notebook outputs for the autotuning interface Re-run cell outputs for 02_the_ising_model and 05_parallel_tempering reflecting the autotuned pipeline — e.g. ising_sample now reports the autotuned gibbs_steps_per_round (n_expl) instead of the removed converged_reason, and the autosample showcase reports N / n_expl / Lambda / round-trip efficiency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * style: ruff-format 05_parallel_tempering notebook (two blank lines before def) Matches the CI-pinned ruff 0.15.18 (a blank line before a top-level function in a notebook cell); local ruff 0.15.17 had not applied it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(05): import tune_schedule/tune_chains from hamon.tuning in the notebook The nrpt.py split moved the tuners to hamon.tuning, but notebook 05's import cell still pulled them from hamon.nrpt, which nbmake caught (ImportError on cell 1). Split the import; nrpt stays in hamon.nrpt. Verified the full notebook executes via nbmake. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
release: 0.6.0 (#42) Bumps version 0.5.0 -> 0.6.0 (pyproject, README citation) and finalizes the CHANGELOG [Unreleased] -> [0.6.0], opening a fresh [Unreleased]. 0.6.0 is a performance + behavioural release. Cold-start NRPT is substantially faster (compile-bound paths cut across the pipeline: numpy diagnostics, jitted draw + round-trip summary, single-compile schedule optimizer, cached program structure, RLF colouring, and a cached-probe fix in chain-count discovery). Two of these change sampling output and so are NOT bit-compatible with 0.5.0 (results remain correct draws from the same distribution): - RLF block colouring changes the block partition. - discover_chain_count may return a chain count 1 lower (within its existing convergence tolerance). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
docs: fix nav references to renamed example notebooks mkdocs.yml and getting-started.md still pointed at the pre-refresh example notebook filenames (00_probabilistic_computing.ipynb, 01_all_of_hamon.ipynb, etc.), which no longer exist after 856de81 renamed/restructured the examples. With strict mode off, mkdocs rendered these as untitled "None" nav entries on GitHub Pages.