Skip to main content

gas/
pool.rs

1use crate::candidate::Candidate;
2use crate::gas::cycle::CycleProgress;
3use crate::gas::Gas;
4use std::sync::atomic::AtomicBool;
5use std::sync::Arc;
6use std::thread;
7
8#[mockall_double::double]
9use crate::rando::Rando;
10/**
11*  Run the algorithm on a set of populations simultaneously using multithreading.
12*
13*  Set sigint to true to stop the iterations manually.
14*
15**/
16pub struct Pool<const N: usize, const NSYMS: usize> {
17    pub progresses: Vec<CycleProgress<N, NSYMS>>,
18    pub handles: Vec<thread::JoinHandle<Candidate<N, NSYMS>>>,
19    pub sigint: Arc<AtomicBool>,
20}
21
22impl<const N: usize, const NSYMS: usize> Pool<N, NSYMS> {
23    pub fn new(
24        gas: Arc<Gas<N, NSYMS>>,
25        nthreads: usize,
26        sigint: Arc<AtomicBool>,
27    ) -> Pool<N, NSYMS> {
28        let mut progresses = Vec::<CycleProgress<N, NSYMS>>::with_capacity(nthreads);
29        let mut handles = Vec::<thread::JoinHandle<Candidate<N, NSYMS>>>::with_capacity(nthreads);
30
31        for _ in 0..nthreads {
32            let igas = gas.clone();
33            let mut progress = CycleProgress::new(&igas, &sigint);
34            progresses.push(progress.clone());
35
36            handles.push(thread::spawn(move || igas.cycle(&mut progress)));
37        }
38        Pool {
39            progresses,
40            handles,
41            sigint,
42        }
43    }
44
45    pub fn is_finished(&self) -> bool {
46        self.handles.iter().all(|h| h.is_finished())
47    }
48
49    pub fn winner(&mut self, gas: Arc<Gas<N, NSYMS>>) -> Candidate<N, NSYMS> {
50        let mut rng = Rando::new();
51        let winners: Vec<Candidate<N, NSYMS>> =
52            self.handles.drain(..).map(|h| h.join().unwrap()).collect();
53        let (winner, _) = gas
54            .final_tournament
55            .run(&winners, &mut rng, &gas.fitness.weights());
56        winner
57    }
58}