summaryrefslogtreecommitdiff
path: root/vendor/petgraph/src/visit/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/petgraph/src/visit/mod.rs')
-rw-r--r--vendor/petgraph/src/visit/mod.rs481
1 files changed, 481 insertions, 0 deletions
diff --git a/vendor/petgraph/src/visit/mod.rs b/vendor/petgraph/src/visit/mod.rs
new file mode 100644
index 00000000..bc152560
--- /dev/null
+++ b/vendor/petgraph/src/visit/mod.rs
@@ -0,0 +1,481 @@
+//! Graph traits and graph traversals.
+//!
+//! ### The `Into-` Traits
+//!
+//! Graph traits like [`IntoNeighbors`][in] create iterators and use the same
+//! pattern that `IntoIterator` does: the trait takes a reference to a graph,
+//! and produces an iterator. These traits are quite composable, but with the
+//! limitation that they only use shared references to graphs.
+//!
+//! ### Graph Traversal
+//!
+//! [`Dfs`](struct.Dfs.html), [`Bfs`][bfs], [`DfsPostOrder`][dfspo] and
+//! [`Topo`][topo] are basic visitors and they use “walker” methods: the
+//! visitors don't hold the graph as borrowed during traversal, only for the
+//! `.next()` call on the walker. They can be converted to iterators
+//! through the [`Walker`][w] trait.
+//!
+//! There is also the callback based traversal [`depth_first_search`][dfs].
+//!
+//! [bfs]: struct.Bfs.html
+//! [dfspo]: struct.DfsPostOrder.html
+//! [topo]: struct.Topo.html
+//! [dfs]: fn.depth_first_search.html
+//! [w]: trait.Walker.html
+//!
+//! ### Other Graph Traits
+//!
+//! The traits are rather loosely coupled at the moment (which is intentional,
+//! but will develop a bit), and there are traits missing that could be added.
+//!
+//! Not much is needed to be able to use the visitors on a graph. A graph
+//! needs to define [`GraphBase`][gb], [`IntoNeighbors`][in] and
+//! [`Visitable`][vis] as a minimum.
+//!
+//! [gb]: trait.GraphBase.html
+//! [in]: trait.IntoNeighbors.html
+//! [vis]: trait.Visitable.html
+//!
+//! ### Graph Trait Implementations
+//!
+//! The following table lists the traits that are implemented for each graph type:
+//!
+//! | | Graph | StableGraph | GraphMap | MatrixGraph | Csr | List |
+//! | --------------------- | :---: | :---------: | :------: | :---------: | :---: | :---: |
+//! | GraphBase | x | x | x | x | x | x |
+//! | GraphProp | x | x | x | x | x | x |
+//! | NodeCount | x | x | x | x | x | x |
+//! | NodeIndexable | x | x | x | x | x | x |
+//! | NodeCompactIndexable | x | | x | | x | x |
+//! | EdgeCount | x | x | x | x | x | x |
+//! | EdgeIndexable | x | x | x | | | |
+//! | Data | x | x | x | x | x | x |
+//! | IntoNodeIdentifiers | x | x | x | x | x | x |
+//! | IntoNodeReferences | x | x | x | x | x | x |
+//! | IntoEdgeReferences | x | x | x | x | x | x |
+//! | IntoNeighbors | x | x | x | x | x | x |
+//! | IntoNeighborsDirected | x | x | x | x | | |
+//! | IntoEdges | x | x | x | x | x | x |
+//! | IntoEdgesDirected | x | x | x | x | | |
+//! | Visitable | x | x | x | x | x | x |
+//! | GetAdjacencyMatrix | x | x | x | x | x | x |
+
+// filter, reversed have their `mod` lines at the end,
+// so that they can use the trait template macros
+pub use self::filter::*;
+pub use self::reversed::*;
+pub use self::undirected_adaptor::*;
+
+#[macro_use]
+mod macros;
+
+mod dfsvisit;
+mod traversal;
+pub use self::dfsvisit::*;
+pub use self::traversal::*;
+
+use fixedbitset::FixedBitSet;
+use std::collections::HashSet;
+use std::hash::{BuildHasher, Hash};
+
+use super::EdgeType;
+use crate::prelude::Direction;
+
+use crate::graph::IndexType;
+
+trait_template! {
+/// Base graph trait: defines the associated node identifier and
+/// edge identifier types.
+pub trait GraphBase {
+ // FIXME: We can drop this escape/nodelegate stuff in Rust 1.18
+ @escape [type NodeId]
+ @escape [type EdgeId]
+ @section nodelegate
+ /// edge identifier
+ type EdgeId: Copy + PartialEq;
+ /// node identifier
+ type NodeId: Copy + PartialEq;
+}
+}
+
+GraphBase! {delegate_impl []}
+GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]}
+
+/// A copyable reference to a graph.
+pub trait GraphRef: Copy + GraphBase {}
+
+impl<G> GraphRef for &G where G: GraphBase {}
+
+trait_template! {
+/// Access to the neighbors of each node
+///
+/// The neighbors are, depending on the graph’s edge type:
+///
+/// - `Directed`: All targets of edges from `a`.
+/// - `Undirected`: All other endpoints of edges connected to `a`.
+pub trait IntoNeighbors : GraphRef {
+ @section type
+ type Neighbors: Iterator<Item=Self::NodeId>;
+ @section self
+ /// Return an iterator of the neighbors of node `a`.
+ fn neighbors(self, a: Self::NodeId) -> Self::Neighbors;
+}
+}
+
+IntoNeighbors! {delegate_impl []}
+
+trait_template! {
+/// Access to the neighbors of each node, through incoming or outgoing edges.
+///
+/// Depending on the graph’s edge type, the neighbors of a given directionality
+/// are:
+///
+/// - `Directed`, `Outgoing`: All targets of edges from `a`.
+/// - `Directed`, `Incoming`: All sources of edges to `a`.
+/// - `Undirected`: All other endpoints of edges connected to `a`.
+pub trait IntoNeighborsDirected : IntoNeighbors {
+ @section type
+ type NeighborsDirected: Iterator<Item=Self::NodeId>;
+ @section self
+ fn neighbors_directed(self, n: Self::NodeId, d: Direction)
+ -> Self::NeighborsDirected;
+}
+}
+
+trait_template! {
+/// Access to the edges of each node.
+///
+/// The edges are, depending on the graph’s edge type:
+///
+/// - `Directed`: All edges from `a`.
+/// - `Undirected`: All edges connected to `a`, with `a` being the source of each edge.
+///
+/// This is an extended version of the trait `IntoNeighbors`; the former
+/// only iterates over the target node identifiers, while this trait
+/// yields edge references (trait [`EdgeRef`][er]).
+///
+/// [er]: trait.EdgeRef.html
+pub trait IntoEdges : IntoEdgeReferences + IntoNeighbors {
+ @section type
+ type Edges: Iterator<Item=Self::EdgeRef>;
+ @section self
+ fn edges(self, a: Self::NodeId) -> Self::Edges;
+}
+}
+
+IntoEdges! {delegate_impl []}
+
+trait_template! {
+/// Access to all edges of each node, in the specified direction.
+///
+/// The edges are, depending on the direction and the graph’s edge type:
+///
+///
+/// - `Directed`, `Outgoing`: All edges from `a`.
+/// - `Directed`, `Incoming`: All edges to `a`.
+/// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each edge.
+/// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each edge.
+///
+/// This is an extended version of the trait `IntoNeighborsDirected`; the former
+/// only iterates over the target node identifiers, while this trait
+/// yields edge references (trait [`EdgeRef`][er]).
+///
+/// [er]: trait.EdgeRef.html
+pub trait IntoEdgesDirected : IntoEdges + IntoNeighborsDirected {
+ @section type
+ type EdgesDirected: Iterator<Item=Self::EdgeRef>;
+ @section self
+ fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected;
+}
+}
+
+IntoEdgesDirected! {delegate_impl []}
+
+trait_template! {
+/// Access to the sequence of the graph’s `NodeId`s.
+pub trait IntoNodeIdentifiers : GraphRef {
+ @section type
+ type NodeIdentifiers: Iterator<Item=Self::NodeId>;
+ @section self
+ fn node_identifiers(self) -> Self::NodeIdentifiers;
+}
+}
+
+IntoNodeIdentifiers! {delegate_impl []}
+IntoNeighborsDirected! {delegate_impl []}
+
+trait_template! {
+/// Define associated data for nodes and edges
+pub trait Data : GraphBase {
+ @section type
+ type NodeWeight;
+ type EdgeWeight;
+}
+}
+
+Data! {delegate_impl []}
+Data! {delegate_impl [['a, G], G, &'a mut G, deref]}
+
+/// An edge reference.
+///
+/// Edge references are used by traits `IntoEdges` and `IntoEdgeReferences`.
+pub trait EdgeRef: Copy {
+ type NodeId;
+ type EdgeId;
+ type Weight;
+ /// The source node of the edge.
+ fn source(&self) -> Self::NodeId;
+ /// The target node of the edge.
+ fn target(&self) -> Self::NodeId;
+ /// A reference to the weight of the edge.
+ fn weight(&self) -> &Self::Weight;
+ /// The edge’s identifier.
+ fn id(&self) -> Self::EdgeId;
+}
+
+impl<N, E> EdgeRef for (N, N, &E)
+where
+ N: Copy,
+{
+ type NodeId = N;
+ type EdgeId = (N, N);
+ type Weight = E;
+
+ fn source(&self) -> N {
+ self.0
+ }
+ fn target(&self) -> N {
+ self.1
+ }
+ fn weight(&self) -> &E {
+ self.2
+ }
+ fn id(&self) -> (N, N) {
+ (self.0, self.1)
+ }
+}
+
+/// A node reference.
+pub trait NodeRef: Copy {
+ type NodeId;
+ type Weight;
+ fn id(&self) -> Self::NodeId;
+ fn weight(&self) -> &Self::Weight;
+}
+
+trait_template! {
+/// Access to the sequence of the graph’s nodes
+pub trait IntoNodeReferences : Data + IntoNodeIdentifiers {
+ @section type
+ type NodeRef: NodeRef<NodeId=Self::NodeId, Weight=Self::NodeWeight>;
+ type NodeReferences: Iterator<Item=Self::NodeRef>;
+ @section self
+ fn node_references(self) -> Self::NodeReferences;
+}
+}
+
+IntoNodeReferences! {delegate_impl []}
+
+impl<Id> NodeRef for (Id, ())
+where
+ Id: Copy,
+{
+ type NodeId = Id;
+ type Weight = ();
+ fn id(&self) -> Self::NodeId {
+ self.0
+ }
+ fn weight(&self) -> &Self::Weight {
+ static DUMMY: () = ();
+ &DUMMY
+ }
+}
+
+impl<Id, W> NodeRef for (Id, &W)
+where
+ Id: Copy,
+{
+ type NodeId = Id;
+ type Weight = W;
+ fn id(&self) -> Self::NodeId {
+ self.0
+ }
+ fn weight(&self) -> &Self::Weight {
+ self.1
+ }
+}
+
+trait_template! {
+/// Access to the sequence of the graph’s edges
+pub trait IntoEdgeReferences : Data + GraphRef {
+ @section type
+ type EdgeRef: EdgeRef<NodeId=Self::NodeId, EdgeId=Self::EdgeId,
+ Weight=Self::EdgeWeight>;
+ type EdgeReferences: Iterator<Item=Self::EdgeRef>;
+ @section self
+ fn edge_references(self) -> Self::EdgeReferences;
+}
+}
+
+IntoEdgeReferences! {delegate_impl [] }
+
+trait_template! {
+ /// Edge kind property (directed or undirected edges)
+pub trait GraphProp : GraphBase {
+ @section type
+ /// The kind of edges in the graph.
+ type EdgeType: EdgeType;
+
+ @section nodelegate
+ fn is_directed(&self) -> bool {
+ <Self::EdgeType>::is_directed()
+ }
+}
+}
+
+GraphProp! {delegate_impl []}
+
+trait_template! {
+ /// The graph’s `NodeId`s map to indices
+ #[allow(clippy::needless_arbitrary_self_type)]
+ pub trait NodeIndexable : GraphBase {
+ @section self
+ /// Return an upper bound of the node indices in the graph
+ /// (suitable for the size of a bitmap).
+ fn node_bound(self: &Self) -> usize;
+ /// Convert `a` to an integer index.
+ fn to_index(self: &Self, a: Self::NodeId) -> usize;
+ /// Convert `i` to a node index. `i` must be a valid value in the graph.
+ fn from_index(self: &Self, i: usize) -> Self::NodeId;
+ }
+}
+
+NodeIndexable! {delegate_impl []}
+
+trait_template! {
+ /// The graph’s `NodeId`s map to indices
+ #[allow(clippy::needless_arbitrary_self_type)]
+ pub trait EdgeIndexable : GraphBase {
+ @section self
+ /// Return an upper bound of the edge indices in the graph
+ /// (suitable for the size of a bitmap).
+ fn edge_bound(self: &Self) -> usize;
+ /// Convert `a` to an integer index.
+ fn to_index(self: &Self, a: Self::EdgeId) -> usize;
+ /// Convert `i` to an edge index. `i` must be a valid value in the graph.
+ fn from_index(self: &Self, i: usize) -> Self::EdgeId;
+ }
+}
+
+EdgeIndexable! {delegate_impl []}
+
+trait_template! {
+/// A graph with a known node count.
+#[allow(clippy::needless_arbitrary_self_type)]
+pub trait NodeCount : GraphBase {
+ @section self
+ fn node_count(self: &Self) -> usize;
+}
+}
+
+NodeCount! {delegate_impl []}
+
+trait_template! {
+/// The graph’s `NodeId`s map to indices, in a range without holes.
+///
+/// The graph's node identifiers correspond to exactly the indices
+/// `0..self.node_bound()`.
+pub trait NodeCompactIndexable : NodeIndexable + NodeCount { }
+}
+
+NodeCompactIndexable! {delegate_impl []}
+
+/// A mapping for storing the visited status for NodeId `N`.
+pub trait VisitMap<N> {
+ /// Mark `a` as visited.
+ ///
+ /// Return **true** if this is the first visit, false otherwise.
+ fn visit(&mut self, a: N) -> bool;
+
+ /// Return whether `a` has been visited before.
+ fn is_visited(&self, a: &N) -> bool;
+}
+
+impl<Ix> VisitMap<Ix> for FixedBitSet
+where
+ Ix: IndexType,
+{
+ fn visit(&mut self, x: Ix) -> bool {
+ !self.put(x.index())
+ }
+ fn is_visited(&self, x: &Ix) -> bool {
+ self.contains(x.index())
+ }
+}
+
+impl<N, S> VisitMap<N> for HashSet<N, S>
+where
+ N: Hash + Eq,
+ S: BuildHasher,
+{
+ fn visit(&mut self, x: N) -> bool {
+ self.insert(x)
+ }
+ fn is_visited(&self, x: &N) -> bool {
+ self.contains(x)
+ }
+}
+
+trait_template! {
+/// A graph that can create a map that tracks the visited status of its nodes.
+#[allow(clippy::needless_arbitrary_self_type)]
+pub trait Visitable : GraphBase {
+ @section type
+ /// The associated map type
+ type Map: VisitMap<Self::NodeId>;
+ @section self
+ /// Create a new visitor map
+ fn visit_map(self: &Self) -> Self::Map;
+ /// Reset the visitor map (and resize to new size of graph if needed)
+ fn reset_map(self: &Self, map: &mut Self::Map);
+}
+}
+Visitable! {delegate_impl []}
+
+trait_template! {
+/// Create or access the adjacency matrix of a graph.
+///
+/// The implementor can either create an adjacency matrix, or it can return
+/// a placeholder if it has the needed representation internally.
+#[allow(clippy::needless_arbitrary_self_type)]
+pub trait GetAdjacencyMatrix : GraphBase {
+ @section type
+ /// The associated adjacency matrix type
+ type AdjMatrix;
+ @section self
+ /// Create the adjacency matrix
+ fn adjacency_matrix(self: &Self) -> Self::AdjMatrix;
+ /// Return true if there is an edge from `a` to `b`, false otherwise.
+ ///
+ /// Computes in O(1) time.
+ fn is_adjacent(self: &Self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
+}
+}
+
+GetAdjacencyMatrix! {delegate_impl []}
+
+trait_template! {
+/// A graph with a known edge count.
+#[allow(clippy::needless_arbitrary_self_type)]
+pub trait EdgeCount : GraphBase {
+ @section self
+ /// Return the number of edges in the graph.
+ fn edge_count(self: &Self) -> usize;
+}
+}
+
+EdgeCount! {delegate_impl []}
+
+mod filter;
+mod reversed;
+mod undirected_adaptor;