Skip to main content

petgraph/visit/
traversal.rs

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