set_genome/
genes.rs

1//! The `Gene` trait is a marker and in combination with the `Genes` struct describes common operations on collections (sets) of genes.
2//!
3//! The genome holds several fields with `Genes` of different types.
4
5use rand::{prelude::IteratorRandom, prelude::SliceRandom, Rng};
6use seahash::SeaHasher;
7use serde::{Deserialize, Serialize};
8use std::{
9    collections::HashSet,
10    hash::{BuildHasher, Hash, Hasher},
11    iter::FromIterator,
12    ops::Deref,
13    ops::DerefMut,
14};
15
16mod connections;
17mod id;
18mod nodes;
19
20pub use connections::Connection;
21pub use id::Id;
22pub use nodes::{
23    activations::{self, Activation},
24    Node,
25};
26
27pub trait Gene: Eq + Hash {
28    fn recombine(&self, other: &Self) -> Self;
29}
30
31#[derive(Clone, Default)]
32pub struct GeneHasher;
33
34impl BuildHasher for GeneHasher {
35    type Hasher = SeaHasher;
36
37    fn build_hasher(&self) -> Self::Hasher {
38        Self::Hasher::new()
39    }
40}
41
42#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
43pub struct Genes<T: Gene>(pub HashSet<T, GeneHasher>);
44
45// see here: https://stackoverflow.com/questions/60882381/what-is-the-fastest-correct-way-to-detect-that-there-are-no-duplicates-in-a-json/60884343#60884343
46impl<T: Gene> Hash for Genes<T> {
47    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
48        let mut hash = 0;
49        for gene in &self.0 {
50            let mut gene_hasher = SeaHasher::new();
51            gene.hash(&mut gene_hasher);
52            hash ^= gene_hasher.finish();
53        }
54        state.write_u64(hash);
55    }
56}
57
58impl<T: Gene> Default for Genes<T> {
59    fn default() -> Self {
60        Genes(Default::default())
61    }
62}
63
64impl<T: Gene> Deref for Genes<T> {
65    type Target = HashSet<T, GeneHasher>;
66
67    fn deref(&self) -> &Self::Target {
68        &self.0
69    }
70}
71
72impl<T: Gene> DerefMut for Genes<T> {
73    fn deref_mut(&mut self) -> &mut Self::Target {
74        &mut self.0
75    }
76}
77
78impl<T: Gene> Genes<T> {
79    pub fn random(&self, rng: &mut impl Rng) -> Option<&T> {
80        self.iter().choose(rng)
81    }
82
83    pub fn drain_into_random(&mut self, rng: &mut impl Rng) -> impl Iterator<Item = T> {
84        let mut random_vec = self.drain().collect::<Vec<T>>();
85        random_vec.shuffle(rng);
86        random_vec.into_iter()
87    }
88
89    pub fn iterate_matching_genes<'a>(
90        &'a self,
91        other: &'a Genes<T>,
92    ) -> impl Iterator<Item = (&'a T, &'a T)> {
93        self.intersection(other)
94            // we know item exists in other as we are iterating the intersection
95            .map(move |item_self| (item_self, other.get(item_self).unwrap()))
96    }
97
98    pub fn iterate_unique_genes<'a>(&'a self, other: &'a Genes<T>) -> impl Iterator<Item = &'a T> {
99        self.symmetric_difference(other)
100    }
101}
102
103impl<T: Gene> FromIterator<T> for Genes<T> {
104    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
105        Genes(iter.into_iter().collect())
106    }
107}
108
109impl<T: Gene + Ord> Genes<T> {
110    pub fn as_sorted_vec(&self) -> Vec<&T> {
111        let mut vec: Vec<&T> = self.iter().collect();
112        vec.sort_unstable();
113        vec
114    }
115}
116
117impl<T: Gene + Clone> Genes<T> {
118    pub fn cross_in(&self, other: &Self, rng: &mut impl Rng) -> Self {
119        self.iterate_matching_genes(other)
120            .map(|(gene_self, gene_other)| {
121                if rng.gen::<f64>() < 0.5 {
122                    gene_self.clone()
123                } else {
124                    gene_self.recombine(gene_other)
125                }
126            })
127            .chain(self.difference(other).cloned())
128            .collect()
129    }
130}