Struct WilcoxonPruner
pub struct WilcoxonPruner { /* private fields */ }Expand description
A statistical pruner: prune a trial that is significantly worse than the incumbent under a paired Wilcoxon signed-rank test.
On each report the trial’s values so far (tracked per trial) are paired,
step-by-step, against the best completed trial’s values at the same steps,
and the trial is pruned when wilcoxon_worse says it is significantly worse
at level alpha. It expects each reported step
to be an independent, comparable sub-evaluation — a problem instance, a
held-out episode reported inline — not a point on a monotone learning curve;
for curves use AshaPruner or
MedianPruner.
§Fanned vs single-seed — what this scheduler actually sees
The design imagines a Wilcoxon prune over a fan’s per-seed samples
(multi-seed protocol).
In a single-seed study the objective
streams a value per report, so the per-report paired test above is honestly
wired. In a multi-seed fan study the loop captures each replicate’s
reports and, after all replicates finish, sends one deterministic aggregate
per aligned step to the scheduler. A decision applies to the whole fan, so
a per-replicate or partially evaluated mid-fan prune remains impossible.
Since M4.0 the finishing
trial’s fan is visible at on_trial_end (its
replicates are populated for a fanned study),
but the other trials in the StudyView still have empty replicates, so
a between-trials fan comparison (this trial’s fan against an incumbent’s)
remains a caller-side operation: read both fans through
Study::trial_fan and call
wilcoxon_worse (the fan’s paired common-random-numbers seeds are exactly
the matched structure that free function wants).
§Why it tracks per-trial state
The frozen seam hands on_report the ask-time
StudyView (which does not contain the reporting trial) and no storage
handle, so the trial’s own earlier reports are nowhere to be read. The pruner
therefore keeps a small per-trial list of (step, value) behind a mutex,
appended as reports arrive and discarded on
on_trial_end. This is transient live-run
bookkeeping, not study state — state is None and the
list is rebuilt from the reports on a resume.
§Multi-objective / determinism
Never prunes a multi-objective study (no single “worse”). The decision reads the ask-time incumbent, so it is replayable, not pre-determined under parallelism (where determinism stops); single-worker with a fixed seed is reproducible.
Implementations§
§impl WilcoxonPruner
impl WilcoxonPruner
pub fn new() -> Self
pub fn new() -> Self
A pruner at DEFAULT_ALPHA with DEFAULT_MIN_PAIRS.
pub fn with_alpha(self, alpha: f64) -> Self
pub fn with_alpha(self, alpha: f64) -> Self
Sets the significance level (smaller = more conservative, prunes less).
pub fn with_min_pairs(self, min_pairs: usize) -> Self
pub fn with_min_pairs(self, min_pairs: usize) -> Self
Sets the minimum number of paired reports before a prune may fire.
pub fn with_objective(self, obj: usize) -> Self
pub fn with_objective(self, obj: usize) -> Self
Selects which objective dimension to gate on (default 0).
Trait Implementations§
§impl Debug for WilcoxonPruner
impl Debug for WilcoxonPruner
§impl Default for WilcoxonPruner
impl Default for WilcoxonPruner
§impl Scheduler for WilcoxonPruner
impl Scheduler for WilcoxonPruner
§fn on_trial_end(
&self,
_study: &StudyView,
trial: &FrozenTrial,
) -> Result<Vec<Command>>
fn on_trial_end( &self, _study: &StudyView, trial: &FrozenTrial, ) -> Result<Vec<Command>>
Discards the finished trial’s tracked history.
§fn state(&self) -> Result<Option<SchedulerState>>
fn state(&self) -> Result<Option<SchedulerState>>
None: the per-trial history is transient live-run bookkeeping, not
persistent study state.