use rand::Rng as _;
use crate::core::candidate::Candidate;
use crate::core::rng::Rng;
pub fn select_random<D: Clone>(
population: &[Candidate<D>],
count: usize,
rng: &mut Rng,
) -> Vec<D> {
if count == 0 {
return Vec::new();
}
assert!(
!population.is_empty(),
"select_random called on empty population with count > 0",
);
let mut out = Vec::with_capacity(count);
for _ in 0..count {
let idx = rng.random_range(0..population.len());
out.push(population[idx].decision.clone());
}
out
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::evaluation::Evaluation;
use crate::core::rng::rng_from_seed;
fn cand(d: u32) -> Candidate<u32> {
Candidate::new(d, Evaluation::new(vec![d as f64]))
}
#[test]
fn returns_count_decisions_from_population() {
let pop = [cand(1), cand(2), cand(3)];
let mut rng = rng_from_seed(42);
let picks = select_random(&pop, 5, &mut rng);
assert_eq!(picks.len(), 5);
for p in &picks {
assert!([1, 2, 3].contains(p));
}
}
#[test]
fn count_zero_returns_empty() {
let pop = [cand(1)];
let mut rng = rng_from_seed(0);
assert!(select_random(&pop, 0, &mut rng).is_empty());
}
#[test]
#[should_panic(expected = "empty population")]
fn empty_population_panics() {
let pop: Vec<Candidate<u32>> = Vec::new();
let mut rng = rng_from_seed(0);
let _ = select_random(&pop, 1, &mut rng);
}
}