extern crate rand;
use std::fmt;
use std::mem;
use std::ptr;
use std::error::Error;
use std::collections::{HashMap};
use std::sync::{Arc, Mutex};
use rand::Rng;
use rand::seq::SliceRandom;
use super::neuron::{
Neuron,
NodeType,
Activation
};
use super::{
edge::{Edge},
counter::{Counter},
neatenv::{NeatEnvironment}
};
use crate::engine::genome::{Genome};
#[derive(Debug)]
pub struct Neat {
pub inputs: Vec<i32>,
pub outputs: Vec<i32>,
pub nodes: HashMap<i32, *mut Neuron>,
pub edges: HashMap<i32, Edge>
}
impl Neat {
pub fn new() -> Self {
Neat {
inputs: Vec::new(),
outputs: Vec::new(),
nodes: HashMap::new(),
edges: HashMap::new()
}
}
#[inline]
pub fn feed_forward(&self, data: &Vec<f64>) -> Result<Vec<f64>, Box<dyn Error>> {
unsafe {
self.reset_neurons();
let mut path = self.give_inputs(data);
while path.len() > 0 {
let curr_node = self.nodes.get(&path.pop().unwrap()).unwrap();
if let Some(val) = (**curr_node).curr_value {
for edge_innov in (**curr_node).outgoing.iter() {
let curr_edge = self.edges.get(edge_innov).unwrap();
if curr_edge.active {
let receiving_node = self.nodes.get(&curr_edge.dst).unwrap();
(**receiving_node).incoming.insert(curr_edge.innov, Some(val * curr_edge.weight));
if (**receiving_node).is_ready() {
path.push((**receiving_node).innov);
}
}
}
}
}
let mut network_output = Vec::with_capacity(self.outputs.len());
for innov in self.outputs.iter() {
let node_val = (**self.nodes.get(innov).unwrap()).curr_value.unwrap();
network_output.push(node_val);
}
Ok(network_output)
}
}
#[inline]
pub fn backprop(&mut self, data: &Vec<f64>, targets: &Vec<f64>, learning_rate: f64) {
let prediction = self.feed_forward(data).unwrap();
let mut path = self.outputs.iter().map(|x| *x).collect::<Vec<_>>();
let mut errors = HashMap::new();
for (output_innov, (answer, guess)) in self.outputs.iter().zip(targets.iter().zip(prediction.iter())) {
errors.insert(*output_innov, answer - guess);
}
unsafe {
while path.len() > 0 {
let curr_node = self.nodes.get(&path.pop().unwrap()).unwrap();
let curr_node_error = *errors.get(&(**curr_node).innov).unwrap() * learning_rate;
for incoming_edge_innov in (**curr_node).incoming.keys() {
let curr_edge = self.edges.get_mut(incoming_edge_innov).unwrap();
if curr_edge.active {
let src_neuron = self.nodes.get(&curr_edge.src).unwrap();
let step = curr_node_error * Neuron::deactivate((**curr_node).activation, (**curr_node).curr_value.unwrap());
curr_edge.weight += step * (**src_neuron).curr_value.unwrap();
errors.insert(curr_edge.src, curr_edge.weight * curr_node_error);
path.push(curr_edge.src);
}
}
}
}
}
#[inline]
unsafe fn reset_neurons(&self) {
for val in self.nodes.values() {
(**val).reset_node();
}
}
#[inline]
pub fn connect(mut self, num_in: i32, num_out: i32, counter: &mut Counter) -> Self {
for i in 0..num_in + num_out {
let innov = counter.next();
let new_node;
if i < num_in {
new_node = Neuron::new(innov, NodeType::Input, Activation::Sigmoid).as_mut_ptr();
self.inputs.push(innov);
} else {
new_node = Neuron::new(innov, NodeType::Output, Activation::Sigmoid).as_mut_ptr();
self.outputs.push(innov);
}
self.nodes.insert(innov, new_node);
}
unsafe {
for i in self.inputs.iter() {
for j in self.outputs.iter() {
let sending = self.nodes.get(i).unwrap();
let receving = self.nodes.get(j).unwrap();
let new_edge = Edge::new((**sending).innov, (**receving).innov, counter.next(), 1.0, true);
(**sending).outgoing.push(new_edge.innov);
(**receving).incoming.insert(new_edge.innov, None);
self.edges.insert(new_edge.innov, new_edge);
}
}
}
self
}
#[inline]
pub fn add_node(&mut self, counter: &mut Counter, activation: Activation) -> Option<*mut Neuron> {
let new_node = Neuron::new(counter.next(), NodeType::Hidden, activation).as_mut_ptr();
let curr_edge = self.edges.get_mut(&self.random_edge()).unwrap();
let sending = self.nodes.get(&curr_edge.src).unwrap();
let receiving = self.nodes.get(&curr_edge.dst).unwrap();
unsafe {
curr_edge.deactivate();
let incoming = Edge::new((**sending).innov, (*new_node).innov, counter.next(), 1.0, true);
let outgoing = Edge::new((*new_node).innov, (**receiving).innov, counter.next(), curr_edge.weight, true);
(**sending).outgoing.retain(|x| x != &(curr_edge.innov));
(**receiving).incoming.remove(&curr_edge.innov);
(**sending).outgoing.push(incoming.innov);
(**receiving).incoming.insert(outgoing.innov, None);
(*new_node).outgoing.push(outgoing.innov);
(*new_node).incoming.insert(incoming.innov, None);
self.edges.insert(incoming.innov, incoming);
self.edges.insert(outgoing.innov, outgoing);
self.nodes.insert((*new_node).innov, new_node);
Some(new_node)
}
}
#[inline]
pub fn add_edge(&mut self, counter: &mut Counter) -> Option<Edge> {
unsafe {
let sending = loop {
let temp = self.nodes.get(&self.random_node()).unwrap();
if (**temp).node_type != NodeType::Output {
break temp;
}
};
let receiving = loop {
let temp = self.nodes.get(&self.random_node()).unwrap();
if (**temp).node_type != NodeType::Input {
break temp;
}
};
if self.valid_connection(sending, receiving) {
let mut r = rand::thread_rng();
let new_edge = Edge::new((**sending).innov, (**receiving).innov, counter.next(), r.gen::<f64>(), true);
(**sending).outgoing.push(new_edge.innov);
(**receiving).incoming.insert(new_edge.innov, None);
let result = new_edge.clone();
self.edges.insert(new_edge.innov, new_edge);
return Some(result)
}
None
}
}
#[inline]
unsafe fn valid_connection(&self, sending: &*mut Neuron, receiving: &*mut Neuron) -> bool {
if sending == receiving {
return false
} else if self.exists(sending, receiving) {
return false
} else if self.cyclical(sending, receiving) {
return false
}
true
}
#[inline]
unsafe fn cyclical(&self, sending: &*mut Neuron, receiving: &*mut Neuron) -> bool {
let mut stack = (**receiving).outgoing
.iter()
.map(|x| self.edges.get(x).unwrap().dst)
.collect::<Vec<_>>();
while stack.len() > 0 {
let curr = self.nodes.get(&stack.pop().unwrap()).unwrap();
if curr == sending {
return true;
}
for i in (**curr).outgoing.iter() {
stack.push(self.edges.get(i).unwrap().dst);
}
}
false
}
#[inline]
unsafe fn exists(&self, sending: &*mut Neuron, receiving: &*mut Neuron) -> bool {
for val in self.edges.values() {
if val.src == (**sending).innov && val.dst == (**receiving).innov {
return true
}
}
false
}
#[inline]
fn random_node(&self) -> i32 {
let index = rand::thread_rng().gen_range(0, self.nodes.len());
for (i, (innov, _)) in self.nodes.iter().enumerate() {
if i == index {
return *innov;
}
}
panic!("Failed to get random node");
}
#[inline]
fn random_edge(&self) -> i32 {
let index = rand::thread_rng().gen_range(0, self.edges.len());
for (i, (innov, _)) in self.edges.iter().enumerate() {
if i == index {
return *innov;
}
}
panic!("Failed to get random edge");
}
#[inline]
unsafe fn give_inputs(&self, data: &Vec<f64>) -> Vec<i32> {
assert!(data.len() == self.inputs.len());
self.inputs.iter().zip(data.iter())
.map(|(node_innov, input)| {
let node = self.nodes.get(node_innov).unwrap();
(**node).curr_value = Some(*input);
(**node).innov
})
.collect()
}
#[inline]
fn edit_weights(&mut self, editable: f32, size: f64) {
let mut r = rand::thread_rng();
for (_, edge) in self.edges.iter_mut() {
if r.gen::<f32>() < editable {
edge.weight = r.gen::<f64>();
} else {
edge.weight *= r.gen_range(-size, size);
}
}
}
#[inline]
fn max_marker(&self) -> i32 {
let mut result = None;
for key in self.edges.keys() {
if result.is_none() || key > result.unwrap() {
result = Some(key);
}
}
*result.unwrap_or_else(|| panic!("Failed to find max marker"))
}
pub fn see(&self) {
unsafe {
for node in self.nodes.values() {
println!("{:?}", **node);
}
for edge in self.edges.values() {
println!("{:?}", edge);
}
}
}
#[inline]
unsafe fn neuron_control(child: &mut Neat, new_node: &*mut Neuron, env: &mut NeatEnvironment) -> Result<(), &'static str>{
let new_node_incoming_edge: i32 = *(**new_node).incoming.keys().next().unwrap();
let new_node_outgoing_edge: i32 = *(**new_node).outgoing.last().unwrap();
let new_node_incoming_neuron = child.edges.get_mut(&new_node_incoming_edge).unwrap().src;
let new_node_outgoing_neuron = child.edges.get_mut(&new_node_outgoing_edge).unwrap().dst;
let neuron_key = (new_node_incoming_neuron, new_node_outgoing_neuron);
if !env.global_nodes.contains_key(&neuron_key) {
let incoming_edge_key = (new_node_incoming_neuron, (**new_node).innov);
let outgoing_edge_key = ((**new_node).innov, new_node_outgoing_neuron);
env.global_edges.insert(incoming_edge_key, child.edges.get(&new_node_incoming_edge).unwrap().clone());
env.global_edges.insert(outgoing_edge_key, child.edges.get(&new_node_outgoing_edge).unwrap().clone());
env.global_nodes.insert(neuron_key, (**new_node).clone());
} else if env.global_nodes.contains_key(&neuron_key) {
let stored_node = env.global_nodes.get(&neuron_key).unwrap().clone().as_mut_ptr();
if !child.nodes.contains_key(&(*stored_node).innov) {
let stored_incoming_edge_key = (new_node_incoming_neuron, (*stored_node).innov);
let stored_outgoing_edge_key = ((*stored_node).innov, new_node_outgoing_neuron);
let stored_incoming_edge = env.global_edges.get(&stored_incoming_edge_key).unwrap().clone();
let stored_outgoing_edge = env.global_edges.get(&stored_outgoing_edge_key).unwrap().clone();
let incoming_node = child.nodes.get(&new_node_incoming_neuron).unwrap();
let outgoing_node = child.nodes.get(&new_node_outgoing_neuron).unwrap();
(**incoming_node).outgoing.remove((**incoming_node).outgoing.iter().position(|&x| x == new_node_incoming_edge).unwrap());
(**incoming_node).outgoing.push(stored_incoming_edge.innov);
(**outgoing_node).incoming.remove(&new_node_outgoing_edge);
(**outgoing_node).incoming.insert(stored_outgoing_edge.innov, None);
child.nodes.remove(&(**new_node).innov);
child.edges.remove(&new_node_incoming_edge);
child.edges.remove(&new_node_outgoing_edge);
child.nodes.insert((*stored_node).innov, stored_node);
child.edges.insert(stored_incoming_edge.innov, stored_incoming_edge);
child.edges.insert(stored_outgoing_edge.innov, stored_outgoing_edge);
env.subtract_count(3);
}
}
Ok(())
}
#[inline]
unsafe fn edge_control(child: &mut Neat, new_edge: Option<Edge>, env: &mut NeatEnvironment) {
if let Some(new_edge) = new_edge {
let key = (new_edge.src, new_edge.dst);
if env.global_edges.contains_key(&key) {
let stored_edge = env.global_edges.get(&key).unwrap();
let src_neuron = child.nodes.get(&stored_edge.src).unwrap();
let dst_neuron = child.nodes.get(&stored_edge.dst).unwrap();
(**src_neuron).outgoing.remove((**src_neuron).outgoing.iter().position(|&x| x == new_edge.innov).unwrap());
(**dst_neuron).incoming.remove(&new_edge.innov);
(**src_neuron).outgoing.push(stored_edge.innov);
(**dst_neuron).incoming.insert(stored_edge.innov, None);
child.edges.remove(&new_edge.innov);
child.edges.insert(stored_edge.innov, stored_edge.clone());
} else {
env.global_edges.insert(key, new_edge.clone());
}
}
}
}
impl Clone for Neat {
fn clone(&self) -> Self {
Neat {
inputs: self.inputs.iter().map(|x| *x).collect(),
outputs: self.outputs.iter().map(|x| *x).collect(),
nodes: self.nodes.iter()
.map(|(key, val)| {
let node = unsafe { (**val).clone() };
(*key, node.as_mut_ptr())
})
.collect(),
edges: self.edges.iter()
.map(|(key, val)| {
(*key, val.clone())
})
.collect()
}
}
}
impl Drop for Neat {
fn drop(&mut self) {
unsafe {
for (_, node) in self.nodes.iter() {
ptr::drop_in_place(*node);
}
}
}
}
unsafe impl Send for Neat {}
unsafe impl Sync for Neat {}
impl PartialEq for Neat {
fn eq(&self, other: &Self) -> bool {
if self.edges.len() != other.edges.len() || self.nodes.len() != other.nodes.len() {
return false;
}
for (one, two) in self.edges.values().zip(other.edges.values()) {
if one != two {
return false;
}
}
true
}
}
impl fmt::Display for Neat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
let address: u64 = mem::transmute(self);
write!(f, "Neat=[{}, {}, {}]", address, self.nodes.len(), self.edges.len())
}
}
}
impl Genome<Neat, NeatEnvironment> for Neat {
#[inline]
fn crossover(one: &Neat, two: &Neat, env: &Arc<Mutex<NeatEnvironment>>, crossover_rate: f32) -> Option<Neat> {
let mut set = (*env).lock().ok()?;
let mut r = rand::thread_rng();
let mut result = (*one).clone();
unsafe {
if r.gen::<f32>() < crossover_rate {
for (innov, edge) in result.edges.iter_mut() {
if two.edges.contains_key(innov) {
if r.gen::<f32>() < 0.5 {
edge.weight = two.edges.get(innov)?.weight;
}
if (!edge.active || !two.edges.get(innov)?.active) && r.gen::<f32>() < set.reactivate? {
(**result.nodes.get(&edge.src)?).outgoing.push(*innov);
(**result.nodes.get(&edge.dst)?).incoming.insert(*innov, None);
edge.activate();
}
}
}
} else {
if r.gen::<f32>() < set.weight_mutate_rate? {
result.edit_weights(set.edit_weights?, set.weight_perturb?);
}
if r.gen::<f32>() < set.new_node_rate? {
let act_func = *set.activation_functions.choose(&mut r)?;
let new_node = result.add_node(set.get_mut_counter(), act_func)?;
Neat::neuron_control(&mut result, &new_node, &mut set).ok()?;
}
if r.gen::<f32>() < set.new_edge_rate? {
let new_edge = result.add_edge(set.get_mut_counter());
Neat::edge_control(&mut result, new_edge, &mut set);
}
}
}
Some(result)
}
fn base(env: &mut NeatEnvironment) -> Neat {
Neat::new()
.connect(
env.input_size.unwrap(),
env.output_size.unwrap(),
env.get_mut_counter()
)
}
fn distance(one: &Neat, two: &Neat, env: &Arc<Mutex<NeatEnvironment>>) -> f64 {
let (mut e, mut d) = (0.0, 0.0);
let (mut w, mut wc) = (0.0, 0.0);
let one_max = one.max_marker();
let two_max = two.max_marker();
let (big, small, small_innov) = if one_max > two_max {
(one, two, two_max)
} else {
(two, one, one_max)
};
for (innov, edge) in big.edges.iter() {
if small.edges.contains_key(innov) {
w += (edge.weight - small.edges.get(innov).unwrap().weight).abs();
wc += 1.0;
continue;
}
if innov > &small_innov {
e += 1.0;
} else {
d += 1.0;
}
}
for innov in small.edges.keys() {
if !big.edges.contains_key(innov) {
d += 1.0;
}
}
let wc = if wc == 0.0 { 1.0 } else { wc };
let lock_env = (*env).lock().unwrap();
((lock_env.c1.unwrap() * e) / big.edges.len() as f64) + ((lock_env.c2.unwrap() * d) / big.edges.len() as f64) + (lock_env.c3.unwrap() * (w / wc))
}
}