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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#[cfg(test)]
#[path = "../../tests/unit/solver/population/population_test.rs"]
mod population_test;
use crate::algorithms::nsga2::{select_and_rank, Objective};
use crate::models::Problem;
use crate::solver::{Individual, Population};
use crate::utils::{compare_floats, Random};
use std::cmp::Ordering::Equal;
use std::sync::Arc;
pub struct DominancePopulation {
problem: Arc<Problem>,
random: Arc<dyn Random + Send + Sync>,
individuals: Vec<Individual>,
weights: Vec<usize>,
offspring_size: usize,
population_size: usize,
}
impl DominancePopulation {
pub fn new(
problem: Arc<Problem>,
random: Arc<dyn Random + Send + Sync>,
population_size: usize,
offspring_size: usize,
elite_size: usize,
) -> Self {
assert!(elite_size < population_size);
let max_size = population_size + offspring_size;
Self {
problem,
random,
individuals: vec![],
weights: (0..max_size)
.map(|idx| {
let weight = max_size - idx;
weight + if idx < elite_size { weight } else { 0 }
})
.collect(),
population_size,
offspring_size,
}
}
}
impl Population for DominancePopulation {
fn add(&mut self, individual: Individual) {
self.individuals.push(individual);
let max_size = self.population_size + self.offspring_size;
let mut best_order =
select_and_rank(self.individuals.as_slice(), self.individuals.len(), self.problem.objective.as_ref())
.iter()
.map(|acd| {
(
acd.index,
acd.crowding_distance,
self.problem.objective.fitness(self.individuals.get(acd.index).unwrap()),
)
})
.collect::<Vec<_>>();
if !best_order.is_empty() {
best_order.dedup_by(|(_, a_cd, a_cost), (_, b_cd, b_cost)| {
compare_floats(*a_cd, *b_cd) == Equal && compare_floats(*a_cost, *b_cost) == Equal
});
self.individuals = best_order.iter().map(|(idx, _, _)| self.individuals[*idx].deep_copy()).collect();
}
if self.individuals.len() > max_size {
self.individuals.truncate(self.population_size);
}
}
fn all<'a>(&'a self) -> Box<dyn Iterator<Item = &Individual> + 'a> {
Box::new(self.individuals.iter())
}
fn best(&self) -> Option<&Individual> {
self.individuals.first()
}
fn select(&self) -> Option<&Individual> {
if self.individuals.is_empty() {
return None;
}
let idx = self.random.weighted(&self.weights[0..self.individuals.len()]);
self.individuals.get(idx)
}
fn size(&self) -> usize {
self.individuals.len()
}
}