radiate_core/
diversity.rs1use crate::{ArithmeticGene, Chromosome, Gene, Genotype};
2
3pub trait Diversity<C: Chromosome>: Send + Sync {
8 fn measure(&self, geno_one: &Genotype<C>, geno_two: &Genotype<C>) -> f32;
9}
10
11pub struct HammingDistance;
15
16impl<G: Gene, C: Chromosome<Gene = G>> Diversity<C> for HammingDistance
17where
18 G::Allele: PartialEq,
19{
20 fn measure(&self, geno_one: &Genotype<C>, geno_two: &Genotype<C>) -> f32 {
21 let mut distance = 0.0;
22 let mut total_genes = 0.0;
23 for (chrom_one, chrom_two) in geno_one.iter().zip(geno_two.iter()) {
24 for (gene_one, gene_two) in chrom_one.iter().zip(chrom_two.iter()) {
25 total_genes += 1.0;
26 if gene_one.allele() != gene_two.allele() {
27 distance += 1.0;
28 }
29 }
30 }
31
32 distance / total_genes
33 }
34}
35
36pub struct EuclideanDistance;
40
41impl<G: ArithmeticGene, C: Chromosome<Gene = G>> Diversity<C> for EuclideanDistance
42where
43 G::Allele: Into<f32> + Copy,
44{
45 fn measure(&self, geno_one: &Genotype<C>, geno_two: &Genotype<C>) -> f32 {
46 let mut distance = 0.0;
47 let mut total_genes = 0.0;
48 for (chrom_one, chrom_two) in geno_one.iter().zip(geno_two.iter()) {
49 for (gene_one, gene_two) in chrom_one.iter().zip(chrom_two.iter()) {
50 let one_as_f32: f32 = (*gene_one.allele()).into();
51 let two_as_f32: f32 = (*gene_two.allele()).into();
52
53 if one_as_f32.is_nan() || two_as_f32.is_nan() {
54 continue;
55 }
56
57 let diff = one_as_f32 - two_as_f32;
58 distance += diff * diff;
59 total_genes += 1.0;
60 }
61 }
62 if total_genes == 0.0 {
63 return 0.0;
64 }
65
66 (distance / total_genes).sqrt()
67 }
68}