use petgraph::graph::{Graph, NodeIndex}; use crate::genetics::gene::Gene; #[derive(Default,Clone)] pub struct Genome { pub(crate) graph: Graph, } impl Genome { pub fn new() -> Self { Self { graph: Graph::::new() } } pub fn from_edges(nodes: Vec,edges: Vec<(usize,usize)>) -> Result { if nodes.len() == 0 { return Err(PlantCreationError::EmptyNodes); } if edges.len() == 0 { return Err(PlantCreationError::EmptyEdges); } let mut graph = Graph::::new(); let gene_indicies = nodes.into_iter().map(|gene|{graph.add_node(gene)}).collect::>(); 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 = 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, }