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, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
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, PartialEq, Eq, PartialOrd, Ord, Hash)]
56pub(crate) struct EdgeDataKey<IndexType: GraphIndexInteger> {
57 inverse: DirectedEdgeIndex<IndexType>,
58 data_index: OptionalEdgeIndex<IndexType>,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
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(start..end)
351 .map(move |(edge_index, &to_node)| DirectedEdge {
352 from: node,
353 to: to_node,
354 index: edge_index,
355 })
356 }
357
358 pub fn iter_incident_edges(
360 &self,
361 node: NodeIndex<IndexType>,
362 ) -> impl Iterator<Item = EdgeIndex<IndexType>> {
363 let forward_node = DirectedNodeIndex::from_bidirected(node, true);
364 let reverse_node = DirectedNodeIndex::from_bidirected(node, false);
365 self.iter_outgoing_edges(forward_node)
366 .chain(self.iter_outgoing_edges(reverse_node))
367 .filter_map(|directed_edge| {
368 let directed_edge_data = self.directed_edge_data(directed_edge.index());
369 if directed_edge.from() == directed_edge.to()
370 || directed_edge.from() == directed_edge.to().invert()
371 {
372 directed_edge_data
373 .is_forward()
374 .then_some(directed_edge_data.edge())
375 } else {
376 Some(directed_edge_data.edge())
377 }
378 })
379 }
380
381 pub fn node_data(&self, node: NodeIndex<IndexType>) -> &NodeData {
382 &self.node_data[node]
383 }
384
385 pub fn edge(&self, edge: EdgeIndex<IndexType>) -> EdgeView<'_, IndexType, EdgeData> {
386 let bidirected_edge_data = &self.edge_data[edge];
387
388 let forward_to = self.edge_array[bidirected_edge_data.forward];
389 let reverse_to = self.edge_array[bidirected_edge_data.reverse];
390
391 if forward_to == reverse_to {
392 let from = forward_to.invert();
394 let to = forward_to;
395 EdgeView {
396 from,
397 to,
398 forward: bidirected_edge_data.forward,
399 reverse: bidirected_edge_data.reverse,
400 data: &bidirected_edge_data.data,
401 }
402 } else if forward_to.invert() == reverse_to {
403 let from = forward_to;
405 let to = forward_to;
406 EdgeView {
407 from,
408 to,
409 forward: bidirected_edge_data.forward,
410 reverse: bidirected_edge_data.reverse,
411 data: &bidirected_edge_data.data,
412 }
413 } else {
414 let from = reverse_to.invert();
416 let to = forward_to;
417 EdgeView {
418 from,
419 to,
420 forward: bidirected_edge_data.forward,
421 reverse: bidirected_edge_data.reverse,
422 data: &bidirected_edge_data.data,
423 }
424 }
425 }
426
427 pub fn directed_edge_data<'this>(
428 &'this self,
429 directed_edge: DirectedEdgeIndex<IndexType>,
430 ) -> DirectedEdgeDataView<'this, IndexType, EdgeData> {
431 let key = &self.edge_data_keys[directed_edge];
432 if let Some(edge) = key.data_index.into_option() {
433 DirectedEdgeDataView {
434 is_forward: true,
435 edge,
436 data: &self.edge_data[edge].data,
437 }
438 } else {
439 let inverse_key = &self.edge_data_keys[key.inverse];
440 let Some(edge) = inverse_key.data_index.into_option() else {
441 panic!(
442 "Edge data for edge {:?} and its inverse {:?} are both missing",
443 directed_edge, key.inverse
444 );
445 };
446 DirectedEdgeDataView {
447 is_forward: false,
448 edge,
449 data: &self.edge_data[edge].data,
450 }
451 }
452 }
453
454 pub fn directed_edge_into_bidirected(
455 &self,
456 directed_edge: DirectedEdgeIndex<IndexType>,
457 ) -> EdgeIndex<IndexType> {
458 let key = &self.edge_data_keys[directed_edge];
459 if let Some(edge) = key.data_index.into_option() {
460 edge
461 } else {
462 let inverse_key = &self.edge_data_keys[key.inverse];
463 inverse_key
464 .data_index
465 .expect("Edge data for directed edge and its inverse are both missing")
466 }
467 }
468}
469
470impl<IndexType> DirectedEdge<IndexType> {
471 pub fn from(&self) -> DirectedNodeIndex<IndexType>
472 where
473 IndexType: Copy,
474 {
475 self.from
476 }
477
478 pub fn to(&self) -> DirectedNodeIndex<IndexType>
479 where
480 IndexType: Copy,
481 {
482 self.to
483 }
484
485 pub fn index(&self) -> DirectedEdgeIndex<IndexType>
486 where
487 IndexType: Copy,
488 {
489 self.index
490 }
491}
492
493impl<'a, IndexType, EdgeData> DirectedEdgeDataView<'a, IndexType, EdgeData> {
494 pub fn is_forward(&self) -> bool {
495 self.is_forward
496 }
497
498 pub fn edge(&self) -> EdgeIndex<IndexType>
499 where
500 IndexType: Copy,
501 {
502 self.edge
503 }
504
505 pub fn data(&self) -> &EdgeData {
506 self.data
507 }
508}
509
510impl<'a, IndexType, EdgeData> EdgeView<'a, IndexType, EdgeData> {
511 pub fn from(&self) -> DirectedNodeIndex<IndexType>
512 where
513 IndexType: Copy,
514 {
515 self.from
516 }
517
518 pub fn to(&self) -> DirectedNodeIndex<IndexType>
519 where
520 IndexType: Copy,
521 {
522 self.to
523 }
524
525 pub fn forward(&self) -> DirectedEdgeIndex<IndexType>
526 where
527 IndexType: Copy,
528 {
529 self.forward
530 }
531
532 pub fn reverse(&self) -> DirectedEdgeIndex<IndexType>
533 where
534 IndexType: Copy,
535 {
536 self.reverse
537 }
538
539 pub fn data(&self) -> &EdgeData {
540 self.data
541 }
542}
543
544impl<IndexType: GraphIndexInteger, EdgeData> BidirectedEdge<IndexType, EdgeData> {
545 pub fn new(
546 from: DirectedNodeIndex<IndexType>,
547 to: DirectedNodeIndex<IndexType>,
548 data: EdgeData,
549 ) -> Self {
550 Self {
551 from: from.into_bidirected(),
552 from_forward: from.is_forward(),
553 to: to.into_bidirected(),
554 to_forward: to.is_forward(),
555 data,
556 }
557 }
558}
559
560impl<IndexType: GraphIndexInteger> BidirectedEdge<IndexType, PlainGfaEdgeData> {
561 pub fn new_gfa(
562 from: DirectedNodeIndex<IndexType>,
563 to: DirectedNodeIndex<IndexType>,
564 overlap: u16,
565 ) -> Self {
566 Self {
567 from: from.into_bidirected(),
568 from_forward: from.is_forward(),
569 to: to.into_bidirected(),
570 to_forward: to.is_forward(),
571 data: PlainGfaEdgeData::new(overlap),
572 }
573 }
574}