use crate::{
core::{context::Context, offspring::Offspring, population::Population, state::State},
operators::GeneticOperator,
};
#[derive(Debug, Clone)]
pub struct Combine<O: ?Sized>(O);
impl<O> Combine<O> {
pub fn new(operators: O) -> Self {
Self(operators)
}
}
macro_rules! impl_genetic_combine {
() => {};
($first:ident) => {
impl<G, F, Fe, R, C, $first> GeneticOperator<G, F, Fe, R, C> for Combine<($first,)>
where
$first: GeneticOperator<G, F, Fe, R, C>,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
self.0.0.apply(state, ctx)
}
}
};
($first:ident, $($rest:ident),+) => {
impl<G, F, Fe, R, C, $first, $($rest),*> GeneticOperator<G, F, Fe, R, C> for Combine<($first, $($rest,)*)>
where
$first: GeneticOperator<G, F, Fe, R, C>,
$($rest: GeneticOperator<G, F, Fe, R, C>),*,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
#[allow(non_snake_case)]
let ($first, $($rest,)*) = &self.0;
let mut population = Population::new();
population.add_offspring($first.apply(state, ctx));
$(
population.add_offspring($rest.apply(state, ctx));
)*
Offspring::Multiple(population)
}
}
impl_genetic_combine!($($rest),*);
};
}
impl_genetic_combine!(
T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
);
impl<G, F, Fe, R, C, O> GeneticOperator<G, F, Fe, R, C> for Combine<[O]>
where
O: GeneticOperator<G, F, Fe, R, C>,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
let mut population = Population::new();
for operator in &self.0 {
population.add_offspring(operator.apply(state, ctx));
}
Offspring::Multiple(population)
}
}
impl<G, F, Fe, R, C, O> GeneticOperator<G, F, Fe, R, C> for Combine<Vec<O>>
where
O: GeneticOperator<G, F, Fe, R, C>,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
let mut population = Population::new();
for operator in &self.0 {
population.add_offspring(operator.apply(state, ctx));
}
Offspring::Multiple(population)
}
}
impl<G, F, Fe, R, C, O> GeneticOperator<G, F, Fe, R, C> for Combine<Box<[O]>>
where
O: GeneticOperator<G, F, Fe, R, C>,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
let mut population = Population::new();
for operator in self.0.iter() {
population.add_offspring(operator.apply(state, ctx));
}
Offspring::Multiple(population)
}
}