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