use rand::{Rng};
use std;
use context::*;
use ea::*;
use ga::*;
use math::*;
use neuro::*;
use problem::*;
use result::*;
use settings::*;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NEIndividual {
genes: Vec<f32>,
fitness: f32,
network: Option<MultilayeredNetwork>,
}
#[allow(dead_code)]
impl<'a> NEIndividual {
fn update_net(&mut self) {
match &mut self.network {
&mut Some(ref mut net) => {
let (mut ws, mut bs) = (Vec::new(), Vec::new());
let mut cur_idx = 0;
for layer in net.iter_layers() {
let inputs_num = layer.get_inputs_num();
ws.push(Vec::from(&self.genes[cur_idx..(cur_idx + inputs_num * layer.len())]));
cur_idx += inputs_num * layer.len();
}
for layer in net.iter_layers() {
bs.push(Vec::from(&self.genes[cur_idx..(cur_idx + layer.len())]));
cur_idx += layer.len();
}
net.set_weights(&ws, &bs);
},
&mut None => {
println!("[update_net] Warning: network is not defined");
}
}
}
}
impl Individual for NEIndividual {
fn new() -> NEIndividual {
NEIndividual{
genes: Vec::new(),
fitness: std::f32::NAN,
network: None,
}
}
fn init<R: Rng>(&mut self, size: usize, mut rng: &mut R) {
self.genes = rand_vector_std_gauss(size as usize, rng);
}
fn get_fitness(&self) -> f32 {
self.fitness
}
fn set_fitness(&mut self, fitness: f32) {
self.fitness = fitness;
}
fn to_vec(&self) -> Option<&[f32]> {
Some(&self.genes)
}
fn to_vec_mut(&mut self) -> Option<&mut Vec<f32>> {
Some(&mut self.genes)
}
fn to_net(&mut self) -> Option<&MultilayeredNetwork> {
self.update_net();
match &self.network {
&Some(ref net) => Some(net),
&None => None
}
}
fn to_net_mut(&mut self) -> Option<&mut MultilayeredNetwork> {
self.update_net();
match &mut self.network {
&mut Some(ref mut net) => {Some(net)},
&mut None => None
}
}
fn set_net(&mut self, net: MultilayeredNetwork) {
let (ws, bs) = net.get_weights();
self.network = Some(net);
self.genes = ws.into_iter()
.fold(Vec::new(), |mut res, w| {
res.extend(w.iter().cloned());
res
});
self.genes.extend(bs.into_iter()
.fold(Vec::new(), |mut res, b| {
res.extend(b.iter().cloned());
res
}));
}
}
pub struct NE<'a, P: Problem + 'a> {
ctx: Option<EAContext<NEIndividual>>,
problem: &'a P,
}
#[allow(dead_code)]
impl<'a, P: Problem> NE<'a, P> {
pub fn new(problem: &'a P) -> NE<'a, P> {
NE {problem: problem,
ctx: None,
}
}
}
impl<'a, P: Problem> EA<'a, P> for NE<'a, P> {
type IndType = NEIndividual;
fn breed(&self, ctx: &mut EAContext<Self::IndType>, sel_inds: &Vec<usize>, children: &mut Vec<Self::IndType>) {
cross(&ctx.population, sel_inds, children, ctx.settings.use_elite, ctx.settings.x_type, ctx.settings.x_prob, ctx.settings.x_alpha, &mut ctx.rng);
mutate(children, ctx.settings.mut_type, ctx.settings.mut_prob, ctx.settings.mut_sigma, &mut ctx.rng);
}
fn run(&mut self, settings: EASettings) -> Result<&EAResult<Self::IndType>, ()> {
println!("run");
let gen_count = settings.gen_count;
let mut ctx = EAContext::new(settings, self.problem);
self.run_with_context(&mut ctx, self.problem, gen_count);
self.ctx = Some(ctx);
Ok(&(&self.ctx.as_ref().expect("Empty EAContext")).result)
}
}
#[cfg(test)]
#[allow(unused_imports)]
mod test {
use rand;
use math::*;
use ne::*;
use neproblem::*;
#[test]
pub fn test_symbolic_regression() {
let (pop_size, gen_count, param_count) = (20, 20, 100);
let settings = EASettings::new(pop_size, gen_count, param_count);
let problem = SymbolicRegressionProblem::new_f();
let mut ne: NE<SymbolicRegressionProblem> = NE::new(&problem);
let res = ne.run(settings).expect("Error: NE result is empty");
println!("result: {:?}", res);
println!("\nbest individual: {:?}", res.best);
}
#[test]
pub fn test_net_get_set() {
let mut rng = rand::thread_rng();
let mut net = MultilayeredNetwork::new(2, 2);
net.add_hidden_layer(10 as usize, ActivationFunctionType::Sigmoid)
.add_hidden_layer(5 as usize, ActivationFunctionType::Sigmoid)
.build(&mut rng, NeuralArchitecture::Multilayered);
let (ws1, bs1) = net.get_weights();
let mut ind = NEIndividual::new();
ind.set_net(net.clone());
let net2 = ind.to_net_mut().unwrap();
let (ws2, bs2) = net2.get_weights();
for k in 0..ws1.len() {
let max_diff = max(&sub(&ws1[k], &ws2[k]));
println!("max diff: {}", max_diff);
assert!(max_diff == 0f32);
let max_diff = max(&sub(&bs1[k], &bs2[k]));
println!("bs1: {:?}", bs1[k]);
println!("bs2: {:?}", bs2[k]);
println!("max diff: {}", max_diff);
assert!(max_diff == 0f32);
}
}
}