pub fn match_graphs<'a>(d1: &'a DiffGraph<'_>, d2: &'a DiffGraph<'_>) -> Vec<Match<'a>> {
    let mut mapping: BTreeMap<&str, &str> = get_initial_mapping(d1, d2);

    let mut matches: Vec<Match> = mapping
        .iter()
        .map(|(from, to)| Match::Full(Matching { from, to }))
        .collect();

    // we use rev adjacency list because we are going to compare the parents
    let rev_adj_list1 = d1.graph.rev_adj_list();
    let rev_adj_list2 = d2.graph.rev_adj_list();

    let mut matched_labels_in_2: HashSet<&str> = mapping.iter().map(|(_, v)| *v).collect();

    let mut prev_mapping = mapping.clone();
    loop {
        let mut new_mapping: Mapping = BTreeMap::new();
        for (k, v) in prev_mapping.iter() {
            let parents_in_1 = rev_adj_list1.get(k).unwrap();
            let parents_in_2 = rev_adj_list2.get(v).unwrap();

            for n in parents_in_1.iter() {
                // don't bother selecting if the node in 1 is already matched
                // as we use a stricter selection for the initial matching
                if mapping.contains_key(n) {
                    continue;
                }
                if let Some(lab) = select(d1, d2, n, &parents_in_2, false) {
                    // if the matched label is already matched to some node in 1, skip
                    if !matched_labels_in_2.contains(lab) {
                        matched_labels_in_2.insert(lab);
                        new_mapping.insert(n, lab);
                    }
                }
            }
        }
        // println!("{:?}", new_mapping);
        // merge
        let new_matches = get_new_matches(&mapping, &new_mapping);
        if new_matches.len() == 0 {
            break;
        }
        for mch in new_matches {
            mapping.insert(mch.from, mch.to);
            matches.push(Match::Partial(mch));
        }
        prev_mapping = new_mapping;
    }

    matches
}
/// Matches both graphs and returns the mapping of nodes from g1 to g2.
///
/// A 'matching' (or match) is a mapping from a graph 1 node to a graph 2 node.
///
/// The list of matches returned by this function is a one to one mapping from graph 1
/// nodes to graph 2 nodes.
///
/// ## Explanation of the algorithm
///
/// 1. Find initial list of matches, Mi: n1i -> n2i
/// 2. If there a parent (say p) of any matched node (say x) in graph 1 is not matched
///     1. L = Find the parents of the node that is matched with x (parents(Mi(x)))
///     2. y = Find the node that most closely matches p in L
///     3. Add y to the matches, Mi(x) = y
/// 3. Iterate until there are no more matches to be found
///
/// The initial matching is called Full matching. The subsequent matches are called partial
/// matches.
Matches both graphs and returns the mapping of nodes from g1 to g2.
A 'matching' (or match) is a mapping from a graph 1 node to a graph 2 node.

