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