petgraph/visit/
traversal.rs

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