The list of matches returned by this function is a one to one mapping from graph 1
nodes to graph 2 nodes.
Matches both graphs and returns the mapping of nodes from g1 to g2 . A ' matching ' ( or match ) is a mapping from a graph 1 node to a graph 2 node . The list of matches returned by this function is a one to one mapping from graph 1 nodes to graph 2 nodes .
pub fn match_graphs<'a>(d1: &'a DiffGraph<'_>, d2: &'a DiffGraph<'_>) -> Vec<Match<'a>> {
    let mut mapping: BTreeMap<&str, &str> = get_initial_mapping(d1, d2);
    let mut matches: Vec<Match> = mapping
        .iter()
        .map(|(from, to)| Match::Full(Matching { from, to }))
        .collect();
    // we use rev adjacency list because we are going to compare the parents
    let rev_adj_list1 = d1.graph.rev_adj_list();
    let rev_adj_list2 = d2.graph.rev_adj_list();
    let mut matched_labels_in_2: HashSet<&str> = mapping.iter().map(|(_, v)| *v).collect();
    let mut prev_mapping = mapping.clone();
    loop {
        let mut new_mapping: Mapping = BTreeMap::new();
        for (k, v) in prev_mapping.iter() {
            let parents_in_1 = rev_adj_list1.get(k).unwrap();
            let parents_in_2 = rev_adj_list2.get(v).unwrap();
            for n in parents_in_1.iter() {
                // don't bother selecting if the node in 1 is already matched
                // as we use a stricter selection for the initial matching
                if mapping.contains_key(n) {
                    continue;
                }
                if let Some(lab) = select(d1, d2, n, &parents_in_2, false) {
                    // if the matched label is already matched to some node in 1, skip
                    if !matched_labels_in_2.contains(lab) {
                        matched_labels_in_2.insert(lab);
                        new_mapping.insert(n, lab);
                    }
                }
            }
        }
        // println!("{:?}", new_mapping);
        // merge
        let new_matches = get_new_matches(&mapping, &new_mapping);
        if new_matches.len() == 0 {
            break;
        }
        for mch in new_matches {
            mapping.insert(mch.from, mch.to);
            matches.push(Match::Partial(mch));
        }
        prev_mapping = new_mapping;
    }
    matches
}
pub fn match_graphs < ' a > ( d1 : & ' a DiffGraph < ' _ > , d2 : & ' a DiffGraph < ' _ > ) -> Vec < Match < ' a > > { let mut mapping : BTreeMap < & str , & str > = get_initial_mapping ( d1 , d2 ) ; let mut matches : Vec < Match > = mapping . iter ( ) . map ( | ( from , to ) | Match :: Full ( Matching { from , to } ) ) . collect ( ) ; // we use rev adjacency list because we are going to compare the parents let rev_adj_list1 = d1 . graph . rev_adj_list ( ) ; let rev_adj_list2 = d2 . graph . rev_adj_list ( ) ; let mut matched_labels_in_2 : HashSet < & str > = mapping . iter ( ) . map ( | ( _ , v ) | * v ) . collect ( ) ; let mut prev_mapping = mapping . clone ( ) ; loop { let mut new_mapping : Mapping = BTreeMap :: new ( ) ; for ( k , v ) in prev_mapping . iter ( ) { let parents_in_1 = rev_adj_list1 . get ( k ) . unwrap ( ) ; let parents_in_2 = rev_adj_list2 . get ( v ) . unwrap ( ) ; for n in parents_in_1 . iter ( ) { // don't bother selecting if the node in 1 is already matched // as we use a stricter selection for the initial matching if mapping . contains_key ( n ) { continue ; } if let Some ( lab ) = select ( d1 , d2 , n , & parents_in_2 , false ) { // if the matched label is already matched to some node in 1, skip if ! matched_labels_in_2 . contains ( lab ) { matched_labels_in_2 . insert ( lab ) ; new_mapping . insert ( n , lab ) ; } } } } // println!("{:?}", new_mapping); // merge let new_matches = get_new_matches ( & mapping , & new_mapping ) ; if new_matches . len ( ) == 0 { break ; } for mch in new_matches { mapping . insert ( mch . from , mch . to ) ; matches . push ( Match :: Partial ( mch ) ) ; } prev_mapping = new_mapping ; } matches }
Matches both graphs and returns the mapping of nodes from g1 to g2.
Matches both graphs and returns the mapping of nodes from g1 to g2 .
d1
&'a DiffGraph<'_>
d2
&'a DiffGraph<'_>
d1
&'a DiffGraph<'_>
d2
&'a DiffGraph<'_>
explanation of the algorithm
1. Find initial list of matches, Mi: n1i -> n2i
2. If there a parent (say p) of any matched node (say x) in graph 1 is not matched
1. L = Find the parents of the node that is matched with x (parents(Mi(x)))
2. y = Find the node that most closely matches p in L
3. Add y to the matches, Mi(x) = y
3. Iterate until there are no more matches to be found

The initial matching is called Full matching. The subsequent matches are called partial
matches.
1 . Find initial list of matches Mi : n1i - > n2i 2 . If there a parent ( say p ) of any matched node ( say x ) in graph 1 is not matched 1 . L = Find the parents of the node that is matched with x ( parents ( Mi ( x ))) 2 . y = Find the node that most closely matches p in L 3 . Add y to the matches Mi ( x ) = y 3 . Iterate until there are no more matches to be found The initial matching is called Full matching . The subsequent matches are called partial matches .