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