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