graphlang 0.1.3

Terminal and graphical tool to create and explore graph grammars.
Documentation

/*
fn match_ullman_update_possible_assignments<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    possibilities: &mut Vec<Vec<bool>>,
) {
    let mut changes = true;
    while changes {
        changes = false;
        for i in 0..subgraph.nodes.len() {
            for j in possibilities[i] {
                for x in subgraph.adjancencies(i) {
                    let mut found_match = false;
                    for y in 0..graph.nodes.len() {
                        if possibilities[x].contains(y) && graph.contains_edge_with_ids((j, y)) {
                            found_match = true;
                            // TODO: break;
                        }
                    }
                    if !found_match {
                        possibilities[i].remove(j);
                        changes = true;
                    }
                }
            }
        }
    }
}

fn match_ullman_step<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    m: &mut Isomorphism<I>,
    possibilities: &mut Vec<Vec<bool>>,
) -> bool {
    match_ullman_update_possible_assignments(&graph, &subgraph, &mut possibilities);
    let assignments = &mut m.0;
    let i =assignments.len();

    // Make sure that every edge between assigned vertices in the subgraph is also an
    // edge in the graph.
    // TODO: Remove?
    //for e in &subgraph.edges {
    //    if e.from < i && e.to < i {
    //        if not graph.has_edge(assignments[edge.first],assignments[edge.second]) {
    //            return False;
    //        }
    //    }
    //}

    // If all the vertices in the subgraph are assigned, then we are done.
    if i == subgraph.nodes.len() {
        return true;
    }

    for j in &possibilities[i] {
        if !assignments.contains_key(j) { // TODO: Check j or y ?
            assignments.push(j);

            // Create a new set of possible assignments, where graph node j is the only
            // possibility for the assignment of subgraph node i.
            let mut new_possible_assignments = possibilities.clone();
            new_possible_assignments[i] = vec![*j]; 

            //    if search(graph,subgraph,assignments,new_possible_assignments):
            if match_ullman_step(graph, subgraph, &mut m, &mut new_possible_assignments) {
                return true;
            }
            assignments.pop();
        }
        possible_assignments[i].remove(j);
        update_possible_assignments(graph,subgraph,possible_assignments)
    }
    false
}

fn match_ullman<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
) -> Option<Isomorphism<I>> {
    let mut m = Isomorphism::default();
    let mut possibilities = Vec::with_capacity(subgraph.nodes.len());
    for row in &mut possibilities {
        *row = Vec::with_capacity(graph.nodes.len());
        for e in row {
            *e = true;
        }
    }
    if match_ullman_step(graph, subgraph, &mut m, &mut possibilities) {
        Some(m)
    } else {
        None
    }
}

// Calc pair candidates
fn pair_candidates<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    m: &Isomorphism<I>,
) -> Vec<(I, I)> {
    let _ = graph;
    let _ = subgraph;
    let _ = m;
    unimplemented!()
}

//
// true  - it is guaranteed that the state s' obtained by addind (a,b) to s
//         is a partial isomorphism if s is
// false - otherwise
fn feasability<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    m: &Isomorphism<I>,
    a: &I,
    b: &I,
) -> bool {
    // Check if b is connected to something in graph ?
    let _ = graph;
    // Check if a is connected to something in subgraph ?
    let _ = subgraph;
    // Check if (a,b) does not collide with another mapping in graph or subgraph
    for (k, v) in &m.0 {
        if k == a {
            return false;
        }
        if v == b {
            return false;
        }
    }
    true
    // TODO: Other checks?
    //let _ = graph;
    //let _ = subgraph;
    //let _ = m;
    //let _ = a;
    //let _ = b;
    //unimplemented!()
}

/// PROCEDURE Match(s)
/// INPUT: an intermediate state s; the initial state s0 has M(s0)=∅
/// OUTPUT: the mappings between the two graphs
fn match_vf2<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    m: &Isomorphism<I>,
) -> Option<Isomorphism<I>> {
    // Paper:
    //  s = (G1,G2,m) ?
    //  m  ... m Isomorphism
    //  G1 = (N1, B1) ... subgraph
    //  G2 = (N2, B2) ... graph
    let mut m = m.clone();
    // IF M(s) covers all the nodes of G2 THEN
    if m.contains_nodes(&subgraph.nodes) {
        // OUTPUT M(s)
        return Some(m);
    } else {
        // Compute the set P(s) of the pairs candidate for inclusion in M(s)
        let p: Vec<(_, _)> = pair_candidates(graph, subgraph, &m);
        for (a, b) in p {
            if feasability(graph, subgraph, &m, &a, &b) {
                // Compute the state s ́ obtained by adding (a, b) to M(s)
                m.0.insert(a, b);
                // CALL Match(s′)
                return match_vf2(graph, subgraph, &m);
            }
        }
        // Restore data structures
        //unimplemented!();
    }
    None
}

#[test]
fn full_graph_isomorphism() {
    let m = Graph {
        nodes: vec![Node::new(0u32, "a"), Node::new(1, "a"), Node::new(2, "a")],
        edges: vec![Edge::new_unlabeled(0, 1), Edge::new_unlabeled(1, 2)],
    };
    let n = Graph {
        nodes: vec![Node::new(0u32, "a"), Node::new(1, "a"), Node::new(2, "a")],
        edges: vec![Edge::new_unlabeled(0, 1), Edge::new_unlabeled(0, 2)],
    };

    let o = match_subgraph(&m, &n);
    let r = {
        let mut r = HashMap::new();
        r.insert(0, 2);
        r.insert(1, 1);
        r.insert(2, 3);
        Isomorphism(r)
    };
    assert_eq!(o, Some(r));
}

/// Currently utilizes VF2: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.101.5342&rep=rep1&type=pdf
pub fn match_subgraph<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
) -> Option<Isomorphism<I>> {
    match_vf2(graph, subgraph, &Isomorphism::default())
}
*/

fn match_custom_step<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
    m: &mut Isomorphism<I>,
    possibilities: &mut Vec<(I,I)>) -> bool {
    unimplemented!()
}

fn match_custom<I: Index, NL: Label, EL: Label>(
    graph: &Graph<I, NL, EL>,
    subgraph: &Graph<I, NL, EL>,
) -> Option<Isomorphism<I>> {
    let mut m = Isomorphism::default();
    let mut possibilities = Vec::with_capacity(subgraph.nodes.len());
    for row in &mut possibilities {
        *row = Vec::with_capacity(graph.nodes.len());
        for e in row {
            *e = true;
        }
    }
    if match_custom_step(graph, subgraph, &mut m, &mut possibilities) {
        Some(m)
    } else {
        None
    }
}