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