use rand::{prelude::IteratorRandom, prelude::SliceRandom, Rng};
use seahash::SeaHasher;
use serde::{Deserialize, Serialize};
use std::{
collections::HashSet,
hash::{BuildHasher, Hash, Hasher},
iter::FromIterator,
ops::Deref,
ops::DerefMut,
};
mod connections;
mod id;
mod nodes;
pub use connections::Connection;
pub use id::Id;
pub use nodes::{
activations::{self, Activation},
Node,
};
pub trait Gene: Eq + Hash {
fn recombine(&self, other: &Self) -> Self;
}
#[derive(Clone, Default)]
pub struct GeneHasher;
impl BuildHasher for GeneHasher {
type Hasher = SeaHasher;
fn build_hasher(&self) -> Self::Hasher {
Self::Hasher::new()
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct Genes<T: Gene>(pub HashSet<T, GeneHasher>);
impl<T: Gene> Hash for Genes<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let mut hash = 0;
for gene in &self.0 {
let mut gene_hasher = SeaHasher::new();
gene.hash(&mut gene_hasher);
hash ^= gene_hasher.finish();
}
state.write_u64(hash);
}
}
impl<T: Gene> Default for Genes<T> {
fn default() -> Self {
Genes(Default::default())
}
}
impl<T: Gene> Deref for Genes<T> {
type Target = HashSet<T, GeneHasher>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Gene> DerefMut for Genes<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: Gene> Genes<T> {
pub fn random(&self, rng: &mut impl Rng) -> Option<&T> {
self.iter().choose(rng)
}
pub fn drain_into_random(&mut self, rng: &mut impl Rng) -> impl Iterator<Item = T> {
let mut random_vec = self.drain().collect::<Vec<T>>();
random_vec.shuffle(rng);
random_vec.into_iter()
}
pub fn iterate_matching_genes<'a>(
&'a self,
other: &'a Genes<T>,
) -> impl Iterator<Item = (&'a T, &'a T)> {
self.intersection(other)
.map(move |item_self| (item_self, other.get(item_self).unwrap()))
}
pub fn iterate_unique_genes<'a>(&'a self, other: &'a Genes<T>) -> impl Iterator<Item = &'a T> {
self.symmetric_difference(other)
}
}
impl<T: Gene> FromIterator<T> for Genes<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Genes(iter.into_iter().collect())
}
}
impl<T: Gene + Ord> Genes<T> {
pub fn as_sorted_vec(&self) -> Vec<&T> {
let mut vec: Vec<&T> = self.iter().collect();
vec.sort_unstable();
vec
}
}
impl<T: Gene + Clone> Genes<T> {
pub fn cross_in(&self, other: &Self, rng: &mut impl Rng) -> Self {
self.iterate_matching_genes(other)
.map(|(gene_self, gene_other)| {
if rng.gen::<f64>() < 0.5 {
gene_self.clone()
} else {
gene_self.recombine(gene_other)
}
})
.chain(self.difference(other).cloned())
.collect()
}
}