graphlib/iterators/
dfs.rs1use crate::graph::Graph;
4use crate::iterators::VertexIter;
5use crate::vertex_id::VertexId;
6
7#[cfg(feature = "no_std")]
8use core::iter::{Chain, Cloned, Peekable};
9use hashbrown::HashSet;
10#[cfg(not(feature = "no_std"))]
11use std::iter::{Chain, Cloned, Peekable};
12
13#[cfg(feature = "no_std")]
14extern crate alloc;
15#[cfg(feature = "no_std")]
16use alloc::vec::Vec;
17
18#[cfg(feature = "no_std")]
19use core::fmt::Debug;
20
21#[cfg(not(feature = "no_std"))]
22use std::fmt::Debug;
23
24#[derive(Debug)]
25pub struct Dfs<'a, T> {
27 unchecked: Peekable<Cloned<Chain<VertexIter<'a>, VertexIter<'a>>>>,
29 black: HashSet<VertexId>,
31 grey: HashSet<VertexId>,
33 pending_stack: Vec<(VertexId, bool)>,
35 iterable: &'a Graph<T>,
37 cached_cyclic: bool,
39}
40
41impl<'a, T> Dfs<'a, T> {
42 pub fn new(graph: &'a Graph<T>) -> Dfs<'_, T> {
43 let unchecked = graph.roots().chain(graph.vertices()).cloned().peekable();
44
45 Dfs {
46 unchecked,
47 iterable: graph,
48 cached_cyclic: false,
49 grey: HashSet::new(),
50 black: HashSet::new(),
51 pending_stack: Vec::new(),
52 }
53 }
54
55 pub fn is_cyclic(&mut self) -> bool {
61 if self.cached_cyclic {
63 return self.cached_cyclic;
64 }
65
66 while self.process_vertex().is_some() {}
68
69 self.cached_cyclic
70 }
71
72 fn process_vertex(&mut self) -> Option<&'a VertexId> {
79 if self.pending_stack.is_empty() {
80 let unchecked = &mut self.unchecked;
82 let black = &self.black;
83
84 let next = unchecked.find(move |v| !black.contains(v));
86
87 if let Some(v) = next {
89 self.pending_stack.push((v, false));
90 }
91 }
92
93 let mut should_return = true;
95 let n = self
96 .pending_stack
97 .pop()
98 .iter()
99 .filter_map(|v| {
101 let (v, already_seen) = v;
102
103 if *already_seen {
106 self.grey.remove(v);
107 self.black.insert(*v);
108 } else {
109 self.grey.insert(*v);
113 self.pending_stack.push((*v, true));
114
115 for v in self.iterable.out_neighbors(v) {
118 if self.grey.contains(v) {
119 self.cached_cyclic = true;
122 } else if !self.black.contains(v) {
123 self.pending_stack.push((*v, false));
124 }
125 }
126 }
127 should_return = !*already_seen;
130 self.iterable.fetch_id_ref(v)
131 })
132 .next();
133 if should_return {
134 n
135 } else {
136 self.process_vertex()
137 }
138 }
139}
140
141impl<'a, T> Iterator for Dfs<'a, T> {
142 type Item = &'a VertexId;
143
144 fn size_hint(&self) -> (usize, Option<usize>) {
145 let remaining = self.iterable.vertex_count() - self.black.len();
146
147 (0, Some(remaining))
148 }
149 fn next(&mut self) -> Option<Self::Item> {
150 (0..self.size_hint().1.unwrap())
151 .filter_map(move |_| self.process_vertex())
152 .next()
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn is_cyclic() {
162 for _ in 0..100 {
170 let mut graph = Graph::new();
171
172 let v = graph.add_vertex(0);
173
174 assert!(graph.add_edge(&v, &v).is_ok(), "Failed to create cycle");
175
176 for _ in 0..100 {
177 graph.add_vertex(0);
178 }
179
180 let mut dfs = graph.dfs();
181
182 for _ in 0..99 {
183 dfs.next();
184 }
185
186 assert!(dfs.is_cyclic());
187 }
188 }
189 #[test]
190 fn not_cyclic() {
191 let mut graph = Graph::new();
192
193 let v1 = graph.add_vertex(());
194 let v2 = graph.add_vertex(());
195 let v3 = graph.add_vertex(());
196
197 graph.add_edge(&v1, &v2);
198 graph.add_edge(&v3, &v2);
199
200 graph.add_vertex(());
201
202 assert_eq!(graph.is_cyclic(), false);
203 }
204
205 #[test]
206 fn not_cyclic_edge_to_successor() {
207 let mut graph = Graph::new();
208
209 let v1 = graph.add_vertex(1);
210 let v2 = graph.add_vertex(2);
211 let v3 = graph.add_vertex(3);
212
213 graph.add_edge(&v1, &v2).unwrap();
214 graph.add_edge(&v2, &v3).unwrap();
215 graph.add_edge(&v1, &v3).unwrap();
216
217 assert_eq!(graph.is_cyclic(), false);
218 }
219
220 #[test]
221 fn not_cyclic_edge_split_merge() {
222 let mut graph = Graph::new();
223
224 let v1 = graph.add_vertex(1);
225 let v2 = graph.add_vertex(2);
226 let v3 = graph.add_vertex(3);
227 let v4 = graph.add_vertex(4);
228 let v5 = graph.add_vertex(5);
229 let v6 = graph.add_vertex(6);
230
231 graph.add_edge(&v1, &v2).unwrap();
232 graph.add_edge(&v2, &v3).unwrap();
233 graph.add_edge(&v3, &v4).unwrap();
234 graph.add_edge(&v3, &v5).unwrap();
235 graph.add_edge(&v4, &v6).unwrap();
236 graph.add_edge(&v5, &v6).unwrap();
237
238 assert_eq!(graph.is_cyclic(), false);
239 }
240
241 #[test]
242 fn not_cyclic_split_merge_continue() {
243 let mut graph = Graph::new();
246
247 let v1 = graph.add_vertex(1);
248 let v2 = graph.add_vertex(2);
249 let v3 = graph.add_vertex(3);
250 let v4 = graph.add_vertex(4);
251 let v5 = graph.add_vertex(5);
252 let v6 = graph.add_vertex(6);
253 let v7 = graph.add_vertex(7);
254
255 graph.add_edge(&v1, &v2).unwrap();
256 graph.add_edge(&v2, &v3).unwrap();
257 graph.add_edge(&v3, &v4).unwrap();
258 graph.add_edge(&v3, &v5).unwrap();
259 graph.add_edge(&v4, &v6).unwrap();
260 graph.add_edge(&v5, &v6).unwrap();
261 graph.add_edge(&v1, &v6).unwrap();
262 graph.add_edge(&v6, &v7).unwrap();
263
264 assert_eq!(graph.is_cyclic(), false);
265 }
266
267 #[test]
268 fn cycle_self_edge() {
269 let mut graph = Graph::new();
270
271 let v1 = graph.add_vertex(1);
272
273 graph.add_edge(&v1, &v1).unwrap();
274
275 assert!(graph.is_cyclic());
276 }
277}