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(
118 nodes: TaggedVec<NodeIndex<IndexType>, NodeData>,
119 edges: TaggedVec<EdgeIndex<IndexType>, BidirectedEdge<IndexType, EdgeData>>,
120 ) -> Self {
121 let mut node_array = TaggedVec::from_iter(iter::repeat_n(
122 DirectedEdgeIndex::from_usize(0),
123 nodes.len() * 2 + 1,
124 ));
125
126 for edge in edges.iter_values() {
128 let from_directed_forward =
129 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
130 node_array[from_directed_forward].increment();
131 let from_directed_reverse =
132 DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward).invert();
133 node_array[from_directed_reverse].increment();
134 }
135
136 let directed_edge_count =
138 node_array
139 .iter_values_mut()
140 .fold(DirectedEdgeIndex::zero(), |sum, element| {
141 let sum = sum.add(*element);
142 *element = sum;
143 sum
144 });
145 assert_eq!(
146 directed_edge_count,
147 node_array.iter_values().last().copied().unwrap(),
148 );
149
150 let mut edge_array = TaggedVec::from_iter(iter::repeat_n(
152 DirectedNodeIndex::from_usize(0),
153 directed_edge_count.into_usize(),
154 ));
155 let mut edge_data_keys = TaggedVec::from_iter(iter::repeat_n(
156 EdgeDataKey {
157 inverse: DirectedEdgeIndex::zero(),
158 data_index: OptionalEdgeIndex::new_none(),
159 },
160 directed_edge_count.into_usize(),
161 ));
162 let mut edge_data = TaggedVec::new();
163
164 for (edge_index, edge) in edges.into_iter() {
167 let from_directed_forward =
168 DirectedNodeIndex::from_bidirected(edge.from, edge.from_forward);
169 let to_directed_forward = DirectedNodeIndex::from_bidirected(edge.to, edge.to_forward);
170 let edge_index_forward = {
171 node_array[from_directed_forward].decrement();
172 node_array[from_directed_forward]
173 };
174
175 let from_directed_reverse = to_directed_forward.invert();
176 let to_directed_reverse = from_directed_forward.invert();
177 let edge_index_reverse = {
178 node_array[from_directed_reverse].decrement();
179 node_array[from_directed_reverse]
180 };
181
182 edge_array[edge_index_forward] = to_directed_forward;
183 edge_array[edge_index_reverse] = to_directed_reverse;
184
185 edge_data_keys[edge_index_forward] = EdgeDataKey {
186 inverse: edge_index_reverse,
187 data_index: edge_index.into(),
188 };
189 edge_data_keys[edge_index_reverse] = EdgeDataKey {
190 inverse: edge_index_forward,
191 data_index: OptionalEdgeIndex::new_none(),
192 };
193
194 let data_index = edge_data.push(BidirectedEdgeData {
195 forward: edge_index_forward,
196 reverse: edge_index_reverse,
197 data: edge.data,
198 });
199 assert_eq!(edge_index, data_index);
200 }
201
202 Self {
203 node_array,
204 edge_array,
205 node_data: nodes,
206 edge_data_keys,
207 edge_data,
208 }
209 }
210
211 pub fn node_count(&self) -> usize {
212 self.node_data.len()
213 }
214
215 pub fn edge_count(&self) -> usize {
216 self.edge_data.len()
217 }
218
219 pub fn iter_nodes(&self) -> impl Iterator<Item = NodeIndex<IndexType>> {
220 self.node_data.iter_indices()
221 }
222
223 pub fn iter_edges(&self) -> impl Iterator<Item = EdgeIndex<IndexType>> {
224 self.edge_data.iter_indices()
225 }
226
227 pub fn iter_outgoing_edges(
228 &self,
229 node: DirectedNodeIndex<IndexType>,
230 ) -> impl Iterator<Item = DirectedEdge<IndexType>> {
231 let start = self.node_array[node];
232 let end = self.node_array[node.add(DirectedNodeIndex::from_usize(1))];
233 self.edge_array
234 .iter()
235 .take(end.into_usize())
236 .skip(start.into_usize())
237 .map(move |(edge_index, &to_node)| DirectedEdge {
238 from: node,
239 to: to_node,
240 index: edge_index,
241 })
242 }
243
244 pub fn iter_incident_edges(
246 &self,
247 node: NodeIndex<IndexType>,
248 ) -> impl Iterator<Item = EdgeIndex<IndexType>> {
249 let forward_node = DirectedNodeIndex::from_bidirected(node, true);
250 let reverse_node = DirectedNodeIndex::from_bidirected(node, false);
251 self.iter_outgoing_edges(forward_node)
252 .chain(self.iter_outgoing_edges(reverse_node))
253 .filter_map(|directed_edge| {
254 let directed_edge_data = self.directed_edge_data(directed_edge.index());
255 if directed_edge.from() == directed_edge.to()
256 || directed_edge.from() == directed_edge.to().invert()
257 {
258 directed_edge_data
259 .is_forward()
260 .then_some(directed_edge_data.edge())
261 } else {
262 Some(directed_edge_data.edge())
263 }
264 })
265 }
266
267 pub fn node_data(&self, node: NodeIndex<IndexType>) -> &NodeData {
268 &self.node_data[node]
269 }
270
271 pub fn edge(&self, edge: EdgeIndex<IndexType>) -> EdgeView<'_, IndexType, EdgeData> {
272 let bidirected_edge_data = &self.edge_data[edge];
273
274 let forward_to = self.edge_array[bidirected_edge_data.forward];
275 let reverse_to = self.edge_array[bidirected_edge_data.reverse];
276
277 if forward_to == reverse_to {
278 let from = forward_to.invert();
280 let to = forward_to;
281 EdgeView {
282 from,
283 to,
284 forward: bidirected_edge_data.forward,
285 reverse: bidirected_edge_data.reverse,
286 data: &bidirected_edge_data.data,
287 }
288 } else if forward_to.invert() == reverse_to {
289 let from = forward_to;
291 let to = forward_to;
292 EdgeView {
293 from,
294 to,
295 forward: bidirected_edge_data.forward,
296 reverse: bidirected_edge_data.reverse,
297 data: &bidirected_edge_data.data,
298 }
299 } else {
300 let from = reverse_to.invert();
302 let to = forward_to;
303 EdgeView {
304 from,
305 to,
306 forward: bidirected_edge_data.forward,
307 reverse: bidirected_edge_data.reverse,
308 data: &bidirected_edge_data.data,
309 }
310 }
311 }
312
313 pub fn directed_edge_data<'this>(
314 &'this self,
315 directed_edge: DirectedEdgeIndex<IndexType>,
316 ) -> DirectedEdgeDataView<'this, IndexType, EdgeData> {
317 let key = &self.edge_data_keys[directed_edge];
318 if let Some(edge) = key.data_index.into_option() {
319 DirectedEdgeDataView {
320 is_forward: true,
321 edge,
322 data: &self.edge_data[edge].data,
323 }
324 } else {
325 let inverse_key = &self.edge_data_keys[key.inverse];
326 let Some(edge) = inverse_key.data_index.into_option() else {
327 panic!(
328 "Edge data for edge {:?} and its inverse {:?} are both missing",
329 directed_edge, key.inverse
330 );
331 };
332 DirectedEdgeDataView {
333 is_forward: false,
334 edge,
335 data: &self.edge_data[edge].data,
336 }
337 }
338 }
339
340 pub fn directed_edge_into_bidirected(
341 &self,
342 directed_edge: DirectedEdgeIndex<IndexType>,
343 ) -> EdgeIndex<IndexType> {
344 let key = &self.edge_data_keys[directed_edge];
345 if let Some(edge) = key.data_index.into_option() {
346 edge
347 } else {
348 let inverse_key = &self.edge_data_keys[key.inverse];
349 inverse_key
350 .data_index
351 .expect("Edge data for directed edge and its inverse are both missing")
352 }
353 }
354}
355
356impl<IndexType> DirectedEdge<IndexType> {
357 pub fn from(&self) -> DirectedNodeIndex<IndexType>
358 where
359 IndexType: Copy,
360 {
361 self.from
362 }
363
364 pub fn to(&self) -> DirectedNodeIndex<IndexType>
365 where
366 IndexType: Copy,
367 {
368 self.to
369 }
370
371 pub fn index(&self) -> DirectedEdgeIndex<IndexType>
372 where
373 IndexType: Copy,
374 {
375 self.index
376 }
377}
378
379impl<'a, IndexType, EdgeData> DirectedEdgeDataView<'a, IndexType, EdgeData> {
380 pub fn is_forward(&self) -> bool {
381 self.is_forward
382 }
383
384 pub fn edge(&self) -> EdgeIndex<IndexType>
385 where
386 IndexType: Copy,
387 {
388 self.edge
389 }
390
391 pub fn data(&self) -> &EdgeData {
392 self.data
393 }
394}
395
396impl<'a, IndexType, EdgeData> EdgeView<'a, IndexType, EdgeData> {
397 pub fn from(&self) -> DirectedNodeIndex<IndexType>
398 where
399 IndexType: Copy,
400 {
401 self.from
402 }
403
404 pub fn to(&self) -> DirectedNodeIndex<IndexType>
405 where
406 IndexType: Copy,
407 {
408 self.to
409 }
410
411 pub fn forward(&self) -> DirectedEdgeIndex<IndexType>
412 where
413 IndexType: Copy,
414 {
415 self.forward
416 }
417
418 pub fn reverse(&self) -> DirectedEdgeIndex<IndexType>
419 where
420 IndexType: Copy,
421 {
422 self.reverse
423 }
424
425 pub fn data(&self) -> &EdgeData {
426 self.data
427 }
428}
429
430impl<IndexType: GraphIndexInteger, EdgeData> BidirectedEdge<IndexType, EdgeData> {
431 pub fn new(
432 from: DirectedNodeIndex<IndexType>,
433 to: DirectedNodeIndex<IndexType>,
434 data: EdgeData,
435 ) -> Self {
436 Self {
437 from: from.into_bidirected(),
438 from_forward: from.is_forward(),
439 to: to.into_bidirected(),
440 to_forward: to.is_forward(),
441 data,
442 }
443 }
444}
445
446impl<IndexType: GraphIndexInteger> BidirectedEdge<IndexType, PlainGfaEdgeData> {
447 pub fn new_gfa(
448 from: DirectedNodeIndex<IndexType>,
449 to: DirectedNodeIndex<IndexType>,
450 overlap: u16,
451 ) -> Self {
452 Self {
453 from: from.into_bidirected(),
454 from_forward: from.is_forward(),
455 to: to.into_bidirected(),
456 to_forward: to.is_forward(),
457 data: PlainGfaEdgeData::new(overlap),
458 }
459 }
460}