1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
use crateBinary as BinaryGenotype;
/// Computes the Hamming distance between two binary DNA sequences.
///
/// The Hamming distance counts the number of positions where the corresponding
/// genes differ.
///
/// # Arguments
///
/// * `dna_a` - First binary DNA sequence.
/// * `dna_b` - Second binary DNA sequence.
///
/// # Returns
///
/// The Hamming distance as an `f64`. If the sequences have different lengths,
/// extra genes in the longer sequence count as differences.
///
/// # Examples
///
/// ```
/// use genetic_algorithms::niching::distance::hamming_distance;
/// use genetic_algorithms::genotypes::Binary;
///
/// let a = vec![Binary { id: 0, value: true }, Binary { id: 1, value: false }, Binary { id: 2, value: true }];
/// let b = vec![Binary { id: 0, value: true }, Binary { id: 1, value: true }, Binary { id: 2, value: false }];
///
/// assert!((hamming_distance(&a, &b) - 2.0).abs() < f64::EPSILON);
/// ```
/// Computes the Euclidean distance between two numeric DNA sequences.
///
/// Each gene's value is converted to `f64` and the standard Euclidean norm
/// is computed: `sqrt(sum((a_i - b_i)^2))`.
///
/// # Arguments
///
/// * `dna_a` - First DNA sequence.
/// * `dna_b` - Second DNA sequence.
///
/// # Returns
///
/// The Euclidean distance as an `f64`.
///
/// # Examples
///
/// ```
/// use genetic_algorithms::niching::distance::euclidean_distance;
/// use genetic_algorithms::genotypes::Range;
///
/// let a = vec![
/// Range::new(0, vec![(0, 10)], 1),
/// Range::new(1, vec![(0, 10)], 2),
/// ];
/// let b = vec![
/// Range::new(0, vec![(0, 10)], 4),
/// Range::new(1, vec![(0, 10)], 6),
/// ];
///
/// let dist = euclidean_distance(&a, &b);
/// assert!((dist - 5.0).abs() < 1e-10);
/// ```
/// Trait for computing distance between two chromosomes' DNA.
///
/// Implement this trait for custom distance metrics.
///
/// # Examples
///
/// ```rust
/// use genetic_algorithms::niching::distance::{DistanceMetric, HammingDistance};
/// use genetic_algorithms::genotypes::Binary as BinaryGene;
///
/// let a = vec![BinaryGene::default(), BinaryGene::default()];
/// let b = vec![BinaryGene::default(), BinaryGene::default()];
/// let d = HammingDistance::distance(&a, &b);
/// assert!(d >= 0.0);
/// ```
/// Hamming distance metric for binary chromosomes.
///
/// # Examples
///
/// ```rust
/// use genetic_algorithms::niching::distance::{DistanceMetric, HammingDistance};
/// use genetic_algorithms::genotypes::Binary as BinaryGene;
///
/// let a = vec![BinaryGene::default(), BinaryGene::default()];
/// let b = vec![BinaryGene::default(), BinaryGene::default()];
/// let d = HammingDistance::distance(&a, &b);
/// assert!(d >= 0.0);
/// ```
;
/// Euclidean distance metric for range chromosomes.
///
/// # Examples
///
/// ```rust
/// use genetic_algorithms::niching::distance::{DistanceMetric, EuclideanDistance};
/// use genetic_algorithms::genotypes::Range as RangeGene;
///
/// let a = vec![RangeGene::new(0, vec![], 1.0_f64), RangeGene::new(1, vec![], 0.0_f64)];
/// let b = vec![RangeGene::new(0, vec![], 0.0_f64), RangeGene::new(1, vec![], 1.0_f64)];
/// let d = EuclideanDistance::distance(&a, &b);
/// assert!((d - std::f64::consts::SQRT_2).abs() < 1e-9);
/// ```
;