genetic_algorithm/genotype/
binary.rs

1use super::builder::{Builder, TryFromBuilderError};
2use super::{EvolveGenotype, Genotype, HillClimbGenotype, PermutateGenotype};
3use crate::chromosome::{BinaryChromosome, ChromosomeManager, GenesHash, GenesOwner};
4use crate::population::Population;
5use itertools::Itertools;
6use num::BigUint;
7use rand::distributions::{Standard, Uniform};
8use rand::prelude::*;
9use rustc_hash::FxHasher;
10use std::fmt;
11use std::hash::{Hash, Hasher};
12
13/// Genes are a vector of booleans. On random initialization, each gene has a 50% probability of
14/// becoming true or false. Each gene has an equal probability of mutating. If a gene mutates, its
15/// value is flipped.
16///
17/// # Example:
18/// ```
19/// use genetic_algorithm::genotype::{Genotype, BinaryGenotype};
20///
21/// let genotype = BinaryGenotype::builder()
22///     .with_genes_size(100)
23///     .with_genes_hashing(false) // optional, defaults to false
24///     .build()
25///     .unwrap();
26/// ```
27#[derive(Clone, Debug)]
28pub struct Binary {
29    pub genes_size: usize,
30    gene_index_sampler: Uniform<usize>,
31    pub seed_genes_list: Vec<Vec<bool>>,
32    pub chromosome_bin: Vec<BinaryChromosome>,
33    pub best_genes: Vec<bool>,
34    pub genes_hashing: bool,
35}
36
37impl TryFrom<Builder<Self>> for Binary {
38    type Error = TryFromBuilderError;
39
40    fn try_from(builder: Builder<Self>) -> Result<Self, Self::Error> {
41        if !builder.genes_size.is_some_and(|x| x > 0) {
42            Err(TryFromBuilderError(
43                "BinaryGenotype requires a genes_size > 0",
44            ))
45        } else {
46            let genes_size = builder.genes_size.unwrap();
47            Ok(Self {
48                genes_size,
49                gene_index_sampler: Uniform::from(0..genes_size),
50                seed_genes_list: builder.seed_genes_list,
51                chromosome_bin: vec![],
52                best_genes: vec![false; genes_size],
53                genes_hashing: builder.genes_hashing,
54            })
55        }
56    }
57}
58
59impl Genotype for Binary {
60    type Allele = bool;
61    type Genes = Vec<Self::Allele>;
62    type Chromosome = BinaryChromosome;
63
64    fn genes_size(&self) -> usize {
65        self.genes_size
66    }
67    fn save_best_genes(&mut self, chromosome: &Self::Chromosome) {
68        self.best_genes.clone_from(&chromosome.genes);
69    }
70    fn load_best_genes(&mut self, chromosome: &mut Self::Chromosome) {
71        chromosome.genes.clone_from(&self.best_genes);
72    }
73    fn best_genes(&self) -> &Self::Genes {
74        &self.best_genes
75    }
76    fn best_genes_slice(&self) -> &[Self::Allele] {
77        self.best_genes.as_slice()
78    }
79    fn genes_slice<'a>(&'a self, chromosome: &'a Self::Chromosome) -> &'a [Self::Allele] {
80        chromosome.genes.as_slice()
81    }
82    fn genes_hashing(&self) -> bool {
83        self.genes_hashing
84    }
85    fn calculate_genes_hash(&self, chromosome: &Self::Chromosome) -> Option<GenesHash> {
86        if self.genes_hashing {
87            let mut s = FxHasher::default();
88            chromosome.genes.hash(&mut s);
89            Some(s.finish())
90        } else {
91            None
92        }
93    }
94
95    fn mutate_chromosome_genes<R: Rng>(
96        &mut self,
97        number_of_mutations: usize,
98        allow_duplicates: bool,
99        chromosome: &mut Self::Chromosome,
100        _scale_index: Option<usize>,
101        rng: &mut R,
102    ) {
103        if allow_duplicates {
104            rng.sample_iter(self.gene_index_sampler)
105                .take(number_of_mutations)
106                .for_each(|index| {
107                    chromosome.genes[index] = !chromosome.genes[index];
108                });
109        } else {
110            rand::seq::index::sample(
111                rng,
112                self.genes_size,
113                number_of_mutations.min(self.genes_size),
114            )
115            .iter()
116            .for_each(|index| {
117                chromosome.genes[index] = !chromosome.genes[index];
118            });
119        }
120        self.reset_chromosome_state(chromosome);
121    }
122
123    fn set_seed_genes_list(&mut self, seed_genes_list: Vec<Self::Genes>) {
124        self.seed_genes_list = seed_genes_list;
125    }
126    fn seed_genes_list(&self) -> &Vec<Self::Genes> {
127        &self.seed_genes_list
128    }
129    fn max_scale_index(&self) -> Option<usize> {
130        None
131    }
132}
133
134impl EvolveGenotype for Binary {
135    fn crossover_chromosome_genes<R: Rng>(
136        &mut self,
137        number_of_crossovers: usize,
138        allow_duplicates: bool,
139        father: &mut Self::Chromosome,
140        mother: &mut Self::Chromosome,
141        rng: &mut R,
142    ) {
143        if allow_duplicates {
144            rng.sample_iter(self.gene_index_sampler)
145                .take(number_of_crossovers)
146                .for_each(|index| {
147                    std::mem::swap(&mut father.genes[index], &mut mother.genes[index]);
148                });
149        } else {
150            rand::seq::index::sample(
151                rng,
152                self.genes_size(),
153                number_of_crossovers.min(self.genes_size()),
154            )
155            .iter()
156            .for_each(|index| {
157                std::mem::swap(&mut father.genes[index], &mut mother.genes[index]);
158            });
159        }
160        self.reset_chromosome_state(mother);
161        self.reset_chromosome_state(father);
162    }
163    fn crossover_chromosome_points<R: Rng>(
164        &mut self,
165        number_of_crossovers: usize,
166        allow_duplicates: bool,
167        father: &mut Self::Chromosome,
168        mother: &mut Self::Chromosome,
169        rng: &mut R,
170    ) {
171        if allow_duplicates {
172            rng.sample_iter(self.gene_index_sampler)
173                .take(number_of_crossovers)
174                .for_each(|index| {
175                    let mother_back = &mut mother.genes[index..];
176                    let father_back = &mut father.genes[index..];
177                    father_back.swap_with_slice(mother_back);
178                });
179        } else {
180            rand::seq::index::sample(
181                rng,
182                self.genes_size(),
183                number_of_crossovers.min(self.genes_size()),
184            )
185            .iter()
186            .sorted_unstable()
187            .chunks(2)
188            .into_iter()
189            .for_each(|mut chunk| match (chunk.next(), chunk.next()) {
190                (Some(start_index), Some(end_index)) => {
191                    let mother_back = &mut mother.genes[start_index..end_index];
192                    let father_back = &mut father.genes[start_index..end_index];
193                    father_back.swap_with_slice(mother_back);
194                }
195                (Some(start_index), _) => {
196                    let mother_back = &mut mother.genes[start_index..];
197                    let father_back = &mut father.genes[start_index..];
198                    father_back.swap_with_slice(mother_back);
199                }
200                _ => (),
201            });
202        }
203        self.reset_chromosome_state(mother);
204        self.reset_chromosome_state(father);
205    }
206
207    fn has_crossover_indexes(&self) -> bool {
208        true
209    }
210    fn has_crossover_points(&self) -> bool {
211        true
212    }
213}
214impl HillClimbGenotype for Binary {
215    fn fill_neighbouring_population<R: Rng>(
216        &mut self,
217        chromosome: &Self::Chromosome,
218        population: &mut Population<Self::Chromosome>,
219        _scale_index: Option<usize>,
220        _rng: &mut R,
221    ) {
222        (0..self.genes_size).for_each(|index| {
223            let mut new_chromosome = self.chromosome_cloner(chromosome);
224            new_chromosome.genes[index] = !new_chromosome.genes[index];
225            self.reset_chromosome_state(&mut new_chromosome);
226            population.chromosomes.push(new_chromosome);
227        });
228    }
229
230    fn neighbouring_population_size(&self) -> BigUint {
231        BigUint::from(self.genes_size)
232    }
233}
234
235impl PermutateGenotype for Binary {
236    fn chromosome_permutations_into_iter<'a>(
237        &'a self,
238    ) -> Box<dyn Iterator<Item = Self::Chromosome> + Send + 'a> {
239        if self.seed_genes_list.is_empty() {
240            Box::new(
241                (0..self.genes_size())
242                    .map(|_| vec![true, false])
243                    .multi_cartesian_product()
244                    .map(BinaryChromosome::new),
245            )
246        } else {
247            Box::new(
248                self.seed_genes_list
249                    .clone()
250                    .into_iter()
251                    .map(BinaryChromosome::new),
252            )
253        }
254    }
255    fn chromosome_permutations_size(&self) -> BigUint {
256        if self.seed_genes_list.is_empty() {
257            BigUint::from(2u8).pow(self.genes_size() as u32)
258        } else {
259            self.seed_genes_list.len().into()
260        }
261    }
262}
263
264impl ChromosomeManager<Self> for Binary {
265    fn random_genes_factory<R: Rng>(&self, rng: &mut R) -> Vec<bool> {
266        if self.seed_genes_list.is_empty() {
267            rng.sample_iter(Standard).take(self.genes_size).collect()
268        } else {
269            self.seed_genes_list.choose(rng).unwrap().clone()
270        }
271    }
272    fn set_genes(&mut self, chromosome: &mut BinaryChromosome, genes: &Vec<bool>) {
273        chromosome.genes.clone_from(genes);
274        self.reset_chromosome_state(chromosome);
275    }
276    fn copy_genes(&mut self, source: &BinaryChromosome, target: &mut BinaryChromosome) {
277        target.genes.clone_from(&source.genes);
278        self.copy_chromosome_state(source, target);
279    }
280    fn chromosome_bin_push(&mut self, chromosome: BinaryChromosome) {
281        self.chromosome_bin.push(chromosome);
282    }
283    fn chromosome_bin_find_or_create(&mut self) -> BinaryChromosome {
284        self.chromosome_bin.pop().unwrap_or_else(|| {
285            let genes = Vec::with_capacity(self.genes_size);
286            BinaryChromosome::new(genes)
287        })
288    }
289    fn chromosomes_cleanup(&mut self) {
290        std::mem::take(&mut self.chromosome_bin);
291    }
292}
293
294impl fmt::Display for Binary {
295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296        writeln!(f, "genotype:")?;
297        writeln!(f, "  genes_size: {}", self.genes_size)?;
298        writeln!(f, "  mutation_type: {:?}", self.mutation_type())?;
299        writeln!(
300            f,
301            "  chromosome_permutations_size: {}",
302            self.chromosome_permutations_size()
303        )?;
304        writeln!(
305            f,
306            "  neighbouring_population_size: {}",
307            self.neighbouring_population_size()
308        )?;
309        writeln!(
310            f,
311            "  expected_number_of_sampled_index_duplicates: {}",
312            self.expected_number_of_sampled_index_duplicates_report()
313        )?;
314        writeln!(f, "  seed_genes: {:?}", self.seed_genes_list.len())
315    }
316}