use super::{
super::utilities::{parameters::Parameters, randomness::random_unit_draw, Solution},
agent::AgentMethods,
};
use crate::{Agent, CommunicationStyle};
use std::marker::PhantomData;
#[derive(Clone, Debug)]
pub struct Team<S, A>
where
S: Solution,
A: AgentMethods<S>,
{
parameters: Parameters,
iteration_number: usize,
agent_list: Vec<A>,
solution_type: PhantomData<S>,
}
pub trait TeamMethods<S: Solution, A: AgentMethods<S> = Agent<S>>: Send {
fn new(parameters: Parameters) -> Self;
fn iterate(&mut self);
fn communicate(&mut self);
fn solve(&mut self);
fn get_best_solution_so_far(&mut self) -> S;
}
impl<S, A> TeamMethods<S, A> for Team<S, A>
where
S: Solution,
A: AgentMethods<S>,
{
fn new(parameters: Parameters) -> Self {
Team {
agent_list: (0..parameters.number_of_agents)
.map(|i| A::new(i, parameters.clone()))
.collect(),
parameters,
iteration_number: 1,
solution_type: Default::default(),
}
}
fn iterate(&mut self) {
match &self.parameters.communication {
CommunicationStyle::ConstantFrequency { frequency } => {
if random_unit_draw() < *frequency {
self.communicate();
}
}
CommunicationStyle::RegularInterval { interval } => {
if self.iteration_number % interval == 0 {
self.communicate();
}
}
CommunicationStyle::ScheduledMeetings { times } => {
if times.into_iter().any(|i| *i == self.iteration_number) {
self.communicate();
}
}
CommunicationStyle::None => {}
}
self.agent_list.iter_mut().for_each(|x| x.iterate());
self.iteration_number += 1;
}
fn communicate(&mut self) {
let solutions: Vec<S> = self
.agent_list
.iter_mut()
.map(|x| x.get_current_solution())
.collect();
self.agent_list
.iter_mut()
.for_each(|x| x.communicate(solutions.clone()));
}
fn solve(&mut self) {
for _ in 0..self.parameters.number_of_iterations {
self.iterate();
}
}
fn get_best_solution_so_far(&mut self) -> S {
(0..self.parameters.number_of_agents)
.map(|i| self.agent_list[i].get_best_solution_so_far())
.collect::<Vec<S>>()
.into_iter()
.max()
.unwrap()
}
}
impl<S, A> Default for Team<S, A>
where
S: Solution,
A: AgentMethods<S>,
{
fn default() -> Self {
Team::new(Default::default())
}
}