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;