use std::marker::PhantomData;
use nalgebra::{Const, OVector, SVector};
use crate::population::EvaluatedPopulation;
pub type ParentPairing<const D: usize> = OVector<usize, Const<D>>;
pub trait Pairing<const D: usize> {
type Chromosome;
type Out;
fn pair<T: Iterator<Item = usize>>(
&self,
population: &EvaluatedPopulation<Self::Chromosome, Self::Out>,
parents: T
) -> impl Iterator<Item = ParentPairing<D>>;
}
pub struct AdjacentPairing<TChromosome, TOutput> {
_phantom1: PhantomData<TChromosome>,
_phantom2: PhantomData<TOutput>,
}
impl<TChromosome, TOutput> AdjacentPairing<TChromosome, TOutput> {
pub fn new() -> Self {
Self {
_phantom1: PhantomData,
_phantom2: PhantomData,
}
}
}
impl<TChromosome, TOutput> Pairing<2> for AdjacentPairing<TChromosome, TOutput> {
type Chromosome = TChromosome;
type Out = TOutput;
fn pair<T: Iterator<Item = usize>>(
&self,
_: &EvaluatedPopulation<Self::Chromosome, Self::Out>,
parents: T
) -> impl Iterator<Item = ParentPairing<2>> {
AdjacentIterator(parents, 0)
}
}
pub struct AdjacentIterator<T: Iterator<Item = usize>>(T, usize);
impl<T: Iterator<Item = usize>> Iterator for AdjacentIterator<T> {
type Item = ParentPairing<2>;
fn next(&mut self) -> Option<Self::Item> {
let first = self.0.next();
let second = self.0.next();
match (first, second) {
// Still two elements left, return them
(Some(first), Some(second)) => {
self.1 = second; // Save previous
Some(ParentPairing::<2>::new(first, second))
},
// Only one element remaining, return it and the previous one
(Some(first), _) => Some(ParentPairing::<2>::new(first, self.1)),
(None, Some(_)) => panic!("Iterators cannot return something after they return none."),
// No more elements
_ => None
}
}
}