Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add our first reference implementations for crossover and mutation functions #28

Merged
merged 8 commits into from
Mar 29, 2024
Merged
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ndarray = { version = "0.15.6", features = ["serde"] }
num-traits = "*"
ordered-float = "*"
rand = "*"
rand_distr = "*"
serde = { version = "*", features = ["derive"] }
serde_json = "*"
tempfile = "*"
Expand Down
22 changes: 22 additions & 0 deletions src/individual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::fs::read_to_string;
use std::io::Error as IOError;
use std::path::Path;
use std::ops::Index;
use std::slice::Iter;

use log::trace;
use num_traits::FromPrimitive;
Expand Down Expand Up @@ -97,6 +98,16 @@ impl<T: Tensor> Individual<T> {
self.layers.len()
}

/// Returns an iterator over the individual's layers.
pub fn iter(&self) -> Iter<'_, Layer<T>> {
self.into_iter()
}

/// Returns a reference to the individual's cost function.
pub fn get_cost_function(&self) -> &CostFunction<T> {
&self.cost_function
}

/// Passes the `input` through the network and returns the intermediate results of each layer.
///
/// # Arguments
Expand Down Expand Up @@ -339,6 +350,17 @@ impl<T: Tensor> Index<usize> for Individual<T> {
}


/// Allows turning a reference to an `Individual` into an iterator over [`Layer`] references.
impl<'a, T: Tensor> IntoIterator for &'a Individual<T> {
type Item = &'a Layer<T>;
type IntoIter = Iter<'a, Layer<T>>;

fn into_iter(self) -> Self::IntoIter {
self.layers.iter()
}
}


#[cfg(test)]
mod tests {
use super::*;
Expand Down
4 changes: 4 additions & 0 deletions src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ impl<T: Tensor> Layer<T> {
let activation = (self.activation)(&weighted_input);
(weighted_input, activation)
}

pub fn size(&self) -> usize {
self.weights.shape().0
}
}


Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod component;
pub mod cost_function;
pub mod individual;
pub mod layer;
pub mod population;
pub mod tensor;
pub mod utils;
pub mod world;

130 changes: 0 additions & 130 deletions src/population.rs

This file was deleted.

64 changes: 63 additions & 1 deletion src/tensor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::fmt::{Debug, Display};
use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign};

use ndarray::{Array2, Axis};
use ndarray::{Array2, Axis, ArrayView};
use num_traits::FromPrimitive;
use num_traits::real::Real;
use serde::Serialize;
Expand All @@ -30,6 +30,11 @@ pub trait TensorBase:

/// Creates a tensor of the specified `shape` with all components equal to `num`.
fn from_num(num: Self::Component, shape: (usize, usize)) -> Self;

fn from_iter<I, J>(iterator: I) -> Self
where
I: IntoIterator<Item = J>,
J: IntoIterator<Item = Self::Component>;

/// Returns the shape of the tensor as a tuple of unsigned integers.
fn shape(&self) -> (usize, usize);
Expand All @@ -40,6 +45,12 @@ pub trait TensorBase:
/// Returns the transpose of itself as a new tensor.
fn transpose(&self) -> Self;

/// Append a row to the tensor.
fn append_row(&mut self, row: &[Self::Component]);

/// Append a column to the tensor.
fn append_column(&mut self, column: &[Self::Component]);

/// Calls function `f` on each component and returns the result as a new tensor.
fn map<F>(&self, f: F) -> Self
where F: FnMut(Self::Component) -> Self::Component;
Expand All @@ -48,6 +59,12 @@ pub trait TensorBase:
fn map_inplace<F>(&mut self, f: F)
where F: FnMut(Self::Component) -> Self::Component;

fn indexed_iter(&self) -> impl Iterator<Item = ((usize, usize), &Self::Component)>;

fn indexed_iter_mut(&mut self) -> impl Iterator<Item = ((usize, usize), &mut Self::Component)>;

fn iter(&self) -> impl Iterator<Item = &Self::Component>;

/// Returns the sum of all rows (0) or columns (1) as a new tensor.
fn sum_axis(&self, axis: usize) -> Self;
}
Expand Down Expand Up @@ -158,6 +175,31 @@ impl<C: TensorComponent> TensorBase for Array2<C> {
fn from_num(num: Self::Component, shape: (usize, usize)) -> Self {
Self::from_elem(shape, num)
}

fn from_iter<I, J>(iterator: I) -> Self
where
I: IntoIterator<Item = J>,
J: IntoIterator<Item = Self::Component>,
{
let mut data = Vec::new();
let mut num_rows: usize = 0;
let mut num_columns: Option<usize> = None;
for row in iterator {
num_rows += 1;
let row_vec: Vec<Self::Component> = row.into_iter().collect();
match num_columns {
Some(n) => {
if n != row_vec.len() { panic!() }
},
None => num_columns = Some(row_vec.len()),
}
data.extend_from_slice(&row_vec);
}
Array2::from_shape_vec(
(num_rows, num_columns.unwrap_or(0)),
data,
).unwrap()
}

fn shape(&self) -> (usize, usize) {
self.dim()
Expand All @@ -174,6 +216,14 @@ impl<C: TensorComponent> TensorBase for Array2<C> {
self.t().to_owned()
}

fn append_row(&mut self, row: &[Self::Component]) {
self.push_row(ArrayView::from(row)).unwrap()
}

fn append_column(&mut self, column: &[Self::Component]) {
self.push_column(ArrayView::from(column)).unwrap()
}

fn map<F>(&self, f: F) -> Self
where F: FnMut(C) -> C {
self.mapv(f)
Expand All @@ -184,6 +234,18 @@ impl<C: TensorComponent> TensorBase for Array2<C> {
self.mapv_inplace(f)
}

fn indexed_iter(&self) -> impl Iterator<Item = ((usize, usize), &Self::Component)> {
Array2::<C>::indexed_iter(self)
}

fn indexed_iter_mut(&mut self) -> impl Iterator<Item = ((usize, usize), &mut Self::Component)> {
Array2::<C>::indexed_iter_mut(self)
}

fn iter(&self) -> impl Iterator<Item = &Self::Component> {
Array2::<C>::iter(self)
}

fn sum_axis(&self, axis: usize) -> Self {
self.sum_axis(Axis(axis)).insert_axis(Axis(axis))
}
Expand Down
Loading
Loading