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}