rapx/analysis/graphs/
scc.rs1use rustc_data_structures::fx::FxHashSet;
2use std::cmp;
3
4#[derive(Debug, Clone, Eq, Hash, PartialEq)]
5pub struct SccExit {
6 pub exit: usize,
7 pub to: usize,
8}
9
10impl SccExit {
11 pub fn new(exit: usize, to: usize) -> Self {
12 SccExit { exit, to }
13 }
14}
15
16#[derive(Debug, Clone)]
17pub struct SccInfo {
18 pub enter: usize, pub nodes: FxHashSet<usize>, pub exits: FxHashSet<SccExit>, pub backnodes: FxHashSet<usize>, }
23
24impl SccInfo {
25 pub fn new(enter: usize) -> Self {
26 SccInfo {
27 enter,
28 nodes: FxHashSet::default(),
29 exits: FxHashSet::default(),
30 backnodes: FxHashSet::default(),
31 }
32 }
33}
34
35pub trait Scc {
36 fn find_scc(&mut self) {
37 let mut stack = Vec::new();
38 let mut instack = FxHashSet::<usize>::default(); let mut dfn = vec![0; self.get_size()];
40 let mut low = vec![0; self.get_size()];
41 let mut time = 0;
42 self.tarjan(0, &mut stack, &mut instack, &mut dfn, &mut low, &mut time);
43 }
44
45 fn on_scc_found(&mut self, root: usize, scc_components: &[usize]); fn get_next(&mut self, root: usize) -> FxHashSet<usize>; fn get_size(&mut self) -> usize; fn tarjan(
50 &mut self,
51 index: usize,
52 stack: &mut Vec<usize>,
53 instack: &mut FxHashSet<usize>,
54 dfn: &mut Vec<usize>,
55 low: &mut Vec<usize>,
56 time: &mut usize,
57 ) {
58 dfn[index] = *time;
59 low[index] = *time;
60 *time += 1;
61 stack.push(index);
62 instack.insert(index);
63 let nexts = self.get_next(index);
64 for next in nexts {
65 if dfn[next] == 0 {
66 self.tarjan(next, stack, instack, dfn, low, time);
67 low[index] = cmp::min(low[index], low[next]);
68 } else if instack.contains(&next) {
69 low[index] = cmp::min(low[index], dfn[next]);
70 }
71 }
72 if dfn[index] == low[index] {
73 let mut component = vec![index];
74 while let Some(top) = stack.pop() {
75 instack.remove(&top);
76 if top == index {
77 break;
78 }
79 component.push(top);
80 }
81 self.on_scc_found(index, &component);
82 }
83 }
84}
85
86#[derive(Debug)]
87pub struct SccTree {
88 pub scc: SccInfo,
89 pub children: Vec<SccTree>,
90}