traitgraph/interface/
mod.rs

1//! The graph traits.
2//!
3//! The traits are roughly split up by different access types:
4//!  - immutable reference (`ImmutableGraphContainer`)
5//!  - mutable reference (`MutableGraphContainer`)
6//!  - immutable reference that must outlive the return value (`TraversableGraph`)
7//!
8//! As it happens, the access types match well to common graph use cases, i.e. queries for nodes and edges, adding and removing nodes and edges as well as iterating over the neighbors of a node.
9
10use crate::index::{GraphIndex, OptionalGraphIndex};
11use crate::walks::{EdgeWalk, NodeWalk};
12use std::iter::FromIterator;
13
14/// A set of traits for subgraphs.
15/// A subgraph is a graph that is backed by an actual graph implementation, but that filters out some nodes or edges.
16pub mod subgraph;
17
18/// Contains the associated types of a graph.
19pub trait GraphBase {
20    /// The data type associated with each node.
21    type NodeData;
22    /// The data type associated with each edge.
23    type EdgeData;
24    /// The optional index type used for nodes.
25    type OptionalNodeIndex: OptionalGraphIndex<Self::NodeIndex>;
26    /// The optional index type used for edges.
27    type OptionalEdgeIndex: OptionalGraphIndex<Self::EdgeIndex>;
28    /// The index type used for nodes.
29    type NodeIndex: GraphIndex<Self::OptionalNodeIndex>;
30    /// The index type used for edges.
31    type EdgeIndex: GraphIndex<Self::OptionalEdgeIndex>;
32
33    /// Returns the none value of the optional node index type used by the trait.
34    fn new_none_optional_node_index(&self) -> Self::OptionalNodeIndex {
35        Self::OptionalNodeIndex::new_none()
36    }
37
38    /// Returns the none value of the optional edge index type used by the trait.
39    fn new_none_optional_edge_index(&self) -> Self::OptionalEdgeIndex {
40        Self::OptionalEdgeIndex::new_none()
41    }
42}
43
44/// A container that contains a set of nodes and edges.
45///
46/// Graphs that implement this trait must have their nodes and edges indexed consecutively.
47pub trait ImmutableGraphContainer: GraphBase {
48    /// An iterator type over the node indices in this graph.
49    type NodeIndices<'a>: Iterator<Item = Self::NodeIndex>
50    where
51        Self: 'a;
52    /// An iterator type over the edge indices in this graph.
53    type EdgeIndices<'a>: Iterator<Item = Self::EdgeIndex>
54    where
55        Self: 'a;
56    /// An iterator type over the node indices in this graph.
57    /// The iterator is independent of the lifetime of self, and hence allows concurrent modifications during iteration.
58    /// Note that any modification to the graph is not reflected in the iterator after construction.
59    type NodeIndicesCopied: Iterator<Item = Self::NodeIndex>;
60    /// An iterator type over the edge indices in this graph.
61    /// The iterator is independent of the lifetime of self, and hence allows concurrent modifications during iteration.
62    /// Note that any modification to the graph is not reflected in the iterator after construction.
63    type EdgeIndicesCopied: Iterator<Item = Self::EdgeIndex>;
64
65    /// Returns an iterator over the node indices in this graph.
66    fn node_indices(&self) -> Self::NodeIndices<'_>;
67
68    /// Returns an iterator over the edge indices in this graph.
69    fn edge_indices(&self) -> Self::EdgeIndices<'_>;
70
71    /// Returns an iterator over the node indices in this graph.
72    /// The iterator is independent of the lifetime of self, and hence allows concurrent modifications during iteration.
73    /// Note that any modification to the graph is not reflected in the iterator after construction.
74    fn node_indices_copied(&self) -> Self::NodeIndicesCopied;
75
76    /// Returns an iterator over the edge indices in this graph.
77    /// The iterator is independent of the lifetime of self, and hence allows concurrent modifications during iteration.
78    /// Note that any modification to the graph is not reflected in the iterator after construction.
79    fn edge_indices_copied(&self) -> Self::EdgeIndicesCopied;
80
81    /// Returns true if this graph contains the given node index.
82    fn contains_node_index(&self, node_id: Self::NodeIndex) -> bool;
83
84    /// Returns true if this graph contains the given edge index.
85    fn contains_edge_index(&self, edge_id: Self::EdgeIndex) -> bool;
86
87    /// Returns the amount of nodes in this graph.
88    fn node_count(&self) -> usize;
89
90    /// Returns the amount of edges in this graph.
91    fn edge_count(&self) -> usize;
92
93    /// Returns a reference to the node data associated with the given node id, or None if there is no such node.
94    fn node_data(&self, node_id: Self::NodeIndex) -> &Self::NodeData;
95
96    /// Returns a reference to the edge data associated with the given edge id, or None if there is no such edge.
97    fn edge_data(&self, edge_id: Self::EdgeIndex) -> &Self::EdgeData;
98
99    /// Returns the endpoints of an edge.
100    fn edge_endpoints(&self, edge_id: Self::EdgeIndex) -> Edge<Self::NodeIndex>;
101
102    /// Returns true if the graph is empty, i.e. contains no nodes or edges.
103    fn is_empty(&self) -> bool {
104        // Zero nodes must imply zero edges.
105        debug_assert!(self.node_count() != 0 || self.edge_count() == 0);
106        self.node_count() == 0
107    }
108
109    /// Returns true if the nodes returned by [`edge_endpoints`](Self::edge_endpoints) are part of the graph for all edges.
110    fn do_all_edges_endpoints_exist(&self) -> bool {
111        for edge_id in self.edge_indices() {
112            let Edge { from_node, to_node } = self.edge_endpoints(edge_id);
113            if !self.contains_node_index(from_node) || !self.contains_node_index(to_node) {
114                return false;
115            }
116        }
117        true
118    }
119}
120
121/// A container that allows adding and removing nodes and edges.
122pub trait MutableGraphContainer: ImmutableGraphContainer {
123    /// Returns a mutable reference to the node data associated with the given node id, or None if there is no such node.
124    fn node_data_mut(&mut self, node_id: Self::NodeIndex) -> &mut Self::NodeData;
125
126    /// Returns a mutable reference to the edge data associated with the given edge id, or None if there is no such edge.
127    fn edge_data_mut(&mut self, edge_id: Self::EdgeIndex) -> &mut Self::EdgeData;
128
129    /// Adds a new node with the given `NodeData` to the graph.
130    fn add_node(&mut self, node_data: Self::NodeData) -> Self::NodeIndex;
131
132    /// Adds a new edge with the given `EdgeData` to the graph.
133    fn add_edge(
134        &mut self,
135        from: Self::NodeIndex,
136        to: Self::NodeIndex,
137        edge_data: Self::EdgeData,
138    ) -> Self::EdgeIndex;
139
140    /// Removes the node with the given id from the graph.
141    /// Note that this may change the ids of existing nodes.
142    fn remove_node(&mut self, node_id: Self::NodeIndex) -> Option<Self::NodeData>;
143
144    /// Removes all nodes with the given ids from the graph.
145    /// The nodes must be passed as a slice and sorted in ascending order.
146    /// Note that this may change the ids of existing nodes.
147    fn remove_nodes_sorted_slice(&mut self, node_ids: &[Self::NodeIndex]) {
148        let mut previous_node_id = None;
149        for node_id in node_ids.iter().copied().rev() {
150            if let Some(previous_node_id) = previous_node_id {
151                debug_assert!(previous_node_id > node_id);
152            }
153            previous_node_id = Some(node_id);
154            self.remove_node(node_id);
155        }
156    }
157
158    /// Removes the edge with the given id from the graph.
159    /// Note that this may change the ids of existing edges.
160    fn remove_edge(&mut self, edge_id: Self::EdgeIndex) -> Option<Self::EdgeData>;
161
162    /// Removes the edges with the given ids from the graph.
163    /// The ids are expected to be given in sorted order.
164    ///
165    /// Note that this may change the ids of existing edges.
166    fn remove_edges_sorted(&mut self, edge_ids: &[Self::EdgeIndex]);
167
168    /// Removes all nodes and edges from the graph.
169    fn clear(&mut self);
170}
171
172/// A graph that can be navigated, i.e. that can iterate the neighbors of its nodes.
173pub trait NavigableGraph: ImmutableGraphContainer + Sized {
174    /// The iterator type used to iterate over the outgoing neighbors of a node.
175    type OutNeighbors<'a>: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>
176    where
177        Self: 'a;
178    /// The iterator type used to iterate over the incoming neighbors of a node.
179    type InNeighbors<'a>: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>
180    where
181        Self: 'a;
182    /// The iterator type used to iterate over the edges between two nodes.
183    type EdgesBetween<'a>: Iterator<Item = Self::EdgeIndex>
184    where
185        Self: 'a;
186
187    /// Returns an iterator over the outgoing neighbors of the given node.
188    fn out_neighbors(&self, node_id: Self::NodeIndex) -> Self::OutNeighbors<'_>;
189    /// Returns an iterator over the incoming neighbors of the given node.
190    fn in_neighbors(&self, node_id: Self::NodeIndex) -> Self::InNeighbors<'_>;
191
192    /// Returns an iterator over the edges `(from_node_id, to_node_id)`.
193    fn edges_between(
194        &self,
195        from_node_id: Self::NodeIndex,
196        to_node_id: Self::NodeIndex,
197    ) -> Self::EdgesBetween<'_>;
198
199    /// Returns true if the graph contains an edge `(from, to)`.
200    fn contains_edge_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> bool {
201        self.edges_between(from, to).next().is_some()
202    }
203
204    /// Returns the amount of edges `(from, to)`.
205    fn edge_count_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> usize {
206        self.edges_between(from, to).count()
207    }
208
209    /// Returns the amount of outgoing edges from a node.
210    fn out_degree(&self, node_id: Self::NodeIndex) -> usize {
211        self.out_neighbors(node_id).count()
212    }
213
214    /// Returns the amount of incoming edges to a node.
215    fn in_degree(&self, node_id: Self::NodeIndex) -> usize {
216        self.in_neighbors(node_id).count()
217    }
218
219    /// Returns true if the given node has indegree == 1 and outdegree == 1.
220    fn is_biunivocal_node(&self, node_id: Self::NodeIndex) -> bool {
221        self.in_degree(node_id) == 1 && self.out_degree(node_id) == 1
222    }
223
224    /// Returns true if the given node has indegree > 1 and outdegree > 1.
225    fn is_bivalent_node(&self, node_id: Self::NodeIndex) -> bool {
226        self.in_degree(node_id) > 1 && self.out_degree(node_id) > 1
227    }
228
229    /// Returns true if the given edge's tail has outdegree > 1.
230    fn is_split_edge(&self, edge_id: Self::EdgeIndex) -> bool {
231        self.out_degree(self.edge_endpoints(edge_id).from_node) > 1
232    }
233
234    /// Returns true if the given edge's head has indegree > 1.
235    fn is_join_edge(&self, edge_id: Self::EdgeIndex) -> bool {
236        self.in_degree(self.edge_endpoints(edge_id).to_node) > 1
237    }
238
239    /// Returns true if the given node has outdegree > 1.
240    fn is_split_node(&self, node_id: Self::NodeIndex) -> bool {
241        self.out_degree(node_id) > 1
242    }
243
244    /// Returns true if the given node has indegree > 1.
245    fn is_join_node(&self, node_id: Self::NodeIndex) -> bool {
246        self.in_degree(node_id) > 1
247    }
248}
249
250/// A helper trait to get the correct walk type from a graph.
251/// This is the factory pattern, where a graph is a factory for walks.
252pub trait WalkableGraph: GraphBase + Sized {
253    /// Create a node-centric walk over the given nodes in this graph.
254    fn create_node_walk<
255        WalkType: NodeWalk<Self, SubwalkType> + FromIterator<Self::NodeIndex>,
256        SubwalkType: NodeWalk<Self, SubwalkType> + ?Sized,
257    >(
258        &self,
259        walk: &[Self::NodeIndex],
260    ) -> WalkType {
261        walk.iter().copied().collect()
262    }
263
264    /// Create an empty node-centric walk in this graph.
265    fn create_empty_node_walk<
266        WalkType: NodeWalk<Self, SubwalkType> + Default,
267        SubwalkType: NodeWalk<Self, SubwalkType> + ?Sized,
268    >(
269        &self,
270    ) -> WalkType {
271        Default::default()
272    }
273
274    /// Create an edge-centric walk over the given edges in this graph.
275    fn create_edge_walk<
276        WalkType: EdgeWalk<Self, SubwalkType> + FromIterator<Self::EdgeIndex>,
277        SubwalkType: EdgeWalk<Self, SubwalkType> + ?Sized,
278    >(
279        &self,
280        walk: &[Self::EdgeIndex],
281    ) -> WalkType {
282        walk.iter().copied().collect()
283    }
284
285    /// Create an empty edge-centric walk in this graph.
286    fn create_empty_edge_walk<
287        WalkType: EdgeWalk<Self, SubwalkType> + Default,
288        SubwalkType: EdgeWalk<Self, SubwalkType> + ?Sized,
289    >(
290        &self,
291    ) -> WalkType {
292        Default::default()
293    }
294}
295impl<Graph: GraphBase> WalkableGraph for Graph {}
296
297/// A graph implementing all common graph traits that do not require mutable access.
298/// This is a useful shortcut for generic type bounds when the graph should not be mutated.
299pub trait StaticGraph: ImmutableGraphContainer + NavigableGraph + WalkableGraph {}
300impl<T: ImmutableGraphContainer + NavigableGraph + WalkableGraph> StaticGraph for T {}
301
302/// A graph implementing all common graph traits, including those requiring mutable access.
303/// This is a useful shortcut for generic type bounds when the graph should be mutated.
304pub trait DynamicGraph: StaticGraph + MutableGraphContainer {}
305impl<T: StaticGraph + MutableGraphContainer> DynamicGraph for T {}
306
307/// An edge represented as a pair of node indices.
308#[derive(Debug, Eq, PartialEq, Clone)]
309pub struct Edge<NodeIndex> {
310    /// The tail of this edge.
311    pub from_node: NodeIndex,
312    /// The head of this edge.
313    pub to_node: NodeIndex,
314}
315
316/// The neighbor of a node, given as the edge used to reach the neighbor node as well as the neighbor node itself.
317#[derive(Debug, Eq, PartialEq, Clone)]
318pub struct Neighbor<NodeIndex, EdgeIndex> {
319    /// The edge used to reach the neighboring node.
320    pub edge_id: EdgeIndex,
321    /// The neighboring node.
322    pub node_id: NodeIndex,
323}
324
325/// An enum encoding an index that can either be a node index or an edge index.
326#[derive(Debug, Eq, PartialEq, Clone)]
327pub enum NodeOrEdge<NodeIndex, EdgeIndex> {
328    /// A node index.
329    Node(NodeIndex),
330    /// An edge index.
331    Edge(EdgeIndex),
332}