Ejemplo n.º 1
0
    def test_pushout_symmetry_directed(self):

        A = nx.DiGraph()
        A.add_nodes_from(["a", "b"])
        A.add_edges_from([("a", "b")])

        B = nx.DiGraph()
        B.add_nodes_from([1, 2, 3])
        B.add_edges_from([(2, 3), (3, 2), (1, 3)])

        C = nx.DiGraph()
        C.add_nodes_from(["x", "y"])
        C.add_edges_from([("x", "x"), ("x", "y")])

        homAB = {"a": 2, "b": 3}
        homAC = {"a": "x", "b": "x"}

        D, homBD, homCD = pushout(
            A, B, C, homAB, homAC
        )
        D_inv, homCD_inv, homBD_inv = pushout(
            A, C, B, homAC, homAB
        )
        assert_equals(len(D.nodes()), len(D_inv.nodes()))
        assert_equals(len(D.edges()), len(D_inv.edges()))
Ejemplo n.º 2
0
    def test_pushout(self):
        D, homBD, homCD = pushout(self.A, self.B, self.C, self.homAB,
                                  self.homAC)
        assert_equals(type(D), nx.DiGraph)

        assert_equals(len(D.nodes()), len(self.D.nodes()))

        assert_equals(len(D.edges()), len(self.D.edges()))
        assert (id(self.B) != id(D))
Ejemplo n.º 3
0
    def test_pushout(self):
        D, homBD, homCD = pushout(
            self.A, self.B, self.C, self.homAB, self.homAC
        )
        assert_equals(type(D), nx.DiGraph)

        assert_equals(len(D.nodes()),
                      len(self.D.nodes()))

        assert_equals(len(D.edges()),
                      len(self.D.edges()))
        assert(id(self.B) != id(D))
Ejemplo n.º 4
0
    def test_pushout_symmetry_directed(self):

        A = nx.DiGraph()
        A.add_nodes_from(["a", "b"])
        A.add_edges_from([("a", "b")])

        B = nx.DiGraph()
        B.add_nodes_from([1, 2, 3])
        B.add_edges_from([(2, 3), (3, 2), (1, 3)])

        C = nx.DiGraph()
        C.add_nodes_from(["x", "y"])
        C.add_edges_from([("x", "x"), ("x", "y")])

        homAB = {"a": 2, "b": 3}
        homAC = {"a": "x", "b": "x"}

        D, homBD, homCD = pushout(A, B, C, homAB, homAC)
        D_inv, homCD_inv, homBD_inv = pushout(A, C, B, homAC, homAB)
        assert_equals(len(D.nodes()), len(D_inv.nodes()))
        assert_equals(len(D.edges()), len(D_inv.edges()))
Ejemplo n.º 5
0
    def test_pushout_inplace(self):
        B_copy = copy.deepcopy(self.B)
        D, homBD, homCD = pushout(
            self.A, B_copy, self.C, self.homAB, self.homAC, inplace=True
        )
        assert_equals(type(D), nx.DiGraph)

        assert_equals(len(D.nodes()),
                      len(self.D.nodes()))

        assert_equals(len(D.edges()),
                      len(self.D.edges()))
        assert(id(B_copy) == id(D))
Ejemplo n.º 6
0
    def test_pushout_inplace(self):
        B_copy = copy.deepcopy(self.B)
        D, homBD, homCD = pushout(self.A,
                                  B_copy,
                                  self.C,
                                  self.homAB,
                                  self.homAC,
                                  inplace=True)
        assert_equals(type(D), nx.DiGraph)

        assert_equals(len(D.nodes()), len(self.D.nodes()))

        assert_equals(len(D.edges()), len(self.D.edges()))
        assert (id(B_copy) == id(D))
