use super::CvSplitter;
use crate::error::{ModelSelectionError, Result};
#[derive(Debug, Clone, Copy, Default)]
pub struct LeaveOneOut;
impl CvSplitter for LeaveOneOut {
fn split(&self, n_samples: usize) -> Result<Vec<(Vec<usize>, Vec<usize>)>> {
if n_samples < 2 {
return Err(ModelSelectionError::NotEnoughSamples {
needed: 2,
got: n_samples,
});
}
let splits = (0..n_samples)
.map(|test_idx| {
let train: Vec<usize> = (0..n_samples).filter(|&i| i != test_idx).collect();
(train, vec![test_idx])
})
.collect();
Ok(splits)
}
fn n_splits(&self) -> usize {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn each_sample_is_test_once() {
let splits = LeaveOneOut.split(5).unwrap();
assert_eq!(splits.len(), 5);
for (i, (train, test)) in splits.iter().enumerate() {
assert_eq!(test, &vec![i]);
assert_eq!(train.len(), 4);
assert!(!train.contains(&i));
}
}
#[test]
fn errors_on_tiny_input() {
assert!(LeaveOneOut.split(1).is_err());
}
}