pub fn compute_immediate_dominators(&self, root: usize) -> Result<FxHashMap<usize, usize>> {
        if !self.vertices.contains_key(&root) {
            bail!("vertex {} not in graph", root);
        }

        let dfs = self.compute_dfs_tree(root)?;
        let dfs_pre_order = dfs.compute_pre_order(root)?;

        let dfs_parent = |vertex| dfs.predecessors[&vertex].iter().next().cloned();

        // DFS-numbering and reverse numbering (starting from 0 instead of 1 as in the paper)
        let dfs_number: FxHashMap<usize, usize> = dfs_pre_order
            .iter()
            .enumerate()
            .map(|(number, vertex)| (*vertex, number))
            .collect();
        let graph_number = &dfs_pre_order;

        let mut ancestor: FxHashMap<usize, Option<usize>> = FxHashMap::default();
        let mut label: FxHashMap<usize, usize> = FxHashMap::default();
        for &vertex in self.vertices.keys() {
            ancestor.insert(vertex, None);
            label.insert(vertex, dfs_number[&vertex]);
        }

        // Compute semidominators in reverse preorder (without root)
        let mut semi = FxHashMap::default();
        for &vertex in dfs_pre_order.iter().skip(1).rev() {
            let mut min_semi = std::usize::MAX;

            for &pred in &self.predecessors[&vertex] {
                if ancestor[&pred].is_some() {
                    compress(&mut ancestor, &mut label, pred);
                }
                min_semi = cmp::min(min_semi, label[&pred]);
            }

            semi.insert(vertex, min_semi);
            label.insert(vertex, min_semi);

            ancestor.insert(vertex, dfs_parent(vertex));
        }
        let semi = semi;

        fn compress(
            ancestor: &mut FxHashMap<usize, Option<usize>>,
            label: &mut FxHashMap<usize, usize>,
            v: usize,
        ) {
            let u = ancestor[&v].unwrap();
            if ancestor[&u].is_some() {
                compress(ancestor, label, u);
                if label[&u] < label[&v] {
                    label.insert(v, label[&u]);
                }
                ancestor.insert(v, ancestor[&u]);
            }
        }

        // Compute immediate dominators in preorder (without root)
        let mut idoms = FxHashMap::default();
        for &vertex in dfs_pre_order.iter().skip(1) {
            let mut idom = dfs_number[&dfs_parent(vertex).unwrap()];
            while idom > semi[&vertex] {
                idom = idoms[&idom];
            }
            idoms.insert(dfs_number[&vertex], idom);
        }
        let idoms = idoms;

        // Translate idoms from DFS-numbering back to graph indices
        let mut graph_idoms = FxHashMap::default();
        for (vertex, idom) in idoms {
            graph_idoms.insert(graph_number[vertex], graph_number[idom]);
        }
        Ok(graph_idoms)
    }
/// Computes immediate dominators for all vertices in the graph
///
/// This implementation is based on the Semi-NCA algorithm described in:
/// Georgiadis, Loukas: Linear-Time Algorithms for Dominators and Related Problems (thesis)
/// <https://www.cs.princeton.edu/research/techreps/TR-737-05>
Computes immediate dominators for all vertices in the graph
This implementation is based on the Semi-NCA algorithm described in:
Georgiadis, Loukas: Linear-Time Algorithms for Dominators and Related Problems (thesis)
Computes immediate dominators for all vertices in the graph This implementation is based on the Semi - NCA algorithm described in : Georgiadis Loukas : Linear - Time Algorithms for Dominators and Related Problems ( thesis )
pub fn compute_immediate_dominators(&self, root: usize) -> Result<FxHashMap<usize, usize>> {
        if !self.vertices.contains_key(&root) {
            bail!("vertex {} not in graph", root);
        }
        let dfs = self.compute_dfs_tree(root)?;
        let dfs_pre_order = dfs.compute_pre_order(root)?;
        let dfs_parent = |vertex| dfs.predecessors[&vertex].iter().next().cloned();
        // DFS-numbering and reverse numbering (starting from 0 instead of 1 as in the paper)
        let dfs_number: FxHashMap<usize, usize> = dfs_pre_order
            .iter()
            .enumerate()
            .map(|(number, vertex)| (*vertex, number))
            .collect();
        let graph_number = &dfs_pre_order;
        let mut ancestor: FxHashMap<usize, Option<usize>> = FxHashMap::default();
        let mut label: FxHashMap<usize, usize> = FxHashMap::default();
        for &vertex in self.vertices.keys() {
            ancestor.insert(vertex, None);
            label.insert(vertex, dfs_number[&vertex]);
        }
        // Compute semidominators in reverse preorder (without root)
        let mut semi = FxHashMap::default();
        for &vertex in dfs_pre_order.iter().skip(1).rev() {
            let mut min_semi = std::usize::MAX;
            for &pred in &self.predecessors[&vertex] {
                if ancestor[&pred].is_some() {
                    compress(&mut ancestor, &mut label, pred);
                }
                min_semi = cmp::min(min_semi, label[&pred]);
            }
            semi.insert(vertex, min_semi);
            label.insert(vertex, min_semi);
            ancestor.insert(vertex, dfs_parent(vertex));
        }
        let semi = semi;
        fn compress(
            ancestor: &mut FxHashMap<usize, Option<usize>>,
            label: &mut FxHashMap<usize, usize>,
            v: usize,
        ) {
            let u = ancestor[&v].unwrap();
            if ancestor[&u].is_some() {
                compress(ancestor, label, u);
                if label[&u] < label[&v] {
                    label.insert(v, label[&u]);
                }
                ancestor.insert(v, ancestor[&u]);
            }
        }
        // Compute immediate dominators in preorder (without root)
        let mut idoms = FxHashMap::default();
        for &vertex in dfs_pre_order.iter().skip(1) {
            let mut idom = dfs_number[&dfs_parent(vertex).unwrap()];
            while idom > semi[&vertex] {
                idom = idoms[&idom];
            }
            idoms.insert(dfs_number[&vertex], idom);
        }
        let idoms = idoms;
        // Translate idoms from DFS-numbering back to graph indices
        let mut graph_idoms = FxHashMap::default();
        for (vertex, idom) in idoms {
            graph_idoms.insert(graph_number[vertex], graph_number[idom]);
        }
        Ok(graph_idoms)
    }
