Skip to content

Commit f4b0c15

Browse files
committed
Add PermutableGenotype support for scaled MultiRangeGenotype
1 parent c03d758 commit f4b0c15

File tree

3 files changed

+403
-18
lines changed

3 files changed

+403
-18
lines changed

src/genotype/multi_range.rs

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::builder::{Builder, TryFromBuilderError};
2-
use super::{EvolveGenotype, Genotype, HillClimbGenotype, MutationType};
2+
use super::{EvolveGenotype, Genotype, HillClimbGenotype, MutationType, PermutateGenotype};
33
use crate::allele::RangeAllele;
44
use crate::chromosome::{ChromosomeManager, GenesHash, GenesOwner, MultiRangeChromosome};
55
use crate::population::Population;
@@ -574,6 +574,190 @@ where
574574
}
575575
}
576576

577+
impl<T: RangeAllele + Into<f64>> PermutateGenotype for MultiRange<T>
578+
where
579+
T: SampleUniform,
580+
Uniform<T>: Send + Sync,
581+
{
582+
fn chromosome_permutations_into_iter<'a>(
583+
&'a self,
584+
chromosome: Option<&Self::Chromosome>,
585+
scale_index: Option<usize>,
586+
) -> Box<dyn Iterator<Item = Self::Chromosome> + Send + 'a> {
587+
if self.seed_genes_list.is_empty() {
588+
match self.mutation_type {
589+
MutationType::Scaled => Box::new(
590+
self.permutable_gene_values_scaled(chromosome, scale_index.unwrap())
591+
.into_iter()
592+
.multi_cartesian_product()
593+
.map(MultiRangeChromosome::new),
594+
),
595+
MutationType::Relative => {
596+
panic!("RangeGenotype is not permutable for MutationType::Relative")
597+
}
598+
MutationType::Random => {
599+
panic!("RangeGenotype is not permutable for MutationType::Random")
600+
}
601+
}
602+
} else {
603+
Box::new(
604+
self.seed_genes_list
605+
.clone()
606+
.into_iter()
607+
.map(MultiRangeChromosome::new),
608+
)
609+
}
610+
}
611+
612+
fn chromosome_permutations_size(&self, scale_index: Option<usize>) -> BigUint {
613+
if self.seed_genes_list.is_empty() {
614+
match self.mutation_type {
615+
MutationType::Scaled => {
616+
let median_chromosome = self.median_chromosome();
617+
self.permutable_gene_values_scaled(
618+
Some(&median_chromosome),
619+
scale_index.unwrap(),
620+
)
621+
.iter()
622+
.map(|v| BigUint::from(v.len()))
623+
.product()
624+
}
625+
MutationType::Relative => {
626+
panic!("RangeGenotype is not permutable for MutationType::Relative")
627+
}
628+
MutationType::Random => {
629+
panic!("RangeGenotype is not permutable for MutationType::Random")
630+
}
631+
}
632+
} else {
633+
self.seed_genes_list.len().into()
634+
}
635+
}
636+
fn mutation_type_allows_permutation(&self) -> bool {
637+
match self.mutation_type {
638+
MutationType::Scaled => true,
639+
MutationType::Relative => false,
640+
MutationType::Random => false,
641+
}
642+
}
643+
}
644+
645+
impl<T: RangeAllele + Into<f64>> MultiRange<T>
646+
where
647+
T: SampleUniform,
648+
Uniform<T>: Send + Sync,
649+
{
650+
// scales should be symmetrical, so the step is simply the scale end
651+
pub fn permutable_gene_values_scaled(
652+
&self,
653+
chromosome: Option<&MultiRangeChromosome<T>>,
654+
scale_index: usize,
655+
) -> Vec<Vec<T>> {
656+
self.allele_ranges
657+
.clone()
658+
.into_iter()
659+
.enumerate()
660+
.map(|(index, allele_range)| {
661+
let allele_range_start = *allele_range.start();
662+
let allele_range_end = *allele_range.end();
663+
664+
let (allele_value_start, allele_value_end) = if let Some(chromosome) = chromosome {
665+
if let Some(previous_scale_index) = scale_index.checked_sub(1) {
666+
let working_range = &self.allele_mutation_scaled_ranges.as_ref().unwrap()
667+
[previous_scale_index][index];
668+
669+
let working_range_start = *working_range.start();
670+
let working_range_end = *working_range.end();
671+
672+
let base_value = chromosome.genes[index];
673+
let value_start = if base_value + working_range_start < allele_range_start {
674+
allele_range_start
675+
} else {
676+
base_value + working_range_start
677+
};
678+
let value_end = if base_value + working_range_end > allele_range_end {
679+
allele_range_end
680+
} else {
681+
base_value + working_range_end
682+
};
683+
684+
(value_start, value_end)
685+
} else {
686+
(allele_range_start, allele_range_end)
687+
}
688+
} else {
689+
(allele_range_start, allele_range_end)
690+
};
691+
692+
let working_range =
693+
&self.allele_mutation_scaled_ranges.as_ref().unwrap()[scale_index][index];
694+
let working_range_step = *working_range.end();
695+
696+
std::iter::successors(Some(allele_value_start), |value| {
697+
if *value < allele_value_end {
698+
let next_value = *value + working_range_step;
699+
if next_value > allele_value_end {
700+
Some(allele_value_end)
701+
} else {
702+
Some(next_value)
703+
}
704+
} else {
705+
None
706+
}
707+
})
708+
.collect()
709+
})
710+
.collect()
711+
}
712+
713+
// pub fn permutable_gene_values_relative(
714+
// &self,
715+
// _chromosome: Option<&MultiRangeChromosome<T>>,
716+
// ) -> Vec<Vec<T>> {
717+
// panic!("MultiRangeGenotype is not permutable for MutationType::Relative");
718+
// }
719+
//
720+
// pub fn permutable_gene_values_random(
721+
// &self,
722+
// _chromosome: Option<&MultiRangeChromosome<T>>,
723+
// ) -> Vec<Vec<T>> {
724+
// panic!("MultiRangeGenotype is not permutable for MutationType::Random");
725+
// }
726+
727+
pub fn median_chromosome(&self) -> MultiRangeChromosome<T> {
728+
let median_genes = self
729+
.allele_ranges
730+
.clone()
731+
.into_iter()
732+
.enumerate()
733+
.map(|(index, allele_range)| {
734+
let allele_range_start = *allele_range.start();
735+
let allele_range_end = *allele_range.end();
736+
737+
let working_range = &self.allele_mutation_scaled_ranges.as_ref().unwrap()[0][index];
738+
let working_range_step = *working_range.end();
739+
740+
let allele_value_iter = std::iter::successors(Some(allele_range_start), |value| {
741+
if *value < allele_range_end {
742+
let next_value = *value + working_range_step;
743+
if next_value > allele_range_end {
744+
Some(allele_range_end)
745+
} else {
746+
Some(next_value)
747+
}
748+
} else {
749+
None
750+
}
751+
});
752+
753+
let median_step = allele_value_iter.clone().count() / 2;
754+
allele_value_iter.clone().nth(median_step).unwrap()
755+
})
756+
.collect();
757+
MultiRangeChromosome::new(median_genes)
758+
}
759+
}
760+
577761
impl<T: RangeAllele + Into<f64>> ChromosomeManager<Self> for MultiRange<T>
578762
where
579763
T: SampleUniform,

src/genotype/range.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ where
588588
T: SampleUniform,
589589
Uniform<T>: Send + Sync,
590590
{
591-
// scales should be symmetrical, so the stap is simply the scale end
591+
// scales should be symmetrical, so the step is simply the scale end
592592
pub fn permutable_gene_values_scaled(
593593
&self,
594594
chromosome: Option<&RangeChromosome<T>>,
@@ -688,21 +688,6 @@ where
688688
}
689689
}
690690

691-
// impl<T: RangeAllele> PermutableGenotype for Range<T>
692-
// where
693-
// T: SampleUniform,
694-
// Uniform<T>: Send + Sync,
695-
// {
696-
// fn chromosome_permutations_into_iter(&self) -> impl Iterator<Item = Self::Chromosome> + Send {
697-
// panic!("RangeGenotype is not permutable");
698-
// #[allow(unreachable_code)]
699-
// [].into_iter()
700-
// }
701-
// fn chromosome_permutations_size(&self) -> BigUint {
702-
// BigUint::default()
703-
// }
704-
// }
705-
706691
impl<T: RangeAllele> ChromosomeManager<Self> for Range<T>
707692
where
708693
T: SampleUniform,

0 commit comments

Comments
 (0)