use crate::traits::ChromosomeT;
pub fn clearing_selection<U: ChromosomeT>(
chromosomes: &[U],
niche_radius: f64,
number_of_couples: usize,
num_parents: usize,
) -> Vec<Vec<usize>> {
let num_parents = num_parents.max(2);
crate::log_debug!(target="selection_events", method="clearing"; "Starting clearing selection with niche_radius={} number_of_couples={}", niche_radius, number_of_couples);
let n = chromosomes.len();
let mut sorted: Vec<(usize, f64)> = chromosomes
.iter()
.enumerate()
.map(|(i, c)| (i, c.fitness()))
.collect();
sorted.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
let mut cleared = vec![false; n];
for rank in 0..sorted.len() {
let (winner_idx, winner_fitness) = sorted[rank];
if cleared[winner_idx] {
continue;
}
crate::log_trace!(target="selection_events", method="clearing"; "Niche winner: index={} fitness={}", winner_idx, winner_fitness);
for &(candidate_idx, candidate_fitness) in &sorted[(rank + 1)..] {
if !cleared[candidate_idx] && (winner_fitness - candidate_fitness).abs() <= niche_radius
{
cleared[candidate_idx] = true;
crate::log_trace!(target="selection_events", method="clearing"; "Cleared: index={} fitness={}", candidate_idx, candidate_fitness);
}
}
}
let eligible: Vec<usize> = (0..n).filter(|&i| !cleared[i]).collect();
crate::log_trace!(target="selection_events", method="clearing"; "Eligible pool size: {}", eligible.len());
if eligible.len() < 2 {
crate::log_debug!(target="selection_events", method="clearing"; "Clearing selection finished: 0 groups (eligible pool too small)");
return Vec::new();
}
let mut rng = crate::rng::make_rng();
let mut mating = Vec::with_capacity(number_of_couples);
use rand::Rng;
while mating.len() < number_of_couples {
let i1 = rng.random_range(0..eligible.len());
let i2_raw = rng.random_range(0..(eligible.len() - 1));
let i2 = if i2_raw >= i1 { i2_raw + 1 } else { i2_raw };
let idx1 = eligible[i1];
let idx2 = eligible[i2];
let mut group = vec![idx1, idx2];
for _ in 2..num_parents {
let extra_i = rng.random_range(0..eligible.len());
group.push(eligible[extra_i]);
}
crate::log_trace!(target="selection_events", method="clearing"; "Mating group: {:?}", group);
mating.push(group);
}
crate::log_debug!(target="selection_events", method="clearing"; "Clearing selection finished: {} groups", mating.len());
mating
}