Skip to content

Commit 086c9f3

Browse files
committed
Add MutationType::Discrete to RangeGenotype for symmetry reasons
1 parent dd2c75e commit 086c9f3

2 files changed

Lines changed: 203 additions & 10 deletions

File tree

src/genotype/range.rs

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ where
102102
let genes_size = builder.genes_size.unwrap();
103103
let allele_range = builder.allele_range.unwrap();
104104
let mutation_type = builder.mutation_type.unwrap_or(MutationType::Random);
105+
let allele_sampler = match mutation_type {
106+
MutationType::Discrete => {
107+
// [start, end+1) for uniform floor() sampling
108+
Uniform::new(*allele_range.start(), *allele_range.end() + T::one())
109+
}
110+
_ => {
111+
// [start, end] for uniform sampling
112+
Uniform::from(allele_range.clone())
113+
}
114+
};
105115
let allele_bandwidth_sampler = match &mutation_type {
106116
MutationType::Range(bandwidth) => {
107117
Some(Uniform::new_inclusive(T::smallest_increment(), bandwidth))
@@ -118,7 +128,7 @@ where
118128
allele_range: allele_range.clone(),
119129
mutation_type,
120130
gene_index_sampler: Uniform::from(0..genes_size),
121-
allele_sampler: Uniform::from(allele_range.clone()),
131+
allele_sampler,
122132
allele_bandwidth_sampler,
123133
current_scale_index: 0,
124134
seed_genes_list: builder.seed_genes_list,
@@ -137,15 +147,21 @@ where
137147
&self.mutation_type
138148
}
139149
pub fn sample_gene_random<R: Rng>(&self, rng: &mut R) -> T {
140-
self.allele_sampler.sample(rng)
150+
match self.mutation_type {
151+
MutationType::Discrete => self.allele_sampler.sample(rng).floor(),
152+
_ => self.allele_sampler.sample(rng),
153+
}
141154
}
142155

143156
// all delta's are positive, because we support unsigned integers as RangeAllele
144157
// quite the overhead to make this work, but I think it is worth it
145158
pub fn mutate_gene<R: Rng>(&self, chromosome: &mut Chromosome<T>, index: usize, rng: &mut R) {
146159
match &self.mutation_type {
147160
MutationType::Random => {
148-
chromosome.genes[index] = self.sample_gene_random(rng);
161+
chromosome.genes[index] = self.allele_sampler.sample(rng);
162+
}
163+
MutationType::Discrete => {
164+
chromosome.genes[index] = self.allele_sampler.sample(rng).floor();
149165
}
150166
MutationType::Range(_) => {
151167
// post-clamp
@@ -178,7 +194,7 @@ where
178194
let allele_range_end = *self.allele_range.end();
179195
if allele_range_end - allele_range_start <= bandwidth {
180196
// Random, leverage existing sampler
181-
chromosome.genes[index] = self.sample_gene_random(rng);
197+
chromosome.genes[index] = self.allele_sampler.sample(rng);
182198
} else {
183199
// Bandwidth
184200
let current_value = chromosome.genes[index];
@@ -219,9 +235,6 @@ where
219235
T::clamped_sub(current_value, delta, *self.allele_range.start());
220236
}
221237
}
222-
MutationType::Discrete => {
223-
panic!("RangeGenotype has no implementation for MutationType::Discrete")
224-
}
225238
}
226239
}
227240
}
@@ -454,7 +467,7 @@ where
454467
}
455468
}
456469
MutationType::Discrete => {
457-
panic!("RangeGenotype has no implementation for MutationType::Discrete")
470+
self.fill_neighbouring_population_discrete(chromosome, population)
458471
}
459472
}
460473
}
@@ -583,6 +596,28 @@ where
583596
};
584597
});
585598
}
599+
fn fill_neighbouring_population_discrete(
600+
&self,
601+
chromosome: &Chromosome<T>,
602+
population: &mut Population<T>,
603+
) {
604+
let starting_value = self.allele_range.start().floor();
605+
let ending_value = self.allele_range.end().floor();
606+
607+
(0..self.genes_size).for_each(|index| {
608+
let mut working_value = starting_value;
609+
let current_value = chromosome.genes[index].floor();
610+
while working_value <= ending_value {
611+
if working_value != current_value {
612+
let mut new_chromosome = population.new_chromosome(chromosome);
613+
new_chromosome.genes[index] = working_value;
614+
new_chromosome.reset_metadata(self.genes_hashing);
615+
population.chromosomes.push(new_chromosome);
616+
}
617+
working_value += T::one();
618+
}
619+
});
620+
}
586621
}
587622

