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
65 pub use self::filter::*;
66 pub use self::reversed::*;
67 
68 #[macro_use]
69 mod macros;
70 
71 mod dfsvisit;
72 mod traversal;
73 pub use self::dfsvisit::*;
74 pub use self::traversal::*;
75 
76 use fixedbitset::FixedBitSet;
77 use std::collections::HashSet;
78 use std::hash::{BuildHasher, Hash};
79 
80 use super::EdgeType;
81 use crate::prelude::Direction;
82 
83 use crate::graph::IndexType;
84 
85 trait_template! {
86 /// Base graph trait: defines the associated node identifier and
87 /// edge identifier types.
88 pub 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 
100 GraphBase! {delegate_impl []}
101 GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]}
102 
103 /// A copyable reference to a graph.
104 pub trait GraphRef: Copy + GraphBase {}
105 
106 impl<'a, G> GraphRef for &'a G where G: GraphBase {}
107 
108 trait_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`.
115 pub 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 
124 IntoNeighbors! {delegate_impl []}
125 
126 trait_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`.
135 pub 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 
144 trait_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
157 pub 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 
165 IntoEdges! {delegate_impl []}
166 
167 trait_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
183 pub 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 
191 IntoEdgesDirected! {delegate_impl []}
192 
193 trait_template! {
194 /// Access to the sequence of the graph’s `NodeId`s.
195 pub 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 
203 IntoNodeIdentifiers! {delegate_impl []}
204 IntoNeighborsDirected! {delegate_impl []}
205 
206 trait_template! {
207 /// Define associated data for nodes and edges
208 pub trait Data : GraphBase {
209     @section type
210     type NodeWeight;
211     type EdgeWeight;
212 }
213 }
214 
215 Data! {delegate_impl []}
216 Data! {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`.
221 pub trait EdgeRef: Copy {
222     type NodeId;
223     type EdgeId;
224     type Weight;
225     /// The source node of the edge.
source(&self) -> Self::NodeId226     fn source(&self) -> Self::NodeId;
227     /// The target node of the edge.
target(&self) -> Self::NodeId228     fn target(&self) -> Self::NodeId;
229     /// A reference to the weight of the edge.
weight(&self) -> &Self::Weight230     fn weight(&self) -> &Self::Weight;
231     /// The edge’s identifier.
id(&self) -> Self::EdgeId232     fn id(&self) -> Self::EdgeId;
233 }
234 
235 impl<'a, N, E> EdgeRef for (N, N, &'a E)
236 where
237     N: Copy,
238 {
239     type NodeId = N;
240     type EdgeId = (N, N);
241     type Weight = E;
242 
source(&self) -> N243     fn source(&self) -> N {
244         self.0
245     }
target(&self) -> N246     fn target(&self) -> N {
247         self.1
248     }
weight(&self) -> &E249     fn weight(&self) -> &E {
250         self.2
251     }
id(&self) -> (N, N)252     fn id(&self) -> (N, N) {
253         (self.0, self.1)
254     }
255 }
256 
257 /// A node reference.
258 pub trait NodeRef: Copy {
259     type NodeId;
260     type Weight;
id(&self) -> Self::NodeId261     fn id(&self) -> Self::NodeId;
weight(&self) -> &Self::Weight262     fn weight(&self) -> &Self::Weight;
263 }
264 
265 trait_template! {
266 /// Access to the sequence of the graph’s nodes
267 pub 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 
276 IntoNodeReferences! {delegate_impl []}
277 
278 impl<Id> NodeRef for (Id, ())
279 where
280     Id: Copy,
281 {
282     type NodeId = Id;
283     type Weight = ();
id(&self) -> Self::NodeId284     fn id(&self) -> Self::NodeId {
285         self.0
286     }
weight(&self) -> &Self::Weight287     fn weight(&self) -> &Self::Weight {
288         static DUMMY: () = ();
289         &DUMMY
290     }
291 }
292 
293 impl<'a, Id, W> NodeRef for (Id, &'a W)
294 where
295     Id: Copy,
296 {
297     type NodeId = Id;
298     type Weight = W;
id(&self) -> Self::NodeId299     fn id(&self) -> Self::NodeId {
300         self.0
301     }
weight(&self) -> &Self::Weight302     fn weight(&self) -> &Self::Weight {
303         self.1
304     }
305 }
306 
307 trait_template! {
308 /// Access to the sequence of the graph’s edges
309 pub 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 
319 IntoEdgeReferences! {delegate_impl [] }
320 
321 trait_template! {
322     /// Edge kind property (directed or undirected edges)
323 pub 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 
335 GraphProp! {delegate_impl []}
336 
337 trait_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 
352 NodeIndexable! {delegate_impl []}
353 
354 trait_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 
369 EdgeIndexable! {delegate_impl []}
370 
371 trait_template! {
372 /// A graph with a known node count.
373 #[allow(clippy::needless_arbitrary_self_type)]
374 pub trait NodeCount : GraphBase {
375     @section self
376     fn node_count(self: &Self) -> usize;
377 }
378 }
379 
380 NodeCount! {delegate_impl []}
381 
382 trait_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()`.
387 pub trait NodeCompactIndexable : NodeIndexable + NodeCount { }
388 }
389 
390 NodeCompactIndexable! {delegate_impl []}
391 
392 /// A mapping for storing the visited status for NodeId `N`.
393 pub trait VisitMap<N> {
394     /// Mark `a` as visited.
395     ///
396     /// Return **true** if this is the first visit, false otherwise.
visit(&mut self, a: N) -> bool397     fn visit(&mut self, a: N) -> bool;
398 
399     /// Return whether `a` has been visited before.
is_visited(&self, a: &N) -> bool400     fn is_visited(&self, a: &N) -> bool;
401 }
402 
403 impl<Ix> VisitMap<Ix> for FixedBitSet
404 where
405     Ix: IndexType,
406 {
visit(&mut self, x: Ix) -> bool407     fn visit(&mut self, x: Ix) -> bool {
408         !self.put(x.index())
409     }
is_visited(&self, x: &Ix) -> bool410     fn is_visited(&self, x: &Ix) -> bool {
411         self.contains(x.index())
412     }
413 }
414 
415 impl<N, S> VisitMap<N> for HashSet<N, S>
416 where
417     N: Hash + Eq,
418     S: BuildHasher,
419 {
visit(&mut self, x: N) -> bool420     fn visit(&mut self, x: N) -> bool {
421         self.insert(x)
422     }
is_visited(&self, x: &N) -> bool423     fn is_visited(&self, x: &N) -> bool {
424         self.contains(x)
425     }
426 }
427 
428 trait_template! {
429 /// A graph that can create a map that tracks the visited status of its nodes.
430 #[allow(clippy::needless_arbitrary_self_type)]
431 pub 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 }
442 Visitable! {delegate_impl []}
443 
444 trait_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)]
450 pub 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 
464 GetAdjacencyMatrix! {delegate_impl []}
465 
466 trait_template! {
467 /// A graph with a known edge count.
468 #[allow(clippy::needless_arbitrary_self_type)]
469 pub 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 
476 EdgeCount! {delegate_impl []}
477 
478 mod filter;
479 mod reversed;
480