use crate::Mutate;
use crate::Sequence;
use rand::Rng;
impl<Insn: Mutate> Sequence<Insn> {
fn random_offset(&self) -> usize {
let mut rng = rand::rng();
if self.0.is_empty() {
0
} else {
rng.random_range(0..self.0.len())
}
}
fn delete_random(&mut self) {
if !self.is_empty() {
let offset = self.random_offset();
self.0.remove(offset);
}
}
fn insert_random(&mut self) {
let offs = self.random_offset();
self.0.insert(offs, Insn::random());
}
fn exchange_random(&mut self) {
if self.len() > 2 {
let offset_a = self.random_offset();
let offset_b = self.random_offset();
self.0.swap(offset_a, offset_b);
}
}
fn replace_random(&mut self) {
if !self.is_empty() {
let offset = self.random_offset();
self.0[offset] = Insn::random();
}
}
fn mutate_random(&mut self) {
if !self.0.is_empty() {
let offset = self.random_offset();
self.0[offset].mutate();
}
}
}
impl<Insn: Mutate> Mutate for Sequence<Insn> {
fn random() -> Self {
let mut s = Self(vec![]);
while rand::random() {
s.insert_random()
}
s
}
fn mutate(&mut self) {
use rand::Rng;
let choice = rand::rng().random_range(0..5);
match choice {
0 => self.delete_random(),
1 => self.insert_random(),
2 => self.exchange_random(),
3 => self.replace_random(),
4 => self.mutate_random(),
_ => unreachable!(),
}
}
}
impl<Insn: Copy> crate::Crossover for Sequence<Insn> {
fn crossover(a: &Self, b: &Self) -> Self {
let min_len = usize::min(a.len(), b.len());
let crossover_point = if min_len == 0 {
0
} else {
rand::rng().random_range(0..min_len)
};
Self(
a.iter()
.take(crossover_point)
.chain(b.iter().skip(crossover_point))
.copied()
.collect(),
)
}
}