use crate::traits::ChromosomeT;
use log::{debug, trace};
use rand::Rng;
pub fn truncation_selection<U: ChromosomeT>(
chromosomes: &[U],
couples: usize,
) -> Vec<(usize, usize)> {
debug!(target="selection_events", method="truncation"; "Starting truncation selection");
let n = chromosomes.len();
if n < 2 {
return Vec::new();
}
let mut indexed: Vec<(usize, f64)> = chromosomes
.iter()
.enumerate()
.map(|(i, c)| (i, c.fitness()))
.collect();
indexed.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
let truncation_size = (n / 2).max(2).min(n);
let elite = &indexed[..truncation_size];
trace!(
target="selection_events", method="truncation";
"Population size {}, truncation size {}", n, truncation_size
);
for (rank, &(original_idx, fit)) in elite.iter().enumerate() {
trace!(
target="selection_events", method="truncation";
"Elite rank {} -> index {} fitness {}", rank, original_idx, fit
);
}
let mut rng = crate::rng::make_rng();
let mut mating = Vec::with_capacity(couples);
for _ in 0..couples {
let a = elite[rng.random_range(0..truncation_size)].0;
let b = elite[rng.random_range(0..truncation_size)].0;
mating.push((a, b));
trace!(
target="selection_events", method="truncation";
"Mating pair: {} - {}", a, b
);
}
debug!(
target="selection_events", method="truncation";
"Truncation selection finished with {} pairs", mating.len()
);
mating
}