traitgraph/implementation/
petgraph_impl.rs1use crate::index::{GraphIndex, GraphIndices};
2use crate::interface::{
3 Edge, GraphBase, ImmutableGraphContainer, MutableGraphContainer, NavigableGraph, Neighbor,
4};
5use num_traits::{PrimInt, ToPrimitive};
6use petgraph::graph::{DiGraph, Edges, EdgesConnecting};
7use petgraph::visit::EdgeRef;
8use petgraph::{Directed, Direction};
9use std::iter::Map;
10
11use crate::interface::subgraph::SubgraphBase;
12pub use petgraph;
13
14#[derive(Debug, Clone)]
16pub struct PetGraph<NodeData, EdgeData>(DiGraph<NodeData, EdgeData, usize>);
17
18impl<NodeData, EdgeData> PetGraph<NodeData, EdgeData> {
19 pub fn new() -> PetGraph<NodeData, EdgeData> {
21 PetGraph(DiGraph::<NodeData, EdgeData, usize>::default())
22 }
23}
24
25impl<NodeData, EdgeData> GraphBase for PetGraph<NodeData, EdgeData> {
26 type NodeData = NodeData;
27 type EdgeData = EdgeData;
28 type OptionalNodeIndex = crate::index::OptionalNodeIndex<usize>;
29 type OptionalEdgeIndex = crate::index::OptionalEdgeIndex<usize>;
30 type NodeIndex = crate::index::NodeIndex<usize>;
31 type EdgeIndex = crate::index::EdgeIndex<usize>;
32}
33
34impl<NodeData, EdgeData> ImmutableGraphContainer for PetGraph<NodeData, EdgeData> {
35 type NodeIndices<'a>
36 = GraphIndices<Self::NodeIndex, Self::OptionalNodeIndex>
37 where
38 Self: 'a;
39 type EdgeIndices<'a>
40 = GraphIndices<Self::EdgeIndex, Self::OptionalEdgeIndex>
41 where
42 Self: 'a;
43
44 type NodeIndicesCopied =
45 GraphIndices<<Self as GraphBase>::NodeIndex, <Self as GraphBase>::OptionalNodeIndex>;
46 type EdgeIndicesCopied =
47 GraphIndices<<Self as GraphBase>::EdgeIndex, <Self as GraphBase>::OptionalEdgeIndex>;
48
49 fn node_indices(&self) -> Self::NodeIndices<'_> {
50 GraphIndices::from((0, self.node_count()))
51 }
52 fn edge_indices(&self) -> Self::EdgeIndices<'_> {
53 GraphIndices::from((0, self.edge_count()))
54 }
55
56 fn node_indices_copied(&self) -> Self::NodeIndicesCopied {
57 GraphIndices::from((0, self.node_count()))
58 }
59
60 fn edge_indices_copied(&self) -> Self::EdgeIndicesCopied {
61 GraphIndices::from((0, self.edge_count()))
62 }
63
64 fn contains_node_index(&self, node_id: Self::NodeIndex) -> bool {
65 self.0.node_weight(node_id.into()).is_some()
66 }
67
68 fn contains_edge_index(&self, edge_id: Self::EdgeIndex) -> bool {
69 self.0.edge_weight(edge_id.into()).is_some()
70 }
71
72 fn node_count(&self) -> usize {
73 self.0.node_count()
74 }
75
76 fn edge_count(&self) -> usize {
77 self.0.edge_count()
78 }
79
80 fn node_data(&self, node_id: Self::NodeIndex) -> &Self::NodeData {
81 self.0.node_weight(node_id.into()).unwrap()
82 }
83
84 fn edge_data(&self, edge_id: Self::EdgeIndex) -> &Self::EdgeData {
85 self.0.edge_weight(edge_id.into()).unwrap()
86 }
87
88 fn edge_endpoints(&self, edge_id: Self::EdgeIndex) -> Edge<Self::NodeIndex> {
89 let endpoints = self.0.edge_endpoints(edge_id.into()).unwrap();
90 Edge {
91 from_node: endpoints.0.index().into(),
92 to_node: endpoints.1.index().into(),
93 }
94 }
95}
96
97impl<NodeData, EdgeData> MutableGraphContainer for PetGraph<NodeData, EdgeData> {
98 fn node_data_mut(&mut self, node_id: Self::NodeIndex) -> &mut Self::NodeData {
99 self.0.node_weight_mut(node_id.into()).unwrap()
100 }
101
102 fn edge_data_mut(&mut self, edge_id: Self::EdgeIndex) -> &mut Self::EdgeData {
103 self.0.edge_weight_mut(edge_id.into()).unwrap()
104 }
105
106 fn add_node(&mut self, node_data: NodeData) -> Self::NodeIndex {
107 self.0.add_node(node_data).index().into()
108 }
109
110 fn add_edge(
111 &mut self,
112 from: Self::NodeIndex,
113 to: Self::NodeIndex,
114 edge_data: EdgeData,
115 ) -> Self::EdgeIndex {
116 self.0
117 .add_edge(from.into(), to.into(), edge_data)
118 .index()
119 .into()
120 }
121
122 fn remove_node(&mut self, node_id: Self::NodeIndex) -> Option<NodeData> {
123 self.0.remove_node(node_id.into())
124 }
125
126 fn remove_edge(&mut self, edge_id: Self::EdgeIndex) -> Option<EdgeData> {
127 self.0.remove_edge(edge_id.into())
128 }
129
130 fn remove_edges_sorted(&mut self, edge_ids: &[Self::EdgeIndex]) {
131 edge_ids.windows(2).for_each(|w| debug_assert!(w[0] < w[1]));
132
133 for edge_id in edge_ids.iter().rev() {
134 self.remove_edge(*edge_id);
135 }
136 }
137
138 fn clear(&mut self) {
139 self.0.clear();
140 }
141}
142
143impl<NodeData, EdgeData> SubgraphBase for PetGraph<NodeData, EdgeData> {
144 type RootGraph = Self;
145
146 fn root(&self) -> &Self::RootGraph {
147 self
148 }
149}
150
151type PetgraphNeighborTranslator<'a, EdgeData, NodeIndex, EdgeIndex> = Map<
152 Edges<'a, EdgeData, Directed, usize>,
153 fn(petgraph::graph::EdgeReference<'a, EdgeData, usize>) -> Neighbor<NodeIndex, EdgeIndex>,
154>;
155
156type PetgraphRestrictedNeighborTranslator<'a, EdgeData, EdgeIndex> = Map<
157 EdgesConnecting<'a, EdgeData, Directed, usize>,
158 fn(petgraph::graph::EdgeReference<'a, EdgeData, usize>) -> EdgeIndex,
159>;
160
161impl<NodeData, EdgeData> NavigableGraph for PetGraph<NodeData, EdgeData> {
162 type OutNeighbors<'a>
163 = PetgraphNeighborTranslator<
164 'a,
165 EdgeData,
166 <Self as GraphBase>::NodeIndex,
167 <Self as GraphBase>::EdgeIndex,
168 >
169 where
170 NodeData: 'a,
171 EdgeData: 'a;
172 type InNeighbors<'a>
173 = PetgraphNeighborTranslator<
174 'a,
175 EdgeData,
176 <Self as GraphBase>::NodeIndex,
177 <Self as GraphBase>::EdgeIndex,
178 >
179 where
180 NodeData: 'a,
181 EdgeData: 'a;
182 type EdgesBetween<'a>
183 = PetgraphRestrictedNeighborTranslator<'a, EdgeData, <Self as GraphBase>::EdgeIndex>
184 where
185 NodeData: 'a,
186 EdgeData: 'a;
187
188 fn out_neighbors(&self, node_id: <Self as GraphBase>::NodeIndex) -> Self::OutNeighbors<'_> {
189 debug_assert!(self.contains_node_index(node_id));
190 self.0
191 .edges_directed(node_id.into(), Direction::Outgoing)
192 .map(|edge| Neighbor {
193 edge_id: <Self as GraphBase>::EdgeIndex::from(edge.id().index()),
194 node_id: <Self as GraphBase>::NodeIndex::from(edge.target().index()),
195 })
196 }
197
198 fn in_neighbors(&self, node_id: <Self as GraphBase>::NodeIndex) -> Self::InNeighbors<'_> {
199 debug_assert!(self.contains_node_index(node_id));
200 self.0
201 .edges_directed(node_id.into(), Direction::Incoming)
202 .map(|edge| Neighbor {
203 edge_id: <Self as GraphBase>::EdgeIndex::from(edge.id().index()),
204 node_id: <Self as GraphBase>::NodeIndex::from(edge.source().index()),
205 })
206 }
207
208 fn edges_between(
209 &self,
210 from_node_id: <Self as GraphBase>::NodeIndex,
211 to_node_id: <Self as GraphBase>::NodeIndex,
212 ) -> Self::EdgesBetween<'_> {
213 debug_assert!(self.contains_node_index(from_node_id));
214 debug_assert!(self.contains_node_index(to_node_id));
215 self.0
216 .edges_connecting(from_node_id.into(), to_node_id.into())
217 .map(|edge| <Self as GraphBase>::EdgeIndex::from(edge.id().index()))
218 }
219
220 fn contains_edge_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> bool {
221 self.0
222 .edges_connecting(from.into(), to.into())
223 .next()
224 .is_some()
225 }
226
227 fn edge_count_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> usize {
228 self.0.edges_connecting(from.into(), to.into()).count()
229 }
230}
231
232impl<IndexType: PrimInt + ToPrimitive + petgraph::graph::IndexType>
233 From<crate::index::NodeIndex<IndexType>> for petgraph::graph::NodeIndex<IndexType>
234{
235 fn from(index: crate::index::NodeIndex<IndexType>) -> Self {
236 petgraph::graph::NodeIndex::new(index.as_usize())
237 }
238}
239
240impl<IndexType: PrimInt + ToPrimitive + petgraph::graph::IndexType>
241 From<crate::index::EdgeIndex<IndexType>> for petgraph::graph::EdgeIndex<IndexType>
242{
243 fn from(index: crate::index::EdgeIndex<IndexType>) -> Self {
244 petgraph::graph::EdgeIndex::new(index.as_usize())
245 }
246}
247
248impl<NodeData: PartialEq, EdgeData: PartialEq> PartialEq for PetGraph<NodeData, EdgeData> {
249 fn eq(&self, other: &Self) -> bool {
250 self.node_count() == other.node_count()
251 || self.edge_count() == other.edge_count()
252 && self
253 .node_indices()
254 .zip(other.node_indices())
255 .all(|(a, b)| a == b && self.node_data(a) == other.node_data(b))
256 && self.edge_indices().zip(other.edge_indices()).all(|(a, b)| {
257 a == b
258 && self.edge_endpoints(a) == other.edge_endpoints(b)
259 && self.edge_data(a) == other.edge_data(b)
260 })
261 }
262}
263
264impl<NodeData: Eq, EdgeData: Eq> Eq for PetGraph<NodeData, EdgeData> {}
265
266impl<NodeData, EdgeData> Default for PetGraph<NodeData, EdgeData> {
267 fn default() -> Self {
268 Self(Default::default())
269 }
270}