use crate::{is_worse, median};
use hyperopt_core::{Pruner, StudyState, Trial};
#[derive(Debug, Clone)]
pub struct MedianPruner {
n_startup_trials: usize,
n_warmup_steps: usize,
min_trials_at_step: usize,
}
impl Default for MedianPruner {
fn default() -> Self {
MedianPruner {
n_startup_trials: 5,
n_warmup_steps: 0,
min_trials_at_step: 1,
}
}
}
impl MedianPruner {
pub fn new() -> Self {
Self::default()
}
pub fn n_startup_trials(mut self, n: usize) -> Self {
self.n_startup_trials = n;
self
}
pub fn n_warmup_steps(mut self, n: usize) -> Self {
self.n_warmup_steps = n;
self
}
pub fn min_trials_at_step(mut self, n: usize) -> Self {
self.min_trials_at_step = n;
self
}
}
impl Pruner for MedianPruner {
fn should_prune(&self, study_state: &StudyState, trial: &Trial) -> bool {
if study_state.n_completed() < self.n_startup_trials {
return false;
}
let Some((step, value)) = trial.last_intermediate() else {
return false;
};
if step < self.n_warmup_steps {
return false;
}
let others = study_state.intermediate_values_at(step);
if others.len() < self.min_trials_at_step {
return false;
}
match median(&others) {
Some(m) => is_worse(study_state.direction(), value, m),
None => false,
}
}
}