cisat/abm/
team.rs

1//! This module contains the Team class, a set of interacting Agents
2
3use super::{
4    super::utilities::{parameters::Parameters, randomness::random_unit_draw, Solution},
5    agent::AgentMethods,
6};
7use crate::{Agent, CommunicationStyle};
8use std::marker::PhantomData;
9
10/// This is the Team construct, which contains a set of Agents
11#[derive(Clone, Debug)]
12pub struct Team<S, A>
13where
14    S: Solution,
15    A: AgentMethods<S>,
16{
17    /// The parameters that the team runs with
18    parameters: Parameters,
19    /// iteration number counter
20    iteration_number: usize,
21    /// The agents contained in the team
22    agent_list: Vec<A>,
23    /// Bookkeeping the solution type
24    solution_type: PhantomData<S>,
25}
26
27/// This is a trait for implementing new teams
28pub trait TeamMethods<S: Solution, A: AgentMethods<S> = Agent<S>>: Send {
29    /// Generates a new agent
30    fn new(parameters: Parameters) -> Self;
31    /// Iterates on the solution
32    fn iterate(&mut self);
33    /// Tell the team to talk
34    fn communicate(&mut self);
35    /// Solves all the way for a solution
36    fn solve(&mut self);
37    /// Gets the best solution found by the team so far
38    fn get_best_solution_so_far(&mut self) -> S;
39}
40
41impl<S, A> TeamMethods<S, A> for Team<S, A>
42where
43    S: Solution,
44    A: AgentMethods<S>,
45{
46    /// This generates a new team
47    fn new(parameters: Parameters) -> Self {
48        Team {
49            agent_list: (0..parameters.number_of_agents)
50                .map(|i| A::new(i, parameters.clone()))
51                .collect(),
52            parameters,
53            iteration_number: 1,
54            solution_type: Default::default(),
55        }
56    }
57
58    /// This runs a single iteration
59    fn iterate(&mut self) {
60        // Check if its time to interact
61        match &self.parameters.communication {
62            CommunicationStyle::ConstantFrequency { frequency } => {
63                if random_unit_draw() < *frequency {
64                    self.communicate();
65                }
66            }
67            CommunicationStyle::RegularInterval { interval } => {
68                if self.iteration_number % interval == 0 {
69                    self.communicate();
70                }
71            }
72            CommunicationStyle::ScheduledMeetings { times } => {
73                if times.into_iter().any(|i| *i == self.iteration_number) {
74                    self.communicate();
75                }
76            }
77            CommunicationStyle::None => {}
78        }
79
80        // Then iterate the agents
81        self.agent_list.iter_mut().for_each(|x| x.iterate());
82
83        // Increment iteration number
84        self.iteration_number += 1;
85    }
86
87    fn communicate(&mut self) {
88        // Get the solutions
89        let solutions: Vec<S> = self
90            .agent_list
91            .iter_mut()
92            .map(|x| x.get_current_solution())
93            .collect();
94
95        // Share the solutions
96        self.agent_list
97            .iter_mut()
98            .for_each(|x| x.communicate(solutions.clone()));
99    }
100
101    /// This runs a bunch of iterations to solve
102    fn solve(&mut self) {
103        for _ in 0..self.parameters.number_of_iterations {
104            self.iterate();
105        }
106    }
107
108    /// This pulls out the best solution from the team
109    fn get_best_solution_so_far(&mut self) -> S {
110        (0..self.parameters.number_of_agents)
111            .map(|i| self.agent_list[i].get_best_solution_so_far())
112            .collect::<Vec<S>>()
113            .into_iter()
114            .max()
115            .unwrap()
116    }
117}
118
119impl<S, A> Default for Team<S, A>
120where
121    S: Solution,
122    A: AgentMethods<S>,
123{
124    fn default() -> Self {
125        Team::new(Default::default())
126    }
127}