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;