Once again I have found time in my personal life to learn rust, and I am resuming a pet project to do so. Thankfully each time I pick up rust it gets easier.
I want to take a genome (which tells me what the network connections should be) and create a network where nodes have references to neurons and neurons have references to nodes.
Here are all my types relevant to this question
pub struct Gene {
pub in_node_id: usize,
pub out_node_id: usize,
pub weight: f64,
enabled: bool
}
pub struct Genome(pub Vec<Gene>);
impl Genome {
pub fn calculate_max_node_id(&self) -> usize {
self.0.iter().fold(0, |acc, conn| {
if conn.in_node_id > acc {
conn.in_node_id
} else if conn.out_node_id > acc {
conn.out_node_id
} else {
acc
}
})
}
}
enum NodeType{
Sensor,
Hidden,
Output,
}
pub struct Node<'a> {
value: f64,
is_active: bool,
has_active_inputs: bool,
input_neurons: Vec<&'a Neuron<'a>>,
active_sum: f64,
}
impl<'a> Node<'a> {
fn create(node_type: NodeType) -> Node<'a> {
Node{
value: 0.,
is_active: node_type == NodeType::Sensor,
has_active_inputs: false,
input_neurons: Vec::new(),
active_sum: 0.,
}
}
}
pub struct Neuron<'a> {
pub in_node: &'a Node<'a>,
pub out_node: &'a Node<'a>,
pub gene: &'a Gene,
}
pub struct Phenome<'a>(pub Vec<Neuron<'a>>);
pub struct Network<'a> {
pub has_bias_node: bool,
pub phenome: Phenome<'a>,
pub nodes: Nodes<'a>,
pub n_sensor_nodes: usize,
pub n_output_nodes: usize,
}
Here is the bit of code I am struggling with
let init_nodes = Nodes::create_disconnected(n_sensor_nodes, n_output_nodes, max_node_id);
let (nodes, phenome) = genome.0.iter().fold((init_nodes, Phenome(Vec::new())), |(mut nodes, mut phenome), gene| {
if gene.enabled {
let in_node = &nodes.0[gene.in_node_id];
let out_node = &nodes.0[gene.out_node_id];
let neuron = Neuron{
in_node,
out_node,
gene
};
nodes.0[gene.out_node_id].input_neurons.push(&neuron);
phenome.0.push(neuron);
}
(nodes, phenome)
});
I hope my attempt clearly converys my intent. I tried to get this to work using various combinations of split_at_mut
and split_first_mut
but couldn't get it to work. I tried to use a fold because I usually think declaratively but happy to abandon it if there is a simpler way.