non_convex_opt/algorithms/differential_evolution/
archive.rs1use crate::utils::opt_prob::FloatNumber as FloatNum;
2use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector};
3use rand::{rngs::StdRng, Rng, SeedableRng};
4
5pub struct Archive<T, D>
6where
7 T: FloatNum,
8 D: Dim,
9 DefaultAllocator: Allocator<D>,
10{
11 pub solutions: Vec<OVector<T, D>>,
12 pub fitness: Vec<T>,
13 pub max_size: usize,
14 rng: StdRng,
15}
16
17impl<T, D> Archive<T, D>
18where
19 T: FloatNum,
20 D: Dim,
21 DefaultAllocator: Allocator<D>,
22{
23 pub fn new(max_size: usize, seed: u64) -> Self {
24 Self {
25 solutions: Vec::with_capacity(max_size),
26 fitness: Vec::with_capacity(max_size),
27 max_size,
28 rng: StdRng::seed_from_u64(seed),
29 }
30 }
31
32 pub fn add_solution(&mut self, solution: OVector<T, D>, fitness: T) {
33 if self.solutions.len() < self.max_size {
34 self.solutions.push(solution);
35 self.fitness.push(fitness);
36 } else if let Some(worst_idx) = self
37 .fitness
38 .iter()
39 .enumerate()
40 .min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
41 .map(|(i, _)| i)
42 {
43 if fitness > self.fitness[worst_idx] {
44 self.solutions[worst_idx] = solution;
45 self.fitness[worst_idx] = fitness;
46 }
47 }
48 }
49
50 pub fn get_random_solution(&mut self) -> Option<&OVector<T, D>> {
51 if self.solutions.is_empty() {
52 None
53 } else {
54 let idx = self.rng.random_range(0..self.solutions.len());
55 Some(&self.solutions[idx])
56 }
57 }
58
59 pub fn is_empty(&self) -> bool {
60 self.solutions.is_empty()
61 }
62
63 pub fn len(&self) -> usize {
64 self.solutions.len()
65 }
66}