radiate_gp/collections/graphs/
iter.rs1use crate::collections::GraphNode;
2use std::collections::VecDeque;
3
4pub trait GraphIterator<'a, T> {
5 fn iter_topological(&'a self) -> GraphTopologicalIterator<'a, T>;
6}
7
8impl<'a, G: AsRef<[GraphNode<T>]>, T> GraphIterator<'a, T> for G {
9 fn iter_topological(&'a self) -> GraphTopologicalIterator<'a, T> {
10 GraphTopologicalIterator::new(self.as_ref())
11 }
12}
13
14pub struct GraphTopologicalIterator<'a, T> {
19 graph: &'a [GraphNode<T>],
20 completed: Vec<bool>,
21 index_queue: VecDeque<usize>,
22 pending_index: usize,
23}
24
25impl<'a, T> GraphTopologicalIterator<'a, T> {
26 pub fn new(graph: &'a [GraphNode<T>]) -> Self {
31 GraphTopologicalIterator {
32 graph,
33 completed: vec![false; graph.len()],
34 index_queue: VecDeque::new(),
35 pending_index: 0,
36 }
37 }
38}
39
40impl<'a, T> Iterator for GraphTopologicalIterator<'a, T> {
52 type Item = &'a GraphNode<T>;
53
54 #[inline]
55 fn next(&mut self) -> Option<Self::Item> {
56 let mut min_pending_index = self.graph.len();
57 for index in self.pending_index..self.graph.len() {
58 if self.completed[index] {
59 continue;
60 }
61
62 let node = &self.graph[index];
63 let mut degree = node.incoming().len();
64 for incoming_index in node.incoming() {
65 let incoming_node = &self.graph[*incoming_index];
66 if self.completed[incoming_node.index()] || incoming_node.is_recurrent() {
67 degree -= 1;
68 }
69 }
70
71 if degree == 0 {
72 self.completed[node.index()] = true;
73 self.index_queue.push_back(node.index());
74 } else {
75 min_pending_index = std::cmp::min(min_pending_index, node.index());
76 }
77 }
78
79 self.pending_index = min_pending_index;
80
81 if let Some(index) = self.index_queue.pop_front() {
82 return Some(&self.graph[index]);
83 }
84
85 None
86 }
87
88 fn size_hint(&self) -> (usize, Option<usize>) {
89 (0, Some(self.graph.len()))
90 }
91
92 fn count(self) -> usize {
93 self.graph.len()
94 }
95}