use crate::{Direction, Trial, TrialState};
#[derive(Debug, Clone)]
pub struct StudyState {
direction: Direction,
trials: Vec<Trial>,
}
impl StudyState {
pub fn new(direction: Direction, trials: Vec<Trial>) -> Self {
StudyState { direction, trials }
}
pub fn direction(&self) -> Direction {
self.direction
}
pub fn trials(&self) -> &[Trial] {
&self.trials
}
pub fn completed_trials(&self) -> impl Iterator<Item = &Trial> {
self.trials
.iter()
.filter(|t| t.state == TrialState::Complete && t.value.is_some())
}
pub fn n_completed(&self) -> usize {
self.completed_trials().count()
}
pub fn intermediate_values_at(&self, step: usize) -> Vec<f64> {
self.trials
.iter()
.filter(|t| matches!(t.state, TrialState::Complete | TrialState::Pruned))
.filter_map(|t| t.value_at_step(step))
.collect()
}
pub fn values_at_or_after(&self, step: usize) -> Vec<f64> {
self.trials
.iter()
.filter_map(|t| t.value_at_or_after(step))
.collect()
}
pub fn best_trial(&self) -> Option<&Trial> {
let mut best: Option<&Trial> = None;
for t in self.completed_trials() {
let v = t.value.unwrap();
match best {
None => best = Some(t),
Some(b) => {
let bv = b.value.unwrap();
let better = match self.direction {
Direction::Minimize => v < bv,
Direction::Maximize => v > bv,
};
if better {
best = Some(t);
}
}
}
}
best
}
}