588623
impl<T: RangeAllele> PermutateGenotype for Range<T>
@@ -604,6 +639,7 @@ where
604639
MutationType::StepScaled(steps) => {
605640
self.permutable_gene_values_step_scaled(index, chromosome, steps)
606641
}
642+
MutationType::Discrete => self.permutable_gene_values_discrete(),
607643
_ => {
608644
panic!(
609645
"RangeGenotype is not permutable for {:?}",
@@ -649,7 +685,7 @@ where
649685
fn allows_permutation(&self) -> bool {
650686
matches!(
651687
self.mutation_type,
652-
MutationType::Step(_) | MutationType::StepScaled(_)
688+
MutationType::Step(_) | MutationType::StepScaled(_) | MutationType::Discrete
653689
)
654690
}
655691
}
@@ -713,6 +749,24 @@ where
713749
.collect()
714750
}
715751

752+
pub fn permutable_gene_values_discrete(&self) -> Vec<T> {
753+
let allele_value_start = self.allele_range.start().floor();
754+
let allele_value_end = self.allele_range.end().floor();
755+
std::iter::successors(Some(allele_value_start), |value| {
756+
if *value < allele_value_end {
757+
let next_value = *value + T::one();
758+
if next_value > allele_value_end {
759+
Some(allele_value_end)
760+
} else {
761+
Some(next_value)
762+
}
763+
} else {
764+
None
765+
}
766+
})
767+
.collect()
768+
}
769+
716770
pub fn chromosome_permutations_size_per_scale(&self) -> Vec<BigUint> {
717771
// first scale is affected by seed_genes_list
718772
let mut results = vec![];
@@ -774,6 +828,24 @@ where
774828
})
775829
.count()
776830
}
831+
MutationType::Discrete => {
832+
let allele_value_start = self.allele_range.start().floor();
833+
let allele_value_end = self.allele_range.end().floor();
834+
835+
std::iter::successors(Some(allele_value_start), |value| {
836+
if *value < allele_value_end {
837+
let next_value = *value + T::one();
838+
if next_value > allele_value_end {
839+
Some(allele_value_end)
840+
} else {
841+
Some(next_value)
842+
}
843+
} else {
844+
None
845+
}
846+
})
847+
.count()
848+
}
777849
_ => {
778850
panic!(
779851
"RangeGenotype is not permutable for {:?}",
@@ -791,7 +863,19 @@ where
791863
Uniform<T>: Send + Sync,
792864
{
793865
fn clone(&self) -> Self {
794-
let allele_sampler = Uniform::from(self.allele_range.clone());
866+
let allele_sampler = match self.mutation_type {
867+
MutationType::Discrete => {
868+
// [start, end+1) for uniform floor() sampling
869+
Uniform::new(
870+
*self.allele_range.start(),
871+
*self.allele_range.end() + T::one(),
872+
)
873+
}
874+
_ => {
875+
// [start, end] for uniform sampling
876+
Uniform::from(self.allele_range.clone())
877+
}
878+
};
795879
let allele_bandwidth_sampler = match &self.mutation_type {
796880
MutationType::Range(bandwidth) => {
797881
Some(Uniform::new_inclusive(T::smallest_increment(), bandwidth))

tests/genotype/range_test.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,31 @@ fn float_mutate_chromosome_single_step_scaled() {
200200
));
201201
}
202202

203+
#[test]
204+
fn float_mutate_chromosome_single_discrete() {
205+
let mut rng = SmallRng::seed_from_u64(0);
206+
let genotype = RangeGenotype::builder()
207+
.with_genes_size(10)
208+
.with_allele_range(0.0..=10.0)
209+
.with_mutation_type(MutationType::Discrete)
210+
.build()
211+
.unwrap();
212+
213+
let mut chromosome = Chromosome::new(genotype.random_genes_factory(&mut rng));
214+
assert!(relative_chromosome_eq(
215+
inspect::chromosome(&chromosome),
216+
vec![4.0, 4.0, 10.0, 5.0, 9.0, 10.0, 6.0, 5.0, 4.0, 9.0],
217+
0.001,
218+
));
219+
220+
genotype.mutate_chromosome_genes(3, false, &mut chromosome, &mut rng);
221+
assert!(relative_chromosome_eq(
222+
inspect::chromosome(&chromosome),
223+
vec![2.0, 4.0, 10.0, 5.0, 9.0, 2.0, 6.0, 5.0, 4.0, 3.0],
224+
0.001,
225+
));
226+
}
227+
203228
#[test]
204229
fn mutate_chromosome_genes_random_with_duplicates() {
205230
let mut rng = SmallRng::seed_from_u64(0);
@@ -429,6 +454,40 @@ fn float_neighbouring_population_2_step_scaled() {
429454
));
430455
}
431456

457+
#[test]
458+
fn float_neighbouring_population_2_discrete() {
459+
let mut rng = SmallRng::seed_from_u64(0);
460+
let genotype = RangeGenotype::builder()
461+
.with_genes_size(2)
462+
.with_allele_range(0.0..=3.0)
463+
.with_mutation_type(MutationType::Discrete)
464+
.build()
465+
.unwrap();
466+
467+
let chromosome = Chromosome::new(genotype.random_genes_factory(&mut rng));
468+
assert!(relative_chromosome_eq(
469+
inspect::chromosome(&chromosome),
470+
vec![1.0, 1.0],
471+
0.001
472+
));
473+
474+
assert_eq!(genotype.neighbouring_population_size(), BigUint::from(4u32));
475+
let mut population = Population::new(vec![], true);
476+
genotype.fill_neighbouring_population(&chromosome, &mut population, &mut rng);
477+
assert!(relative_population_eq(
478+
inspect::population(&population),
479+
vec![
480+
vec![0.0, 1.0],
481+
vec![2.0, 1.0],
482+
vec![3.0, 1.0],
483+
vec![1.0, 0.0],
484+
vec![1.0, 2.0],
485+
vec![1.0, 3.0]
486+
],
487+
0.001,
488+
));
489+
}
490+
432491
#[test]
433492
fn float_neighbouring_population_3() {
434493
let mut rng = SmallRng::seed_from_u64(0);
@@ -655,6 +714,56 @@ fn float_chromosome_permutations_2_step_scaled() {
655714
));
656715
}
657716

717+
#[test]
718+
fn float_chromosome_permutations_2_discrete() {
719+
let mut rng = SmallRng::seed_from_u64(0);
720+
let genotype = RangeGenotype::builder()
721+
.with_genes_size(2)
722+
.with_allele_range(0.0..=3.0)
723+
.with_mutation_type(MutationType::Discrete)
724+
.build()
725+
.unwrap();
726+
727+
assert_eq!(
728+
genotype.chromosome_permutations_size(),
729+
BigUint::from(16u32)
730+
);
731+
732+
let chromosome = Chromosome::new(genotype.random_genes_factory(&mut rng));
733+
assert!(relative_chromosome_eq(
734+
inspect::chromosome(&chromosome),
735+
vec![1.0, 1.0],
736+
0.001
737+
));
738+
739+
let chromosomes = genotype
740+
.chromosome_permutations_into_iter(Some(&chromosome))
741+
.collect::<Vec<_>>();
742+
743+
assert!(relative_population_eq(
744+
inspect::chromosomes(&chromosomes),
745+
vec![
746+
vec![0.0, 0.0],
747+
vec![0.0, 1.0],
748+
vec![0.0, 2.0],
749+
vec![0.0, 3.0],
750+
vec![1.0, 0.0],
751+
vec![1.0, 1.0],
752+
vec![1.0, 2.0],
753+
vec![1.0, 3.0],
754+
vec![2.0, 0.0],
755+
vec![2.0, 1.0],
756+
vec![2.0, 2.0],
757+
vec![2.0, 3.0],
758+
vec![3.0, 0.0],
759+
vec![3.0, 1.0],
760+
vec![3.0, 2.0],
761+
vec![3.0, 3.0],
762+
],
763+
0.001,
764+
));
765+
}
766+
658767
#[test]
659768
fn integer_mutate_chromosome_single_random() {
660769
let mut rng = SmallRng::seed_from_u64(0);

0 commit comments

Comments
 (0)