#[macro_use]
extern crate serde_derive;
extern crate rand;
extern crate mli;
use std::collections::BTreeSet;
use std::cmp;
use rand::{Rng, Rand};
use std::ops::Range;
use std::iter::Rev;
use mli::{Stateless, MateRand, Mutate};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
struct Opcode<Ins> {
instruction: Ins,
first: usize,
second: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Mep<Ins> {
program: Vec<Opcode<Ins>>,
mutate_lambda: usize,
crossover_points: usize,
inputs: usize,
outputs: usize,
}
impl<Ins> Mep<Ins> {
pub fn new<R>(
inputs: usize,
outputs: usize,
internal_instruction_count: usize,
mutate_lambda: usize,
crossover_points: usize,
rng: &mut R,
) -> Self
where
R: Rng,
Ins: Rand,
{
Mep {
program: (0..internal_instruction_count + outputs)
.map(|i| if i < internal_instruction_count {
Opcode {
instruction: rng.gen(),
first: rng.gen_range(0, i + inputs),
second: rng.gen_range(0, i + inputs),
}
} else {
Opcode {
instruction: rng.gen(),
first: rng.gen_range(0, internal_instruction_count + inputs),
second: rng.gen_range(0, internal_instruction_count + inputs),
}
})
.collect(),
mutate_lambda: mutate_lambda,
crossover_points: crossover_points,
inputs: inputs,
outputs: outputs,
}
}
}
impl<Ins, R> MateRand<R> for Mep<Ins>
where
R: Rng,
Ins: Clone,
{
fn mate(&self, rhs: &Self, rng: &mut R) -> Self {
assert!(self.inputs == rhs.inputs);
assert!(self.outputs == rhs.outputs);
let total_instructions = cmp::min(self.program.len(), rhs.program.len());
let crossover_choice = rng.gen_range(0, 2);
Mep {
program:
(0..rng.gen_range(1, cmp::min((total_instructions / 2).saturating_add(2), {
if crossover_choice == 0 {self}
else {rhs}}.crossover_points.saturating_add(2))))
.map(|_| rng.gen_range(0, total_instructions))
.chain(Some(total_instructions))
.fold(BTreeSet::new(), |mut set, i| {set.insert(i); set})
.iter()
.scan(0, |prev, x| {let out = Some(*prev..*x); *prev = *x; out})
.enumerate()
.flat_map(|(index, range)| {
{if index % 2 == 0 {self} else {rhs}}.program[range].iter().cloned()
})
.collect(),
mutate_lambda: if self.mutate_lambda < rhs.mutate_lambda {
rng.gen_range(self.mutate_lambda, rhs.mutate_lambda.saturating_add(1))
} else {
rng.gen_range(rhs.mutate_lambda, self.mutate_lambda.saturating_add(1))
},
crossover_points: if self.crossover_points < rhs.crossover_points {
rng.gen_range(self.crossover_points, rhs.crossover_points.saturating_add(1))
} else {
rng.gen_range(rhs.crossover_points, self.crossover_points.saturating_add(1))
},
inputs: self.inputs,
outputs: self.outputs,
}
}
}
impl<Ins, R> Mutate<R> for Mep<Ins>
where
Ins: Mutate<R>,
R: Rng,
{
fn mutate(&mut self, rng: &mut R) {
let effective_lambda = self.mutate_lambda.saturating_add(1);
if rng.gen_range(0, effective_lambda) == 0 {
match rng.gen_range(0, 2) {
0 => self.mutate_lambda = self.mutate_lambda.saturating_add(1),
_ => self.mutate_lambda = self.mutate_lambda.saturating_sub(1),
}
}
if rng.gen_range(0, effective_lambda) == 0 {
match rng.gen_range(0, 2) {
0 => self.crossover_points = self.crossover_points.saturating_add(1),
_ => self.crossover_points = self.crossover_points.saturating_sub(1),
}
}
let plen = self.program.len();
loop {
let choice = rng.gen_range(0, plen.saturating_add(effective_lambda));
if choice >= plen {
break;
}
let op = &mut self.program[choice];
match rng.gen_range(0, 3) {
0 => op.instruction.mutate(rng),
1 => {
op.first = if choice >= plen - self.outputs {
rng.gen_range(0, self.inputs + plen - self.outputs)
} else {
rng.gen_range(0, choice + self.inputs)
}
}
_ => {
op.second = if choice >= plen - self.outputs {
rng.gen_range(0, self.inputs + plen - self.outputs)
} else {
rng.gen_range(0, choice + self.inputs)
}
}
}
}
}
}
impl<'a, Ins, Param> Stateless<'a, &'a [Param], ResultIterator<'a, Ins, Param>> for Mep<Ins>
where Param: Clone
{
fn process(&'a self, inputs: &'a [Param]) -> ResultIterator<'a, Ins, Param> {
ResultIterator {
mep: self,
buff: vec![None; self.program.len()],
solve_iter: ((self.program.len() + self.inputs - self.outputs)..(self.program.len() +
self.inputs))
.rev(),
inputs: inputs,
}
}
}
pub struct ResultIterator<'a, Ins, Param>
where
Ins: 'a,
Param: 'a,
{
mep: &'a Mep<Ins>,
buff: Vec<Option<Param>>,
solve_iter: Rev<Range<usize>>,
inputs: &'a [Param],
}
impl<'a, Ins, Param> ResultIterator<'a, Ins, Param> {
#[inline]
fn op_solved(&mut self, i: usize) -> Param
where
Param: Clone,
Ins: Stateless<'a, (Param, Param), Param>,
{
if i < self.mep.inputs {
return unsafe { self.inputs.get_unchecked(i) }.clone();
}
let possible = unsafe { self.buff.get_unchecked(i - self.mep.inputs) }.clone();
match possible {
Some(x) => x,
None => {
let op = unsafe { self.mep.program.get_unchecked(i - self.mep.inputs) };
let result = op.instruction.process((
self.op_solved(op.first),
self.op_solved(op.second),
));
unsafe { *self.buff.get_unchecked_mut(i - self.mep.inputs) = Some(result.clone()) };
result
}
}
}
}
impl<'a, Ins, Param> Iterator for ResultIterator<'a, Ins, Param>
where Param: Clone,
Ins: Stateless<'a, (Param, Param), Param>
{
type Item = Param;
#[inline]
fn next(&mut self) -> Option<Param> {
match self.solve_iter.next() {
None => None,
Some(i) => Some(self.op_solved(i)),
}
}
}
#[cfg(test)]
mod tests {
use rand::{Isaac64Rng, SeedableRng, Rand};
use super::*;
#[derive(Clone)]
struct Op;
impl<R> Mutate<R> for Op {
fn mutate(&mut self, _: &mut R) {}
}
impl<'a> Stateless<'a, (i32, i32), i32> for Op {
fn process(&'a self, inputs: (i32, i32)) -> i32 {
inputs.0 + inputs.1
}
}
impl Rand for Op {
fn rand<R>(_: &mut R) -> Self {
Op
}
}
#[test]
fn mep() {
let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
let (mut a, b) = {
let mut clos = || Mep::<Op>::new(3, 1, 10, 10, 10, &mut rng);
(clos(), clos())
};
a.mutate(&mut rng);
let c = a.mate(&b, &mut rng);
let inputs = [2i32, 3, 4];
c.process(&inputs[..]).collect::<Vec<_>>();
}
}