// pub struct EvaluatedChromosome { // chromosome: TInput, // evaluation: TResult, // } use rand::{Rng, RngCore}; use crate::comparison::BetterThanOperator; pub trait Selection { fn select(&mut self, count: usize, evaluations: &Vec, better_than: &dyn BetterThanOperator) -> impl Iterator; } pub struct TournamentSelection { rng: Box, p: f64, k: usize } impl TournamentSelection { pub fn new(k: usize, p: f64) -> Self { assert!(0.0 <= p && p <= 1.0); assert!(k > 0); Self { rng: Box::new(rand::rng()), p, k } } fn tournament(&mut self, idxs: &mut Vec, evaluations: &Vec, better_than: &dyn BetterThanOperator) -> usize { idxs.sort_by(|&i, &j| better_than.ordering(&evaluations[i], &evaluations[j])); let mut p_selector = self.rng.random_range(0.0..=1.0f64); let p = self.p; let k = self.k; let mut selected = idxs[k - 1]; // let's say p = 0.7 // the best has probability 0.7 of being selected // if the best is not selected, the second has 0.7 probability of being selected... (that's 0.7 * 0.3 without conditions) // and so on. The last element has the remaining probability. for i in 0..k-1 { if p_selector <= p { selected = i; break; } p_selector -= p; // 'Expand' the rest to '100%' again p_selector /= 1.0 - p; } selected } } impl Selection for TournamentSelection { fn select(&mut self, count: usize, evaluations: &Vec, better_than: &dyn BetterThanOperator) -> impl Iterator { // 1. Rank // fn rank(l: &Vec) -> Vec { // let mut indices = (0..l.len()).collect::>(); // let mut ranks = vec![0; l.len()]; // // argsort... // indices.sort_by_key(|&i| &l[i]); // for (rank, idx) in indices.into_iter().enumerate() { // ranks[idx] = rank; // } // ranks // } // let ranks = rank(evaluations); // 2. Let's choose k random 'count' times // let mut already_selected = vec![false; evaluations.len()]; let mut k_selected_idxs = vec![0; self.k]; (0..count).map(move |_| { for selected_idx in k_selected_idxs.iter_mut() { *selected_idx = self.rng.random_range(0..evaluations.len()); } self.tournament(&mut k_selected_idxs, evaluations, better_than) }) } }