pub fn compute_immediate_dominators ( & self , root : usize ) -> Result < FxHashMap < usize , usize > > { if ! self . vertices . contains_key ( & root ) { bail ! ( " " root ) ; } let dfs = self . compute_dfs_tree ( root ) ? ; let dfs_pre_order = dfs . compute_pre_order ( root ) ? ; let dfs_parent = | vertex | dfs . predecessors [ & vertex ] . iter ( ) . next ( ) . cloned ( ) ; // DFS-numbering and reverse numbering (starting from 0 instead of 1 as in the paper) let dfs_number : FxHashMap < usize , usize > = dfs_pre_order . iter ( ) . enumerate ( ) . map ( | ( number , vertex ) | ( * vertex , number ) ) . collect ( ) ; let graph_number = & dfs_pre_order ; let mut ancestor : FxHashMap < usize , Option < usize > > = FxHashMap :: default ( ) ; let mut label : FxHashMap < usize , usize > = FxHashMap :: default ( ) ; for & vertex in self . vertices . keys ( ) { ancestor . insert ( vertex , None ) ; label . insert ( vertex , dfs_number [ & vertex ] ) ; } // Compute semidominators in reverse preorder (without root) let mut semi = FxHashMap :: default ( ) ; for & vertex in dfs_pre_order . iter ( ) . skip ( 1 ) . rev ( ) { let mut min_semi = std :: usize :: MAX ; for & pred in & self . predecessors [ & vertex ] { if ancestor [ & pred ] . is_some ( ) { compress ( & mut ancestor , & mut label , pred ) ; } min_semi = cmp :: min ( min_semi , label [ & pred ] ) ; } semi . insert ( vertex , min_semi ) ; label . insert ( vertex , min_semi ) ; ancestor . insert ( vertex , dfs_parent ( vertex ) ) ; } let semi = semi ; fn compress ( ancestor : & mut FxHashMap < usize , Option < usize > > , label : & mut FxHashMap < usize , usize > , v : usize , ) { let u = ancestor [ & v ] . unwrap ( ) ; if ancestor [ & u ] . is_some ( ) { compress ( ancestor , label , u ) ; if label [ & u ] < label [ & v ] { label . insert ( v , label [ & u ] ) ; } ancestor . insert ( v , ancestor [ & u ] ) ; } } // Compute immediate dominators in preorder (without root) let mut idoms = FxHashMap :: default ( ) ; for & vertex in dfs_pre_order . iter ( ) . skip ( 1 ) { let mut idom = dfs_number [ & dfs_parent ( vertex ) . unwrap ( ) ] ; while idom > semi [ & vertex ] { idom = idoms [ & idom ] ; } idoms . insert ( dfs_number [ & vertex ] , idom ) ; } let idoms = idoms ; // Translate idoms from DFS-numbering back to graph indices let mut graph_idoms = FxHashMap :: default ( ) ; for ( vertex , idom ) in idoms { graph_idoms . insert ( graph_number [ vertex ] , graph_number [ idom ] ) ; } Ok ( graph_idoms ) }
Computes immediate dominators for all vertices in the graph
This implementation is based on the Semi-NCA algorithm described in:
Georgiadis, Loukas: Linear-Time Algorithms for Dominators and Related Problems (thesis)
<https://www.cs.princeton.edu/research/techreps/TR-737-05>
Computes immediate dominators for all vertices in the graph This implementation is based on the Semi - NCA algorithm described in : Georgiadis Loukas : Linear - Time Algorithms for Dominators and Related Problems ( thesis ) <https : // www . cs . princeton . edu / research / techreps / TR - 737 - 05 >
&self
root
usize
&self
root
usize