meiosis 0.1.0

An evolutionary algorithm library with as many compile time checks as possible.
Documentation
use rand::distributions::Distribution;
use rand::distributions::Standard;
use rand::Rng;

use crate::genotype::Distance;
use crate::random::Random;

use super::Gene;
use super::Genotype;

impl<G, const GENE_COUNT: usize> Genotype for [G; GENE_COUNT]
where
    G: Gene,
{
    type Gene = G;
}

impl<G, const GENE_COUNT: usize> Distance for [G; GENE_COUNT]
where
    G: Gene + PartialEq,
{
    /// For arrays of the same size we can simply use the hamming distance.
    #[allow(clippy::cast_precision_loss, clippy::float_arithmetic, clippy::as_conversions)]
    fn distance(&self, other: &Self) -> f32 {
        self.iter()
            .zip(other)
            .fold(0.0, |distance, (l, r)| distance + if l == r { 0. } else { 1. })
            / GENE_COUNT as f32
    }
}

impl<G, const GENE_COUNT: usize> Random for [G; GENE_COUNT]
where
    Standard: Distribution<G>,
{
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
        Self: Sized,
    {
        core::array::from_fn(|_| rng.gen())
    }
}

#[cfg(test)]
mod tests {
    use crate::genotype::Distance;

    #[test]
    fn distance() {
        // the genomes share a single gene out of 3, so their distance is 2/3
        let arr1 = [1, 2, 3];
        let arr2 = [3, 2, 1];

        assert!((arr1.distance(&arr2) - 0.66666).abs() < 0.0001)
    }
}