74 lines
1.8 KiB
Rust
74 lines
1.8 KiB
Rust
use petgraph::graph::{Graph, NodeIndex};
|
|
|
|
use crate::genetics::gene::Gene;
|
|
|
|
#[derive(Default,Clone)]
|
|
pub struct Genome {
|
|
pub(crate) graph: Graph<Gene,()>,
|
|
}
|
|
|
|
impl Genome {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
graph: Graph::<Gene,()>::new()
|
|
}
|
|
}
|
|
pub fn from_edges(nodes: Vec<Gene>,edges: Vec<(usize,usize)>) -> Result<Self,PlantCreationError> {
|
|
if nodes.len() == 0 {
|
|
return Err(PlantCreationError::EmptyNodes);
|
|
}
|
|
|
|
if edges.len() == 0 {
|
|
return Err(PlantCreationError::EmptyEdges);
|
|
}
|
|
|
|
let mut graph = Graph::<Gene,()>::new();
|
|
let gene_indicies = nodes.into_iter().map(|gene|{graph.add_node(gene)}).collect::<Vec<NodeIndex>>();
|
|
edges.into_iter().map(|(node_a,node_b)|graph.add_edge(gene_indicies[node_a], gene_indicies[node_b], ()));
|
|
|
|
return Ok(Self {
|
|
graph
|
|
});
|
|
}
|
|
}
|
|
|
|
// Vibecoded
|
|
use std::fmt::{self, Display};
|
|
|
|
impl Display for Genome {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let graph = &self.graph;
|
|
|
|
if graph.node_count() == 0 {
|
|
return Ok(());
|
|
}
|
|
|
|
let root = NodeIndex::new(0);
|
|
let mut stack: Vec<(NodeIndex, usize)> = vec![(root, 0)];
|
|
|
|
while let Some((node, depth)) = stack.pop() {
|
|
let indent = "\t".repeat(depth);
|
|
writeln!(f, "{}{}", indent, graph[node])?;
|
|
|
|
// push in reverse to preserve child order
|
|
let mut children: Vec<NodeIndex> = graph
|
|
.neighbors(node)
|
|
.filter(|&n| n != node) // skip self-loops
|
|
.collect();
|
|
|
|
children.reverse();
|
|
for child in children {
|
|
stack.push((child, depth + 1));
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum PlantCreationError {
|
|
EmptyNodes,
|
|
EmptyEdges,
|
|
}
|
|
|