radiate_gp/collections/graphs/
iter.rs1use crate::{Node, NodeType, collections::GraphNode};
2use radiate_core::Valid;
3use std::collections::VecDeque;
4
5pub trait GraphIterator<'a, T> {
8 fn iter_topological(&'a self) -> GraphTopologicalIterator<'a, T>;
9
10 fn get_nodes_of_type(
11 &'a self,
12 node_type: NodeType,
13 ) -> impl Iterator<Item = &'a GraphNode<T>> + 'a
14 where
15 Self: AsRef<[GraphNode<T>]>,
16 T: 'a,
17 {
18 self.as_ref()
19 .iter()
20 .filter(move |node| node.node_type() == node_type)
21 }
22}
23
24impl<'a, G: AsRef<[GraphNode<T>]>, T> GraphIterator<'a, T> for G {
25 fn iter_topological(&'a self) -> GraphTopologicalIterator<'a, T> {
26 GraphTopologicalIterator::new(self.as_ref())
27 }
28}
29
30pub struct GraphTopologicalIterator<'a, T> {
34 graph: &'a [GraphNode<T>],
35 completed: Vec<bool>,
36 index_queue: VecDeque<usize>,
37 pending_index: usize,
38}
39
40impl<'a, T> GraphTopologicalIterator<'a, T> {
41 pub fn new(graph: &'a [GraphNode<T>]) -> Self {
46 let is_valid = !graph.iter().any(|node| !node.is_valid());
47 GraphTopologicalIterator {
48 graph,
49 completed: vec![false; graph.len()],
50 index_queue: VecDeque::with_capacity(graph.len()),
51 pending_index: if is_valid { 0 } else { graph.len() },
52 }
53 }
54}
55
56impl<'a, T> Iterator for GraphTopologicalIterator<'a, T> {
68 type Item = &'a GraphNode<T>;
69
70 #[inline]
71 fn next(&mut self) -> Option<Self::Item> {
72 let mut min_pending_index = self.graph.len();
73 for index in self.pending_index..self.graph.len() {
74 if self.completed[index] {
75 continue;
76 }
77
78 let node = &self.graph[index];
79
80 let mut degree = node.incoming().len();
81 for incoming_index in node.incoming() {
82 let incoming_node = &self.graph[*incoming_index];
83 if self.completed[incoming_node.index()] || incoming_node.is_recurrent() {
84 degree -= 1;
85 }
86 }
87
88 if degree == 0 {
89 self.completed[node.index()] = true;
90 self.index_queue.push_back(node.index());
91 } else {
92 min_pending_index = std::cmp::min(min_pending_index, node.index());
93 }
94 }
95
96 self.pending_index = min_pending_index;
97 self.index_queue.pop_front().map(|idx| &self.graph[idx])
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::collections::{Graph, GraphNode, NodeType};
105 use crate::ops::Op;
106
107 #[test]
108 fn test_graph_iterator() {
109 let graph = Graph::new(vec![
110 GraphNode::from((0, NodeType::Input, Op::var(0))).with_outgoing([2]),
111 GraphNode::from((1, NodeType::Input, Op::var(1))).with_outgoing([2]),
112 GraphNode::from((2, NodeType::Vertex, Op::add()))
113 .with_incoming([0, 1])
114 .with_outgoing([3]),
115 GraphNode::from((3, NodeType::Output, Op::linear())).with_incoming([2]),
116 ]);
117
118 let mut iter = graph.iter_topological();
119
120 assert_eq!(iter.next().unwrap().index(), 0);
121 assert_eq!(iter.next().unwrap().index(), 1);
122 assert_eq!(iter.next().unwrap().index(), 2);
123 assert_eq!(iter.next().unwrap().index(), 3);
124 assert!(iter.next().is_none());
125 }
126
127 #[test]
128 fn test_graph_iterator_recurrent() {
129 let nodes = vec![
130 GraphNode::from((0, NodeType::Input, Op::var(0), vec![], vec![2])),
131 GraphNode::from((1, NodeType::Input, Op::var(1), vec![], vec![2])),
132 GraphNode::from((2, NodeType::Vertex, Op::add(), vec![0, 1], vec![3])),
133 GraphNode::from((3, NodeType::Vertex, Op::mul(), vec![2], vec![2])),
134 GraphNode::from((4, NodeType::Output, Op::linear(), vec![3], vec![])),
135 ];
136
137 let graph = Graph::new(nodes);
138 let mut iter = graph.iter_topological();
139
140 assert_eq!(iter.next().unwrap().index(), 0);
141 assert_eq!(iter.next().unwrap().index(), 1);
142 assert_eq!(iter.next().unwrap().index(), 2);
143 assert_eq!(iter.next().unwrap().index(), 3);
144 assert_eq!(iter.next().unwrap().index(), 4);
145 assert!(iter.next().is_none());
146 }
147
148 #[test]
149 fn test_graph_iterator_disconnected() {
150 let nodes = vec![
151 GraphNode::from((0, NodeType::Input, Op::var(0))).with_outgoing([2]),
152 GraphNode::from((1, NodeType::Input, Op::var(1))),
153 GraphNode::from((2, NodeType::Vertex, Op::add())).with_incoming([0]),
154 GraphNode::from((3, NodeType::Output, Op::linear())).with_incoming([2]),
155 ];
156
157 let results = Graph::new(nodes)
158 .iter_topological()
159 .map(|node| node.index())
160 .collect::<Vec<usize>>();
161
162 assert!(results.is_empty());
163 }
164
165 #[test]
166 fn test_graph_deep_cycles() {
167 let mut graph = Graph::<Op<f32>>::default();
168
169 graph.insert(NodeType::Input, Op::var(0));
170 graph.insert(NodeType::Vertex, Op::diff());
171 graph.insert(NodeType::Output, Op::sigmoid());
172 graph.insert(NodeType::Vertex, Op::div());
173 graph.insert(NodeType::Vertex, Op::pow());
174 graph.insert(NodeType::Edge, Op::weight());
175 graph.insert(NodeType::Edge, Op::identity());
176 graph.insert(NodeType::Vertex, Op::exp());
177 graph.insert(NodeType::Vertex, Op::cos());
178 graph.insert(NodeType::Edge, Op::weight());
179
180 graph.attach(0, 1);
181 graph.attach(1, 1);
182 graph.attach(4, 1);
183 graph.attach(7, 1);
184 graph.attach(1, 2);
185 graph.attach(3, 2);
186 graph.attach(9, 2);
187 graph.attach(0, 3);
188 graph.attach(5, 3);
189 graph.attach(0, 4);
190 graph.attach(8, 4);
191 graph.attach(1, 5);
192 graph.attach(3, 6);
193 graph.attach(4, 7);
194 graph.attach(6, 8);
195 graph.attach(7, 9);
196
197 graph.set_cycles(vec![]);
198
199 let results = graph
200 .iter_topological()
201 .map(|node| node.index())
202 .collect::<Vec<usize>>();
203
204 assert_eq!(results, vec![0, 1, 3, 4, 5, 6, 7, 8, 9, 2]);
205 }
206}