petgraph/visit/
mod.rs

1//! Graph traits and graph traversals.
2//!
3//! ### The `Into-` Traits
4//!
5//! Graph traits like [`IntoNeighbors`][in] create iterators and use the same
6//! pattern that `IntoIterator` does: the trait takes a reference to a graph,
7//! and produces an iterator. These traits are quite composable, but with the
8//! limitation that they only use shared references to graphs.
9//!
10//! ### Graph Traversal
11//!
12//! [`Dfs`](struct.Dfs.html), [`Bfs`][bfs], [`DfsPostOrder`][dfspo] and
13//! [`Topo`][topo]  are basic visitors and they use “walker” methods: the
14//! visitors don't hold the graph as borrowed during traversal, only for the
15//! `.next()` call on the walker. They can be converted to iterators
16//! through the [`Walker`][w] trait.
17//!
18//! There is also the callback based traversal [`depth_first_search`][dfs].
19//!
20//! [bfs]: struct.Bfs.html
21//! [dfspo]: struct.DfsPostOrder.html
22//! [topo]: struct.Topo.html
23//! [dfs]: fn.depth_first_search.html
24//! [w]: trait.Walker.html
25//!
26//! ### Other Graph Traits
27//!
28//! The traits are rather loosely coupled at the moment (which is intentional,
29//! but will develop a bit), and there are traits missing that could be added.
30//!
31//! Not much is needed to be able to use the visitors on a graph. A graph
32//! needs to define [`GraphBase`][gb], [`IntoNeighbors`][in] and
33//! [`Visitable`][vis] as a minimum.
34//!
35//! [gb]: trait.GraphBase.html
36//! [in]: trait.IntoNeighbors.html
37//! [vis]: trait.Visitable.html
38//!
39//! ### Graph Trait Implementations
40//!
41//! The following table lists the traits that are implemented for each graph type:
42//!
43//! |                       | Graph | StableGraph | GraphMap | MatrixGraph | Csr   | List  |
44//! | --------------------- | :---: | :---------: | :------: | :---------: | :---: | :---: |
45//! | GraphBase             | x     |  x          |    x     | x           | x     |  x    |
46//! | GraphProp             | x     |  x          |    x     | x           | x     |  x    |
47//! | NodeCount             | x     |  x          |    x     | x           | x     |  x    |
48//! | NodeIndexable         | x     |  x          |    x     | x           | x     |  x    |
49//! | NodeCompactIndexable  | x     |             |    x     |             | x     |  x    |
50//! | EdgeCount             | x     |  x          |    x     | x           | x     |  x    |
51//! | EdgeIndexable         | x     |  x          |    x     |             |       |       |
52//! | Data                  | x     |  x          |    x     | x           | x     |  x    |
53//! | IntoNodeIdentifiers   | x     |  x          |    x     | x           | x     |  x    |
54//! | IntoNodeReferences    | x     |  x          |    x     | x           | x     |  x    |
55//! | IntoEdgeReferences    | x     |  x          |    x     | x           | x     |  x    |
56//! | IntoNeighbors         | x     |  x          |    x     | x           | x     |  x    |
57//! | IntoNeighborsDirected | x     |  x          |    x     | x           |       |       |
58//! | IntoEdges             | x     |  x          |    x     | x           | x     |  x    |
59//! | IntoEdgesDirected     | x     |  x          |    x     | x           |       |       |
60//! | Visitable             | x     |  x          |    x     | x           | x     |  x    |
61//! | GetAdjacencyMatrix    | x     |  x          |    x     | x           | x     |  x    |
62
63// filter, reversed have their `mod` lines at the end,
64// so that they can use the trait template macros
65pub use self::filter::*;
66pub use self::reversed::*;
67pub use self::undirected_adaptor::*;
68
69#[macro_use]
70mod macros;
71
72mod dfsvisit;
73mod traversal;
74pub use self::dfsvisit::*;
75pub use self::traversal::*;
76
77use fixedbitset::FixedBitSet;
78use std::collections::HashSet;
79use std::hash::{BuildHasher, Hash};
80
81use super::EdgeType;
82use crate::prelude::Direction;
83
84use crate::graph::IndexType;
85
86trait_template! {
87/// Base graph trait: defines the associated node identifier and
88/// edge identifier types.
89pub trait GraphBase {
90    // FIXME: We can drop this escape/nodelegate stuff in Rust 1.18
91    @escape [type NodeId]
92    @escape [type EdgeId]
93    @section nodelegate
94    /// edge identifier
95    type EdgeId: Copy + PartialEq;
96    /// node identifier
97    type NodeId: Copy + PartialEq;
98}
99}
100
101GraphBase! {delegate_impl []}
102GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]}
103
104/// A copyable reference to a graph.
105pub trait GraphRef: Copy + GraphBase {}
106
107impl<G> GraphRef for &G where G: GraphBase {}
108
109trait_template! {
110/// Access to the neighbors of each node
111///
112/// The neighbors are, depending on the graph’s edge type:
113///
114/// - `Directed`: All targets of edges from `a`.
115/// - `Undirected`: All other endpoints of edges connected to `a`.
116pub trait IntoNeighbors : GraphRef {
117    @section type
118    type Neighbors: Iterator<Item=Self::NodeId>;
119    @section self
120    /// Return an iterator of the neighbors of node `a`.
121    fn neighbors(self, a: Self::NodeId) -> Self::Neighbors;
122}
123}
124
125IntoNeighbors! {delegate_impl []}
126
127trait_template! {
128/// Access to the neighbors of each node, through incoming or outgoing edges.
129///
130/// Depending on the graph’s edge type, the neighbors of a given directionality
131/// are:
132///
133/// - `Directed`, `Outgoing`: All targets of edges from `a`.
134/// - `Directed`, `Incoming`: All sources of edges to `a`.
135/// - `Undirected`: All other endpoints of edges connected to `a`.
136pub trait IntoNeighborsDirected : IntoNeighbors {
137    @section type
138    type NeighborsDirected: Iterator<Item=Self::NodeId>;
139    @section self
140    fn neighbors_directed(self, n: Self::NodeId, d: Direction)
141        -> Self::NeighborsDirected;
142}
143}
144
145trait_template! {
146/// Access to the edges of each node.
147///
148/// The edges are, depending on the graph’s edge type:
149///
150/// - `Directed`: All edges from `a`.
151/// - `Undirected`: All edges connected to `a`, with `a` being the source of each edge.
152///
153/// This is an extended version of the trait `IntoNeighbors`; the former
154/// only iterates over the target node identifiers, while this trait
155/// yields edge references (trait [`EdgeRef`][er]).
156///
157/// [er]: trait.EdgeRef.html
158pub trait IntoEdges : IntoEdgeReferences + IntoNeighbors {
159    @section type
160    type Edges: Iterator<Item=Self::EdgeRef>;
161    @section self
162    fn edges(self, a: Self::NodeId) -> Self::Edges;
163}
164}
165
166IntoEdges! {delegate_impl []}
167
168trait_template! {
169/// Access to all edges of each node, in the specified direction.
170///
171/// The edges are, depending on the direction and the graph’s edge type:
172///
173///
174/// - `Directed`, `Outgoing`: All edges from `a`.
175/// - `Directed`, `Incoming`: All edges to `a`.
176/// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each edge.
177/// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each edge.
178///
179/// This is an extended version of the trait `IntoNeighborsDirected`; the former
180/// only iterates over the target node identifiers, while this trait
181/// yields edge references (trait [`EdgeRef`][er]).
182///
183/// [er]: trait.EdgeRef.html
184pub trait IntoEdgesDirected : IntoEdges + IntoNeighborsDirected {
185    @section type
186    type EdgesDirected: Iterator<Item=Self::EdgeRef>;
187    @section self
188    fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected;
189}
190}
191
192IntoEdgesDirected! {delegate_impl []}
193
194trait_template! {
195/// Access to the sequence of the graph’s `NodeId`s.
196pub trait IntoNodeIdentifiers : GraphRef {
197    @section type
198    type NodeIdentifiers: Iterator<Item=Self::NodeId>;
199    @section self
200    fn node_identifiers(self) -> Self::NodeIdentifiers;
201}
202}
203
204IntoNodeIdentifiers! {delegate_impl []}
205IntoNeighborsDirected! {delegate_impl []}
206
207trait_template! {
208/// Define associated data for nodes and edges
209pub trait Data : GraphBase {
210    @section type
211    type NodeWeight;
212    type EdgeWeight;
213}
214}
215
216Data! {delegate_impl []}
217Data! {delegate_impl [['a, G], G, &'a mut G, deref]}
218
219/// An edge reference.
220///
221/// Edge references are used by traits `IntoEdges` and `IntoEdgeReferences`.
222pub trait EdgeRef: Copy {
223    type NodeId;
224    type EdgeId;
225    type Weight;
226    /// The source node of the edge.
227    fn source(&self) -> Self::NodeId;
228    /// The target node of the edge.
229    fn target(&self) -> Self::NodeId;
230    /// A reference to the weight of the edge.
231    fn weight(&self) -> &Self::Weight;
232    /// The edge’s identifier.
233    fn id(&self) -> Self::EdgeId;
234}
235
236impl<N, E> EdgeRef for (N, N, &E)
237where
238    N: Copy,
239{
240    type NodeId = N;
241    type EdgeId = (N, N);
242    type Weight = E;
243
244    fn source(&self) -> N {
245        self.0
246    }
247    fn target(&self) -> N {
248        self.1
249    }
250    fn weight(&self) -> &E {
251        self.2
252    }
253    fn id(&self) -> (N, N) {
254        (self.0, self.1)
255    }
256}
257
258/// A node reference.
259pub trait NodeRef: Copy {
260    type NodeId;
261    type Weight;
262    fn id(&self) -> Self::NodeId;
263    fn weight(&self) -> &Self::Weight;
264}
265
266trait_template! {
267/// Access to the sequence of the graph’s nodes
268pub trait IntoNodeReferences : Data + IntoNodeIdentifiers {
269    @section type
270    type NodeRef: NodeRef<NodeId=Self::NodeId, Weight=Self::NodeWeight>;
271    type NodeReferences: Iterator<Item=Self::NodeRef>;
272    @section self
273    fn node_references(self) -> Self::NodeReferences;
274}
275}
276
277IntoNodeReferences! {delegate_impl []}
278
279impl<Id> NodeRef for (Id, ())
280where
281    Id: Copy,
282{
283    type NodeId = Id;
284    type Weight = ();
285    fn id(&self) -> Self::NodeId {
286        self.0
287    }
288    fn weight(&self) -> &Self::Weight {
289        static DUMMY: () = ();
290        &DUMMY
291    }
292}
293
294impl<Id, W> NodeRef for (Id, &W)
295where
296    Id: Copy,
297{
298    type NodeId = Id;
299    type Weight = W;
300    fn id(&self) -> Self::NodeId {
301        self.0
302    }
303    fn weight(&self) -> &Self::Weight {
304        self.1
305    }
306}
307
308trait_template! {
309/// Access to the sequence of the graph’s edges
310pub trait IntoEdgeReferences : Data + GraphRef {
311    @section type
312    type EdgeRef: EdgeRef<NodeId=Self::NodeId, EdgeId=Self::EdgeId,
313                          Weight=Self::EdgeWeight>;
314    type EdgeReferences: Iterator<Item=Self::EdgeRef>;
315    @section self
316    fn edge_references(self) -> Self::EdgeReferences;
317}
318}
319
320IntoEdgeReferences! {delegate_impl [] }
321
322trait_template! {
323    /// Edge kind property (directed or undirected edges)
324pub trait GraphProp : GraphBase {
325    @section type
326    /// The kind of edges in the graph.
327    type EdgeType: EdgeType;
328
329    @section nodelegate
330    fn is_directed(&self) -> bool {
331        <Self::EdgeType>::is_directed()
332    }
333}
334}
335
336GraphProp! {delegate_impl []}
337
338trait_template! {
339    /// The graph’s `NodeId`s map to indices
340    #[allow(clippy::needless_arbitrary_self_type)]
341    pub trait NodeIndexable : GraphBase {
342        @section self
343        /// Return an upper bound of the node indices in the graph
344        /// (suitable for the size of a bitmap).
345        fn node_bound(self: &Self) -> usize;
346        /// Convert `a` to an integer index.
347        fn to_index(self: &Self, a: Self::NodeId) -> usize;
348        /// Convert `i` to a node index. `i` must be a valid value in the graph.
349        fn from_index(self: &Self, i: usize) -> Self::NodeId;
350    }
351}
352
353NodeIndexable! {delegate_impl []}
354
355trait_template! {
356    /// The graph’s `NodeId`s map to indices
357    #[allow(clippy::needless_arbitrary_self_type)]
358    pub trait EdgeIndexable : GraphBase {
359        @section self
360        /// Return an upper bound of the edge indices in the graph
361        /// (suitable for the size of a bitmap).
362        fn edge_bound(self: &Self) -> usize;
363        /// Convert `a` to an integer index.
364        fn to_index(self: &Self, a: Self::EdgeId) -> usize;
365        /// Convert `i` to an edge index. `i` must be a valid value in the graph.
366        fn from_index(self: &Self, i: usize) -> Self::EdgeId;
367    }
368}
369
370EdgeIndexable! {delegate_impl []}
371
372trait_template! {
373/// A graph with a known node count.
374#[allow(clippy::needless_arbitrary_self_type)]
375pub trait NodeCount : GraphBase {
376    @section self
377    fn node_count(self: &Self) -> usize;
378}
379}
380
381NodeCount! {delegate_impl []}
382
383trait_template! {
384/// The graph’s `NodeId`s map to indices, in a range without holes.
385///
386/// The graph's node identifiers correspond to exactly the indices
387/// `0..self.node_bound()`.
388pub trait NodeCompactIndexable : NodeIndexable + NodeCount { }
389}
390
391NodeCompactIndexable! {delegate_impl []}
392
393/// A mapping for storing the visited status for NodeId `N`.
394pub trait VisitMap<N> {
395    /// Mark `a` as visited.
396    ///
397    /// Return **true** if this is the first visit, false otherwise.
398    fn visit(&mut self, a: N) -> bool;
399
400    /// Return whether `a` has been visited before.
401    fn is_visited(&self, a: &N) -> bool;
402}
403
404impl<Ix> VisitMap<Ix> for FixedBitSet
405where
406    Ix: IndexType,
407{
408    fn visit(&mut self, x: Ix) -> bool {
409        !self.put(x.index())
410    }
411    fn is_visited(&self, x: &Ix) -> bool {
412        self.contains(x.index())
413    }
414}
415
416impl<N, S> VisitMap<N> for HashSet<N, S>
417where
418    N: Hash + Eq,
419    S: BuildHasher,
420{
421    fn visit(&mut self, x: N) -> bool {
422        self.insert(x)
423    }
424    fn is_visited(&self, x: &N) -> bool {
425        self.contains(x)
426    }
427}
428
429trait_template! {
430/// A graph that can create a map that tracks the visited status of its nodes.
431#[allow(clippy::needless_arbitrary_self_type)]
432pub trait Visitable : GraphBase {
433    @section type
434    /// The associated map type
435    type Map: VisitMap<Self::NodeId>;
436    @section self
437    /// Create a new visitor map
438    fn visit_map(self: &Self) -> Self::Map;
439    /// Reset the visitor map (and resize to new size of graph if needed)
440    fn reset_map(self: &Self, map: &mut Self::Map);
441}
442}
443Visitable! {delegate_impl []}
444
445trait_template! {
446/// Create or access the adjacency matrix of a graph.
447///
448/// The implementor can either create an adjacency matrix, or it can return
449/// a placeholder if it has the needed representation internally.
450#[allow(clippy::needless_arbitrary_self_type)]
451pub trait GetAdjacencyMatrix : GraphBase {
452    @section type
453    /// The associated adjacency matrix type
454    type AdjMatrix;
455    @section self
456    /// Create the adjacency matrix
457    fn adjacency_matrix(self: &Self) -> Self::AdjMatrix;
458    /// Return true if there is an edge from `a` to `b`, false otherwise.
459    ///
460    /// Computes in O(1) time.
461    fn is_adjacent(self: &Self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
462}
463}
464
465GetAdjacencyMatrix! {delegate_impl []}
466
467trait_template! {
468/// A graph with a known edge count.
469#[allow(clippy::needless_arbitrary_self_type)]
470pub trait EdgeCount : GraphBase {
471    @section self
472    /// Return the number of edges in the graph.
473    fn edge_count(self: &Self) -> usize;
474}
475}
476
477EdgeCount! {delegate_impl []}
478
479mod filter;
480mod reversed;
481mod undirected_adaptor;