M env/src/comparison/mod.rs => env/src/comparison/mod.rs +8 -0
@@ 1,5 1,13 @@
pub trait BetterThanOperator<T> {
fn better_than(self: &Self, a: &T, b: &T) -> bool;
+
+ fn ordering(&self, a: &T, b: &T) -> std::cmp::Ordering {
+ if self.better_than(a, b) {
+ std::cmp::Ordering::Less
+ } else {
+ std::cmp::Ordering::Greater
+ }
+ }
}
pub struct MinimizingOperator;
M env/src/main.rs => env/src/main.rs +1 -0
@@ 1,6 1,7 @@
pub mod fitness;
pub mod crossover;
pub mod bounded;
+pub mod selection;
pub mod initializer;
pub mod terminating;
pub mod perturbation;
A env/src/selection.rs => env/src/selection.rs +90 -0
@@ 0,0 1,90 @@
+// pub struct EvaluatedChromosome<TInput, TResult> {
+// chromosome: TInput,
+// evaluation: TResult,
+// }
+
+use rand::{Rng, RngCore};
+
+use crate::comparison::BetterThanOperator;
+
+pub trait Selection<T> {
+ fn select(&mut self, count: usize, evaluations: &Vec<T>, better_than: &dyn BetterThanOperator<T>) -> impl Iterator<Item = usize>;
+}
+
+pub struct TournamentSelection {
+ rng: Box<dyn RngCore>,
+ 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<T: PartialOrd>(&mut self, idxs: &mut Vec<usize>, evaluations: &Vec<T>, better_than: &dyn BetterThanOperator<T>) -> 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<T: Ord> Selection<T> for TournamentSelection {
+ fn select(&mut self, count: usize, evaluations: &Vec<T>, better_than: &dyn BetterThanOperator<T>) -> impl Iterator<Item = usize> {
+ // 1. Rank
+ // fn rank<T: Ord>(l: &Vec<T>) -> Vec<usize> {
+ // let mut indices = (0..l.len()).collect::<Vec<_>>();
+ // 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)
+ })
+ }
+}