Trait GroupTrait

Source
pub trait GroupTrait<T, const N: usize, const R: usize> {
    type Err: Debug;
    type Out: Serialize;

    // Required methods
    fn new(data: [T; N]) -> Self;
    fn one_cycle_with_output(&mut self) -> Result<Self::Out, Self::Err>;
    fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Individual<T>>
       where T: 'a;

    // Provided methods
    fn init<I>() -> Self
       where I: InitializerTrait<T, N>,
             Self: Sized { ... }
    fn reset_id(&self) { ... }
    fn clone_values(&self) -> Vec<T>
       where T: Clone { ... }
}
Expand description

A trait for evolutionary processes over a group of individuals.

This trait defines a method, one_cycle_with_output. When it is called, it should perform three steps.

  1. Fitness: Assign a fitness score to each individual. These scores depend on all individuals in the group.

  2. Select: Select individuals based on the fitness scores. Unselected individuals are removed from the group.

  3. Replenish: Replenish the group with new individuals. Create them from remaining ones.

Optionally, you can output data about this cycle. If you don’t want to output any data, set type Out = ();.

  • T - A type of individuals of this group.
  • N - The number of individuals.
  • R - The number of individuals after individuals are reduced by selector.

§Example

use std::{collections::{HashMap, HashSet}, mem::swap, rc::Rc};
use scarlet_queen_core::{EachCrateIndividual, FitnessIndividualTrait, GroupTrait, Individual, InitializerTrait, ReplenisherIndividualTrait, SelectorIndividualTrait};

#[derive(PartialEq, Eq, Debug)]
struct IndividualWrapper<const N: usize, const R: usize>(Rc<Individual<u8>>);
impl<const N: usize, const R: usize> IndividualWrapper<N, R> {
    fn new_for_test(id: usize, value: u8) -> IndividualWrapper<N, R> {
        IndividualWrapper(Rc::new(Individual::new_with_id(id, value)))
    }
}

impl<const N: usize, const R: usize> EachCrateIndividual for IndividualWrapper<N, R> {
    type Item = u8;

    fn new(individual: &Rc<Individual<Self::Item>>) -> Self {
        IndividualWrapper(Rc::clone(individual))
    }

    fn get_individual(&self) -> &Individual<Self::Item> {
        &self.0
    }
}

impl<const N: usize, const R: usize> FitnessIndividualTrait for IndividualWrapper<N, R> {
    fn fitness(&self, other: &Self) -> usize {
        if self.get_value() >= other.get_value() {
            1
        } else {
            0
        }
    }
}
impl<const N: usize, const R: usize> SelectorIndividualTrait<R> for IndividualWrapper<N, R> {
    type Err = String;

    fn selected_ids<'a, G>(
        group: G,
        _scores: std::collections::HashMap<usize, usize>,
    ) -> Result<std::collections::HashSet<usize>, Self::Err>
        where
            G: IntoIterator<Item = &'a Self>,
            Self: 'a {
        let group: Vec<&IndividualWrapper<N, R>> = group.into_iter().collect::<Vec<&IndividualWrapper<N, R>>>();
        if group.len() < R {
            return Err(String::from("The size of group is not enough."));
        };
        Ok(
            group
                .into_iter()
                .map(|v| v.get_id())
                .take(R)
                .collect::<HashSet<usize>>()
        )
    }
}
impl<const N: usize, const R: usize> ReplenisherIndividualTrait<N, R> for IndividualWrapper<N, R> {
    fn replenish<'a, G>(group: G) -> Vec<<Self as EachCrateIndividual>::Item>
        where
            G: IntoIterator<Item = &'a Self>,
            Self: 'a {
        group
            .into_iter()
            .map(|v| *v.get_value())
            .collect::<Vec<u8>>()
            .into_iter()
            .cycle()
            .take(N - R)
            .collect::<Vec<u8>>()
    }
}
#[derive(PartialEq, Eq, Debug)]
struct Group<const N: usize, const R: usize>(Vec<IndividualWrapper<N, R>>);
impl<const N: usize, const R: usize> GroupTrait<u8, N, R> for Group<N, R> {
    type Err = String;
    type Out = ();

    fn new(data: [u8; N]) -> Self {
        Group(
            data
                .into_iter()
                .enumerate()
                .map(|(i, v)| IndividualWrapper::new_for_test(i, v))
                .collect::<Vec<_>>()
        )
    }

    fn one_cycle_with_output(&mut self) -> Result<(), Self::Err> {
        let scores: HashMap<usize, usize> = IndividualWrapper::fitness_group(self.0.iter());
        self.0.sort_by_key(|v| -(*scores.get(&v.get_id()).unwrap() as isize));
        let selector: HashSet<usize> = IndividualWrapper::selected_ids(self.0.iter(), scores)?;
        let mut data_for_edit: Vec<IndividualWrapper<N, R>> = Vec::new();
        swap(&mut data_for_edit, &mut self.0);
        self.0 = data_for_edit
            .into_iter()
            .filter_map(|v| {
                if selector.contains(&v.get_id()) {
                    Some(v)
                } else {
                    None
                }
            })
            .collect::<Vec<IndividualWrapper<N, R>>>();
        let new_individuals: Vec<u8> = IndividualWrapper::replenish(self.0.iter());
        self.0.extend(
            new_individuals
                .into_iter()
                .map(|v| IndividualWrapper::new(&Rc::new(Individual::new_with_id(0, v)))),
        );
        self.reset_id();
        Ok(())
    }

    fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Individual<u8>>
        where
            u8: 'a {
        self.0.iter().map(|v| v.get_individual())
    }
}

struct Initializer {}

impl<const N: usize> InitializerTrait<u8, N> for Initializer {
    fn initialize() -> [u8; N] {
        let mut i: u8 = 0;
        [0; N].map(|_| {
            i += 1;
            i - 1
        })
    }
}

let mut group: Group<15, 12> = Group::init::<Initializer>();

group.one_cycle_with_output().unwrap();

assert_eq!(group.clone_values(), vec![14u8, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 14, 13, 12]);

Required Associated Types§

Source

type Err: Debug

An error of cycle.

Source

type Out: Serialize

An output of cycle.

Required Methods§

Source

fn new(data: [T; N]) -> Self

Create Self from an array. The return value is already assigned a number.

  • data - An array of individuals
Source

fn one_cycle_with_output(&mut self) -> Result<Self::Out, Self::Err>

Run one cycle with outputing and update individuals. The elements of self must be already assigned a number before calling this method.

Source

fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Individual<T>>
where T: 'a,

Create an iterator of individuals.

  • 'a - A lifetime of self.

Provided Methods§

Source

fn init<I>() -> Self
where I: InitializerTrait<T, N>, Self: Sized,

Initialize Self by I algorithm. The elements of self must be already assigned a number.

  • I - An algorithm of initializing.(The type which has the algorithm)
Source

fn reset_id(&self)

Assign numbers to individuals in order.

Source

fn clone_values(&self) -> Vec<T>
where T: Clone,

Clone individuals of this group.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§