feat: implement IntoIterator for &Study and add iter() method

Enables idiomatic `for trial in &study` iteration over completed trials.
This commit is contained in:
Manuel Raimann
2026-02-11 17:54:09 +01:00
parent db0314a1d1
commit 9b4a8321b5
2 changed files with 69 additions and 0 deletions
+25
View File
@@ -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>
where
V: PartialOrd + Clone + fmt::Display,
+44
View File
@@ -2097,3 +2097,47 @@ fn test_retries_with_zero_max_retries_same_as_optimize() {
assert_eq!(call_count.get(), 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]);
}