Skip to content

feat: replicate averaging in run_adaptive()/screen()/sobol_indices() - #124

Merged
jc-macdonald merged 1 commit into
mainfrom
feat/122-run-adaptive-replication
Aug 20, 2026
Merged

feat: replicate averaging in run_adaptive()/screen()/sobol_indices()#124
jc-macdonald merged 1 commit into
mainfrom
feat/122-run-adaptive-replication

Conversation

@jc-macdonald

Copy link
Copy Markdown
Collaborator

Summary

Closes #122. run_grid(..., n_reps=N) (#112) and run_successive_halving/run_hyperband all support rep-aware simulators (introspection-detected). run_adaptive() (NSGA-II) and screen()/sobol_indices() (Morris/Sobol) didn't -- both always evaluated a single, fixed draw, no matter how many trials/trajectories were run.

Why this matters

Found using run_adaptive to derive VBPCA hyperparameter recommendations for extreme-aspect-ratio regimes (yoavram-lab/VBPCApy#116). It's the same fragility a different investigation already hit expensively: yoavram-lab/pp-eigentest#29 -- a single-draw Morris screen (screen() doesn't vary rep either) produced a "hyperparameter matters" finding that turned out to be a threshold artifact of one particular data draw, not a real effect.

Changes

  • run_adaptive(..., n_reps=1): for n_reps>1, averages each trial's objective(s) over n_reps replicate draws before returning them to Optuna. Detects rep-aware simulators the same way run_grid does (reuses _generate_accepts_rep).
  • screen(..., n_reps=1) / sobol_indices(..., n_reps=1): same averaging, applied to the bare run_fn callable these take instead of a Simulator -- a new _run_fn_accepts_rep() mirrors the introspection convention for run_fn(cfg, *, rep=0).
  • Both default to n_reps=1, reproducing today's behavior exactly.

Test plan

  • just ci (ruff format/check, mypy --strict, pytest --cov) passes at 99.4% coverage
  • New tests: n_reps rejects <1; default n_reps=1 matches pre-run_adaptive() and screen()/sobol_indices() don't support rep-aware simulators like run_grid does #122 output exactly; a non-rep-aware run_fn/simulator gets called n_reps times with an identical draw (redundant compute, correct result); a rep-aware one receives incrementing rep=0..n_reps-1 and the returned scores reflect the true mean across draws (verified numerically for run_adaptive, and via observed-rep-set for screen/sobol_indices)

🤖 Generated with Claude Code

…122)

run_grid(..., n_reps=N) (#112) detects rep-aware simulators and varies
the replicate index; run_successive_halving/run_hyperband do too via
the same _run_single/_generate_accepts_rep helpers. run_adaptive()
(NSGA-II) and screen()/sobol_indices() (Morris/Sobol) didn't -- they
always evaluated a single, fixed draw.

Found deriving VBPCA hyperparameter recommendations via run_adaptive
for extreme-aspect-ratio data regimes (yoavram-lab/VBPCApy#116): the
same fragility class a different investigation already hit expensively
(yoavram-lab/pp-eigentest#29 -- a single-draw Morris screen produced a
"hyperparameter matters" finding that turned out to be a threshold
artifact of one data draw, not a real effect).

run_adaptive gains n_reps (mirrors run_grid's Simulator convention);
screen()/sobol_indices() gain n_reps applied to the bare run_fn
callable instead, via the same rep-keyword introspection convention.
Both default to n_reps=1 (today's behavior).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jc-macdonald
jc-macdonald merged commit 63729b5 into main Aug 20, 2026
4 checks passed
@jc-macdonald
jc-macdonald deleted the feat/122-run-adaptive-replication branch August 20, 2026 15:56
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.

run_adaptive() and screen()/sobol_indices() don't support rep-aware simulators like run_grid does

1 participant