feat: implement IntoIterator for &Study and add iter() method
Enables idiomatic `for trial in &study` iteration over completed trials.
This commit is contained in:
@@ -1790,6 +1790,31 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V> Study<V>
|
||||||
|
where
|
||||||
|
V: PartialOrd + Clone,
|
||||||
|
{
|
||||||
|
/// Returns an iterator over all completed trials.
|
||||||
|
///
|
||||||
|
/// This clones the internal trial list, so it is suitable for
|
||||||
|
/// analysis and iteration but not for hot paths.
|
||||||
|
pub fn iter(&self) -> std::vec::IntoIter<CompletedTrial<V>> {
|
||||||
|
self.trials().into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> IntoIterator for &Study<V>
|
||||||
|
where
|
||||||
|
V: PartialOrd + Clone,
|
||||||
|
{
|
||||||
|
type Item = CompletedTrial<V>;
|
||||||
|
type IntoIter = std::vec::IntoIter<CompletedTrial<V>>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V> fmt::Display for Study<V>
|
impl<V> fmt::Display for Study<V>
|
||||||
where
|
where
|
||||||
V: PartialOrd + Clone + fmt::Display,
|
V: PartialOrd + Clone + fmt::Display,
|
||||||
|
|||||||
@@ -2097,3 +2097,47 @@ fn test_retries_with_zero_max_retries_same_as_optimize() {
|
|||||||
assert_eq!(call_count.get(), 5);
|
assert_eq!(call_count.get(), 5);
|
||||||
assert_eq!(study.n_trials(), 5);
|
assert_eq!(study.n_trials(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Tests: IntoIterator for &Study
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_iterator_iterates_all_trials() {
|
||||||
|
let study: Study<f64> = Study::with_sampler(Direction::Minimize, RandomSampler::with_seed(42));
|
||||||
|
let x_param = FloatParam::new(0.0, 10.0);
|
||||||
|
|
||||||
|
for _ in 0..5 {
|
||||||
|
let mut trial = study.create_trial();
|
||||||
|
let x = x_param.suggest(&mut trial).unwrap();
|
||||||
|
study.complete_trial(trial, x * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
for trial in &study {
|
||||||
|
assert_eq!(trial.state, optimizer::TrialState::Complete);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
assert_eq!(count, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_iterator_empty_study() {
|
||||||
|
let study: Study<f64> = Study::new(Direction::Minimize);
|
||||||
|
|
||||||
|
let count = (&study).into_iter().count();
|
||||||
|
assert_eq!(count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_iterator_preserves_insertion_order() {
|
||||||
|
let study: Study<f64> = Study::new(Direction::Minimize);
|
||||||
|
|
||||||
|
for i in 0..3 {
|
||||||
|
let trial = study.create_trial();
|
||||||
|
study.complete_trial(trial, f64::from(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ids: Vec<u64> = (&study).into_iter().map(|t| t.id).collect();
|
||||||
|
assert_eq!(ids, vec![0, 1, 2]);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user