Ejemplo n.º 7
0
def _get_rule_projections(hierarchy,
                          origin_id,
                          rule,
                          instance,
                          rhs_typing=None,
                          ignore=None):
    if ignore is None:
        ignore = []
    if rhs_typing is None:
        rhs_typing = {}
    projections = {}
    if rule.is_relaxing():
        for graph, origin_typing in hierarchy.get_descendants(
                origin_id).items():
            if graph not in ignore:
                if hierarchy.is_graph(graph):
                    # Compute canonical P_T
                    l_t, l_l_t, l_t_t = image_factorization(
                        rule.lhs, hierarchy.get_graph(graph),
                        compose(instance, origin_typing))

                    # Compute canonical R_T
                    r_t, l_t_r_t, r_r_t = pushout(rule.p, l_t, rule.rhs, l_l_t,
                                                  rule.p_rhs)

                    # Modify P_T and R_T according to the controlling
                    # relation rhs_typing
                    if graph in rhs_typing.keys():
                        r_t_factorization = {
                            r_r_t[k]: v
                            for k, v in rhs_typing[graph].items()
                        }
                        added_t_nodes = set()
                        for n in r_t.nodes():
                            if n in r_t_factorization.keys():
                                # If corresponding R_T node is specified in
                                # the controlling relation add nodes of T
                                # that type it to P
                                t_nodes = r_t_factorization[n]
                                for t_node in t_nodes:
                                    if t_node not in l_t_t.values() and\
                                       t_node not in added_t_nodes:
                                        new_p_node = primitives.generate_new_node_id(
                                            l_t, t_node)
                                        primitives.add_node(l_t, new_p_node)
                                        added_t_nodes.add(t_node)
                                        l_t_r_t[new_p_node] = n
                                        l_t_t[new_p_node] = t_node
                                    else:
                                        l_t_r_t[keys_by_value(l_t_t,
                                                              t_node)[0]] = n

                    projections[graph] = {
                        "rule": Rule(lhs=l_t, p=l_t, rhs=r_t, p_rhs=l_t_r_t),
                        "instance": l_t_t,
                        "l_l_t": l_l_t,
                        "p_p_t": {k: l_l_t[v]
                                  for k, v in rule.p_lhs.items()},
                        "r_r_t": r_r_t
                    }

    return projections
Ejemplo n.º 8
0
def _rewrite_base(hierarchy,
                  graph_id,
                  rule,
                  instance,
                  rhs_typing,
                  inplace=False):
    g_m, p_g_m, g_m_g =\
        pullback_complement(rule.p, rule.lhs, hierarchy.get_graph(graph_id),
                            rule.p_lhs, instance, inplace)

    g_prime, g_m_g_prime, r_g_prime = pushout(rule.p, g_m, rule.rhs, p_g_m,
                                              rule.p_rhs, inplace)

    relation_updates = []
    for related_g in hierarchy.adjacent_relations(graph_id):
        relation_updates.append((graph_id, related_g))

    updated_homomorphisms = dict()

    for typing_graph in hierarchy.successors(graph_id):

        new_hom = copy.deepcopy(
            hierarchy.adj[graph_id][typing_graph]["mapping"])
        removed_nodes = set()
        new_nodes = dict()

        for node in rule.lhs.nodes():
            p_keys = keys_by_value(rule.p_lhs, node)
            # nodes that were removed
            if len(p_keys) == 0:
                removed_nodes.add(instance[node])
            elif len(p_keys) == 1:
                if typing_graph not in rhs_typing.keys() or\
                   rule.p_rhs[p_keys[0]] not in rhs_typing[typing_graph].keys():
                    if r_g_prime[rule.p_rhs[p_keys[0]]] in new_hom.keys():
                        removed_nodes.add(r_g_prime[rule.p_rhs[p_keys[0]]])
            # nodes were clonned
            elif len(p_keys) > 1:
                for k in p_keys:
                    if typing_graph in rhs_typing.keys() and\
                       rule.p_rhs[k] in rhs_typing[typing_graph].keys():
                        new_nodes[r_g_prime[rule.p_rhs[k]]] =\
                            list(rhs_typing[typing_graph][rule.p_rhs[k]])[0]
                    else:
                        removed_nodes.add(r_g_prime[rule.p_rhs[k]])

        for node in rule.rhs.nodes():
            p_keys = keys_by_value(rule.p_rhs, node)

            # nodes that were added
            if len(p_keys) == 0:
                if typing_graph in rhs_typing.keys():
                    if node in rhs_typing[typing_graph].keys():
                        new_nodes[node] = list(
                            rhs_typing[typing_graph][node])[0]

            # nodes that were merged
            elif len(p_keys) > 1:
                for k in p_keys:
                    removed_nodes.add(p_g_m[k])
                # assign new type of node
                if typing_graph in rhs_typing.keys():
                    if node in rhs_typing[typing_graph].keys():
                        new_type = list(rhs_typing[typing_graph][node])
                        new_nodes[r_g_prime[node]] = new_type

        # update homomorphisms
        for n in removed_nodes:
            if n in new_hom.keys():
                del new_hom[n]

        new_hom.update(new_nodes)

        updated_homomorphisms.update({(graph_id, typing_graph): new_hom})

    return {
        "graph": (g_m, p_g_m, g_m_g, g_prime, g_m_g_prime, r_g_prime),
        "homomorphisms": updated_homomorphisms,
        "relations": relation_updates
    }
