-
Notifications
You must be signed in to change notification settings - Fork 0
/
rank_selection.rs
39 lines (34 loc) · 1.35 KB
/
rank_selection.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
use crate::{Individual, Selection};
use rand::thread_rng;
use rayon::prelude::*;
use std::cmp::Ordering;
use rand::distributions::{Distribution, WeightedIndex};
/// # Rank Selection
///
/// It creates an ranking of the individuals based on their fitness, where the works takes 1, the next 2, and follows
/// linearly so that the best receives `n` (number of individuals in the population). Then it chooses the individuals
/// with probability based on the ranking value.
#[derive(Clone, Default)]
pub struct RankSelection;
impl<T: Individual> Selection<T> for RankSelection {
fn get_mating_pool(&self, initial_population: &Vec<T>) -> Vec<T> {
let mut sorted_population = initial_population.clone();
sorted_population.par_sort_by(|a, b| {
a.get_fitness()
.partial_cmp(&b.get_fitness())
.unwrap_or(Ordering::Equal)
});
let population_size = sorted_population.len();
let weights: Vec<_> = (1..=population_size).map(|rank| rank).collect();
let dist = WeightedIndex::new(&weights).unwrap();
(0..population_size)
.into_par_iter()
.map_init(
|| thread_rng(),
|mut rng, _| {
let index = dist.sample(&mut rng);
sorted_population[index].clone()
})
.collect()
}
}