use std::marker::PhantomData; use nalgebra::{allocator::Allocator, DefaultAllocator, Dim}; use rand::{Rng, RngCore}; use eoa_lib::perturbation::PerturbationOperator; use crate::tsp::NodePermutation; pub struct SwapPerturbation { _phantom: PhantomData } impl SwapPerturbation { pub fn new() -> Self { Self { _phantom: PhantomData } } } impl PerturbationOperator for SwapPerturbation where D: Dim, DefaultAllocator: Allocator, DefaultAllocator: Allocator, { type Chromosome = NodePermutation; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { let first = rng.random_range(0..chromosome.permutation.len()); let second = rng.random_range(0..chromosome.permutation.len()); chromosome.permutation.swap_rows(first, second); } } pub struct MovePerturbation { _phantom: PhantomData } impl MovePerturbation { pub fn new() -> Self { Self { _phantom: PhantomData } } } impl PerturbationOperator for MovePerturbation where D: Dim, DefaultAllocator: Allocator, DefaultAllocator: Allocator, { type Chromosome = NodePermutation; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { let from = rng.random_range(0..chromosome.permutation.len()); let to = rng.random_range(0..chromosome.permutation.len()); let element = chromosome.permutation[from]; if from < to { for i in from..to { chromosome.permutation[i] = chromosome.permutation[i + 1]; } } else { for i in (to+1..=from).rev() { chromosome.permutation[i] = chromosome.permutation[i - 1]; } } chromosome.permutation[to] = element; } } pub struct ReverseSubsequencePerturbation { _phantom: PhantomData, min_subsequence_len: usize, max_subsequence_len: usize, } impl ReverseSubsequencePerturbation { pub fn new() -> Self { Self { _phantom: PhantomData, max_subsequence_len: usize::MAX, min_subsequence_len: 0, } } } impl PerturbationOperator for ReverseSubsequencePerturbation where D: Dim, DefaultAllocator: Allocator, DefaultAllocator: Allocator, { type Chromosome = NodePermutation; fn perturb(&self, chromosome: &mut Self::Chromosome, rng: &mut dyn RngCore) { let len = chromosome.permutation.len(); let index = rng.random_range(0..chromosome.permutation.len()); let subsequence_len = rng.random_range( self.min_subsequence_len..(chromosome.permutation.len().min(self.max_subsequence_len)) ); // Reverse the subsequence between start and end (inclusive) let mut left = index; let mut right = (index + subsequence_len) % len; while left != right { chromosome.permutation.swap_rows(left, right); left += 1; left %= len; if left == right { break; } if right > 0 { right -= 1; } else { right = len - 1; } } } }