radiate_engines/steps/
evaluate.rs1use radiate_core::{
2 Chromosome, Ecosystem, MetricSet, Objective, Problem, engine::EngineStep, metric_names,
3 thread_pool::ThreadPool,
4};
5use std::sync::Arc;
6
7pub trait Evaluator<C: Chromosome, T>: Send + Sync {
8 fn eval(
9 &self,
10 ecosystem: &mut Ecosystem<C>,
11 thread_pool: Arc<ThreadPool>,
12 problem: Arc<dyn Problem<C, T>>,
13 ) -> usize;
14}
15
16pub struct SequentialEvaluator;
17
18impl<C: Chromosome, T> Evaluator<C, T> for SequentialEvaluator
19where
20 C: Chromosome + 'static,
21{
22 fn eval(
23 &self,
24 ecosystem: &mut Ecosystem<C>,
25 _thread_pool: Arc<ThreadPool>,
26 problem: Arc<dyn Problem<C, T>>,
27 ) -> usize {
28 let mut count = 0;
29 for individual in ecosystem.population.iter_mut() {
30 if individual.score().is_some() {
31 continue;
32 } else {
33 let geno = individual.take_genotype();
34 let score = problem.eval(&geno);
35 individual.set_score(Some(score));
36 individual.set_genotype(geno);
37 count += 1;
38 }
39 }
40
41 count
42 }
43}
44
45pub struct WorkerPoolEvaluator;
46
47impl<C: Chromosome, T> Evaluator<C, T> for WorkerPoolEvaluator
48where
49 C: Chromosome + 'static,
50 T: Send + Sync + 'static,
51{
52 fn eval(
53 &self,
54 ecosystem: &mut Ecosystem<C>,
55 thread_pool: Arc<ThreadPool>,
56 problem: Arc<dyn Problem<C, T>>,
57 ) -> usize {
58 let mut jobs = Vec::new();
59 let len = ecosystem.population.len();
60 for idx in 0..len {
61 if ecosystem.population[idx].score().is_none() {
62 let geno = ecosystem.population[idx].take_genotype();
63 jobs.push((idx, geno));
64 }
65 }
66
67 let work_results = jobs
68 .into_iter()
69 .map(|(idx, geno)| {
70 let problem = Arc::clone(&problem);
71 thread_pool.submit_with_result(move || {
72 let score = problem.eval(&geno);
73 (idx, score, geno)
74 })
75 })
76 .collect::<Vec<_>>();
77
78 let count = work_results.len();
79 for work_result in work_results {
80 let (idx, score, genotype) = work_result.result();
81 ecosystem.population[idx].set_score(Some(score));
82 ecosystem.population[idx].set_genotype(genotype);
83 }
84
85 count
86 }
87}
88
89pub struct EvaluateStep<C: Chromosome, T> {
90 pub(crate) objective: Objective,
91 pub(crate) evaluator: Arc<dyn Evaluator<C, T>>,
92 pub(crate) problem: Arc<dyn Problem<C, T>>,
93 pub(crate) thread_pool: Arc<ThreadPool>,
94}
95
96impl<C: Chromosome, T> EvaluateStep<C, T> {
97 pub fn new(
98 objective: Objective,
99 thread_pool: Arc<ThreadPool>,
100 problem: Arc<dyn Problem<C, T>>,
101 evaluator: Arc<dyn Evaluator<C, T>>,
102 ) -> Self {
103 EvaluateStep {
104 objective,
105 evaluator,
106 problem,
107 thread_pool,
108 }
109 }
110}
111
112impl<C, T> EngineStep<C> for EvaluateStep<C, T>
113where
114 C: Chromosome + 'static,
115{
116 fn execute(&mut self, _: usize, metrics: &mut MetricSet, ecosystem: &mut Ecosystem<C>) {
117 let timer = std::time::Instant::now();
118
119 let count = self.evaluator.eval(
120 ecosystem,
121 Arc::clone(&self.thread_pool),
122 Arc::clone(&self.problem),
123 ) as f32;
124
125 self.objective.sort(&mut ecosystem.population);
126
127 metrics.upsert_operations(metric_names::FITNESS, count, timer.elapsed());
128 }
129}