radiate_selectors/
linear_rank.rs1use radiate_core::{Chromosome, Objective, Optimize, Population, Select, pareto, random_provider};
2
3pub struct LinearRankSelector {
4 selection_pressure: f32,
5}
6
7impl LinearRankSelector {
8 pub fn new(selection_pressure: f32) -> Self {
9 LinearRankSelector { selection_pressure }
10 }
11}
12
13impl<C: Chromosome + Clone> Select<C> for LinearRankSelector {
14 fn select(
15 &self,
16 population: &Population<C>,
17 objective: &Objective,
18 count: usize,
19 ) -> Population<C> {
20 let fitness_values = match objective {
21 Objective::Single(opt) => {
22 let scores = population
23 .get_scores()
24 .map(|score| score.as_f32())
25 .collect::<Vec<f32>>();
26 let total = scores.iter().sum::<f32>();
27 let mut fitness_values =
28 scores.iter().map(|&fit| fit / total).collect::<Vec<f32>>();
29
30 if let Optimize::Minimize = opt {
31 fitness_values.reverse();
32 }
33
34 fitness_values
35 }
36 Objective::Multi(_) => {
37 let weights =
38 pareto::weights(&population.get_scores().collect::<Vec<_>>(), objective);
39 let total_weights = weights.iter().sum::<f32>();
40 weights
41 .iter()
42 .map(|&fit| fit / total_weights)
43 .collect::<Vec<f32>>()
44 }
45 };
46
47 let total_rank = (1..=fitness_values.len()).map(|i| i as f32).sum::<f32>();
48 let mut selected_population = Vec::with_capacity(count);
49
50 for _ in 0..count {
51 let target = random_provider::range(0.0..total_rank);
52 let mut cumulative_rank = 0.0;
53
54 for (rank, _) in fitness_values.iter().enumerate() {
55 cumulative_rank += (rank + 1) as f32 * self.selection_pressure;
56 if cumulative_rank > target {
57 selected_population.push(population[rank].clone());
58 break;
59 }
60 }
61 }
62
63 Population::new(selected_population)
64 }
65}