use std::fmt::Debug;
use std::ops::{Add, AddAssign, Deref, Mul, MulAssign};
use crate::neural_network::layer_trait::Layer;
use ndarray::prelude::*;
use ndarray::Array;
pub struct Link(Option<usize>, Option<usize>);
pub struct Nnet<T> where T : Clone + Default + Debug + AddAssign + MulAssign + Add<i32, Output = T> + Mul<i32> + Mul<i32, Output = T> {
pub layers : Vec<Box<dyn Layer<T>>>,
pub are_weights_initialised : bool,
pub are_biases_initialised : bool
}
impl<T> Nnet<T> where T : Clone + Default + Debug + AddAssign + MulAssign + Add<i32, Output = T> + Mul<i32> + Mul<i32, Output = T> {
pub fn new() -> Nnet<T> {
Nnet {
layers: Vec::new(),
are_weights_initialised: false,
are_biases_initialised: false
}
}
pub fn add_layer(&mut self, layer : Box<dyn Layer<T>>) -> usize {
self.layers.push(layer);
self.layers.len()-1
}
pub fn forward(&mut self, input: Array<T, IxDyn>) -> Result<(Array<T, IxDyn>), &str> {
if !self.are_biases_initialised {
return Err("You have not initialised the biases for this neural network!");
}
if !self.are_weights_initialised {
return Err("You have not initialised the weights for this neural network!");
}
let mut current_input = input;
for layer in &self.layers {
if layer.get_weights().shape() == &[0 as usize] {
continue;
}
let weights = layer.get_weights();
let bias = layer.get_bias();
let number_of_input_elements = current_input.shape()[0];
let number_of_output_elements = weights.len()/number_of_input_elements;
let mut result = Vec::new();
for i in 0.. number_of_output_elements {
let mut current_res : T = T::default();
for j in i*number_of_input_elements..(i+1)*number_of_input_elements {
let value = current_input[j%number_of_input_elements].clone()*weights[j];
current_res += value;
}
current_res = current_res.clone() + bias;
result.push(current_res.clone());
}
current_input = Array::from_vec(result).into_dyn();
}
Ok(current_input)
}
pub fn initialise_weights(&mut self, weights : Vec<Array<i32, Ix1>>) ->Result<(), String> {
if weights.len() != (self.layers.len()-1) {
return Err(format!("{} sets of weights expected. Received {}!", self.layers.len()-1, weights.len()));
}
for i in 0..self.layers.len()-1 {
self.layers[i].change_weights(weights[i].clone())
}
self.are_weights_initialised = true;
Ok(())
}
pub fn initialise_biases(&mut self, biases : Vec<i32>) ->Result<(), String> {
if biases.len() != (self.layers.len()-1) {
return Err(format!("{} biases expected. Received {}!", self.layers.len()-1, biases.len()));
}
for i in 0..self.layers.len()-1 {
self.layers[i].change_bias(biases[i])
}
self.are_biases_initialised = true;
Ok(())
}
}