Ejemplo n.º 9
0
def get_rule_projections(tx, hierarchy, graph_id, rule, instance, rhs_typing=None):
    """Execute the query finding rule liftings."""
    if rhs_typing is None:
        rhs_typing = {}

    projections = {}

    if rule.is_relaxing():
        if len(rule.lhs.nodes()) > 0:
            lhs_instance = {
                n: instance[n] for n in rule.lhs.nodes()
            }
            lhs_vars = {
                n: n for n in rule.lhs.nodes()}
            match_instance_vars = {
                v: lhs_instance[k] for k, v in lhs_vars.items()
            }

            # Match nodes
            query = "// Match nodes the instance of the rewritten graph \n"
            query += "MATCH {}".format(
                ", ".join([
                    "({}:{} {{id: '{}'}})".format(k, graph_id, v)
                    for k, v in match_instance_vars.items()
                ])
            )
            query += "\n\n"

            carry_vars = list(lhs_vars.values())
            for k, v in lhs_vars.items():
                query += (
                    "OPTIONAL MATCH (n)<-[:typing*1..]-({})\n".format(v) +
                    "WITH {} \n".format(
                        ", ".join(
                            carry_vars +
                            ["collect(DISTINCT {{type:'node', origin: {}.id, id: n.id, graph:labels(n)[0], attrs: properties(n)}}) as {}_dict\n".format(
                                v, v)])
                    )
                )
                carry_vars.append("{}_dict".format(v))

            # Match edges
            for (u, v) in rule.p.edges():
                edge_var = "{}_{}".format(lhs_vars[u], lhs_vars[v])
                query += "OPTIONAL MATCH ({}_instance)-[{}:edge]->({}_instance)\n".format(
                    lhs_vars[u],
                    edge_var,
                    lhs_vars[v])
                query += "WHERE ({})<-[:typing*1..]-({}) AND ({})<-[:typing*1..]-({})\n".format(
                    "{}_instance".format(lhs_vars[u]), lhs_vars[u],
                    "{}_instance".format(lhs_vars[v]), lhs_vars[v])
                query += (
                    "WITH {} \n".format(
                        ", ".join(carry_vars + [
                            "collect({{type: 'edge', source: {}.id, target: {}.id, graph:labels({})[0], attrs: properties({})}}) as {}\n".format(
                                "{}_instance".format(lhs_vars[u]),
                                "{}_instance".format(lhs_vars[v]),
                                "{}_instance".format(lhs_vars[u]),
                                edge_var,
                                edge_var)
                        ])
                    )
                )
                carry_vars.append(edge_var)
            query += "RETURN {}".format(
                ", ".join(
                    ["{}_dict as {}".format(v, v) for v in lhs_vars.values()] +
                    ["{}_{}".format(lhs_vars[u], lhs_vars[v]) for u, v in rule.p.edges()]))

            result = tx.run(query)
            record = result.single()

            l_l_ts = {}
            l_nodes = {}
            l_edges = {}
            for k, v in record.items():
                if len(v) > 0:
                    if v[0]["type"] == "node":
                        for el in v:
                            l_node = keys_by_value(instance, el["origin"])[0]
                            if el["graph"] not in l_nodes:
                                l_nodes[el["graph"]] = {}
                                l_l_ts[el["graph"]] = {}
                            if el["id"] not in l_nodes[el["graph"]]:
                                l_nodes[el["graph"]][el["id"]] = {}
                            l_nodes[el["graph"]][el["id"]] = attrs_union(
                                l_nodes[el["graph"]][el["id"]],
                                attrs_intersection(
                                    generic.convert_props_to_attrs(el["attrs"]),
                                    get_node(rule.lhs, l_node)))
                            l_l_ts[el["graph"]][l_node] = el["id"]
                    else:
                        for el in v:
                            l_sources = keys_by_value(l_l_ts[el["graph"]], el["source"])
                            l_targets = keys_by_value(l_l_ts[el["graph"]], el["target"])

                            for l_source in l_sources:
                                for l_target in l_targets:
                                    if exists_edge(rule.l, l_source, l_target):
                                        if el["graph"] not in l_edges:
                                            l_edges[el["graph"]] = {}
                                        if (el["source"], el["target"]) not in l_edges[el["graph"]]:
                                            l_edges[el["graph"]][(el["source"], el["target"])] = {}
                                        l_edges[el["graph"]][(el["source"], el["target"])] =\
                                            attrs_union(
                                                l_edges[el["graph"]][(el["source"], el["target"])],
                                                attrs_intersection(
                                                    generic.convert_props_to_attrs(el["attrs"]),
                                                    get_edge(rule.lhs, l_source, l_target)))

        for graph, typing in hierarchy.get_descendants(graph_id).items():
            if graph in l_nodes:
                nodes = l_nodes[graph]
            else:
                nodes = {}
            if graph in l_edges:
                edges = l_edges[graph]
            else:
                edges = {}

            l = nx.DiGraph()
            add_nodes_from(l, [(k, v) for k, v in nodes.items()])
            if graph in l_edges:
                add_edges_from(
                    l,
                    [(s, t, v) for (s, t), v in edges.items()])

            rhs, p_rhs, r_r_t = pushout(
                rule.p, l, rule.rhs, compose(rule.p_lhs, l_l_ts[graph]), rule.p_rhs)

            l_t_t = {n: n for n in nodes}

            # Modify P_T and R_T according to the controlling
            # relation rhs_typing
            if graph in rhs_typing.keys():
                r_t_factorization = {
                    r_r_t[k]: v
                    for k, v in rhs_typing[graph].items()
                }
                added_t_nodes = set()
                for n in rhs.nodes():
                    if n in r_t_factorization.keys():
                        # If corresponding R_T node is specified in
                        # the controlling relation add nodes of T
                        # that type it to P
                        t_nodes = r_t_factorization[n]
                        for t_node in t_nodes:
                            if t_node not in l_t_t.values() and\
                               t_node not in added_t_nodes:
                                new_p_node = generate_new_id(
                                    l.nodes(), t_node)
                                l.add_node(new_p_node)
                                added_t_nodes.add(t_node)
                                p_rhs[new_p_node] = n
                                l_t_t[new_p_node] = t_node
                            else:
                                p_rhs[keys_by_value(l_t_t, t_node)[0]] = n

            projections[graph] = {
                "rule": Rule(p=l, rhs=rhs, p_rhs=p_rhs),
                "instance": l_t_t,
                "l_l_t": l_l_ts[graph],
                "p_p_t": {k: l_l_ts[graph][v] for k, v in rule.p_lhs.items()},
                "r_r_t": r_r_t
            }

    return projections