use crate::traits::ChromosomeT;
use rand::Rng;
#[cfg(all(not(target_arch = "wasm32"), feature = "parallel"))]
use rayon::prelude::*;
pub fn tournament<U>(
chromosomes: &[U],
couples: usize,
_number_of_threads: usize,
num_parents: usize,
) -> Vec<Vec<usize>>
where
U: ChromosomeT + Send + Sync + 'static + Clone,
{
tournament_impl(chromosomes, couples, num_parents)
}
fn tournament_impl<U>(chromosomes: &[U], couples: usize, num_parents: usize) -> Vec<Vec<usize>>
where
U: ChromosomeT + Send + Sync + 'static + Clone,
{
crate::log_debug!(target="selection_events", method="tournament"; "Starting tournament selection");
let num_parents = num_parents.max(2);
let couples = if couples * num_parents > chromosomes.len() {
chromosomes.len() / num_parents
} else {
couples
};
let total_contestants = couples * num_parents;
#[cfg(all(not(target_arch = "wasm32"), feature = "parallel"))]
let winners: Vec<usize> = (0..total_contestants)
.into_par_iter()
.map(|_| {
let mut rng = crate::rng::make_rng();
let index_1 = rng.random_range(0..chromosomes.len());
let index_2 = rng.random_range(0..chromosomes.len());
crate::log_trace!(target="selection_events", method="tournament"; "Tournament between {} and {}", index_1, index_2);
if chromosomes[index_1].fitness() >= chromosomes[index_2].fitness() {
index_1
} else {
index_2
}
})
.collect();
#[cfg(any(target_arch = "wasm32", not(feature = "parallel")))]
let winners: Vec<usize> = (0..total_contestants)
.map(|_| {
let mut rng = crate::rng::make_rng();
let index_1 = rng.random_range(0..chromosomes.len());
let index_2 = rng.random_range(0..chromosomes.len());
crate::log_trace!(target="selection_events", method="tournament"; "Tournament between {} and {}", index_1, index_2);
if chromosomes[index_1].fitness() >= chromosomes[index_2].fitness() {
index_1
} else {
index_2
}
})
.collect();
let mut mating = Vec::new();
for chunk in winners.chunks(num_parents) {
if chunk.len() == num_parents {
let group = chunk.to_vec();
crate::log_trace!(target="selection_events", method="tournament"; "Mating group: {:?}", group);
mating.push(group);
}
}
crate::log_debug!(target="selection_events", method="tournament"; "Tournament selection finished");
mating
}