/rust/registry/src/index.crates.io-1949cf8c6b5b557f/petgraph-0.8.3/src/visit/traversal.rs
Line | Count | Source |
1 | | use alloc::{collections::VecDeque, vec::Vec}; |
2 | | |
3 | | use super::{ |
4 | | GraphRef, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, Reversed, VisitMap, |
5 | | Visitable, |
6 | | }; |
7 | | use crate::Incoming; |
8 | | |
9 | | /// Visit nodes of a graph in a depth-first-search (DFS) emitting nodes in |
10 | | /// preorder (when they are first discovered). |
11 | | /// |
12 | | /// The traversal starts at a given node and only traverses nodes reachable |
13 | | /// from it. |
14 | | /// |
15 | | /// `Dfs` is not recursive. |
16 | | /// |
17 | | /// `Dfs` does not itself borrow the graph, and because of this you can run |
18 | | /// a traversal over a graph while still retaining mutable access to it, if you |
19 | | /// use it like the following example: |
20 | | /// |
21 | | /// ``` |
22 | | /// use petgraph::Graph; |
23 | | /// use petgraph::visit::Dfs; |
24 | | /// |
25 | | /// let mut graph = Graph::<_,()>::new(); |
26 | | /// let a = graph.add_node(0); |
27 | | /// |
28 | | /// let mut dfs = Dfs::new(&graph, a); |
29 | | /// while let Some(nx) = dfs.next(&graph) { |
30 | | /// // we can access `graph` mutably here still |
31 | | /// graph[nx] += 1; |
32 | | /// } |
33 | | /// |
34 | | /// assert_eq!(graph[a], 1); |
35 | | /// ``` |
36 | | /// |
37 | | /// **Note:** The algorithm may not behave correctly if nodes are removed |
38 | | /// during iteration. It may not necessarily visit added nodes or edges. |
39 | | #[derive(Clone, Debug)] |
40 | | pub struct Dfs<N, VM> { |
41 | | /// The stack of nodes to visit |
42 | | pub stack: Vec<N>, |
43 | | /// The map of discovered nodes |
44 | | pub discovered: VM, |
45 | | } |
46 | | |
47 | | impl<N, VM> Default for Dfs<N, VM> |
48 | | where |
49 | | VM: Default, |
50 | | { |
51 | 0 | fn default() -> Self { |
52 | 0 | Dfs { |
53 | 0 | stack: Vec::new(), |
54 | 0 | discovered: VM::default(), |
55 | 0 | } |
56 | 0 | } |
57 | | } |
58 | | |
59 | | impl<N, VM> Dfs<N, VM> |
60 | | where |
61 | | N: Copy + PartialEq, |
62 | | VM: VisitMap<N>, |
63 | | { |
64 | | /// Create a new **Dfs**, using the graph's visitor map, and put **start** |
65 | | /// in the stack of nodes to visit. |
66 | 0 | pub fn new<G>(graph: G, start: N) -> Self |
67 | 0 | where |
68 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
69 | | { |
70 | 0 | let mut dfs = Dfs::empty(graph); |
71 | 0 | dfs.move_to(start); |
72 | 0 | dfs |
73 | 0 | } |
74 | | |
75 | | /// Create a `Dfs` from a vector and a visit map |
76 | 0 | pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self { |
77 | 0 | Dfs { stack, discovered } |
78 | 0 | } |
79 | | |
80 | | /// Clear the visit state |
81 | 2 | pub fn reset<G>(&mut self, graph: G) |
82 | 2 | where |
83 | 2 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
84 | | { |
85 | 2 | graph.reset_map(&mut self.discovered); |
86 | 2 | self.stack.clear(); |
87 | 2 | } <petgraph::visit::traversal::Dfs<u32, hashbrown::set::HashSet<u32>>>::reset::<&petgraph::graphmap::GraphMap<u32, (), petgraph::Directed, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>> Line | Count | Source | 81 | 2 | pub fn reset<G>(&mut self, graph: G) | 82 | 2 | where | 83 | 2 | G: GraphRef + Visitable<NodeId = N, Map = VM>, | 84 | | { | 85 | 2 | graph.reset_map(&mut self.discovered); | 86 | 2 | self.stack.clear(); | 87 | 2 | } |
Unexecuted instantiation: <petgraph::visit::traversal::Dfs<_, _>>::reset::<_> |
88 | | |
89 | | /// Create a new **Dfs** using the graph's visitor map, and no stack. |
90 | 1 | pub fn empty<G>(graph: G) -> Self |
91 | 1 | where |
92 | 1 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
93 | | { |
94 | 1 | Dfs { |
95 | 1 | stack: Vec::new(), |
96 | 1 | discovered: graph.visit_map(), |
97 | 1 | } |
98 | 1 | } <petgraph::visit::traversal::Dfs<u32, hashbrown::set::HashSet<u32>>>::empty::<&petgraph::graphmap::GraphMap<u32, (), petgraph::Directed, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>> Line | Count | Source | 90 | 1 | pub fn empty<G>(graph: G) -> Self | 91 | 1 | where | 92 | 1 | G: GraphRef + Visitable<NodeId = N, Map = VM>, | 93 | | { | 94 | 1 | Dfs { | 95 | 1 | stack: Vec::new(), | 96 | 1 | discovered: graph.visit_map(), | 97 | 1 | } | 98 | 1 | } |
Unexecuted instantiation: <petgraph::visit::traversal::Dfs<_, _>>::empty::<_> |
99 | | |
100 | | /// Keep the discovered map, but clear the visit stack and restart |
101 | | /// the dfs from a particular node. |
102 | 0 | pub fn move_to(&mut self, start: N) { |
103 | 0 | self.stack.clear(); |
104 | 0 | self.stack.push(start); |
105 | 0 | } Unexecuted instantiation: <petgraph::visit::traversal::Dfs<u32, hashbrown::set::HashSet<u32>>>::move_to Unexecuted instantiation: <petgraph::visit::traversal::Dfs<_, _>>::move_to |
106 | | |
107 | | /// Return the next node in the dfs, or **None** if the traversal is done. |
108 | 0 | pub fn next<G>(&mut self, graph: G) -> Option<N> |
109 | 0 | where |
110 | 0 | G: IntoNeighbors<NodeId = N>, |
111 | | { |
112 | 0 | while let Some(node) = self.stack.pop() { |
113 | 0 | if self.discovered.visit(node) { |
114 | 0 | for succ in graph.neighbors(node) { |
115 | 0 | if !self.discovered.is_visited(&succ) { |
116 | 0 | self.stack.push(succ); |
117 | 0 | } |
118 | | } |
119 | 0 | return Some(node); |
120 | 0 | } |
121 | | } |
122 | 0 | None |
123 | 0 | } Unexecuted instantiation: <petgraph::visit::traversal::Dfs<u32, hashbrown::set::HashSet<u32>>>::next::<petgraph::visit::reversed::Reversed<&petgraph::graphmap::GraphMap<u32, (), petgraph::Directed, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>>> Unexecuted instantiation: <petgraph::visit::traversal::Dfs<_, _>>::next::<_> |
124 | | } |
125 | | |
126 | | /// Visit nodes in a depth-first-search (DFS) emitting nodes in postorder |
127 | | /// (each node after all its descendants have been emitted). |
128 | | /// |
129 | | /// `DfsPostOrder` is not recursive. |
130 | | /// |
131 | | /// The traversal starts at a given node and only traverses nodes reachable |
132 | | /// from it. |
133 | | #[derive(Clone, Debug)] |
134 | | pub struct DfsPostOrder<N, VM> { |
135 | | /// The stack of nodes to visit |
136 | | pub stack: Vec<N>, |
137 | | /// The map of discovered nodes |
138 | | pub discovered: VM, |
139 | | /// The map of finished nodes |
140 | | pub finished: VM, |
141 | | } |
142 | | |
143 | | impl<N, VM> Default for DfsPostOrder<N, VM> |
144 | | where |
145 | | VM: Default, |
146 | | { |
147 | 0 | fn default() -> Self { |
148 | 0 | DfsPostOrder { |
149 | 0 | stack: Vec::new(), |
150 | 0 | discovered: VM::default(), |
151 | 0 | finished: VM::default(), |
152 | 0 | } |
153 | 0 | } |
154 | | } |
155 | | |
156 | | impl<N, VM> DfsPostOrder<N, VM> |
157 | | where |
158 | | N: Copy + PartialEq, |
159 | | VM: VisitMap<N>, |
160 | | { |
161 | | /// Create a new `DfsPostOrder` using the graph's visitor map, and put |
162 | | /// `start` in the stack of nodes to visit. |
163 | 0 | pub fn new<G>(graph: G, start: N) -> Self |
164 | 0 | where |
165 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
166 | | { |
167 | 0 | let mut dfs = Self::empty(graph); |
168 | 0 | dfs.move_to(start); |
169 | 0 | dfs |
170 | 0 | } |
171 | | |
172 | | /// Create a new `DfsPostOrder` using the graph's visitor map, and no stack. |
173 | 0 | pub fn empty<G>(graph: G) -> Self |
174 | 0 | where |
175 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
176 | | { |
177 | 0 | DfsPostOrder { |
178 | 0 | stack: Vec::new(), |
179 | 0 | discovered: graph.visit_map(), |
180 | 0 | finished: graph.visit_map(), |
181 | 0 | } |
182 | 0 | } |
183 | | |
184 | | /// Clear the visit state |
185 | 0 | pub fn reset<G>(&mut self, graph: G) |
186 | 0 | where |
187 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
188 | | { |
189 | 0 | graph.reset_map(&mut self.discovered); |
190 | 0 | graph.reset_map(&mut self.finished); |
191 | 0 | self.stack.clear(); |
192 | 0 | } |
193 | | |
194 | | /// Keep the discovered and finished map, but clear the visit stack and restart |
195 | | /// the dfs from a particular node. |
196 | 0 | pub fn move_to(&mut self, start: N) { |
197 | 0 | self.stack.clear(); |
198 | 0 | self.stack.push(start); |
199 | 0 | } |
200 | | |
201 | | /// Return the next node in the traversal, or `None` if the traversal is done. |
202 | 0 | pub fn next<G>(&mut self, graph: G) -> Option<N> |
203 | 0 | where |
204 | 0 | G: IntoNeighbors<NodeId = N>, |
205 | | { |
206 | 0 | while let Some(&nx) = self.stack.last() { |
207 | 0 | if self.discovered.visit(nx) { |
208 | | // First time visiting `nx`: Push neighbors, don't pop `nx` |
209 | 0 | for succ in graph.neighbors(nx) { |
210 | 0 | if !self.discovered.is_visited(&succ) { |
211 | 0 | self.stack.push(succ); |
212 | 0 | } |
213 | | } |
214 | | } else { |
215 | 0 | self.stack.pop(); |
216 | 0 | if self.finished.visit(nx) { |
217 | | // Second time: All reachable nodes must have been finished |
218 | 0 | return Some(nx); |
219 | 0 | } |
220 | | } |
221 | | } |
222 | 0 | None |
223 | 0 | } |
224 | | } |
225 | | |
226 | | /// A breadth first search (BFS) of a graph. |
227 | | /// |
228 | | /// The traversal starts at a given node and only traverses nodes reachable |
229 | | /// from it. |
230 | | /// |
231 | | /// `Bfs` is not recursive. |
232 | | /// |
233 | | /// `Bfs` does not itself borrow the graph, and because of this you can run |
234 | | /// a traversal over a graph while still retaining mutable access to it, if you |
235 | | /// use it like the following example: |
236 | | /// |
237 | | /// ``` |
238 | | /// use petgraph::Graph; |
239 | | /// use petgraph::visit::Bfs; |
240 | | /// |
241 | | /// let mut graph = Graph::<_,()>::new(); |
242 | | /// let a = graph.add_node(0); |
243 | | /// |
244 | | /// let mut bfs = Bfs::new(&graph, a); |
245 | | /// while let Some(nx) = bfs.next(&graph) { |
246 | | /// // we can access `graph` mutably here still |
247 | | /// graph[nx] += 1; |
248 | | /// } |
249 | | /// |
250 | | /// assert_eq!(graph[a], 1); |
251 | | /// ``` |
252 | | /// |
253 | | /// **Note:** The algorithm may not behave correctly if nodes are removed |
254 | | /// during iteration. It may not necessarily visit added nodes or edges. |
255 | | #[derive(Clone)] |
256 | | pub struct Bfs<N, VM> { |
257 | | /// The queue of nodes to visit |
258 | | pub stack: VecDeque<N>, |
259 | | /// The map of discovered nodes |
260 | | pub discovered: VM, |
261 | | } |
262 | | |
263 | | impl<N, VM> Default for Bfs<N, VM> |
264 | | where |
265 | | VM: Default, |
266 | | { |
267 | 0 | fn default() -> Self { |
268 | 0 | Bfs { |
269 | 0 | stack: VecDeque::new(), |
270 | 0 | discovered: VM::default(), |
271 | 0 | } |
272 | 0 | } |
273 | | } |
274 | | |
275 | | impl<N, VM> Bfs<N, VM> |
276 | | where |
277 | | N: Copy + PartialEq, |
278 | | VM: VisitMap<N>, |
279 | | { |
280 | | /// Create a new **Bfs**, using the graph's visitor map, and put **start** |
281 | | /// in the stack of nodes to visit. |
282 | 0 | pub fn new<G>(graph: G, start: N) -> Self |
283 | 0 | where |
284 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
285 | | { |
286 | 0 | let mut discovered = graph.visit_map(); |
287 | 0 | discovered.visit(start); |
288 | 0 | let mut stack = VecDeque::new(); |
289 | 0 | stack.push_front(start); |
290 | 0 | Bfs { stack, discovered } |
291 | 0 | } |
292 | | |
293 | | /// Return the next node in the bfs, or **None** if the traversal is done. |
294 | 0 | pub fn next<G>(&mut self, graph: G) -> Option<N> |
295 | 0 | where |
296 | 0 | G: IntoNeighbors<NodeId = N>, |
297 | | { |
298 | 0 | if let Some(node) = self.stack.pop_front() { |
299 | 0 | for succ in graph.neighbors(node) { |
300 | 0 | if self.discovered.visit(succ) { |
301 | 0 | self.stack.push_back(succ); |
302 | 0 | } |
303 | | } |
304 | | |
305 | 0 | return Some(node); |
306 | 0 | } |
307 | 0 | None |
308 | 0 | } |
309 | | } |
310 | | |
311 | | /// A topological order traversal for a graph. |
312 | | /// |
313 | | /// **Note** that `Topo` only visits nodes that are not part of cycles, |
314 | | /// i.e. nodes in a true DAG. Use other visitors like [`DfsPostOrder`] or |
315 | | /// algorithms like [`kosaraju_scc`][crate::algo::kosaraju_scc()] to handle |
316 | | /// graphs with possible cycles. |
317 | | #[derive(Clone)] |
318 | | pub struct Topo<N, VM> { |
319 | | tovisit: Vec<N>, |
320 | | ordered: VM, |
321 | | } |
322 | | |
323 | | impl<N, VM> Default for Topo<N, VM> |
324 | | where |
325 | | VM: Default, |
326 | | { |
327 | 0 | fn default() -> Self { |
328 | 0 | Topo { |
329 | 0 | tovisit: Vec::new(), |
330 | 0 | ordered: VM::default(), |
331 | 0 | } |
332 | 0 | } |
333 | | } |
334 | | |
335 | | impl<N, VM> Topo<N, VM> |
336 | | where |
337 | | N: Copy + PartialEq, |
338 | | VM: VisitMap<N>, |
339 | | { |
340 | | /// Create a new `Topo`, using the graph's visitor map, and put all |
341 | | /// initial nodes in the to visit list. |
342 | 0 | pub fn new<G>(graph: G) -> Self |
343 | 0 | where |
344 | 0 | G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>, |
345 | | { |
346 | 0 | let mut topo = Self::empty(graph); |
347 | 0 | topo.extend_with_initials(graph); |
348 | 0 | topo |
349 | 0 | } |
350 | | |
351 | | /// Create a new `Topo` with initial nodes. |
352 | | /// |
353 | | /// Nodes with incoming edges are ignored. |
354 | 0 | pub fn with_initials<G, I>(graph: G, initials: I) -> Self |
355 | 0 | where |
356 | 0 | G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>, |
357 | 0 | I: IntoIterator<Item = N>, |
358 | | { |
359 | | Topo { |
360 | 0 | tovisit: initials |
361 | 0 | .into_iter() |
362 | 0 | .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none()) |
363 | 0 | .collect(), |
364 | 0 | ordered: graph.visit_map(), |
365 | | } |
366 | 0 | } |
367 | | |
368 | 0 | fn extend_with_initials<G>(&mut self, g: G) |
369 | 0 | where |
370 | 0 | G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>, |
371 | | { |
372 | | // find all initial nodes (nodes without incoming edges) |
373 | 0 | self.tovisit.extend( |
374 | 0 | g.node_identifiers() |
375 | 0 | .filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()), |
376 | | ); |
377 | 0 | } |
378 | | |
379 | | /* Private until it has a use */ |
380 | | /// Create a new `Topo`, using the graph's visitor map with *no* starting |
381 | | /// index specified. |
382 | 0 | fn empty<G>(graph: G) -> Self |
383 | 0 | where |
384 | 0 | G: GraphRef + Visitable<NodeId = N, Map = VM>, |
385 | | { |
386 | 0 | Topo { |
387 | 0 | ordered: graph.visit_map(), |
388 | 0 | tovisit: Vec::new(), |
389 | 0 | } |
390 | 0 | } |
391 | | |
392 | | /// Clear visited state, and put all initial nodes in the to visit list. |
393 | 0 | pub fn reset<G>(&mut self, graph: G) |
394 | 0 | where |
395 | 0 | G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>, |
396 | | { |
397 | 0 | graph.reset_map(&mut self.ordered); |
398 | 0 | self.tovisit.clear(); |
399 | 0 | self.extend_with_initials(graph); |
400 | 0 | } |
401 | | |
402 | | /// Return the next node in the current topological order traversal, or |
403 | | /// `None` if the traversal is at the end. |
404 | | /// |
405 | | /// *Note:* The graph may not have a complete topological order, and the only |
406 | | /// way to know is to run the whole traversal and make sure it visits every node. |
407 | 0 | pub fn next<G>(&mut self, g: G) -> Option<N> |
408 | 0 | where |
409 | 0 | G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>, |
410 | | { |
411 | | // Take an unvisited element and find which of its neighbors are next |
412 | 0 | while let Some(nix) = self.tovisit.pop() { |
413 | 0 | if self.ordered.is_visited(&nix) { |
414 | 0 | continue; |
415 | 0 | } |
416 | 0 | self.ordered.visit(nix); |
417 | 0 | for neigh in g.neighbors(nix) { |
418 | | // Look at each neighbor, and those that only have incoming edges |
419 | | // from the already ordered list, they are the next to visit. |
420 | 0 | if Reversed(g) |
421 | 0 | .neighbors(neigh) |
422 | 0 | .all(|b| self.ordered.is_visited(&b)) |
423 | 0 | { |
424 | 0 | self.tovisit.push(neigh); |
425 | 0 | } |
426 | | } |
427 | 0 | return Some(nix); |
428 | | } |
429 | 0 | None |
430 | 0 | } |
431 | | } |
432 | | |
433 | | /// A walker is a traversal state, but where part of the traversal |
434 | | /// information is supplied manually to each next call. |
435 | | /// |
436 | | /// This for example allows graph traversals that don't hold a borrow of the |
437 | | /// graph they are traversing. |
438 | | pub trait Walker<Context> { |
439 | | type Item; |
440 | | /// Advance to the next item |
441 | | fn walk_next(&mut self, context: Context) -> Option<Self::Item>; |
442 | | |
443 | | /// Create an iterator out of the walker and given `context`. |
444 | 0 | fn iter(self, context: Context) -> WalkerIter<Self, Context> |
445 | 0 | where |
446 | 0 | Self: Sized, |
447 | 0 | Context: Clone, |
448 | | { |
449 | 0 | WalkerIter { |
450 | 0 | walker: self, |
451 | 0 | context, |
452 | 0 | } |
453 | 0 | } |
454 | | } |
455 | | |
456 | | /// A walker and its context wrapped into an iterator. |
457 | | #[derive(Clone, Debug)] |
458 | | pub struct WalkerIter<W, C> { |
459 | | walker: W, |
460 | | context: C, |
461 | | } |
462 | | |
463 | | impl<W, C> WalkerIter<W, C> |
464 | | where |
465 | | W: Walker<C>, |
466 | | C: Clone, |
467 | | { |
468 | 0 | pub fn context(&self) -> C { |
469 | 0 | self.context.clone() |
470 | 0 | } |
471 | | |
472 | 0 | pub fn inner_ref(&self) -> &W { |
473 | 0 | &self.walker |
474 | 0 | } |
475 | | |
476 | 0 | pub fn inner_mut(&mut self) -> &mut W { |
477 | 0 | &mut self.walker |
478 | 0 | } |
479 | | } |
480 | | |
481 | | impl<W, C> Iterator for WalkerIter<W, C> |
482 | | where |
483 | | W: Walker<C>, |
484 | | C: Clone, |
485 | | { |
486 | | type Item = W::Item; |
487 | 0 | fn next(&mut self) -> Option<Self::Item> { |
488 | 0 | self.walker.walk_next(self.context.clone()) |
489 | 0 | } |
490 | | } |
491 | | |
492 | | impl<C, W: ?Sized> Walker<C> for &mut W |
493 | | where |
494 | | W: Walker<C>, |
495 | | { |
496 | | type Item = W::Item; |
497 | 0 | fn walk_next(&mut self, context: C) -> Option<Self::Item> { |
498 | 0 | (**self).walk_next(context) |
499 | 0 | } |
500 | | } |
501 | | |
502 | | impl<G> Walker<G> for Dfs<G::NodeId, G::Map> |
503 | | where |
504 | | G: IntoNeighbors + Visitable, |
505 | | { |
506 | | type Item = G::NodeId; |
507 | 0 | fn walk_next(&mut self, context: G) -> Option<Self::Item> { |
508 | 0 | self.next(context) |
509 | 0 | } |
510 | | } |
511 | | |
512 | | impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map> |
513 | | where |
514 | | G: IntoNeighbors + Visitable, |
515 | | { |
516 | | type Item = G::NodeId; |
517 | 0 | fn walk_next(&mut self, context: G) -> Option<Self::Item> { |
518 | 0 | self.next(context) |
519 | 0 | } |
520 | | } |
521 | | |
522 | | impl<G> Walker<G> for Bfs<G::NodeId, G::Map> |
523 | | where |
524 | | G: IntoNeighbors + Visitable, |
525 | | { |
526 | | type Item = G::NodeId; |
527 | 0 | fn walk_next(&mut self, context: G) -> Option<Self::Item> { |
528 | 0 | self.next(context) |
529 | 0 | } |
530 | | } |
531 | | |
532 | | impl<G> Walker<G> for Topo<G::NodeId, G::Map> |
533 | | where |
534 | | G: IntoNeighborsDirected + Visitable, |
535 | | { |
536 | | type Item = G::NodeId; |
537 | 0 | fn walk_next(&mut self, context: G) -> Option<Self::Item> { |
538 | 0 | self.next(context) |
539 | 0 | } |
540 | | } |