genetic_algorithm/genotype/
binary.rs1use 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#[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}