cisat/abm/cohort.rs
1//! This module contains the Cohort class, a container for multiple Teams.
2
3use super::{
4 super::utilities::{parameters::Parameters, Solution},
5 agent::{Agent, AgentMethods},
6 team::{Team, TeamMethods},
7};
8use crate::problems::Ackley;
9use rayon::prelude::*;
10use std::marker::PhantomData;
11
12/// This is the Cohort class, a container for multiple teams
13///
14/// The cohort allows you to run a set of teams easily to achieve statistical significance:
15/// ```
16/// use cisat::{Parameters, Cohort, problems::Ackley};
17/// let mut x = Cohort::<Ackley>::new(Parameters::default());
18/// x.solve();
19/// ```
20///Above, we specify one generic parameters `Ackley`, which tells the `Cohort` which problem to solve.
21/// However, we can get more complciated than that! For instance, we feed in a struct that implements
22/// `AgentMethods` to specific which type of agent to use:
23/// ```
24/// use cisat::{Parameters, Cohort, problems::Ackley, Agent};
25/// let mut x = Cohort::<Ackley, Agent<Ackley>>::new(Parameters::default());
26/// x.solve();
27/// ```
28/// Here, we just fed in the in-build `Agent` class which already implements `AgentMethods`. You can
29/// implement the trait yourself to define a new agent though. The same applies for 'Team' and
30/// 'TeamMethods':
31/// ```
32/// use cisat::{Parameters, Cohort, problems::Ackley, Agent, Team};
33/// let mut x = Cohort::<Ackley, Agent<Ackley>, Team<Ackley, Agent<Ackley>>>::new(Parameters::default());
34/// x.solve();
35/// ```
36
37#[derive(Clone, Debug)]
38pub struct Cohort<S = Ackley, A = Agent<S>, T = Team<S, A>>
39where
40 S: Solution,
41 A: AgentMethods<S>,
42 T: TeamMethods<S, A>,
43{
44 /// This contains the parameters for the class
45 parameters: Parameters,
46 /// This contains the teams in the cohort
47 team_list: Vec<T>,
48 /// Bookkeeping the solution type
49 solution_type: PhantomData<S>,
50 /// Bookkeeping the agent-type
51 agent_type: PhantomData<A>,
52}
53
54impl<S, A, T> Cohort<S, A, T>
55where
56 S: Solution,
57 A: AgentMethods<S>,
58 T: TeamMethods<S, A>,
59{
60 /// This generates a new cohort
61 pub fn new(parameters: Parameters) -> Cohort<S, A, T> {
62 Cohort {
63 team_list: (0..parameters.number_of_teams)
64 .map(|_| T::new(parameters.clone()))
65 .collect(),
66 solution_type: Default::default(),
67 parameters,
68 agent_type: Default::default(),
69 }
70 }
71
72 /// This runs the cohort using parallelism
73 pub fn solve(&mut self) {
74 self.team_list.par_iter_mut().for_each(|x| x.solve());
75 }
76
77 /// This runs a single iteration
78 pub fn iterate(&mut self) {
79 self.team_list.iter_mut().for_each(|x| x.iterate());
80 }
81
82 /// Get the current best solution
83 pub fn get_best_solution_so_far(&mut self) -> f64 {
84 (0..self.parameters.number_of_teams)
85 .map(|i| self.team_list[i].get_best_solution_so_far())
86 .collect::<Vec<S>>()
87 .into_iter()
88 .max()
89 .unwrap()
90 .get_quality_scalar()
91 }
92}
93
94impl Default for Cohort {
95 fn default() -> Self {
96 Cohort::new(Default::default())
97 }
98}