petgraph/visit/
traversal.rs

1use alloc::{collections::VecDeque, vec::Vec};
2
3use super::{
4    GraphRef, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, Reversed, VisitMap,
5    Visitable,
6};
7use 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)]
40pub 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
47impl<N, VM> Default for Dfs<N, VM>
48where
49    VM: Default,
50{
51    fn default() -> Self {
52        Dfs {
53            stack: Vec::new(),
54            discovered: VM::default(),
55        }
56    }
57}
58
59impl<N, VM> Dfs<N, VM>
60where
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    pub fn new<G>(graph: G, start: N) -> Self
67    where
68        G: GraphRef + Visitable<NodeId = N, Map = VM>,
69    {
70        let mut dfs = Dfs::empty(graph);
71        dfs.move_to(start);
72        dfs
73    }
74
75    /// Create a `Dfs` from a vector and a visit map
76    pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self {
77        Dfs { stack, discovered }
78    }
79
80    /// Clear the visit state
81    pub fn reset<G>(&mut self, graph: G)
82    where
83        G: GraphRef + Visitable<NodeId = N, Map = VM>,
84    {
85        graph.reset_map(&mut self.discovered);
86        self.stack.clear();
87    }
88
89    /// Create a new **Dfs** using the graph's visitor map, and no stack.
90    pub fn empty<G>(graph: G) -> Self
91    where
92        G: GraphRef + Visitable<NodeId = N, Map = VM>,
93    {
94        Dfs {
95            stack: Vec::new(),
96            discovered: graph.visit_map(),
97        }
98    }
99
100    /// Keep the discovered map, but clear the visit stack and restart
101    /// the dfs from a particular node.
102    pub fn move_to(&mut self, start: N) {
103        self.stack.clear();
104        self.stack.push(start);
105    }
106
107    /// Return the next node in the dfs, or **None** if the traversal is done.
108    pub fn next<G>(&mut self, graph: G) -> Option<N>
109    where
110        G: IntoNeighbors<NodeId = N>,
111    {
112        while let Some(node) = self.stack.pop() {
113            if self.discovered.visit(node) {
114                for succ in graph.neighbors(node) {
115                    if !self.discovered.is_visited(&succ) {
116                        self.stack.push(succ);
117                    }
118                }
119                return Some(node);
120            }
121        }
122        None
123    }
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)]
134pub 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
143impl<N, VM> Default for DfsPostOrder<N, VM>
144where
145    VM: Default,
146{
147    fn default() -> Self {
148        DfsPostOrder {
149            stack: Vec::new(),
150            discovered: VM::default(),
151            finished: VM::default(),
152        }
153    }
154}
155
156impl<N, VM> DfsPostOrder<N, VM>
157where
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    pub fn new<G>(graph: G, start: N) -> Self
164    where
165        G: GraphRef + Visitable<NodeId = N, Map = VM>,
166    {
167        let mut dfs = Self::empty(graph);
168        dfs.move_to(start);
169        dfs
170    }
171
172    /// Create a new `DfsPostOrder` using the graph's visitor map, and no stack.
173    pub fn empty<G>(graph: G) -> Self
174    where
175        G: GraphRef + Visitable<NodeId = N, Map = VM>,
176    {
177        DfsPostOrder {
178            stack: Vec::new(),
179            discovered: graph.visit_map(),
180            finished: graph.visit_map(),
181        }
182    }
183
184    /// Clear the visit state
185    pub fn reset<G>(&mut self, graph: G)
186    where
187        G: GraphRef + Visitable<NodeId = N, Map = VM>,
188    {
189        graph.reset_map(&mut self.discovered);
190        graph.reset_map(&mut self.finished);
191        self.stack.clear();
192    }
193
194    /// Keep the discovered and finished map, but clear the visit stack and restart
195    /// the dfs from a particular node.
196    pub fn move_to(&mut self, start: N) {
197        self.stack.clear();
198        self.stack.push(start);
199    }
200
201    /// Return the next node in the traversal, or `None` if the traversal is done.
202    pub fn next<G>(&mut self, graph: G) -> Option<N>
203    where
204        G: IntoNeighbors<NodeId = N>,
205    {
206        while let Some(&nx) = self.stack.last() {
207            if self.discovered.visit(nx) {
208                // First time visiting `nx`: Push neighbors, don't pop `nx`
209                for succ in graph.neighbors(nx) {
210                    if !self.discovered.is_visited(&succ) {
211                        self.stack.push(succ);
212                    }
213                }
214            } else {
215                self.stack.pop();
216                if self.finished.visit(nx) {
217                    // Second time: All reachable nodes must have been finished
218                    return Some(nx);
219                }
220            }
221        }
222        None
223    }
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)]
256pub 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
263impl<N, VM> Default for Bfs<N, VM>
264where
265    VM: Default,
266{
267    fn default() -> Self {
268        Bfs {
269            stack: VecDeque::new(),
270            discovered: VM::default(),
271        }
272    }
273}
274
275impl<N, VM> Bfs<N, VM>
276where
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    pub fn new<G>(graph: G, start: N) -> Self
283    where
284        G: GraphRef + Visitable<NodeId = N, Map = VM>,
285    {
286        let mut discovered = graph.visit_map();
287        discovered.visit(start);
288        let mut stack = VecDeque::new();
289        stack.push_front(start);
290        Bfs { stack, discovered }
291    }
292
293    /// Return the next node in the bfs, or **None** if the traversal is done.
294    pub fn next<G>(&mut self, graph: G) -> Option<N>
295    where
296        G: IntoNeighbors<NodeId = N>,
297    {
298        if let Some(node) = self.stack.pop_front() {
299            for succ in graph.neighbors(node) {
300                if self.discovered.visit(succ) {
301                    self.stack.push_back(succ);
302                }
303            }
304
305            return Some(node);
306        }
307        None
308    }
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)]
318pub struct Topo<N, VM> {
319    tovisit: Vec<N>,
320    ordered: VM,
321}
322
323impl<N, VM> Default for Topo<N, VM>
324where
325    VM: Default,
326{
327    fn default() -> Self {
328        Topo {
329            tovisit: Vec::new(),
330            ordered: VM::default(),
331        }
332    }
333}
334
335impl<N, VM> Topo<N, VM>
336where
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    pub fn new<G>(graph: G) -> Self
343    where
344        G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
345    {
346        let mut topo = Self::empty(graph);
347        topo.extend_with_initials(graph);
348        topo
349    }
350
351    /// Create a new `Topo` with initial nodes.
352    ///
353    /// Nodes with incoming edges are ignored.
354    pub fn with_initials<G, I>(graph: G, initials: I) -> Self
355    where
356        G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
357        I: IntoIterator<Item = N>,
358    {
359        Topo {
360            tovisit: initials
361                .into_iter()
362                .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
363                .collect(),
364            ordered: graph.visit_map(),
365        }
366    }
367
368    fn extend_with_initials<G>(&mut self, g: G)
369    where
370        G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
371    {
372        // find all initial nodes (nodes without incoming edges)
373        self.tovisit.extend(
374            g.node_identifiers()
375                .filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()),
376        );
377    }
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    fn empty<G>(graph: G) -> Self
383    where
384        G: GraphRef + Visitable<NodeId = N, Map = VM>,
385    {
386        Topo {
387            ordered: graph.visit_map(),
388            tovisit: Vec::new(),
389        }
390    }
391
392    /// Clear visited state, and put all initial nodes in the to visit list.
393    pub fn reset<G>(&mut self, graph: G)
394    where
395        G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
396    {
397        graph.reset_map(&mut self.ordered);
398        self.tovisit.clear();
399        self.extend_with_initials(graph);
400    }
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    pub fn next<G>(&mut self, g: G) -> Option<N>
408    where
409        G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
410    {
411        // Take an unvisited element and find which of its neighbors are next
412        while let Some(nix) = self.tovisit.pop() {
413            if self.ordered.is_visited(&nix) {
414                continue;
415            }
416            self.ordered.visit(nix);
417            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                if Reversed(g)
421                    .neighbors(neigh)
422                    .all(|b| self.ordered.is_visited(&b))
423                {
424                    self.tovisit.push(neigh);
425                }
426            }
427            return Some(nix);
428        }
429        None
430    }
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.
438pub 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    fn iter(self, context: Context) -> WalkerIter<Self, Context>
445    where
446        Self: Sized,
447        Context: Clone,
448    {
449        WalkerIter {
450            walker: self,
451            context,
452        }
453    }
454}
455
456/// A walker and its context wrapped into an iterator.
457#[derive(Clone, Debug)]
458pub struct WalkerIter<W, C> {
459    walker: W,
460    context: C,
461}
462
463impl<W, C> WalkerIter<W, C>
464where
465    W: Walker<C>,
466    C: Clone,
467{
468    pub fn context(&self) -> C {
469        self.context.clone()
470    }
471
472    pub fn inner_ref(&self) -> &W {
473        &self.walker
474    }
475
476    pub fn inner_mut(&mut self) -> &mut W {
477        &mut self.walker
478    }
479}
480
481impl<W, C> Iterator for WalkerIter<W, C>
482where
483    W: Walker<C>,
484    C: Clone,
485{
486    type Item = W::Item;
487    fn next(&mut self) -> Option<Self::Item> {
488        self.walker.walk_next(self.context.clone())
489    }
490}
491
492impl<C, W: ?Sized> Walker<C> for &mut W
493where
494    W: Walker<C>,
495{
496    type Item = W::Item;
497    fn walk_next(&mut self, context: C) -> Option<Self::Item> {
498        (**self).walk_next(context)
499    }
500}
501
502impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
503where
504    G: IntoNeighbors + Visitable,
505{
506    type Item = G::NodeId;
507    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
508        self.next(context)
509    }
510}
511
512impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
513where
514    G: IntoNeighbors + Visitable,
515{
516    type Item = G::NodeId;
517    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
518        self.next(context)
519    }
520}
521
522impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
523where
524    G: IntoNeighbors + Visitable,
525{
526    type Item = G::NodeId;
527    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
528        self.next(context)
529    }
530}
531
532impl<G> Walker<G> for Topo<G::NodeId, G::Map>
533where
534    G: IntoNeighborsDirected + Visitable,
535{
536    type Item = G::NodeId;
537    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
538        self.next(context)
539    }
540}