Skip to content

Tags: dek3rr/hamon

Tags

v0.8.0

Toggle v0.8.0's commit message
Release 0.8.0

v0.7.0

Toggle v0.7.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
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>

v0.6.0

Toggle v0.6.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
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>

v0.5.0

Toggle v0.5.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
release: 0.5.0 (#31)

Bump version 0.4.0 -> 0.5.0 and cut the 0.5.0 changelog entry
(dated 2026-06-21). Records the refreshed example notebooks under
Changed and opens a fresh [Unreleased] section.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

v0.4.0

Toggle v0.4.0's commit message
chore: release 0.4.0

Version bumped to 0.4.0; CHANGELOG Unreleased section cut as
[0.4.0] - 2026-06-12; README citation version updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

v0.3.0

Toggle v0.3.0's commit message
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.

v0.2.0

Toggle v0.2.0's commit message
release: v0.2.0

v0.1.0

Toggle v0.1.0's commit message
v0.1.0: first release as Hamon