From 914ee761437025cc3ab6fc0fa3bfc37cd0c68225 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 8 Nov 2025 09:08:27 +0100 Subject: [PATCH] feat: split params out of PerturbationOperator to allow for non-'static PerturbationOperator This means PerturbationOperators can now hold non-'static references. Right away, utilize this in the Random2OptPerturbation for the TSPInstance. --- codes/eoa_lib/src/perturbation/mod.rs | 80 +++++++++++++++++---------- codes/tsp_hw01/src/perturbations.rs | 12 ++-- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/codes/eoa_lib/src/perturbation/mod.rs b/codes/eoa_lib/src/perturbation/mod.rs index 6e6d0e9d14d7e89133a94cc058b1c689779d1f31..89b88637867ef409aeb7758150458219eea31f03 100644 --- a/codes/eoa_lib/src/perturbation/mod.rs +++ b/codes/eoa_lib/src/perturbation/mod.rs @@ -6,7 +6,7 @@ use rand_distr::{uniform, Normal, NormalError, Uniform}; use crate::binary_string::BinaryString; -pub trait AnyPerturbationOperator: Any { +pub trait AsAny: Any { fn as_any(&self) -> &dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any; } @@ -14,7 +14,7 @@ pub trait AnyPerturbationOperator: Any { pub enum Wrapped<'a, T> { Single, Wrapped(&'a dyn PerturbationOperator), - ListWrapped(Vec<&'a dyn PerturbationOperator>), + ListWrapped(Vec<&'a (dyn PerturbationOperator)>), } pub enum WrappedMut<'a, T> { @@ -23,9 +23,18 @@ pub enum WrappedMut<'a, T> { ListWrapped(Vec<&'a mut dyn PerturbationOperator>), } -pub trait PerturbationOperator: AnyPerturbationOperator { +pub struct NoParams; +pub trait PerturbationOperator { type Chromosome; + fn try_get_params(&self) -> Option<&dyn Any> { + None + } + + fn try_get_params_mut(&mut self) -> Option<&mut dyn Any> { + None + } + fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore); fn wrapped(&self) -> Wrapped<'_, Self::Chromosome> { @@ -37,9 +46,7 @@ pub trait PerturbationOperator: AnyPerturbationOperator { } } -impl AnyPerturbationOperator for T -where - T: Any + 'static +impl AsAny for T { fn as_any(&self) -> &dyn Any { self @@ -53,7 +60,7 @@ pub struct IdentityPerturbation { _phantom: PhantomData } -impl PerturbationOperator for IdentityPerturbation { +impl PerturbationOperator for IdentityPerturbation { type Chromosome = TChromosome; fn perturb(&self, _: &mut Self::Chromosome, _: &mut dyn RngCore) { @@ -212,7 +219,7 @@ impl RandomDistributionPerturbation> { } } -impl + 'static, const LEN: usize> PerturbationOperator for RandomDistributionPerturbation { +impl, const LEN: usize> PerturbationOperator for RandomDistributionPerturbation { type Chromosome = SVector; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { @@ -336,33 +343,36 @@ where } /// Perform given perturbation only with given probability -pub struct MutationPerturbation { - perturbation: Box>, +pub struct MutationPerturbationParams { pub probability: f64 } +pub struct MutationPerturbation<'a, T> { + perturbation: Box + 'a>, + params: MutationPerturbationParams +} -impl MutationPerturbation { - pub fn new(perturbation: Box>, probability: f64) -> Self { +impl<'a, T> MutationPerturbation<'a, T> { + pub fn new(perturbation: Box + 'a>, probability: f64) -> Self { Self { perturbation, - probability + params: MutationPerturbationParams { probability } } } pub fn apply_to_mutations( base_perturbation: &mut dyn PerturbationOperator, - apply: &mut dyn FnMut(&mut MutationPerturbation) + apply: &mut dyn FnMut(&mut MutationPerturbationParams) ) { apply_to_perturbations(base_perturbation, apply); } } -pub fn apply_to_perturbations>( +pub fn apply_to_perturbations( base_perturbation: &mut dyn PerturbationOperator, apply: &mut dyn FnMut(&mut U) ) { - if let Some(mutation) = base_perturbation.as_any_mut().downcast_mut::() { - apply(mutation); + if let Some(params) = base_perturbation.try_get_params_mut().map(|p| p.downcast_mut::()).flatten() { + apply(params) } match base_perturbation.wrapped_mut() { @@ -378,11 +388,11 @@ pub fn apply_to_perturbations PerturbationOperator for MutationPerturbation { +impl<'a, T> PerturbationOperator for MutationPerturbation<'a, T> { type Chromosome = T; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { - if rng.random_bool(self.probability) { + if rng.random_bool(self.params.probability) { self.perturbation.perturb(chromosome, rng); } } @@ -394,21 +404,29 @@ impl PerturbationOperator for MutationPerturbation { fn wrapped_mut(&mut self) -> WrappedMut<'_, Self::Chromosome> { WrappedMut::Wrapped(self.perturbation.as_mut()) } + + fn try_get_params(&self) -> Option<&dyn Any> { + Some(self.params.as_any()) + } + + fn try_get_params_mut(&mut self) -> Option<&mut dyn Any> { + Some(self.params.as_any_mut()) + } } -pub struct CombinedPerturbation { - perturbations: Vec>>, +pub struct CombinedPerturbation<'a, T> { + perturbations: Vec + 'a>>, } -impl CombinedPerturbation { - pub fn new(perturbations: Vec>>) -> Self { +impl<'a, T> CombinedPerturbation<'a, T> { + pub fn new(perturbations: Vec + 'a>>) -> Self { Self { perturbations, } } } -impl PerturbationOperator for CombinedPerturbation { +impl<'a, T> PerturbationOperator for CombinedPerturbation<'a, T> { type Chromosome = T; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { @@ -428,23 +446,25 @@ impl PerturbationOperator for CombinedPerturbation { WrappedMut::ListWrapped( self.perturbations .iter_mut() - .map(|p| p.as_mut()).collect()) + .map::<&mut (dyn PerturbationOperator + '_), _> + (|p| p.as_mut()).collect() + ) } } -pub struct OneOfPerturbation { - perturbations: Vec>> +pub struct OneOfPerturbation<'a, T> { + perturbations: Vec + 'a>> } -impl OneOfPerturbation { - pub fn new(perturbations: Vec>>) -> Self { +impl<'a, T> OneOfPerturbation<'a, T> { + pub fn new(perturbations: Vec + 'a>>) -> Self { Self { perturbations } } } -impl PerturbationOperator for OneOfPerturbation { +impl<'a, T> PerturbationOperator for OneOfPerturbation<'a, T> { type Chromosome = T; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { diff --git a/codes/tsp_hw01/src/perturbations.rs b/codes/tsp_hw01/src/perturbations.rs index 4ff3e444c3fc117d62cd1061924be9a21118ee7c..2eb0b124165e889a614d441dcd060cebf08e0bb2 100644 --- a/codes/tsp_hw01/src/perturbations.rs +++ b/codes/tsp_hw01/src/perturbations.rs @@ -121,37 +121,37 @@ where } } -pub struct Random2OptPerturbation +pub struct Random2OptPerturbation<'a, D> where D: Dim, DefaultAllocator: nalgebra::allocator::Allocator { - instance: TSPInstance, + instance: &'a TSPInstance, retries: usize, reversal: ReverseSubsequencePerturbation, _phantom: PhantomData } -impl Random2OptPerturbation +impl<'a, D> Random2OptPerturbation<'a, D> where D: Dim, DefaultAllocator: nalgebra::allocator::Allocator { - pub fn new(instance: &TSPInstance, retries: usize) -> Self { + pub fn new(instance: &'a TSPInstance, retries: usize) -> Self { let mut reversal = ReverseSubsequencePerturbation::new(); reversal.min_subsequence_len = 5; reversal.max_subsequence_len = 15; Self { retries, - instance: instance.clone(), + instance, reversal, _phantom: PhantomData } } } -impl PerturbationOperator for Random2OptPerturbation +impl<'a, D> PerturbationOperator for Random2OptPerturbation<'a, D> where D: Dim, DefaultAllocator: nalgebra::allocator::Allocator,