extern crate rand;
extern crate simple_matrix;
extern crate radiate;
use std::sync::{Arc, RwLock};
use rand::rngs::ThreadRng;
use rand::Rng;
use simple_matrix::Matrix;
use crate::tree::*;
use super::{
network::NeuralNetwork,
evenv::TreeEnvionment
};
use radiate::engine::genome::Genome;
#[derive(Debug, Clone, PartialEq)]
pub struct NetNode {
pub neural_network: NeuralNetwork,
pub input_size: i32,
pub output: u8
}
impl NetNode {
pub fn new(input_size: i32, output_options: &Vec<i32>) -> Self {
let mut r = rand::thread_rng();
let output = output_options[r.gen_range(0, output_options.len())] as u8;
Self {
neural_network: NeuralNetwork::new(input_size).fill_random(),
input_size,
output
}
}
}
pub type Evtree = Tree<NetNode>;
impl Evtree {
pub fn gut_random_node(&mut self, r: &mut ThreadRng) {
let index = r.gen_range(0, self.len()) as usize;
let temp_node = self.get_mut(index).unwrap();
temp_node.neural_network = NeuralNetwork::new(temp_node.input_size);
}
#[inline]
pub fn edit_random_node_networks(&mut self, weight_mutate: f32, weight_transform: f32, layer_mutate: f32) {
for node in self.iter_mut() {
node.neural_network.edit_weights(weight_mutate, weight_transform, layer_mutate);
}
}
#[inline]
pub fn asymmetry(&self) -> f32 {
let mut total: f32 = 0.0;
for node in self.in_order_iter() {
total += node.height() as f32 * node.neural_network.weight_sum();
}
total.sin()
}
pub fn propagate(&self, inputs: Matrix<f32>) -> u8 {
let mut curr_node = self.root_opt()
.expect("No root node.");
loop {
let node_output = curr_node.neural_network.feed_forward(inputs.clone());
let (mut max_index, mut temp_value) = (0, None);
for i in 0..node_output.len() {
if node_output[i] > node_output[max_index] || temp_value.is_none() {
max_index = i;
temp_value = Some(node_output[i]);
}
}
if curr_node.is_leaf() {
return curr_node.output;
} else {
let next_node = if max_index == 0 {
curr_node.left_child_opt().or_else(|| {
curr_node.right_child_opt()
})
} else {
curr_node.right_child_opt().or_else(|| {
curr_node.left_child_opt()
})
};
curr_node = next_node
.expect("Non-leaf node doesn't have any children.");
}
}
}
}
impl Genome<Evtree, TreeEnvionment> for Evtree {
#[inline]
fn crossover(one: &Evtree, two: &Evtree, settings: &Arc<RwLock<TreeEnvionment>>, crossover_rate: f32) -> Option<Evtree> {
let set = &*(*settings).read().unwrap();
let mut result = one.clone();
let mut r = rand::thread_rng();
let mut node_one = one.get_biased_random_node();
let mut node_two = two.get_biased_random_node();
while node_one.depth() + node_two.height() > set.max_height? {
node_one = one.get_biased_random_node();
node_two = two.get_biased_random_node();
}
if r.gen::<f32>() < crossover_rate {
let node_index = one.index_of(&node_one);
result.replace(node_index, node_two.deepcopy());
} else {
if r.gen::<f32>() < set.get_network_mutation_rate() {
result.edit_random_node_networks(set.weight_mutate_rate?, set.weight_transform_rate?, set.layer_mutate_rate?);
}
if r.gen::<f32>() < set.node_add_rate? {
result.insert_random(NetNode::new(set.input_size?, set.get_outputs()));
}
if r.gen::<f32>() < set.shuffle_rate? {
result.shuffle_tree(&mut r);
}
if r.gen::<f32>() < set.gut_rate? {
result.gut_random_node(&mut r);
}
result.update_size();
}
Some(result)
}
fn base(settings: &mut TreeEnvionment) -> Evtree {
let mut nodes = (0..(2 * settings.get_max_height()) - 1)
.map(|_| Some(NetNode::new(settings.get_input_size(), settings.get_outputs())))
.collect::<Vec<_>>();
Evtree::from_slice(&mut nodes[..])
}
fn distance(one: &Evtree, two: &Evtree, _settings: &Arc<RwLock<TreeEnvionment>>) -> f32 {
(one.asymmetry() - two.asymmetry()).abs()
}
}