1use std::iter;
2
3use bitvec::vec::BitVec;
4use permutation::Permutation;
5use tagged_vec::TaggedVec;
6
7use crate::{
8 index::{
9 DirectedEdgeIndex, DirectedNodeIndex, EdgeIndex, GraphIndexInteger, NodeIndex,
10 OptionalEdgeIndex,
11 },
12 io::gfa1::PlainGfaEdgeData,
13};
14
15#[cfg(test)]
16mod tests;
17
18#[derive(Debug)]
19pub struct BidirectedAdjacencyArray<IndexType: GraphIndexInteger, NodeData, EdgeData> {
20 pub(crate) node_array: TaggedVec<DirectedNodeIndex<IndexType>, DirectedEdgeIndex<IndexType>>,
27
28 pub(crate) edge_array: TaggedVec<DirectedEdgeIndex<IndexType>, DirectedNodeIndex<IndexType>>,
33
34 pub(crate) node_data: TaggedVec<NodeIndex<IndexType>, NodeData>,
40
41 pub(crate) edge_data_keys: TaggedVec<DirectedEdgeIndex<IndexType>, EdgeDataKey<IndexType>>,
48
49 pub(crate) edge_data: TaggedVec<EdgeIndex<IndexType>, BidirectedEdgeData<IndexType, EdgeData>>,
53}
54
55#[derive(Debug, Clone, Copy)]
56pub(crate) struct EdgeDataKey<IndexType: GraphIndexInteger> {
57 inverse: DirectedEdgeIndex<IndexType>,
58 data_index: OptionalEdgeIndex<IndexType>,
59}
60
61#[derive(Debug, Clone, Copy)]
62pub(crate) struct BidirectedEdgeData<IndexType, EdgeData> {
63 forward: DirectedEdgeIndex<IndexType>,
64 reverse: DirectedEdgeIndex<IndexType>,
65 data: EdgeData,
66}
67
68pub struct DirectedEdge<IndexType> {
69 from: DirectedNodeIndex<IndexType>,
70 to: DirectedNodeIndex<IndexType>,
71 index: DirectedEdgeIndex<IndexType>,
72}
73
74pub struct DirectedEdgeDataView<'a, IndexType, EdgeData> {
75 is_forward: bool,
76 edge: EdgeIndex<IndexType>,
77 data: &'a EdgeData,
78}
79
80pub struct EdgeView<'a, IndexType, EdgeData> {
81 from: DirectedNodeIndex<IndexType>,
82 to: DirectedNodeIndex<IndexType>,
83 forward: DirectedEdgeIndex<IndexType>,
84 reverse: DirectedEdgeIndex<IndexType>,
85 data: &'a EdgeData,
86}
87
88#[derive(Debug, Clone, Hash, PartialEq, Eq)]
89pub struct BidirectedEdge<IndexType, EdgeData> {
90 pub from: NodeIndex<IndexType>,
91 pub from_forward: bool,
93 pub to: NodeIndex<IndexType>,
94 pub to_forward: bool,
96 pub data: EdgeData,
97}
98
99impl<IndexType: GraphIndexInteger, NodeData, EdgeData>
100 BidirectedAdjacencyArray<IndexType, NodeData, EdgeData>
101{
102 pub fn new(
120 nodes: TaggedVec<NodeIndex<IndexType>, NodeData>,
121 edges: TaggedVec<EdgeIndex<IndexType>, BidirectedEdge<IndexType, EdgeData>>,
122 ) -> Self {
123 let mut node_array = TaggedVec::from_iter(iter::repeat_n(
124 DirectedEdgeIndex::from_usize(0),
125 nodes.len() * 2 + 1,
126 ));
127
128 for edge in edges.iter_values() {
130 let from_directed_forward =
131 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
132 node_array[from_directed_forward].increment();
133 let from_directed_reverse =
134 DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward).invert();
135 node_array[from_directed_reverse].increment();
136 }
137
138 let directed_edge_count =
140 node_array
141 .iter_values_mut()
142 .fold(DirectedEdgeIndex::zero(), |sum, element| {
143 let sum = sum.add(*element);
144 *element = sum;
145 sum
146 });
147 assert_eq!(
148 directed_edge_count,
149 node_array.iter_values().last().copied().unwrap(),
150 );
151
152 let mut edge_array = TaggedVec::from_iter(iter::repeat_n(
154 DirectedNodeIndex::from_usize(0),
155 directed_edge_count.into_usize(),
156 ));
157 let mut edge_data_keys = TaggedVec::from_iter(iter::repeat_n(
158 EdgeDataKey {
159 inverse: DirectedEdgeIndex::zero(),
160 data_index: OptionalEdgeIndex::new_none(),
161 },
162 directed_edge_count.into_usize(),
163 ));
164 let mut edge_data = TaggedVec::new();
165
166 for (edge_index, edge) in edges.into_iter() {
169 let from_directed_forward =
170 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
171 let to_directed_forward = DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward);
172 let edge_index_forward = {
173 node_array[from_directed_forward].decrement();
174 node_array[from_directed_forward]
175 };
176
177 let from_directed_reverse = to_directed_forward.invert();
178 let to_directed_reverse = from_directed_forward.invert();
179 let edge_index_reverse = {
180 node_array[from_directed_reverse].decrement();
181 node_array[from_directed_reverse]
182 };
183
184 edge_array[edge_index_forward] = to_directed_forward;
185 edge_array[edge_index_reverse] = to_directed_reverse;
186
187 edge_data_keys[edge_index_forward] = EdgeDataKey {
188 inverse: edge_index_reverse,
189 data_index: edge_index.into(),
190 };
191 edge_data_keys[edge_index_reverse] = EdgeDataKey {
192 inverse: edge_index_forward,
193 data_index: OptionalEdgeIndex::new_none(),
194 };
195
196 let data_index = edge_data.push(BidirectedEdgeData {
197 forward: edge_index_forward,
198 reverse: edge_index_reverse,
199 data: edge.data,
200 });
201 assert_eq!(edge_index, data_index);
202 }
203
204 Self {
205 node_array,
206 edge_array,
207 node_data: nodes,
208 edge_data_keys,
209 edge_data,
210 }
211 }
212
213 pub fn reorder_edges(
217 &mut self,
218 node: DirectedNodeIndex<IndexType>,
219 comparator: impl FnMut(
220 DirectedNodeIndex<IndexType>,
221 DirectedNodeIndex<IndexType>,
222 ) -> std::cmp::Ordering,
223 ) {
224 self.reorder_edges_with_buffers(
225 node,
226 comparator,
227 &mut Permutation::one(0),
228 &mut BitVec::new(),
229 );
230 }
231
232 fn reorder_edges_with_buffers(
233 &mut self,
234 node: DirectedNodeIndex<IndexType>,
235 mut comparator: impl FnMut(
236 DirectedNodeIndex<IndexType>,
237 DirectedNodeIndex<IndexType>,
238 ) -> std::cmp::Ordering,
239 permutation: &mut Permutation,
240 bitvec: &mut BitVec,
241 ) {
242 let offset = self.node_array[node].into_usize();
243 let limit = self.node_array[node.add(DirectedNodeIndex::from_usize(1))].into_usize();
244
245 permutation.assign_from_sort_by(
247 &self.edge_array.as_untagged_slice()[offset..limit],
248 |a, b| comparator(*a, *b),
249 );
250
251 permutation
253 .apply_slice_in_place(&mut self.edge_array.as_untagged_mut_slice()[offset..limit]);
254
255 bitvec.clear();
257 bitvec.resize(limit - offset, false);
258 for edge_index in offset..limit {
259 if bitvec[edge_index - offset] {
260 continue;
261 }
262
263 let permuted_edge_index =
264 DirectedEdgeIndex::from_usize(permutation.apply_idx(edge_index - offset) + offset);
265 let edge_index = DirectedEdgeIndex::from_usize(edge_index);
266 let inverse_edge_index = self.edge_data_keys[edge_index].inverse;
267
268 self.edge_data_keys[inverse_edge_index].inverse = permuted_edge_index;
269
270 if (offset..limit).contains(&inverse_edge_index.into_usize()) {
271 bitvec.set(inverse_edge_index.into_usize() - offset, true);
274
275 let permuted_inverse_edge_index = DirectedEdgeIndex::from_usize(
276 permutation.apply_idx(inverse_edge_index.into_usize() - offset) + offset,
277 );
278 self.edge_data_keys[edge_index].inverse = permuted_inverse_edge_index;
279 }
280 }
281
282 permutation
283 .apply_slice_in_place(&mut self.edge_data_keys.as_untagged_mut_slice()[offset..limit]);
284
285 bitvec.clear();
287 bitvec.resize(limit - offset, false);
288 for edge_index in offset..limit {
289 if bitvec[edge_index - offset] {
290 continue;
291 }
292
293 let edge_index = DirectedEdgeIndex::from_usize(edge_index);
294 let inverse_edge_index = self.edge_data_keys[edge_index].inverse;
295
296 let edge_data_key = self.edge_data_keys[edge_index]
297 .data_index
298 .into_option()
299 .xor(
300 self.edge_data_keys[inverse_edge_index]
301 .data_index
302 .into_option(),
303 )
304 .unwrap();
305 let edge_data = &mut self.edge_data[edge_data_key];
306
307 if (offset..limit).contains(&edge_data.forward.into_usize()) {
308 edge_data.forward = DirectedEdgeIndex::from_usize(
309 permutation.apply_idx(edge_data.forward.into_usize() - offset) + offset,
310 );
311 }
312
313 if (offset..limit).contains(&edge_data.reverse.into_usize()) {
314 edge_data.reverse = DirectedEdgeIndex::from_usize(
315 permutation.apply_idx(edge_data.reverse.into_usize() - offset) + offset,
316 );
317 }
318
319 if (offset..limit).contains(&inverse_edge_index.into_usize()) {
320 bitvec.set(inverse_edge_index.into_usize() - offset, true);
323 }
324 }
325 }
326
327 pub fn node_count(&self) -> usize {
328 self.node_data.len()
329 }
330
331 pub fn edge_count(&self) -> usize {
332 self.edge_data.len()
333 }
334
335 pub fn iter_nodes(&self) -> impl Iterator<Item = NodeIndex<IndexType>> {
336 self.node_data.iter_indices()
337 }
338
339 pub fn iter_edges(&self) -> impl Iterator<Item = EdgeIndex<IndexType>> {
340 self.edge_data.iter_indices()
341 }
342
343 pub fn iter_outgoing_edges(
344 &self,
345 node: DirectedNodeIndex<IndexType>,
346 ) -> impl Iterator<Item = DirectedEdge<IndexType>> {
347 let start = self.node_array[node];
348 let end = self.node_array[node.add(DirectedNodeIndex::from_usize(1))];
349 self.edge_array
350 .iter()
351 .take(end.into_usize())
352 .skip(start.into_usize())
353 .map(move |(edge_index, &to_node)| DirectedEdge {
354 from: node,
355 to: to_node,
356 index: edge_index,
357 })
358 }
359
360 pub fn iter_incident_edges(
362 &self,
363 node: NodeIndex<IndexType>,
364 ) -> impl Iterator<Item = EdgeIndex<IndexType>> {
365 let forward_node = DirectedNodeIndex::from_bidirected(node, true);
366 let reverse_node = DirectedNodeIndex::from_bidirected(node, false);
367 self.iter_outgoing_edges(forward_node)
368 .chain(self.iter_outgoing_edges(reverse_node))
369 .filter_map(|directed_edge| {
370 let directed_edge_data = self.directed_edge_data(directed_edge.index());
371 if directed_edge.from() == directed_edge.to()
372 || directed_edge.from() == directed_edge.to().invert()
373 {
374 directed_edge_data
375 .is_forward()
376 .then_some(directed_edge_data.edge())
377 } else {
378 Some(directed_edge_data.edge())
379 }
380 })
381 }
382
383 pub fn node_data(&self, node: NodeIndex<IndexType>) -> &NodeData {
384 &self.node_data[node]
385 }
386
387 pub fn edge(&self, edge: EdgeIndex<IndexType>) -> EdgeView<'_, IndexType, EdgeData> {
388 let bidirected_edge_data = &self.edge_data[edge];
389
390 let forward_to = self.edge_array[bidirected_edge_data.forward];
391 let reverse_to = self.edge_array[bidirected_edge_data.reverse];
392
393 if forward_to == reverse_to {
394 let from = forward_to.invert();
396 let to = forward_to;
397 EdgeView {
398 from,
399 to,
400 forward: bidirected_edge_data.forward,
401 reverse: bidirected_edge_data.reverse,
402 data: &bidirected_edge_data.data,
403 }
404 } else if forward_to.invert() == reverse_to {
405 let from = forward_to;
407 let to = forward_to;
408 EdgeView {
409 from,
410 to,
411 forward: bidirected_edge_data.forward,
412 reverse: bidirected_edge_data.reverse,
413 data: &bidirected_edge_data.data,
414 }
415 } else {
416 let from = reverse_to.invert();
418 let to = forward_to;
419 EdgeView {
420 from,
421 to,
422 forward: bidirected_edge_data.forward,
423 reverse: bidirected_edge_data.reverse,
424 data: &bidirected_edge_data.data,
425 }
426 }
427 }
428
429 pub fn directed_edge_data<'this>(
430 &'this self,
431 directed_edge: DirectedEdgeIndex<IndexType>,
432 ) -> DirectedEdgeDataView<'this, IndexType, EdgeData> {
433 let key = &self.edge_data_keys[directed_edge];
434 if let Some(edge) = key.data_index.into_option() {
435 DirectedEdgeDataView {
436 is_forward: true,
437 edge,
438 data: &self.edge_data[edge].data,
439 }
440 } else {
441 let inverse_key = &self.edge_data_keys[key.inverse];
442 let Some(edge) = inverse_key.data_index.into_option() else {
443 panic!(
444 "Edge data for edge {:?} and its inverse {:?} are both missing",
445 directed_edge, key.inverse
446 );
447 };
448 DirectedEdgeDataView {
449 is_forward: false,
450 edge,
451 data: &self.edge_data[edge].data,
452 }
453 }
454 }
455
456 pub fn directed_edge_into_bidirected(
457 &self,
458 directed_edge: DirectedEdgeIndex<IndexType>,
459 ) -> EdgeIndex<IndexType> {
460 let key = &self.edge_data_keys[directed_edge];
461 if let Some(edge) = key.data_index.into_option() {
462 edge
463 } else {
464 let inverse_key = &self.edge_data_keys[key.inverse];
465 inverse_key
466 .data_index
467 .expect("Edge data for directed edge and its inverse are both missing")
468 }
469 }
470}
471
472impl<IndexType> DirectedEdge<IndexType> {
473 pub fn from(&self) -> DirectedNodeIndex<IndexType>
474 where
475 IndexType: Copy,
476 {
477 self.from
478 }
479
480 pub fn to(&self) -> DirectedNodeIndex<IndexType>
481 where
482 IndexType: Copy,
483 {
484 self.to
485 }
486
487 pub fn index(&self) -> DirectedEdgeIndex<IndexType>
488 where
489 IndexType: Copy,
490 {
491 self.index
492 }
493}
494
495impl<'a, IndexType, EdgeData> DirectedEdgeDataView<'a, IndexType, EdgeData> {
496 pub fn is_forward(&self) -> bool {
497 self.is_forward
498 }
499
500 pub fn edge(&self) -> EdgeIndex<IndexType>
501 where
502 IndexType: Copy,
503 {
504 self.edge
505 }
506
507 pub fn data(&self) -> &EdgeData {
508 self.data
509 }
510}
511
512impl<'a, IndexType, EdgeData> EdgeView<'a, IndexType, EdgeData> {
513 pub fn from(&self) -> DirectedNodeIndex<IndexType>
514 where
515 IndexType: Copy,
516 {
517 self.from
518 }
519
520 pub fn to(&self) -> DirectedNodeIndex<IndexType>
521 where
522 IndexType: Copy,
523 {
524 self.to
525 }
526
527 pub fn forward(&self) -> DirectedEdgeIndex<IndexType>
528 where
529 IndexType: Copy,
530 {
531 self.forward
532 }
533
534 pub fn reverse(&self) -> DirectedEdgeIndex<IndexType>
535 where
536 IndexType: Copy,
537 {
538 self.reverse
539 }
540
541 pub fn data(&self) -> &EdgeData {
542 self.data
543 }
544}
545
546impl<IndexType: GraphIndexInteger, EdgeData> BidirectedEdge<IndexType, EdgeData> {
547 pub fn new(
548 from: DirectedNodeIndex<IndexType>,
549 to: DirectedNodeIndex<IndexType>,
550 data: EdgeData,
551 ) -> Self {
552 Self {
553 from: from.into_bidirected(),
554 from_forward: from.is_forward(),
555 to: to.into_bidirected(),
556 to_forward: to.is_forward(),
557 data,
558 }
559 }
560}
561
562impl<IndexType: GraphIndexInteger> BidirectedEdge<IndexType, PlainGfaEdgeData> {
563 pub fn new_gfa(
564 from: DirectedNodeIndex<IndexType>,
565 to: DirectedNodeIndex<IndexType>,
566 overlap: u16,
567 ) -> Self {
568 Self {
569 from: from.into_bidirected(),
570 from_forward: from.is_forward(),
571 to: to.into_bidirected(),
572 to_forward: to.is_forward(),
573 data: PlainGfaEdgeData::new(overlap),
574 }
575 }
576}