~ruther/ctu-fee-eoa

e9632af4480ade6e25d2891d275064c410f638a4 — Rutherther a month ago 0ef7b7f
feat(tsp): add 2opt perturbation for subsequence reversal
1 files changed, 55 insertions(+), 2 deletions(-)

M codes/tsp_hw01/src/perturbations.rs
M codes/tsp_hw01/src/perturbations.rs => codes/tsp_hw01/src/perturbations.rs +55 -2
@@ 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<D> {
    _phantom: PhantomData<D>


@@ 120,3 120,56 @@ where
        }
    }
}

pub struct Random2OptPerturbation<D>
where
    D: Dim,
    DefaultAllocator: nalgebra::allocator::Allocator<D, D>
{
    instance: TSPInstance<D>,
    retries: usize,
    reversal: ReverseSubsequencePerturbation<D>,
    _phantom: PhantomData<D>
}

impl<D> Random2OptPerturbation<D>
where
    D: Dim,
    DefaultAllocator: nalgebra::allocator::Allocator<D, D>
{
    pub fn new(instance: &TSPInstance<D>, 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<D> PerturbationOperator for Random2OptPerturbation<D>
where
    D: Dim,
    DefaultAllocator: nalgebra::allocator::Allocator<D>,
    DefaultAllocator: nalgebra::allocator::Allocator<D, D>,
{
    type Chromosome = NodePermutation<D>;

    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;
            }
        }
    }
}