use position::Position;
use cppn::{Cppn, CppnNodeType};
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub enum NodeConnectivity {
In,
Out,
InOut,
}
#[derive(Clone, Debug)]
pub struct Node<P, T>
where
P: Position,
{
pub position: P,
pub node_info: T,
pub node_connectivity: NodeConnectivity,
}
#[derive(Clone, Debug)]
pub struct Layer<P, T>
where
P: Position,
{
nodes: Vec<Node<P, T>>,
}
impl<P, T> Layer<P, T>
where
P: Position,
{
pub fn new() -> Self {
Layer { nodes: Vec::new() }
}
pub fn nodes(&self) -> &[Node<P, T>] {
&self.nodes
}
pub fn add_node(&mut self, position: P, node_info: T, node_connectivity: NodeConnectivity) {
self.nodes.push(Node {
position: position,
node_info: node_info,
node_connectivity: node_connectivity,
});
}
}
#[derive(Clone)]
pub struct Link<'a, P, T>
where
P: Position + 'a,
T: 'a,
{
pub source: &'a Node<P, T>,
pub target: &'a Node<P, T>,
pub source_idx: (usize, usize), pub target_idx: (usize, usize), pub outputs: Vec<f64>,
pub distance_square: f64,
}
#[derive(Clone, Debug)]
struct LayerLink {
from_layer: usize,
to_layer: usize,
max_distance_square: Option<f64>,
}
#[derive(Clone, Debug)]
pub struct Substrate<P, T>
where
P: Position,
{
layers: Vec<Layer<P, T>>,
layer_links: Vec<LayerLink>,
}
impl<P, T> Substrate<P, T>
where
P: Position,
{
pub fn new() -> Self {
Substrate {
layers: Vec::new(),
layer_links: Vec::new(),
}
}
pub fn layers(&self) -> &[Layer<P, T>] {
&self.layers
}
pub fn add_layer(&mut self, layer: Layer<P, T>) -> usize {
let layer_idx = self.layers.len();
self.layers.push(layer);
return layer_idx;
}
pub fn add_layer_link(
&mut self,
from_layer: usize,
to_layer: usize,
max_distance_square: Option<f64>,
) {
self.layer_links.push(LayerLink {
from_layer: from_layer,
to_layer: to_layer,
max_distance_square: max_distance_square,
});
}
pub fn each_link<'a, N, L, EXTID, F>(
&'a self,
cppn: &'a mut Cppn<'a, N, L, EXTID>,
callback: &mut F,
) where
N: CppnNodeType,
L: Copy + Debug + Send + Sized + Into<f64> + 'a,
EXTID: Copy + Debug + Send + Sized + Ord + 'a,
F: FnMut(Link<'a, P, T>),
{
for layer_link in self.layer_links.iter() {
for (source_idx, source) in self.layers[layer_link.from_layer].nodes.iter().enumerate()
{
match source.node_connectivity {
NodeConnectivity::Out | NodeConnectivity::InOut => {}
NodeConnectivity::In => {
continue;
}
}
for (target_idx, target) in
self.layers[layer_link.to_layer].nodes.iter().enumerate()
{
match target.node_connectivity {
NodeConnectivity::In | NodeConnectivity::InOut => {}
NodeConnectivity::Out => {
continue;
}
}
let distance_sq = source.position.distance_square(&target.position);
if let Some(max_d_sq) = layer_link.max_distance_square {
if distance_sq > max_d_sq {
continue;
}
}
let inputs_to_cppn = [source.position.coords(), target.position.coords()];
let outputs_from_cppn = cppn.calculate(&inputs_to_cppn);
let link = Link {
source: source,
target: target,
source_idx: (layer_link.from_layer, source_idx),
target_idx: (layer_link.to_layer, target_idx),
outputs: outputs_from_cppn,
distance_square: distance_sq,
};
callback(link);
}
}
}
}
}