traitgraph_algo/
components.rs

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
12/// Returns the weakly connected components of a graph.
13///
14/// If the graph is empty, no WCCs are returned.
15/// Otherwise, the WCCs are cloned into new graphs, without preserving the node or edge indices.
16pub 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/// Returns the weakly connected components of a graph.
30///
31/// Also returns a mapping from node indices in the WCCs to node indices in the source graph,
32/// and a mapping from edge indices in the WCCs to edge indices in the source graph.
33///
34/// If the graph is empty, no WCCs are returned.
35/// Otherwise, the WCCs are cloned into new graphs, without preserving the node or edge indices.
36#[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            //println!("add_node: {:?}", node);
67            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                        //println!("f: ({:?}, {:?}) becomes ({:?}, {:?})", node, neighbor_id, subnode, subneighbor);
84                        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                // Handle self loops only once in the forward case.
93                // Otherwise, two identical versions of the loop would be added to the subgraph.
94                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                        //println!("r: ({:?}, {:?}) becomes ({:?}, {:?})", neighbor_id, node, subneighbor, subnode);
110                        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
123/// Returns true if the graph is strongly connected.
124pub 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
160/// Returns true if the given edge is a strong bridge.
161/// Note that this function assumes that the graph is strongly connected, and always returns true otherwise.
162pub 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
197/// Compute the strong bridges of the graph with a naive O(m^2) algorithm.
198/// Note that this function assumes that the graph is strongly connected, and returns all edges otherwise.
199pub 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
206/// Returns the strongly connected components of a graph.
207///
208/// If the graph is empty, no SCCs are returned.
209/// Otherwise, an array is returned that maps each node to a root node representing its SCC.
210/// Node that if the node ids are not consecutive, this mapping is still returned as consecutive array.
211pub 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    // 0 will be overridden with the first reset.
218    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    //println!("nodes: {:?}", nodes);
232
233    let mut bfs = PreOrderBackwardBfs::new_without_start(graph);
234    for root_node in nodes {
235        if visited[root_node.as_usize()] {
236            //println!("Reverse processing {:?}", root_node);
237            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    //println!("result: {:?}", result);
252    result
253}
254
255/// Returns the strongly connected components of a graph whose indices are non-consecutive.
256///
257/// If the graph is empty, no SCCs are returned.
258/// Otherwise, an array is returned that maps each node to a root node representing its SCC.
259pub 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    // 0 will be overridden with the first reset.
270    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    //println!("nodes: {:?}", nodes);
284
285    let mut bfs = PreOrderBackwardBfs::new_without_start(graph);
286    for root_node in nodes {
287        if visited.contains(&root_node) {
288            //println!("Reverse processing {:?}", root_node);
289            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    //println!("result: {:?}", result);
304    result
305}
306
307/// Extract the subgraphs of the given graph according to the given node_mapping.
308///
309/// The node indices of the graph are assumed to match the indices of the vector given as node mapping.
310/// The return value is a vector of graphs of which each is the induced subgraph of a set of nodes with the same mapped value.
311pub 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    // invert node mapping in linear time
320    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    // extract subgraphs
334    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
370/// Returns true if the given graph is a cycle.
371pub 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    /////////////////////////////////////////////////////////
832
833    #[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    /////////////////////////////////////////////////////////
1039
1040    #[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    /////////////////////////////////////////////////////////
1243
1244    #[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}