use std::{convert::Infallible, error::Error}; use nalgebra::SVector; use rand_distr::{Normal, NormalError}; use crate::{local_search::LocalSearchStats, perturbation::{apply_to_perturbations, PerturbationOperator, RandomDistributionPerturbation}}; pub trait EvolutionaryStrategy { type Err: Error + 'static; fn step(&mut self, perturbation: &mut TPerturbation, better: bool, stats: &LocalSearchStats ) -> Result<(), Self::Err>; } fn normal_one_to_five(perturbation: &mut RandomDistributionPerturbation>, better: bool) -> Result<(), NormalError> { let exp: f64 = if better { 1.0 } else { 0.0 } - 0.2; let sigma = perturbation.std_dev(); let new_sigma = sigma * exp.exp().powf(1.0 / LEN as f64); // Hopefully prevent cases when the sigma goes too low let new_sigma = if new_sigma < 0.000000001 { 0.000000001 } else { new_sigma }; perturbation.set_std_dev(new_sigma)?; Ok(()) } pub struct OneToFiveStrategy; impl>, TOut> EvolutionaryStrategy for OneToFiveStrategy { type Err = NormalError; fn step(&mut self, perturbation: &mut TPerturbation, better: bool, _: &LocalSearchStats, TOut> ) -> Result<(), Self::Err> { let mut found = false; let mut result = Ok(()); apply_to_perturbations::<_, RandomDistributionPerturbation>>( perturbation, &mut |perturbation| { found = true; result = normal_one_to_five(perturbation, better); } ); if !found { panic!("There is no random distribution perturbation!"); } result } } pub struct IdentityStrategy; impl EvolutionaryStrategy for IdentityStrategy { type Err = Infallible; fn step(&mut self, _: &mut TPerturbation, _: bool, _: &LocalSearchStats ) -> Result<(), Self::Err> { Ok(()) } }