1use super::traversal::{
2 PostOrderForwardDfs, PreOrderBackwardBfs, PreOrderForwardBfs, PreOrderUndirectedBfs,
3};
4use crate::traversal::ForbiddenEdge;
5use hashbrown::{HashMap, HashSet};
6use std::collections::LinkedList;
7use traitgraph::index::GraphIndex;
8use traitgraph::index::OptionalGraphIndex;
9use traitgraph::interface::NodeOrEdge;
10use traitgraph::interface::{DynamicGraph, MutableGraphContainer, StaticGraph};
11
12pub fn decompose_weakly_connected_components<Graph: Default + DynamicGraph>(
17 graph: &Graph,
18) -> Vec<Graph>
19where
20 Graph::NodeData: Clone,
21 Graph::EdgeData: Clone,
22{
23 decompose_weakly_connected_components_with_mappings(graph)
24 .into_iter()
25 .map(|(graph, _, _)| graph)
26 .collect()
27}
28
29#[allow(clippy::type_complexity)]
37pub fn decompose_weakly_connected_components_with_mappings<Graph: Default + DynamicGraph>(
38 graph: &Graph,
39) -> Vec<(Graph, Vec<Graph::NodeIndex>, Vec<Graph::EdgeIndex>)>
40where
41 Graph::NodeData: Clone,
42 Graph::EdgeData: Clone,
43{
44 let mut result = Vec::new();
45 let mut nodes: Vec<_> = graph.node_indices().collect();
46 let mut visited = vec![false; graph.node_count()];
47 let mut bfs = PreOrderUndirectedBfs::new_without_start(graph);
48
49 while let Some(start) = nodes.pop() {
50 if visited[start.as_usize()] {
51 continue;
52 }
53
54 let rank_offset = bfs.continue_traversal_from(start).as_usize();
55 let mut subgraph = Graph::default();
56 let mut node_mapping = Vec::new();
57 let mut edge_mapping = Vec::new();
58
59 while let Some(node) = bfs.next() {
60 let node = if let NodeOrEdge::Node(node) = node {
61 node
62 } else {
63 continue;
64 };
65 visited[node.as_usize()] = true;
66 let subnode = subgraph.add_node(graph.node_data(node).clone());
68 node_mapping.push(node);
69
70 for out_neighbor in graph.out_neighbors(node) {
71 let neighbor_id = out_neighbor.node_id;
72 debug_assert!(
73 graph.contains_edge_between(node, neighbor_id),
74 "f: Edge missing: ({:?}, {:?})",
75 node,
76 neighbor_id
77 );
78 let edge_id = out_neighbor.edge_id;
79 if let Some(subneighbor) = bfs.rank_of(neighbor_id) {
80 let subneighbor = (subneighbor.as_usize() - rank_offset).into();
81 if subgraph.contains_node_index(subneighbor) {
82 let edge_data = graph.edge_data(edge_id).clone();
83 subgraph.add_edge(subnode, subneighbor, edge_data);
85 edge_mapping.push(edge_id);
86 }
87 }
88 }
89 for in_neighbor in graph.in_neighbors(node) {
90 let neighbor_id = in_neighbor.node_id;
91
92 if neighbor_id == node {
95 continue;
96 }
97 debug_assert!(
98 graph.contains_edge_between(neighbor_id, node),
99 "r: Edge missing: ({:?}, {:?})",
100 neighbor_id,
101 node
102 );
103 let edge_id = in_neighbor.edge_id;
104
105 if let Some(subneighbor) = bfs.rank_of(neighbor_id) {
106 let subneighbor = (subneighbor.as_usize() - rank_offset).into();
107 if subgraph.contains_node_index(subneighbor) {
108 let edge_data = graph.edge_data(edge_id).clone();
109 subgraph.add_edge(subneighbor, subnode, edge_data);
111 edge_mapping.push(edge_id);
112 }
113 }
114 }
115 }
116
117 result.push((subgraph, node_mapping, edge_mapping));
118 }
119
120 result
121}
122
123pub fn is_strongly_connected<Graph: StaticGraph>(graph: &Graph) -> bool {
125 if graph.is_empty() {
126 return true;
127 }
128
129 let traversal = PreOrderForwardBfs::new(graph, graph.node_indices().next().unwrap());
130 let mut traversal_node_count = 0;
131
132 for node_or_edge in traversal {
133 if let NodeOrEdge::Node(_) = node_or_edge {
134 traversal_node_count += 1;
135 }
136 }
137
138 if traversal_node_count != graph.node_count() {
139 debug_assert!(traversal_node_count < graph.node_count());
140 return false;
141 }
142
143 let traversal = PreOrderBackwardBfs::new(graph, graph.node_indices().next().unwrap());
144 let mut traversal_node_count = 0;
145
146 for node_or_edge in traversal {
147 if let NodeOrEdge::Node(_) = node_or_edge {
148 traversal_node_count += 1;
149 }
150 }
151
152 if traversal_node_count != graph.node_count() {
153 debug_assert!(traversal_node_count < graph.node_count());
154 return false;
155 }
156
157 true
158}
159
160pub fn is_strong_bridge<Graph: StaticGraph>(graph: &Graph, edge: Graph::EdgeIndex) -> bool {
163 debug_assert!(is_strongly_connected(graph));
164
165 let mut traversal = PreOrderForwardBfs::new(graph, graph.node_indices().next().unwrap());
166 let forbidden_edge = ForbiddenEdge::new(edge);
167 let mut traversal_node_count = 0;
168
169 while let Some(node_or_edge) = traversal.next_with_forbidden_subgraph(&forbidden_edge) {
170 if let NodeOrEdge::Node(_) = node_or_edge {
171 traversal_node_count += 1;
172 }
173 }
174
175 if traversal_node_count != graph.node_count() {
176 debug_assert!(traversal_node_count < graph.node_count());
177 return true;
178 }
179
180 let mut traversal = PreOrderBackwardBfs::new(graph, graph.node_indices().next().unwrap());
181 let mut traversal_node_count = 0;
182
183 while let Some(node_or_edge) = traversal.next_with_forbidden_subgraph(&forbidden_edge) {
184 if let NodeOrEdge::Node(_) = node_or_edge {
185 traversal_node_count += 1;
186 }
187 }
188
189 if traversal_node_count != graph.node_count() {
190 debug_assert!(traversal_node_count < graph.node_count());
191 return true;
192 }
193
194 false
195}
196
197pub fn naively_compute_strong_bridges<Graph: StaticGraph>(graph: &Graph) -> Vec<Graph::EdgeIndex> {
200 graph
201 .edge_indices()
202 .filter(|&edge_index| is_strong_bridge(graph, edge_index))
203 .collect()
204}
205
206pub fn decompose_strongly_connected_components<Graph: StaticGraph>(
212 graph: &Graph,
213) -> Vec<Graph::NodeIndex> {
214 let mut result: Vec<_> = graph.node_indices().collect();
215 let mut nodes = LinkedList::new();
216 let mut visited = vec![false; graph.node_count()];
217 let mut dfs = PostOrderForwardDfs::new_without_start(graph);
219
220 for node in graph.node_indices() {
221 if !visited[node.as_usize()] {
222 dfs.continue_traversal_from(node);
223
224 while let Some(node) = dfs.next(graph) {
225 visited[node.as_usize()] = true;
226 nodes.push_front(node);
227 }
228 }
229 }
230
231 let mut bfs = PreOrderBackwardBfs::new_without_start(graph);
234 for root_node in nodes {
235 if visited[root_node.as_usize()] {
236 bfs.continue_traversal_from(root_node);
238
239 for node in &mut bfs {
240 let node = if let NodeOrEdge::Node(node) = node {
241 node
242 } else {
243 continue;
244 };
245 visited[node.as_usize()] = false;
246 result[node.as_usize()] = root_node;
247 }
248 }
249 }
250
251 result
253}
254
255pub fn decompose_strongly_connected_components_non_consecutive<Graph: StaticGraph>(
260 graph: &Graph,
261) -> HashMap<Graph::NodeIndex, Graph::NodeIndex> {
262 if graph.node_count() == 0 {
263 return HashMap::new();
264 }
265
266 let mut result = HashMap::with_capacity(graph.node_count());
267 let mut nodes = LinkedList::new();
268 let mut visited = HashSet::new();
269 let mut dfs = PostOrderForwardDfs::new_without_start(graph);
271
272 for node in graph.node_indices() {
273 if !visited.contains(&node) {
274 dfs.continue_traversal_from(node);
275
276 while let Some(node) = dfs.next(graph) {
277 visited.insert(node);
278 nodes.push_front(node);
279 }
280 }
281 }
282
283 let mut bfs = PreOrderBackwardBfs::new_without_start(graph);
286 for root_node in nodes {
287 if visited.contains(&root_node) {
288 bfs.continue_traversal_from(root_node);
290
291 for node in &mut bfs {
292 let node = if let NodeOrEdge::Node(node) = node {
293 node
294 } else {
295 continue;
296 };
297 visited.remove(&node);
298 result.insert(node, root_node);
299 }
300 }
301 }
302
303 result
305}
306
307pub fn extract_subgraphs_from_node_mapping<Graph: Default + MutableGraphContainer + StaticGraph>(
312 graph: &Graph,
313 node_mapping: &[Graph::NodeIndex],
314) -> Vec<Graph>
315where
316 Graph::NodeData: Clone,
317 Graph::EdgeData: Clone,
318{
319 let mut root_node_map = vec![usize::MAX; graph.node_count()];
321 let mut subgraph_node_indices = Vec::new();
322 for (node_index, root_node) in node_mapping.iter().enumerate() {
323 let node_index = Graph::NodeIndex::from(node_index);
324 let subgraph_index = root_node_map[root_node.as_usize()];
325 if subgraph_index == usize::MAX {
326 root_node_map[root_node.as_usize()] = subgraph_node_indices.len();
327 subgraph_node_indices.push(vec![node_index]);
328 } else {
329 subgraph_node_indices[subgraph_index].push(node_index);
330 }
331 }
332
333 let mut id_map = Vec::new();
335 let mut extracted_nodes = vec![Graph::OptionalNodeIndex::new_none(); graph.node_count()];
336
337 subgraph_node_indices
338 .iter()
339 .map(|subgraph_node_indices| {
340 let mut subgraph = Graph::default();
341 id_map.clear();
342 let root_node = node_mapping[subgraph_node_indices.first().unwrap().as_usize()];
343
344 for &node in subgraph_node_indices {
345 let subgraph_node = subgraph.add_node(graph.node_data(node).clone());
346 extracted_nodes[node.as_usize()] = subgraph_node.into();
347 id_map.push(node);
348 }
349
350 for subgraph_node in subgraph.node_indices_copied() {
351 let node = id_map[subgraph_node.as_usize()];
352 for neighbor in graph.out_neighbors(node) {
353 let edge = neighbor.edge_id;
354 let neighbor_node = neighbor.node_id;
355
356 if node_mapping[neighbor_node.as_usize()] == root_node {
357 let subgraph_neighbor_node =
358 extracted_nodes[neighbor_node.as_usize()].into().unwrap();
359 let edge_data = graph.edge_data(edge);
360 subgraph.add_edge(subgraph_node, subgraph_neighbor_node, edge_data.clone());
361 }
362 }
363 }
364
365 subgraph
366 })
367 .collect()
368}
369
370pub fn is_cycle<Graph: StaticGraph>(graph: &Graph) -> bool {
372 is_strongly_connected(graph) && graph.node_count() == graph.edge_count()
373}
374
375#[cfg(test)]
376mod tests {
377 use crate::components::{
378 decompose_strongly_connected_components,
379 decompose_weakly_connected_components_with_mappings, extract_subgraphs_from_node_mapping,
380 is_strongly_connected, naively_compute_strong_bridges,
381 };
382 use std::fmt::Debug;
383 use traitgraph::implementation::petgraph_impl::PetGraph;
384 use traitgraph::index::GraphIndex;
385 use traitgraph::interface::{GraphBase, ImmutableGraphContainer, MutableGraphContainer};
386
387 fn debug_assert_node_data<Graph: ImmutableGraphContainer>(
388 graph: &Graph,
389 required_node_data: &mut [<Graph as GraphBase>::NodeData],
390 ) where
391 <Graph as GraphBase>::NodeData: Ord + Clone + Debug,
392 {
393 let mut node_data: Vec<_> = graph
394 .node_indices()
395 .map(|i| graph.node_data(i))
396 .cloned()
397 .collect();
398 node_data.sort();
399 required_node_data.sort();
400 debug_assert_eq!(&node_data[..], required_node_data);
401 }
402
403 fn debug_assert_edge_data<Graph: ImmutableGraphContainer>(
404 graph: &Graph,
405 required_edge_data: &mut [Graph::EdgeData],
406 ) where
407 Graph::EdgeData: Ord + Clone + Debug,
408 {
409 let mut edge_data: Vec<_> = graph
410 .edge_indices()
411 .map(|i| graph.edge_data(i))
412 .cloned()
413 .collect();
414 edge_data.sort();
415 required_edge_data.sort();
416 debug_assert_eq!(&edge_data[..], required_edge_data);
417 }
418
419 #[test]
420 fn test_decompose_weakly_connected_components_scc() {
421 let mut graph = PetGraph::new();
422 let n0 = graph.add_node(0);
423 let n1 = graph.add_node(1);
424 let n2 = graph.add_node(2);
425 let n3 = graph.add_node(3);
426 let n4 = graph.add_node(4);
427 let _e0 = graph.add_edge(n0, n1, 10);
428 let _e1 = graph.add_edge(n1, n2, 11);
429 let _e15 = graph.add_edge(n1, n2, 115);
430 let _e2 = graph.add_edge(n2, n3, 12);
431 let _e3 = graph.add_edge(n3, n4, 13);
432 let _e4 = graph.add_edge(n4, n0, 14);
433 let _e45 = graph.add_edge(n4, n0, 145);
434 let _e5 = graph.add_edge(n1, n0, 15);
435 let _e6 = graph.add_edge(n2, n1, 16);
436 let _e7 = graph.add_edge(n3, n2, 17);
437 let _e8 = graph.add_edge(n4, n3, 18);
438 let _e9 = graph.add_edge(n0, n4, 19);
439 let _e10 = graph.add_edge(n2, n2, 20);
440 let result = decompose_weakly_connected_components_with_mappings(&graph);
441 debug_assert_eq!(result.len(), 1);
442 let (result, node_mapping, edge_mapping) = result.first().unwrap();
443 debug_assert_eq!(result.node_count(), graph.node_count());
444 debug_assert_eq!(result.edge_count(), graph.edge_count());
445
446 let mut node_data: Vec<_> = graph
447 .node_indices()
448 .map(|i| result.node_data(i))
449 .copied()
450 .collect();
451 node_data.sort_unstable();
452 debug_assert_eq!(node_data, vec![0, 1, 2, 3, 4]);
453
454 let mut edge_data: Vec<_> = graph
455 .edge_indices()
456 .map(|i| result.edge_data(i))
457 .copied()
458 .collect();
459 edge_data.sort_unstable();
460 debug_assert_eq!(
461 edge_data,
462 vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 115, 145]
463 );
464
465 for node in result.node_indices() {
466 debug_assert_eq!(
467 result.node_data(node),
468 graph.node_data(node_mapping[node.as_usize()])
469 );
470 }
471
472 for edge in result.edge_indices() {
473 debug_assert_eq!(
474 result.edge_data(edge),
475 graph.edge_data(edge_mapping[edge.as_usize()])
476 );
477 }
478 }
479
480 #[test]
481 fn test_decompose_weakly_connected_components_one_wc_with_two_sccs() {
482 let mut graph = PetGraph::new();
483 let n0 = graph.add_node(0);
484 let n1 = graph.add_node(1);
485 let n2 = graph.add_node(2);
486 let n3 = graph.add_node(3);
487 let n4 = graph.add_node(4);
488 let _e0 = graph.add_edge(n0, n1, 10);
489 let _e1 = graph.add_edge(n1, n2, 11);
490 let _e2 = graph.add_edge(n2, n3, 12);
491 let _e3 = graph.add_edge(n3, n4, 13);
492 let _e4 = graph.add_edge(n1, n0, 15);
493 let _e5 = graph.add_edge(n3, n2, 17);
494 let _e6 = graph.add_edge(n4, n3, 18);
495 let _e7 = graph.add_edge(n2, n2, 20);
496 let _e8 = graph.add_edge(n2, n2, 21);
497 let result = decompose_weakly_connected_components_with_mappings(&graph);
498 debug_assert_eq!(result.len(), 1);
499 let (result, node_mapping, edge_mapping) = result.first().unwrap();
500 debug_assert_eq!(result.node_count(), graph.node_count());
501 debug_assert_eq!(result.edge_count(), graph.edge_count());
502
503 let mut node_data: Vec<_> = graph
504 .node_indices()
505 .map(|i| result.node_data(i))
506 .copied()
507 .collect();
508 node_data.sort_unstable();
509 debug_assert_eq!(node_data, vec![0, 1, 2, 3, 4]);
510
511 let mut edge_data: Vec<_> = graph
512 .edge_indices()
513 .map(|i| result.edge_data(i))
514 .copied()
515 .collect();
516 edge_data.sort_unstable();
517 debug_assert_eq!(edge_data, vec![10, 11, 12, 13, 15, 17, 18, 20, 21]);
518
519 for node in result.node_indices() {
520 debug_assert_eq!(
521 result.node_data(node),
522 graph.node_data(node_mapping[node.as_usize()])
523 );
524 }
525
526 for edge in result.edge_indices() {
527 debug_assert_eq!(
528 result.edge_data(edge),
529 graph.edge_data(edge_mapping[edge.as_usize()])
530 );
531 }
532 }
533
534 #[test]
535 fn test_decompose_weakly_connected_components_multiple_wccs() {
536 let mut graph = PetGraph::new();
537 let n0 = graph.add_node(0);
538 let n1 = graph.add_node(1);
539 let n2 = graph.add_node(2);
540 let n3 = graph.add_node(3);
541 let n4 = graph.add_node(4);
542 let n5 = graph.add_node(5);
543 graph.add_edge(n0, n0, 10);
544 graph.add_edge(n1, n2, 11);
545 graph.add_edge(n1, n2, 115);
546 graph.add_edge(n3, n4, 12);
547 graph.add_edge(n4, n5, 13);
548 let result = decompose_weakly_connected_components_with_mappings(&graph);
549 debug_assert_eq!(result.len(), 3);
550 let first = result[2].0.clone();
551 let second = result[1].0.clone();
552 let third = result[0].0.clone();
553 debug_assert_eq!(first.node_count(), 1);
554 debug_assert_eq!(first.edge_count(), 1);
555 debug_assert_eq!(second.node_count(), 2);
556 debug_assert_eq!(second.edge_count(), 2);
557 debug_assert_eq!(third.node_count(), 3);
558 debug_assert_eq!(third.edge_count(), 2);
559
560 debug_assert_eq!(first.node_data(0.into()), &0);
561 debug_assert_eq!(second.node_data(1.into()), &1);
562 debug_assert_eq!(second.node_data(0.into()), &2);
563 debug_assert_eq!(third.node_data(2.into()), &3);
564 debug_assert_eq!(third.node_data(1.into()), &4);
565 debug_assert_eq!(third.node_data(0.into()), &5);
566
567 debug_assert_eq!(first.edge_data(0.into()), &10);
568 debug_assert_eq!(second.edge_data(0.into()), &115);
569 debug_assert_eq!(second.edge_data(1.into()), &11);
570 debug_assert_eq!(third.edge_data(1.into()), &12);
571 debug_assert_eq!(third.edge_data(0.into()), &13);
572
573 for (result, node_mapping, edge_mapping) in &result {
574 for node in result.node_indices() {
575 debug_assert_eq!(
576 result.node_data(node),
577 graph.node_data(node_mapping[node.as_usize()])
578 );
579 }
580
581 for edge in result.edge_indices() {
582 debug_assert_eq!(
583 result.edge_data(edge),
584 graph.edge_data(edge_mapping[edge.as_usize()])
585 );
586 }
587 }
588 }
589
590 #[test]
591 fn test_decompose_weakly_connected_components_empty_graph() {
592 let graph = PetGraph::<(), ()>::new();
593 let result = decompose_weakly_connected_components_with_mappings(&graph);
594 debug_assert_eq!(result.len(), 0);
595 }
596
597 #[test]
598 fn test_decompose_weakly_connected_components_nearly_scc() {
599 let mut graph = PetGraph::new();
600 let n0 = graph.add_node(0);
601 let n1 = graph.add_node(1);
602 let n2 = graph.add_node(2);
603 let n3 = graph.add_node(3);
604 let n4 = graph.add_node(4);
605 let _e0 = graph.add_edge(n0, n1, 10);
606 let _e05 = graph.add_edge(n0, n1, 105);
607 let _e1 = graph.add_edge(n1, n2, 11);
608 let _e2 = graph.add_edge(n2, n3, 12);
609 let _e3 = graph.add_edge(n3, n4, 13);
610 let _e4 = graph.add_edge(n4, n1, 14);
611 let _e5 = graph.add_edge(n1, n4, 15);
612 let _e6 = graph.add_edge(n2, n1, 16);
613 let _e7 = graph.add_edge(n3, n2, 17);
614 let _e8 = graph.add_edge(n4, n3, 18);
615 let _e9 = graph.add_edge(n0, n4, 19);
616 let _e10 = graph.add_edge(n2, n2, 20);
617 let result = decompose_weakly_connected_components_with_mappings(&graph);
618 debug_assert_eq!(result.len(), 1);
619 let (result, node_mapping, edge_mapping) = result.first().unwrap();
620 debug_assert_eq!(result.node_count(), graph.node_count());
621 debug_assert_eq!(result.edge_count(), graph.edge_count());
622
623 let mut node_data: Vec<_> = graph
624 .node_indices()
625 .map(|i| result.node_data(i))
626 .copied()
627 .collect();
628 node_data.sort_unstable();
629 debug_assert_eq!(node_data, vec![0, 1, 2, 3, 4]);
630
631 let mut edge_data: Vec<_> = graph
632 .edge_indices()
633 .map(|i| result.edge_data(i))
634 .copied()
635 .collect();
636 edge_data.sort_unstable();
637 debug_assert_eq!(
638 edge_data,
639 vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 105]
640 );
641
642 for node in result.node_indices() {
643 debug_assert_eq!(
644 result.node_data(node),
645 graph.node_data(node_mapping[node.as_usize()])
646 );
647 }
648
649 for edge in result.edge_indices() {
650 debug_assert_eq!(
651 result.edge_data(edge),
652 graph.edge_data(edge_mapping[edge.as_usize()])
653 );
654 }
655 }
656
657 #[test]
658 fn test_decompose_weakly_connected_components_nearly_scc_reverse() {
659 let mut graph = PetGraph::new();
660 let n0 = graph.add_node(0);
661 let n1 = graph.add_node(1);
662 let n2 = graph.add_node(2);
663 let n3 = graph.add_node(3);
664 let n4 = graph.add_node(4);
665 let _e0 = graph.add_edge(n4, n1, 10);
666 let _e1 = graph.add_edge(n1, n2, 11);
667 let _e2 = graph.add_edge(n2, n3, 12);
668 let _e3 = graph.add_edge(n3, n4, 13);
669 let _e4 = graph.add_edge(n4, n0, 14);
670 let _e5 = graph.add_edge(n1, n0, 15);
671 let _e55 = graph.add_edge(n1, n0, 155);
672 let _e6 = graph.add_edge(n2, n1, 16);
673 let _e7 = graph.add_edge(n3, n2, 17);
674 let _e8 = graph.add_edge(n4, n3, 18);
675 let _e9 = graph.add_edge(n1, n4, 19);
676 let _e10 = graph.add_edge(n2, n2, 20);
677 let result = decompose_weakly_connected_components_with_mappings(&graph);
678 debug_assert_eq!(result.len(), 1);
679 let (result, node_mapping, edge_mapping) = result.first().unwrap();
680 debug_assert_eq!(result.node_count(), graph.node_count());
681 debug_assert_eq!(result.edge_count(), graph.edge_count());
682
683 let mut node_data: Vec<_> = graph
684 .node_indices()
685 .map(|i| result.node_data(i))
686 .copied()
687 .collect();
688 node_data.sort_unstable();
689 debug_assert_eq!(node_data, vec![0, 1, 2, 3, 4]);
690
691 let mut edge_data: Vec<_> = graph
692 .edge_indices()
693 .map(|i| result.edge_data(i))
694 .copied()
695 .collect();
696 edge_data.sort_unstable();
697 debug_assert_eq!(
698 edge_data,
699 vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 155]
700 );
701
702 for node in result.node_indices() {
703 debug_assert_eq!(
704 result.node_data(node),
705 graph.node_data(node_mapping[node.as_usize()])
706 );
707 }
708
709 for edge in result.edge_indices() {
710 debug_assert_eq!(
711 result.edge_data(edge),
712 graph.edge_data(edge_mapping[edge.as_usize()])
713 );
714 }
715 }
716
717 #[test]
718 fn test_scc_check_scc() {
719 let mut graph = PetGraph::new();
720 let n0 = graph.add_node(0);
721 let n1 = graph.add_node(1);
722 let n2 = graph.add_node(2);
723 let n3 = graph.add_node(3);
724 let n4 = graph.add_node(4);
725 graph.add_edge(n0, n1, 10);
726 graph.add_edge(n1, n2, 11);
727 graph.add_edge(n2, n3, 12);
728 graph.add_edge(n3, n4, 13);
729 graph.add_edge(n4, n0, 14);
730 graph.add_edge(n1, n0, 15);
731 graph.add_edge(n1, n0, 155);
732 graph.add_edge(n2, n1, 16);
733 graph.add_edge(n3, n2, 17);
734 graph.add_edge(n4, n3, 18);
735 graph.add_edge(n0, n4, 19);
736 graph.add_edge(n2, n2, 20);
737 debug_assert!(is_strongly_connected(&graph));
738 }
739
740 #[test]
741 fn test_scc_check_one_wc_with_two_sccs() {
742 let mut graph = PetGraph::new();
743 let n0 = graph.add_node(0);
744 let n1 = graph.add_node(1);
745 let n2 = graph.add_node(2);
746 let n3 = graph.add_node(3);
747 let n4 = graph.add_node(4);
748 graph.add_edge(n0, n1, 10);
749 graph.add_edge(n1, n2, 11);
750 graph.add_edge(n2, n3, 12);
751 graph.add_edge(n3, n4, 13);
752 graph.add_edge(n1, n0, 15);
753 graph.add_edge(n1, n0, 155);
754 graph.add_edge(n3, n2, 17);
755 graph.add_edge(n4, n3, 18);
756 graph.add_edge(n2, n2, 20);
757 debug_assert!(!is_strongly_connected(&graph));
758 }
759
760 #[test]
761 fn test_scc_check_multiple_wccs() {
762 let mut graph = PetGraph::new();
763 let n0 = graph.add_node(0);
764 let n1 = graph.add_node(1);
765 let n2 = graph.add_node(2);
766 let n3 = graph.add_node(3);
767 let n4 = graph.add_node(4);
768 let n5 = graph.add_node(5);
769 graph.add_edge(n0, n0, 10);
770 graph.add_edge(n1, n2, 11);
771 graph.add_edge(n2, n1, 13);
772 graph.add_edge(n3, n4, 12);
773 graph.add_edge(n3, n4, 125);
774 graph.add_edge(n4, n5, 13);
775 graph.add_edge(n5, n3, 13);
776 debug_assert!(!is_strongly_connected(&graph));
777 }
778
779 #[test]
780 fn test_scc_check_empty_graph() {
781 let graph = PetGraph::<(), ()>::new();
782 debug_assert!(is_strongly_connected(&graph));
783 }
784
785 #[test]
786 fn test_scc_check_nearly_scc() {
787 let mut graph = PetGraph::new();
788 let n0 = graph.add_node(0);
789 let n1 = graph.add_node(1);
790 let n2 = graph.add_node(2);
791 let n3 = graph.add_node(3);
792 let n4 = graph.add_node(4);
793 graph.add_edge(n0, n1, 10);
794 graph.add_edge(n1, n2, 11);
795 graph.add_edge(n2, n3, 12);
796 graph.add_edge(n3, n4, 13);
797 graph.add_edge(n4, n1, 14);
798 graph.add_edge(n1, n4, 15);
799 graph.add_edge(n1, n4, 155);
800 graph.add_edge(n2, n1, 16);
801 graph.add_edge(n3, n2, 17);
802 graph.add_edge(n4, n3, 18);
803 graph.add_edge(n0, n4, 19);
804 graph.add_edge(n2, n2, 20);
805 debug_assert!(!is_strongly_connected(&graph));
806 }
807
808 #[test]
809 fn test_scc_check_nearly_scc_reverse() {
810 let mut graph = PetGraph::new();
811 let n0 = graph.add_node(0);
812 let n1 = graph.add_node(1);
813 let n2 = graph.add_node(2);
814 let n3 = graph.add_node(3);
815 let n4 = graph.add_node(4);
816 graph.add_edge(n4, n1, 10);
817 graph.add_edge(n1, n2, 11);
818 graph.add_edge(n2, n3, 12);
819 graph.add_edge(n3, n4, 13);
820 graph.add_edge(n4, n0, 14);
821 graph.add_edge(n1, n0, 15);
822 graph.add_edge(n1, n0, 155);
823 graph.add_edge(n2, n1, 16);
824 graph.add_edge(n3, n2, 17);
825 graph.add_edge(n4, n3, 18);
826 graph.add_edge(n1, n4, 19);
827 graph.add_edge(n2, n2, 20);
828 debug_assert!(!is_strongly_connected(&graph));
829 }
830
831 #[test]
834 fn test_decompose_sccs_scc() {
835 let mut graph = PetGraph::new();
836 let n0 = graph.add_node(0);
837 let n1 = graph.add_node(1);
838 let n2 = graph.add_node(2);
839 let n3 = graph.add_node(3);
840 let n4 = graph.add_node(4);
841 graph.add_edge(n0, n1, 10);
842 graph.add_edge(n1, n2, 11);
843 graph.add_edge(n2, n3, 12);
844 graph.add_edge(n3, n4, 13);
845 graph.add_edge(n4, n0, 14);
846 graph.add_edge(n1, n0, 15);
847 graph.add_edge(n1, n0, 155);
848 graph.add_edge(n2, n1, 16);
849 graph.add_edge(n3, n2, 17);
850 graph.add_edge(n4, n3, 18);
851 graph.add_edge(n0, n4, 19);
852 graph.add_edge(n2, n2, 20);
853 debug_assert!(is_strongly_connected(&graph));
854
855 let node_map = decompose_strongly_connected_components(&graph);
856 debug_assert_eq!(node_map, vec![n0; 5]);
857
858 let result = extract_subgraphs_from_node_mapping(&graph, &node_map);
859 debug_assert_eq!(result.len(), 1);
860 let result = result.first().unwrap();
861 debug_assert_eq!(result.node_count(), graph.node_count());
862 debug_assert_eq!(result.edge_count(), graph.edge_count());
863
864 debug_assert_node_data(result, &mut [0, 1, 2, 3, 4]);
865 debug_assert_edge_data(
866 result,
867 &mut [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 155],
868 );
869 }
870
871 #[test]
872 fn test_decompose_sccs_one_wc_with_two_sccs() {
873 let mut graph = PetGraph::new();
874 let n0 = graph.add_node(0);
875 let n1 = graph.add_node(1);
876 let n2 = graph.add_node(2);
877 let n3 = graph.add_node(3);
878 let n4 = graph.add_node(4);
879 graph.add_edge(n0, n1, 10);
880 graph.add_edge(n1, n2, 11);
881 graph.add_edge(n2, n3, 12);
882 graph.add_edge(n3, n4, 13);
883 graph.add_edge(n1, n0, 15);
884 graph.add_edge(n1, n0, 155);
885 graph.add_edge(n3, n2, 17);
886 graph.add_edge(n4, n3, 1);
887 graph.add_edge(n2, n2, 20);
888 debug_assert!(!is_strongly_connected(&graph));
889
890 let node_map = decompose_strongly_connected_components(&graph);
891 debug_assert_eq!(node_map, vec![n0, n0, n2, n2, n2]);
892
893 let result = extract_subgraphs_from_node_mapping(&graph, &node_map);
894 debug_assert_eq!(result.len(), 2);
895 let first = &result[0];
896 let second = &result[1];
897 debug_assert_eq!(first.node_count(), 2);
898 debug_assert_eq!(first.edge_count(), 3);
899 debug_assert_eq!(second.node_count(), 3);
900 debug_assert_eq!(second.edge_count(), 5);
901
902 debug_assert_node_data(first, &mut [0, 1]);
903 debug_assert_edge_data(first, &mut [10, 15, 155]);
904 debug_assert_node_data(second, &mut [2, 3, 4]);
905 debug_assert_edge_data(second, &mut [1, 12, 13, 17, 20]);
906 }
907
908 #[test]
909 fn test_decompose_sccs_multiple_wccs() {
910 let mut graph = PetGraph::new();
911 let n0 = graph.add_node(0);
912 let n1 = graph.add_node(1);
913 let n2 = graph.add_node(2);
914 let n3 = graph.add_node(3);
915 let n4 = graph.add_node(4);
916 let n5 = graph.add_node(5);
917 graph.add_edge(n0, n0, 10);
918 graph.add_edge(n1, n2, 11);
919 graph.add_edge(n2, n1, 13);
920 graph.add_edge(n3, n4, 12);
921 graph.add_edge(n3, n4, 125);
922 graph.add_edge(n4, n5, 13);
923 graph.add_edge(n5, n3, 13);
924 debug_assert!(!is_strongly_connected(&graph));
925
926 let node_map = decompose_strongly_connected_components(&graph);
927 debug_assert_eq!(node_map, vec![n0, n1, n1, n3, n3, n3]);
928
929 let result = extract_subgraphs_from_node_mapping(&graph, &node_map);
930 debug_assert_eq!(result.len(), 3);
931 let first = &result[0];
932 let second = &result[1];
933 let third = &result[2];
934 debug_assert_eq!(first.node_count(), 1);
935 debug_assert_eq!(first.edge_count(), 1);
936 debug_assert_eq!(second.node_count(), 2);
937 debug_assert_eq!(second.edge_count(), 2);
938 debug_assert_eq!(third.node_count(), 3);
939 debug_assert_eq!(third.edge_count(), 4);
940
941 debug_assert_node_data(first, &mut [0]);
942 debug_assert_edge_data(first, &mut [10]);
943 debug_assert_node_data(second, &mut [1, 2]);
944 debug_assert_edge_data(second, &mut [11, 13]);
945 debug_assert_node_data(third, &mut [3, 4, 5]);
946 debug_assert_edge_data(third, &mut [12, 125, 13, 13]);
947 }
948
949 #[test]
950 fn test_decompose_sccs_empty_graph() {
951 let graph = PetGraph::<(), ()>::new();
952 debug_assert!(is_strongly_connected(&graph));
953 let node_map = decompose_strongly_connected_components(&graph);
954 debug_assert_eq!(node_map, vec![]);
955 debug_assert!(extract_subgraphs_from_node_mapping(&graph, &node_map).is_empty());
956 }
957
958 #[test]
959 fn test_decompose_sccs_nearly_scc() {
960 let mut graph = PetGraph::new();
961 let n0 = graph.add_node(0);
962 let n1 = graph.add_node(1);
963 let n2 = graph.add_node(2);
964 let n3 = graph.add_node(3);
965 let n4 = graph.add_node(4);
966 graph.add_edge(n0, n1, 10);
967 graph.add_edge(n1, n2, 11);
968 graph.add_edge(n2, n3, 12);
969 graph.add_edge(n3, n4, 13);
970 graph.add_edge(n4, n1, 14);
971 graph.add_edge(n1, n4, 15);
972 graph.add_edge(n1, n4, 155);
973 graph.add_edge(n2, n1, 16);
974 graph.add_edge(n3, n2, 17);
975 graph.add_edge(n4, n3, 18);
976 graph.add_edge(n0, n4, 19);
977 graph.add_edge(n2, n2, 20);
978 debug_assert!(!is_strongly_connected(&graph));
979
980 let node_map = decompose_strongly_connected_components(&graph);
981 debug_assert_eq!(node_map, vec![n0, n1, n1, n1, n1]);
982
983 let result = extract_subgraphs_from_node_mapping(&graph, &node_map);
984 debug_assert_eq!(result.len(), 2);
985 let first = &result[0];
986 let second = &result[1];
987 debug_assert_eq!(first.node_count(), 1);
988 debug_assert_eq!(first.edge_count(), 0);
989 debug_assert_eq!(second.node_count(), 4);
990 debug_assert_eq!(second.edge_count(), 10);
991
992 debug_assert_node_data(first, &mut [0]);
993 debug_assert_edge_data(first, &mut []);
994 debug_assert_node_data(second, &mut [1, 2, 3, 4]);
995 debug_assert_edge_data(second, &mut [11, 12, 13, 14, 15, 155, 16, 17, 18, 20]);
996 }
997
998 #[test]
999 fn test_decompose_sccs_nearly_scc_reverse() {
1000 let mut graph = PetGraph::new();
1001 let n0 = graph.add_node(0);
1002 let n1 = graph.add_node(1);
1003 let n2 = graph.add_node(2);
1004 let n3 = graph.add_node(3);
1005 let n4 = graph.add_node(4);
1006 graph.add_edge(n4, n1, 10);
1007 graph.add_edge(n1, n2, 11);
1008 graph.add_edge(n2, n3, 12);
1009 graph.add_edge(n3, n4, 13);
1010 graph.add_edge(n4, n0, 14);
1011 graph.add_edge(n1, n0, 15);
1012 graph.add_edge(n1, n0, 155);
1013 graph.add_edge(n2, n1, 16);
1014 graph.add_edge(n3, n2, 17);
1015 graph.add_edge(n4, n3, 18);
1016 graph.add_edge(n1, n4, 19);
1017 graph.add_edge(n2, n2, 20);
1018 debug_assert!(!is_strongly_connected(&graph));
1019
1020 let node_map = decompose_strongly_connected_components(&graph);
1021 debug_assert_eq!(node_map, vec![n0, n1, n1, n1, n1]);
1022
1023 let result = extract_subgraphs_from_node_mapping(&graph, &node_map);
1024 debug_assert_eq!(result.len(), 2);
1025 let first = &result[0];
1026 let second = &result[1];
1027 debug_assert_eq!(first.node_count(), 1);
1028 debug_assert_eq!(first.edge_count(), 0);
1029 debug_assert_eq!(second.node_count(), 4);
1030 debug_assert_eq!(second.edge_count(), 9);
1031
1032 debug_assert_node_data(first, &mut [0]);
1033 debug_assert_edge_data(first, &mut []);
1034 debug_assert_node_data(second, &mut [1, 2, 3, 4]);
1035 debug_assert_edge_data(second, &mut [10, 11, 12, 13, 16, 17, 18, 19, 20]);
1036 }
1037
1038 #[test]
1041 fn test_extract_subgraphs_scc() {
1042 let mut graph = PetGraph::new();
1043 let n0 = graph.add_node(0);
1044 let n1 = graph.add_node(1);
1045 let n2 = graph.add_node(2);
1046 let n3 = graph.add_node(3);
1047 let n4 = graph.add_node(4);
1048 graph.add_edge(n0, n1, 10);
1049 graph.add_edge(n1, n2, 11);
1050 graph.add_edge(n2, n3, 12);
1051 graph.add_edge(n3, n4, 13);
1052 graph.add_edge(n4, n0, 14);
1053 graph.add_edge(n1, n0, 15);
1054 graph.add_edge(n1, n0, 155);
1055 graph.add_edge(n2, n1, 16);
1056 graph.add_edge(n3, n2, 17);
1057 graph.add_edge(n4, n3, 18);
1058 graph.add_edge(n0, n4, 19);
1059 graph.add_edge(n2, n2, 20);
1060 debug_assert!(is_strongly_connected(&graph));
1061 let extracted = extract_subgraphs_from_node_mapping(
1062 &graph,
1063 &decompose_strongly_connected_components(&graph),
1064 );
1065 debug_assert_eq!(1, extracted.len());
1066 debug_assert!(is_strongly_connected(&extracted[0]));
1067 debug_assert_eq!(5, extracted[0].node_count());
1068 debug_assert_eq!(12, extracted[0].edge_count());
1069 }
1070
1071 #[test]
1072 fn test_extract_subgraphs_one_wc_with_two_sccs() {
1073 let mut graph = PetGraph::new();
1074 let n0 = graph.add_node(0);
1075 let n1 = graph.add_node(1);
1076 let n2 = graph.add_node(2);
1077 let n3 = graph.add_node(3);
1078 let n4 = graph.add_node(4);
1079 graph.add_edge(n0, n1, 10);
1080 graph.add_edge(n1, n2, 11);
1081 graph.add_edge(n2, n3, 12);
1082 graph.add_edge(n3, n4, 13);
1083 graph.add_edge(n1, n0, 15);
1084 graph.add_edge(n1, n0, 155);
1085 graph.add_edge(n3, n2, 17);
1086 graph.add_edge(n4, n3, 1);
1087 graph.add_edge(n0, n3, 18);
1088 graph.add_edge(n2, n2, 20);
1089 debug_assert!(!is_strongly_connected(&graph));
1090 let extracted = extract_subgraphs_from_node_mapping(
1091 &graph,
1092 &decompose_strongly_connected_components(&graph),
1093 );
1094 debug_assert_eq!(2, extracted.len());
1095 for (i, graph) in extracted.iter().enumerate() {
1096 debug_assert!(
1097 is_strongly_connected(&extracted[i]),
1098 "Graph {} not strongly connected: {:?}",
1099 i,
1100 graph
1101 );
1102 }
1103
1104 debug_assert_eq!(2, extracted[0].node_count());
1105 debug_assert_eq!(3, extracted[0].edge_count());
1106 debug_assert_eq!(3, extracted[1].node_count());
1107 debug_assert_eq!(5, extracted[1].edge_count());
1108 }
1109
1110 #[test]
1111 fn test_extract_subgraphs_multiple_wccs() {
1112 let mut graph = PetGraph::new();
1113 let n0 = graph.add_node(0);
1114 let n1 = graph.add_node(1);
1115 let n2 = graph.add_node(2);
1116 let n3 = graph.add_node(3);
1117 let n4 = graph.add_node(4);
1118 let n5 = graph.add_node(5);
1119 graph.add_edge(n0, n0, 10);
1120 graph.add_edge(n1, n2, 11);
1121 graph.add_edge(n2, n1, 13);
1122 graph.add_edge(n3, n4, 12);
1123 graph.add_edge(n3, n4, 125);
1124 graph.add_edge(n4, n5, 13);
1125 graph.add_edge(n5, n3, 13);
1126 debug_assert!(!is_strongly_connected(&graph));
1127 let extracted = extract_subgraphs_from_node_mapping(
1128 &graph,
1129 &decompose_strongly_connected_components(&graph),
1130 );
1131 debug_assert_eq!(3, extracted.len());
1132 for (i, graph) in extracted.iter().enumerate() {
1133 debug_assert!(
1134 is_strongly_connected(&extracted[i]),
1135 "Graph {} not strongly connected: {:?}",
1136 i,
1137 graph
1138 );
1139 }
1140
1141 debug_assert_eq!(1, extracted[0].node_count());
1142 debug_assert_eq!(1, extracted[0].edge_count());
1143 debug_assert_eq!(2, extracted[1].node_count());
1144 debug_assert_eq!(2, extracted[1].edge_count());
1145 debug_assert_eq!(3, extracted[2].node_count());
1146 debug_assert_eq!(4, extracted[2].edge_count());
1147 }
1148
1149 #[test]
1150 fn test_extract_subgraphs_empty_graph() {
1151 let graph = PetGraph::<(), ()>::new();
1152 debug_assert!(is_strongly_connected(&graph));
1153 let extracted = extract_subgraphs_from_node_mapping(
1154 &graph,
1155 &decompose_strongly_connected_components(&graph),
1156 );
1157 debug_assert!(extracted.is_empty());
1158 }
1159
1160 #[test]
1161 fn test_extract_subgraphs_nearly_scc() {
1162 let mut graph = PetGraph::new();
1163 let n0 = graph.add_node(0);
1164 let n1 = graph.add_node(1);
1165 let n2 = graph.add_node(2);
1166 let n3 = graph.add_node(3);
1167 let n4 = graph.add_node(4);
1168 graph.add_edge(n0, n1, 10);
1169 graph.add_edge(n1, n2, 11);
1170 graph.add_edge(n2, n3, 12);
1171 graph.add_edge(n3, n4, 13);
1172 graph.add_edge(n4, n1, 14);
1173 graph.add_edge(n1, n4, 15);
1174 graph.add_edge(n1, n4, 155);
1175 graph.add_edge(n2, n1, 16);
1176 graph.add_edge(n3, n2, 17);
1177 graph.add_edge(n4, n3, 18);
1178 graph.add_edge(n0, n4, 19);
1179 graph.add_edge(n2, n2, 20);
1180 debug_assert!(!is_strongly_connected(&graph));
1181 let extracted = extract_subgraphs_from_node_mapping(
1182 &graph,
1183 &decompose_strongly_connected_components(&graph),
1184 );
1185 debug_assert_eq!(2, extracted.len());
1186 for (i, graph) in extracted.iter().enumerate() {
1187 debug_assert!(
1188 is_strongly_connected(&extracted[i]),
1189 "Graph {} not strongly connected: {:?}",
1190 i,
1191 graph
1192 );
1193 }
1194
1195 debug_assert_eq!(1, extracted[0].node_count());
1196 debug_assert_eq!(0, extracted[0].edge_count());
1197 debug_assert_eq!(4, extracted[1].node_count());
1198 debug_assert_eq!(10, extracted[1].edge_count());
1199 }
1200
1201 #[test]
1202 fn test_extract_subgraphs_nearly_scc_reverse() {
1203 let mut graph = PetGraph::new();
1204 let n0 = graph.add_node(0);
1205 let n1 = graph.add_node(1);
1206 let n2 = graph.add_node(2);
1207 let n3 = graph.add_node(3);
1208 let n4 = graph.add_node(4);
1209 graph.add_edge(n4, n1, 10);
1210 graph.add_edge(n1, n2, 11);
1211 graph.add_edge(n2, n3, 12);
1212 graph.add_edge(n3, n4, 13);
1213 graph.add_edge(n4, n0, 14);
1214 graph.add_edge(n1, n0, 15);
1215 graph.add_edge(n1, n0, 155);
1216 graph.add_edge(n2, n1, 16);
1217 graph.add_edge(n3, n2, 17);
1218 graph.add_edge(n4, n3, 18);
1219 graph.add_edge(n1, n4, 19);
1220 graph.add_edge(n2, n2, 20);
1221 debug_assert!(!is_strongly_connected(&graph));
1222 let extracted = extract_subgraphs_from_node_mapping(
1223 &graph,
1224 &decompose_strongly_connected_components(&graph),
1225 );
1226 debug_assert_eq!(2, extracted.len());
1227 for (i, graph) in extracted.iter().enumerate() {
1228 debug_assert!(
1229 is_strongly_connected(&extracted[i]),
1230 "Graph {} not strongly connected: {:?}",
1231 i,
1232 graph
1233 );
1234 }
1235
1236 debug_assert_eq!(1, extracted[0].node_count());
1237 debug_assert_eq!(0, extracted[0].edge_count());
1238 debug_assert_eq!(4, extracted[1].node_count());
1239 debug_assert_eq!(9, extracted[1].edge_count());
1240 }
1241
1242 #[test]
1245 fn test_compute_strong_bridges() {
1246 #![allow(clippy::many_single_char_names)]
1247 let mut graph = PetGraph::new();
1248 let a = graph.add_node("a");
1249 let b = graph.add_node("b");
1250 let c = graph.add_node("c");
1251 let d = graph.add_node("d");
1252 let e = graph.add_node("e");
1253 let f = graph.add_node("f");
1254 let g = graph.add_node("g");
1255 let h = graph.add_node("h");
1256 let i = graph.add_node("i");
1257 let j = graph.add_node("j");
1258 let k = graph.add_node("k");
1259 let l = graph.add_node("l");
1260
1261 let _e0 = graph.add_edge(a, b, ());
1262 let e1 = graph.add_edge(a, f, ());
1263 let e2 = graph.add_edge(b, c, ());
1264 let _e3 = graph.add_edge(c, b, ());
1265 let _e4 = graph.add_edge(c, d, ());
1266 let _e5 = graph.add_edge(c, e, ());
1267 let e6 = graph.add_edge(d, a, ());
1268 let _e7 = graph.add_edge(e, b, ());
1269 let _e8 = graph.add_edge(e, d, ());
1270 let _e9 = graph.add_edge(f, g, ());
1271 let e10 = graph.add_edge(f, h, ());
1272 let e11 = graph.add_edge(g, i, ());
1273 let e12 = graph.add_edge(g, j, ());
1274 let e13 = graph.add_edge(h, g, ());
1275 let e14 = graph.add_edge(i, f, ());
1276 let e15 = graph.add_edge(j, k, ());
1277 let e16 = graph.add_edge(j, l, ());
1278 let e17 = graph.add_edge(k, g, ());
1279 let e18 = graph.add_edge(l, e, ());
1280
1281 let expected = vec![e1, e2, e6, e10, e11, e12, e13, e14, e15, e16, e17, e18];
1282 debug_assert_eq!(expected, naively_compute_strong_bridges(&graph));
1283 }
1284}