From e9632af4480ade6e25d2891d275064c410f638a4 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 1 Nov 2025 19:41:39 +0100 Subject: [PATCH] feat(tsp): add 2opt perturbation for subsequence reversal --- codes/tsp_hw01/src/perturbations.rs | 57 ++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/codes/tsp_hw01/src/perturbations.rs b/codes/tsp_hw01/src/perturbations.rs index f62385a0357f347d9a347b113545917ed3f0591e..a5c65d94623729d0655b27eb578fea81b4f9976b 100644 --- a/codes/tsp_hw01/src/perturbations.rs +++ b/codes/tsp_hw01/src/perturbations.rs @@ -1,8 +1,8 @@ use std::marker::PhantomData; use nalgebra::{allocator::Allocator, DefaultAllocator, Dim}; use rand::{Rng, RngCore}; -use eoa_lib::perturbation::PerturbationOperator; -use crate::tsp::NodePermutation; +use eoa_lib::{fitness::FitnessFunction, perturbation::PerturbationOperator}; +use crate::tsp::{NodePermutation, TSPInstance}; pub struct SwapPerturbation { _phantom: PhantomData @@ -120,3 +120,56 @@ where } } } + +pub struct Random2OptPerturbation +where + D: Dim, + DefaultAllocator: nalgebra::allocator::Allocator +{ + instance: TSPInstance, + retries: usize, + reversal: ReverseSubsequencePerturbation, + _phantom: PhantomData +} + +impl Random2OptPerturbation +where + D: Dim, + DefaultAllocator: nalgebra::allocator::Allocator +{ + pub fn new(instance: &TSPInstance, retries: usize) -> Self { + let mut reversal = ReverseSubsequencePerturbation::new(); + reversal.min_subsequence_len = 5; + reversal.max_subsequence_len = 15; + + Self { + retries, + instance: instance.clone(), + reversal, + _phantom: PhantomData + } + } +} + +impl PerturbationOperator for Random2OptPerturbation +where + D: Dim, + DefaultAllocator: nalgebra::allocator::Allocator, + DefaultAllocator: nalgebra::allocator::Allocator, +{ + type Chromosome = NodePermutation; + + fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { + let original_fitness = self.instance.fit(chromosome).unwrap(); + + for _ in 0..self.retries { + let mut cloned = chromosome.clone(); + self.reversal.perturb(&mut cloned, rng); + let new_fitness = self.instance.fit(&cloned).unwrap(); + if new_fitness < original_fitness { + std::mem::swap(chromosome, &mut cloned); + return; + } + } + } +}