bidirected_adjacency_array/
graph.rs1use std::iter;
2
3use tagged_vec::TaggedVec;
4
5use crate::index::{
6 DirectedEdgeIndex, DirectedNodeIndex, EdgeIndex, GraphIndexInteger, NodeIndex,
7 OptionalEdgeIndex,
8};
9
10#[cfg(test)]
11mod tests;
12
13#[derive(Debug)]
14pub struct BidirectedAdjacencyArray<IndexType: GraphIndexInteger, NodeData, EdgeData> {
15 node_array: TaggedVec<DirectedNodeIndex<IndexType>, DirectedEdgeIndex<IndexType>>,
22
23 edge_array: TaggedVec<DirectedEdgeIndex<IndexType>, DirectedNodeIndex<IndexType>>,
28
29 node_data: TaggedVec<NodeIndex<IndexType>, NodeData>,
35
36 edge_data_keys: TaggedVec<DirectedEdgeIndex<IndexType>, EdgeDataKey<IndexType>>,
43
44 edge_data: TaggedVec<EdgeIndex<IndexType>, BidirectedEdgeData<IndexType, EdgeData>>,
48}
49
50#[derive(Debug, Clone, Copy)]
51struct EdgeDataKey<IndexType: GraphIndexInteger> {
52 inverse: DirectedEdgeIndex<IndexType>,
53 data_index: OptionalEdgeIndex<IndexType>,
54}
55
56#[derive(Debug)]
57struct BidirectedEdgeData<IndexType, EdgeData> {
58 forward: DirectedEdgeIndex<IndexType>,
59 reverse: DirectedEdgeIndex<IndexType>,
60 data: EdgeData,
61}
62
63pub struct DirectedEdge<IndexType> {
64 from: DirectedNodeIndex<IndexType>,
65 to: DirectedNodeIndex<IndexType>,
66 index: DirectedEdgeIndex<IndexType>,
67}
68
69pub struct DirectedEdgeDataView<'a, IndexType, EdgeData> {
70 is_forward: bool,
71 edge: EdgeIndex<IndexType>,
72 data: &'a EdgeData,
73}
74
75pub struct EdgeView<'a, IndexType, EdgeData> {
76 from: DirectedNodeIndex<IndexType>,
77 to: DirectedNodeIndex<IndexType>,
78 forward: DirectedEdgeIndex<IndexType>,
79 reverse: DirectedEdgeIndex<IndexType>,
80 data: &'a EdgeData,
81}
82
83#[derive(Debug, Clone, Hash, PartialEq, Eq)]
84pub struct BidirectedEdge<IndexType, EdgeData> {
85 pub from: NodeIndex<IndexType>,
86 pub from_forward: bool,
88 pub to: NodeIndex<IndexType>,
89 pub to_forward: bool,
91 pub data: EdgeData,
92}
93
94impl<IndexType: GraphIndexInteger, NodeData, EdgeData>
95 BidirectedAdjacencyArray<IndexType, NodeData, EdgeData>
96{
97 pub fn new(
98 nodes: TaggedVec<NodeIndex<IndexType>, NodeData>,
99 edges: TaggedVec<EdgeIndex<IndexType>, BidirectedEdge<IndexType, EdgeData>>,
100 ) -> Self {
101 let mut node_array = TaggedVec::from_iter(iter::repeat_n(
102 DirectedEdgeIndex::from_usize(0),
103 nodes.len() * 2 + 1,
104 ));
105
106 for edge in edges.iter_values() {
108 let from_directed_forward =
109 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
110 node_array[from_directed_forward].increment();
111 let from_directed_reverse =
112 DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward).invert();
113 node_array[from_directed_reverse].increment();
114 }
115
116 let directed_edge_count =
118 node_array
119 .iter_values_mut()
120 .fold(DirectedEdgeIndex::zero(), |sum, element| {
121 let sum = sum.add(*element);
122 *element = sum;
123 sum
124 });
125 assert_eq!(
126 directed_edge_count,
127 node_array.iter_values().last().copied().unwrap(),
128 );
129
130 let mut edge_array = TaggedVec::from_iter(iter::repeat_n(
132 DirectedNodeIndex::from_usize(0),
133 directed_edge_count.into_usize(),
134 ));
135 let mut edge_data_keys = TaggedVec::from_iter(iter::repeat_n(
136 EdgeDataKey {
137 inverse: DirectedEdgeIndex::zero(),
138 data_index: OptionalEdgeIndex::new_none(),
139 },
140 directed_edge_count.into_usize(),
141 ));
142 let mut edge_data = TaggedVec::new();
143
144 for (edge_index, edge) in edges.into_iter() {
147 let from_directed_forward =
148 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
149 let to_directed_forward = DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward);
150 let edge_index_forward = {
151 node_array[from_directed_forward].decrement();
152 node_array[from_directed_forward]
153 };
154
155 let from_directed_reverse = to_directed_forward.invert();
156 let to_directed_reverse = from_directed_forward.invert();
157 let edge_index_reverse = {
158 node_array[from_directed_reverse].decrement();
159 node_array[from_directed_reverse]
160 };
161
162 edge_array[edge_index_forward] = to_directed_forward;
163 edge_array[edge_index_reverse] = to_directed_reverse;
164
165 edge_data_keys[edge_index_forward] = EdgeDataKey {
166 inverse: edge_index_reverse,
167 data_index: edge_index.into(),
168 };
169 edge_data_keys[edge_index_reverse] = EdgeDataKey {
170 inverse: edge_index_forward,
171 data_index: OptionalEdgeIndex::new_none(),
172 };
173
174 let data_index = edge_data.push(BidirectedEdgeData {
175 forward: edge_index_forward,
176 reverse: edge_index_reverse,
177 data: edge.data,
178 });
179 assert_eq!(edge_index, data_index);
180 }
181
182 Self {
183 node_array,
184 edge_array,
185 node_data: nodes,
186 edge_data_keys,
187 edge_data,
188 }
189 }
190
191 pub fn node_count(&self) -> usize {
192 self.node_data.len()
193 }
194
195 pub fn edge_count(&self) -> usize {
196 self.edge_data.len()
197 }
198
199 pub fn iter_nodes(&self) -> impl Iterator<Item = NodeIndex<IndexType>> {
200 self.node_data.iter_indices()
201 }
202
203 pub fn iter_edges(&self) -> impl Iterator<Item = EdgeIndex<IndexType>> {
204 self.edge_data.iter_indices()
205 }
206
207 pub fn iter_outgoing_edges(
208 &self,
209 node: DirectedNodeIndex<IndexType>,
210 ) -> impl Iterator<Item = DirectedEdge<IndexType>> {
211 let start = self.node_array[node];
212 let end = self.node_array[node.add(DirectedNodeIndex::from_usize(1))];
213 self.edge_array
214 .iter()
215 .take(end.into_usize())
216 .skip(start.into_usize())
217 .map(move |(edge_index, &to_node)| DirectedEdge {
218 from: node,
219 to: to_node,
220 index: edge_index,
221 })
222 }
223
224 pub fn iter_incident_edges(
226 &self,
227 node: NodeIndex<IndexType>,
228 ) -> impl Iterator<Item = EdgeIndex<IndexType>> {
229 let forward_node = DirectedNodeIndex::from_bidirected(node, true);
230 let reverse_node = DirectedNodeIndex::from_bidirected(node, false);
231 self.iter_outgoing_edges(forward_node)
232 .chain(self.iter_outgoing_edges(reverse_node))
233 .filter_map(|directed_edge| {
234 let directed_edge_data = self.directed_edge_data(directed_edge.index());
235 if directed_edge.from() == directed_edge.to()
236 || directed_edge.from() == directed_edge.to().invert()
237 {
238 directed_edge_data
239 .is_forward()
240 .then_some(directed_edge_data.edge())
241 } else {
242 Some(directed_edge_data.edge())
243 }
244 })
245 }
246
247 pub fn node_data(&self, node: NodeIndex<IndexType>) -> &NodeData {
248 &self.node_data[node]
249 }
250
251 pub fn edge(&self, edge: EdgeIndex<IndexType>) -> EdgeView<'_, IndexType, EdgeData> {
252 let bidirected_edge_data = &self.edge_data[edge];
253
254 let forward_to = self.edge_array[bidirected_edge_data.forward];
255 let reverse_to = self.edge_array[bidirected_edge_data.reverse];
256
257 if forward_to == reverse_to {
258 let from = forward_to.invert();
260 let to = forward_to;
261 EdgeView {
262 from,
263 to,
264 forward: bidirected_edge_data.forward,
265 reverse: bidirected_edge_data.reverse,
266 data: &bidirected_edge_data.data,
267 }
268 } else if forward_to.invert() == reverse_to {
269 let from = forward_to;
271 let to = forward_to;
272 EdgeView {
273 from,
274 to,
275 forward: bidirected_edge_data.forward,
276 reverse: bidirected_edge_data.reverse,
277 data: &bidirected_edge_data.data,
278 }
279 } else {
280 let from = reverse_to.invert();
282 let to = forward_to;
283 EdgeView {
284 from,
285 to,
286 forward: bidirected_edge_data.forward,
287 reverse: bidirected_edge_data.reverse,
288 data: &bidirected_edge_data.data,
289 }
290 }
291 }
292
293 pub fn directed_edge_data<'this>(
294 &'this self,
295 directed_edge: DirectedEdgeIndex<IndexType>,
296 ) -> DirectedEdgeDataView<'this, IndexType, EdgeData> {
297 let key = &self.edge_data_keys[directed_edge];
298 if let Some(edge) = key.data_index.into_option() {
299 DirectedEdgeDataView {
300 is_forward: true,
301 edge,
302 data: &self.edge_data[edge].data,
303 }
304 } else {
305 let inverse_key = &self.edge_data_keys[key.inverse];
306 let Some(edge) = inverse_key.data_index.into_option() else {
307 panic!(
308 "Edge data for edge {:?} and its inverse {:?} are both missing",
309 directed_edge, key.inverse
310 );
311 };
312 DirectedEdgeDataView {
313 is_forward: false,
314 edge,
315 data: &self.edge_data[edge].data,
316 }
317 }
318 }
319
320 pub fn directed_edge_into_bidirected(
321 &self,
322 directed_edge: DirectedEdgeIndex<IndexType>,
323 ) -> EdgeIndex<IndexType> {
324 let key = &self.edge_data_keys[directed_edge];
325 if let Some(edge) = key.data_index.into_option() {
326 edge
327 } else {
328 let inverse_key = &self.edge_data_keys[key.inverse];
329 inverse_key
330 .data_index
331 .expect("Edge data for directed edge and its inverse are both missing")
332 }
333 }
334}
335
336impl<IndexType> DirectedEdge<IndexType> {
337 pub fn from(&self) -> DirectedNodeIndex<IndexType>
338 where
339 IndexType: Copy,
340 {
341 self.from
342 }
343
344 pub fn to(&self) -> DirectedNodeIndex<IndexType>
345 where
346 IndexType: Copy,
347 {
348 self.to
349 }
350
351 pub fn index(&self) -> DirectedEdgeIndex<IndexType>
352 where
353 IndexType: Copy,
354 {
355 self.index
356 }
357}
358
359impl<'a, IndexType, EdgeData> DirectedEdgeDataView<'a, IndexType, EdgeData> {
360 pub fn is_forward(&self) -> bool {
361 self.is_forward
362 }
363
364 pub fn edge(&self) -> EdgeIndex<IndexType>
365 where
366 IndexType: Copy,
367 {
368 self.edge
369 }
370
371 pub fn data(&self) -> &EdgeData {
372 self.data
373 }
374}
375
376impl<'a, IndexType, EdgeData> EdgeView<'a, IndexType, EdgeData> {
377 pub fn from(&self) -> DirectedNodeIndex<IndexType>
378 where
379 IndexType: Copy,
380 {
381 self.from
382 }
383
384 pub fn to(&self) -> DirectedNodeIndex<IndexType>
385 where
386 IndexType: Copy,
387 {
388 self.to
389 }
390
391 pub fn forward(&self) -> DirectedEdgeIndex<IndexType>
392 where
393 IndexType: Copy,
394 {
395 self.forward
396 }
397
398 pub fn reverse(&self) -> DirectedEdgeIndex<IndexType>
399 where
400 IndexType: Copy,
401 {
402 self.reverse
403 }
404
405 pub fn data(&self) -> &EdgeData {
406 self.data
407 }
408}