use std::marker::PhantomData;
use better_any::{Tid, TidAble};
use derive_more::{Deref, DerefMut};
use eyre::ensure;
use crate::{
component::{AnyComponent, ExecResult},
population::AsSolutionsMut,
CustomState, Problem, State,
};
pub mod common;
pub mod de;
pub mod functional;
pub use common::{
BitFlipMutation, InversionMutation, NormalMutation, PartialRandomBitstring,
PartialRandomSpread, ScrambleMutation, SwapMutation, TranslocationMutation, UniformMutation,
};
pub trait Mutation<P: Problem>: AnyComponent {
fn mutate(
&self,
solution: &mut P::Encoding,
problem: &P,
state: &mut State<P>,
) -> ExecResult<()>;
}
pub fn mutation<T, P>(component: &T, problem: &P, state: &mut State<P>) -> ExecResult<()>
where
P: Problem,
T: Mutation<P>,
{
let mut population = state.populations_mut().pop();
for solution in population.as_solutions_mut() {
component.mutate(solution, problem, state)?;
}
state.populations_mut().push(population);
Ok(())
}
#[derive(Deref, DerefMut, Tid)]
pub struct MutationStrength<T: AnyComponent + 'static>(
#[deref]
#[deref_mut]
f64,
PhantomData<T>,
);
impl<T: AnyComponent> MutationStrength<T> {
pub fn new(value: f64) -> Self {
Self(value, PhantomData)
}
}
impl<T: AnyComponent> CustomState<'_> for MutationStrength<T> {}
#[derive(Deref, DerefMut, Tid)]
pub struct MutationRate<T: AnyComponent + 'static>(
#[deref]
#[deref_mut]
f64,
PhantomData<T>,
);
impl<T: AnyComponent> MutationRate<T> {
pub fn new(value: f64) -> Self {
Self(value, PhantomData)
}
pub fn value(&self) -> ExecResult<f64> {
ensure!(
(0.0..=1.0).contains(&self.0),
"mutation rate must be in [0, 1]"
);
Ok(self.0)
}
}
impl<T: AnyComponent> CustomState<'_> for MutationRate<T> {}