non_convex_opt/algorithms/differential_evolution/
archive.rs

1use 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}