Exemple #1
0
 def add_node_attrs_rhs(self, n, attrs):
     """Add attrs to a node in the rhs."""
     if n not in self.rhs.nodes():
         raise RuleError(
             "Node %s does not exist in the right "
             "hand side of the rule" % n)
     primitives.add_node_attrs(self.rhs, n, attrs)
Exemple #2
0
def relation_to_span(g1,
                     g2,
                     relation,
                     edges=False,
                     attrs=False,
                     directed=True):
    """Convert a relation to a span."""
    if directed:
        new_graph = nx.DiGraph()
    else:
        new_graph = nx.Graph()
    left_h = dict()
    right_h = dict()

    for a, b in relation:
        new_node = str(a) + "_" + str(b)
        new_graph.add_node(new_node)
        if attrs:
            common_attrs = attrs_intersection(g1.node[a], g2.node[b])
            add_node_attrs(new_graph, new_node, common_attrs)
        left_h[new_node] = a
        right_h[new_node] = b

    for n1 in new_graph.nodes():
        for n2 in new_graph.nodes():
            if (left_h[n1], left_h[n2]) in g1.edges() and\
               (right_h[n1], right_h[n2]) in g2.edges():
                new_graph.add_edge(n1, n2)
                common_attrs = attrs_intersection(
                    g1.edge[left_h[n1]][left_h[n2]],
                    g2.edge[right_h[n1]][right_h[n2]],
                )
                add_edge_attrs(new_graph, n1, n2, common_attrs)

    return (new_graph, left_h, right_h)
Exemple #3
0
 def _add_node_attrs_lhs(self, n, attrs):
     if n not in self.lhs.nodes():
         raise RuleError(
             "Node '%s' does not exist in the lhs "
             "of the rule" % n)
     primitives.add_node_attrs(self.lhs, n, attrs)
     p_nodes = keys_by_value(self.p_rhs, n)
     for p_node in p_nodes:
         primitives.add_node_attrs(self.p, p_node, attrs)
Exemple #4
0
def _propagate_values(hie, id, parent, mapping):
    anc = hie.get_ancestors(parent)
    graph = hie.node[id].graph
    parent_gr = hie.node[parent].graph
    for (anc_id, anc_typ) in anc.items():
        anc_gr = hie.node[anc_id].graph
        for node in mapping:
            if mapping[node] in anc_typ:
                prim.add_node_attrs(anc_gr, anc_typ[mapping[node]],
                                    graph.node[node])
    for node in mapping:
        prim.add_node_attrs(parent_gr, mapping[node], graph.node[node])
Exemple #5
0
def _propagate_values(hie, id, parent, mapping):
    anc = hie.get_ancestors(parent)
    graph = hie.node[id].graph
    parent_gr = hie.node[parent].graph
    for (anc_id, anc_typ) in anc.items():
        anc_gr = hie.node[anc_id].graph
        for node in mapping:
            if mapping[node] in anc_typ:
                prim.add_node_attrs(anc_gr, anc_typ[mapping[node]],
                                    graph.node[node])
    for node in mapping:
        prim.add_node_attrs(parent_gr, mapping[node],
                            graph.node[node])
Exemple #6
0
 def add_node_attrs(self, n, attrs):
     """Add node attributes to a node in the graph."""
     if n not in self.lhs.nodes():
         raise RuleError(
             "Node '%s' does not exist in the left "
             "hand side of the rule" % n)
     p_keys = keys_by_value(self.p_lhs, n)
     if len(p_keys) == 0:
         raise RuleError(
             "Node '%s' is being removed by the rule, "
             "cannot add attributes" % n)
     for k in p_keys:
         primitives.add_node_attrs(self.rhs, self.p_rhs[k], attrs)
     return
Exemple #7
0
def pushout_from_relation(g1, g2, relation, inplace=False):
    """Find the pushout from a relation."""

    left_dict = left_relation_dict(relation)
    right_dict = right_relation_dict(relation)

    if inplace is True:
        g12 = g1
    else:
        g12 = copy.deepcopy(g1)

    g1_g12 = id_of(g12.nodes())
    g2_g12 = dict()

    for node in g1.nodes():
        if node in left_dict.keys():
            for g2_node in left_dict[node]:
                g2_g12[g2_node] = node

    for node in g2.nodes():
        if node not in right_dict.keys():
            add_node(g12, node, g2.node[node])
            g2_g12[node] = node
        elif len(right_dict[node]) == 1:
            node_attrs_diff = dict_sub(
                g2.node[node],
                g1.node[list(right_dict[node])[0]])
            add_node_attrs(
                g12, list(right_dict[node])[0], node_attrs_diff)
        elif len(right_dict[node]) > 1:
            new_name = merge_nodes(g12, right_dict[node])
            for g1_node in right_dict[node]:
                g1_g12[g1_node] = new_name
            g2_g12[node] = new_name
            node_attrs_diff = dict_sub(
                g2.node[node],
                g12.node[new_name])
            add_node_attrs(g12, new_name, node_attrs_diff)

    for u, v in g2.edges():
        if (g2_g12[u], g2_g12[v]) not in g12.edges():
            add_edge(g12, g2_g12[u], g2_g12[v], get_edge(g2, u, v))
        else:
            edge_attrs_diff = dict_sub(
                g2.edge[u][v],
                g12.edge[g2_g12[u]][g2_g12[v]])
            add_edge_attrs(g12, g2_g12[u], g2_g12[v], edge_attrs_diff)
    return (g12, g1_g12, g2_g12)
Exemple #8
0
def remove_attributes(hie, g_id, parent, node, json_attrs):
    """remove the attributes from json_attrs from the node"""
    attrs = prim.json_dict_to_attrs(json_attrs)
    if isinstance(hie.node[g_id], GraphNode):
        lhs = nx.DiGraph()
        lhs.add_node(node)
        add_node_attrs(lhs, node, attrs)
        ppp = nx.DiGraph()
        ppp.add_node(node)
        rhs = nx.DiGraph()
        rhs.add_node(node)
        rule = Rule(ppp, lhs, rhs)
        _rewrite(hie, g_id, rule, {node: node})
    elif isinstance(hie.node[g_id], RuleNode):
        hie.node[g_id].rule.remove_node_attrs_rhs(node, attrs)
    else:
        raise ValueError("node is neither a rule nor a graph")
Exemple #9
0
def add_attributes(hie, g_id, parent, node, json_attrs):
    """add the attributes from the json_attrs dict to a node"""
    attrs = prim.json_dict_to_attrs(json_attrs)
    if isinstance(hie.node[g_id], GraphNode):
        for typing in hie.successors(g_id):
            mapping = hie.edge[g_id][typing].mapping
            if node in mapping:
                parent_attrs = hie.node[typing].graph.node[mapping[node]]
                if not valid_attributes(attrs, parent_attrs):
                    raise ValueError("Attributes not in node {} of {}".format(
                        mapping[node], typing))
        prim.add_node_attrs(hie.node[g_id].graph, node, attrs)

    elif isinstance(hie.node[g_id], RuleNode):
        hie.node[g_id].rule.add_node_attrs_rhs(node, attrs)
    else:
        raise ValueError("node is neither a rule nor a graph")
Exemple #10
0
def remove_attributes(hie, g_id, parent, node, json_attrs):
    """remove the attributes from json_attrs from the node"""
    attrs = prim.json_dict_to_attrs(json_attrs)
    if isinstance(hie.node[g_id], GraphNode):
        lhs = nx.DiGraph()
        lhs.add_node(node)
        add_node_attrs(lhs, node, attrs)
        ppp = nx.DiGraph()
        ppp.add_node(node)
        rhs = nx.DiGraph()
        rhs.add_node(node)
        rule = Rule(ppp, lhs, rhs)
        _rewrite(hie, g_id, rule, {node: node})
    elif isinstance(hie.node[g_id], RuleNode):
        hie.node[g_id].rule.remove_node_attrs_rhs(node, attrs)
    else:
        raise ValueError("node is neither a rule nor a graph")
Exemple #11
0
def add_attributes(hie, g_id, parent, node, json_attrs):
    """add the attributes from the json_attrs dict to a node"""
    attrs = prim.json_dict_to_attrs(json_attrs)
    if isinstance(hie.node[g_id], GraphNode):
        for typing in hie.successors(g_id):
            mapping = hie.edge[g_id][typing].mapping
            if node in mapping:
                parent_attrs = hie.node[typing].graph.node[mapping[node]]
                if not valid_attributes(attrs, parent_attrs):
                    raise ValueError("Attributes not in node {} of {}"
                                     .format(mapping[node], typing))
        prim.add_node_attrs(hie.node[g_id].graph, node, attrs)

    elif isinstance(hie.node[g_id], RuleNode):
        hie.node[g_id].rule.add_node_attrs_rhs(node, attrs)
    else:
        raise ValueError("node is neither a rule nor a graph")
Exemple #12
0
    def inject_add_node_attrs(self, n, attrs):
        """Inject addition of  node attributes by the rule.

        First, tries to find a node with the id `n` in the
        left-hand side, injects its attrs add to all the `rhs` nodes
        related to it through l<-p->r, if found,
        otherwise, tries to find the corresponding node in
        the preserved part and adds attrs to the node to which `n`
        maps in p->r, if it is not found in `p`, tries to find it in
        the `rhs` (it helps us to implement injection
        of the node attrs add to only one of the clone nodes, or to new nodes,
        or to merged nodes).

        Parameters
        ----------
        n1 : hashable
            Id of an edge's source node in `lhs`, `p` or `rhs`.
        n2 : hashable
            Id of an edge's target node in `lhs`, `p` or `rhs`.
        attrs : dict
            Dictionary with attrs to add

        Raises
        ------
        RuleError
            If node `n` does not exist in the rhs of the rule

        """
        if n not in self.lhs.nodes() + self.p.nodes() + self.rhs.nodes():
            raise RuleError(
                "Node '%s' exists in neither lhs, nor p, nor rhs of the rule" %
                n)
        r_nodes = set()
        if n in self.lhs.nodes():
            p_keys = keys_by_value(self.p_lhs, n)
            for p in p_keys:
                r_nodes.add(self.p_rhs[p])
        elif n in self.p.nodes():
            r_nodes.add(self.p_rhs[n])
        elif n in self.rhs.nodes():
            r_nodes.add(n)
        for r in r_nodes:
            primitives.add_node_attrs(self.rhs, r, attrs)
        return
Exemple #13
0
def pushout_from_relation(g1, g2, relation, inplace=False):
    """Find the pushout from a relation."""

    left_dict = left_relation_dict(relation)
    right_dict = right_relation_dict(relation)

    if inplace is True:
        g12 = g1
    else:
        g12 = copy.deepcopy(g1)

    g1_g12 = id_of(g12.nodes())
    g2_g12 = dict()

    for node in g1.nodes():
        if node in left_dict.keys():
            for g2_node in left_dict[node]:
                g2_g12[g2_node] = node

    for node in g2.nodes():
        if node not in right_dict.keys():
            add_node(g12, node, g2.node[node])
            g2_g12[node] = node
        elif len(right_dict[node]) == 1:
            node_attrs_diff = dict_sub(g2.node[node],
                                       g1.node[list(right_dict[node])[0]])
            add_node_attrs(g12, list(right_dict[node])[0], node_attrs_diff)
        elif len(right_dict[node]) > 1:
            new_name = merge_nodes(g12, right_dict[node])
            for g1_node in right_dict[node]:
                g1_g12[g1_node] = new_name
            g2_g12[node] = new_name
            node_attrs_diff = dict_sub(g2.node[node], g12.node[new_name])
            add_node_attrs(g12, new_name, node_attrs_diff)

    for u, v in g2.edges():
        if (g2_g12[u], g2_g12[v]) not in g12.edges():
            add_edge(g12, g2_g12[u], g2_g12[v], get_edge(g2, u, v))
        else:
            edge_attrs_diff = dict_sub(g2.edge[u][v],
                                       g12.edge[g2_g12[u]][g2_g12[v]])
            add_edge_attrs(g12, g2_g12[u], g2_g12[v], edge_attrs_diff)
    return (g12, g1_g12, g2_g12)
Exemple #14
0
def relation_to_span(g1, g2, relation, edges=False, attrs=False, directed=True):
        """Convert a relation to a span."""
        if directed:
            new_graph = nx.DiGraph()
        else:
            new_graph = nx.Graph()
        left_h = dict()
        right_h = dict()

        for a, b in relation:
            new_node = str(a) + "_" + str(b)
            new_graph.add_node(new_node)
            if attrs:
                common_attrs = attrs_intersection(
                    g1.node[a],
                    g2.node[b]
                )
                add_node_attrs(new_graph, new_node, common_attrs)
            left_h[new_node] = a
            right_h[new_node] = b

        for n1 in new_graph.nodes():
            for n2 in new_graph.nodes():
                if (left_h[n1], left_h[n2]) in g1.edges() and\
                   (right_h[n1], right_h[n2]) in g2.edges():
                    new_graph.add_edge(n1, n2)
                    common_attrs = attrs_intersection(
                        g1.edge[left_h[n1]][left_h[n2]],
                        g2.edge[right_h[n1]][right_h[n2]],
                    )
                    add_edge_attrs(
                        new_graph,
                        n1, n2,
                        common_attrs
                    )

        return (new_graph, left_h, right_h)
Exemple #15
0
def pushout(a, b, c, a_b, a_c, inplace=False):
    """Find the pushour of the span b <- a -> c."""
    check_homomorphism(a, b, a_b)
    check_homomorphism(a, c, a_c)

    if inplace is True:
        d = b
    else:
        d = copy.deepcopy(b)

    b_d = id_of(b.nodes())
    c_d = dict()

    # Add/merge nodes
    for c_n in c.nodes():
        a_keys = keys_by_value(a_c, c_n)
        # Add nodes
        if len(a_keys) == 0:
            add_node(d, c_n, c.node[c_n])
            c_d[c_n] = c_n
        # Keep nodes
        elif len(a_keys) == 1:
            c_d[a_c[a_keys[0]]] = a_b[a_keys[0]]
        # Merge nodes
        else:
            nodes_to_merge = []
            for k in a_keys:
                nodes_to_merge.append(a_b[k])
            new_name = merge_nodes(d, nodes_to_merge)
            c_d[c_n] = new_name
            for node in nodes_to_merge:
                b_d[node] = new_name

    # Add edges
    for (n1, n2) in c.edges():
        if b.is_directed():
            if (c_d[n1], c_d[n2]) not in d.edges():
                add_edge(
                    d, c_d[n1], c_d[n2],
                    get_edge(c, n1, n2))
        else:
            if (c_d[n1], c_d[n2]) not in d.edges() and\
               (c_d[n2], c_d[n1]) not in d.edges():
                add_edge(
                    d, c_d[n1], c_d[n2],
                    get_edge(c, n1, n2)
                )

    # Add node attrs
    for c_n in c.nodes():
        a_keys = keys_by_value(a_c, c_n)
        # Add attributes to the nodes which stayed invariant
        if len(a_keys) == 1:
            attrs_to_add = dict_sub(
                c.node[c_n],
                a.node[a_keys[0]]
            )
            add_node_attrs(d, c_d[c_n], attrs_to_add)
        # Add attributes to the nodes which were merged
        elif len(a_keys) > 1:
            merged_attrs = {}
            for k in a_keys:
                merged_attrs = merge_attributes(
                    merged_attrs,
                    a.node[k]
                )
            attrs_to_add = dict_sub(c.node[c_n], merged_attrs)
            add_node_attrs(d, c_d[c_n], attrs_to_add)

    # Add edge attrs
    for (n1, n2) in c.edges():
        d_n1 = c_d[n1]
        d_n2 = c_d[n2]
        if d.is_directed():
            attrs_to_add = dict_sub(
                get_edge(c, n1, n2),
                get_edge(d, d_n1, d_n2)
            )
            add_edge_attrs(
                d, c_d[n1], c_d[n2],
                attrs_to_add
            )
        else:
            attrs_to_add = dict_sub(
                get_edge(c, n1, n2),
                get_edge(d, d_n1, d_n2)
            )
            add_edge_attrs(
                d, c_d[n1], c_d[n2],
                attrs_to_add
            )
    return (d, b_d, c_d)
Exemple #16
0
def pushout(a, b, c, a_b, a_c, inplace=False):
    """Find the pushour of the span b <- a -> c."""
    check_homomorphism(a, b, a_b)
    check_homomorphism(a, c, a_c)

    if inplace is True:
        d = b
    else:
        d = copy.deepcopy(b)

    b_d = id_of(b.nodes())
    c_d = dict()

    # Add/merge nodes
    for c_n in c.nodes():
        a_keys = keys_by_value(a_c, c_n)
        # Add nodes
        if len(a_keys) == 0:
            add_node(d, c_n, c.node[c_n])
            c_d[c_n] = c_n
        # Keep nodes
        elif len(a_keys) == 1:
            c_d[a_c[a_keys[0]]] = a_b[a_keys[0]]
        # Merge nodes
        else:
            nodes_to_merge = []
            for k in a_keys:
                nodes_to_merge.append(a_b[k])
            new_name = merge_nodes(d, nodes_to_merge)
            c_d[c_n] = new_name
            for node in nodes_to_merge:
                b_d[node] = new_name

    # Add edges
    for (n1, n2) in c.edges():
        if b.is_directed():
            if (c_d[n1], c_d[n2]) not in d.edges():
                add_edge(d, c_d[n1], c_d[n2], get_edge(c, n1, n2))
        else:
            if (c_d[n1], c_d[n2]) not in d.edges() and\
               (c_d[n2], c_d[n1]) not in d.edges():
                add_edge(d, c_d[n1], c_d[n2], get_edge(c, n1, n2))

    # Add node attrs
    for c_n in c.nodes():
        a_keys = keys_by_value(a_c, c_n)
        # Add attributes to the nodes which stayed invariant
        if len(a_keys) == 1:
            attrs_to_add = dict_sub(c.node[c_n], a.node[a_keys[0]])
            add_node_attrs(d, c_d[c_n], attrs_to_add)
        # Add attributes to the nodes which were merged
        elif len(a_keys) > 1:
            merged_attrs = {}
            for k in a_keys:
                merged_attrs = merge_attributes(merged_attrs, a.node[k])
            attrs_to_add = dict_sub(c.node[c_n], merged_attrs)
            add_node_attrs(d, c_d[c_n], attrs_to_add)

    # Add edge attrs
    for (n1, n2) in c.edges():
        d_n1 = c_d[n1]
        d_n2 = c_d[n2]
        if d.is_directed():
            attrs_to_add = dict_sub(get_edge(c, n1, n2),
                                    get_edge(d, d_n1, d_n2))
            add_edge_attrs(d, c_d[n1], c_d[n2], attrs_to_add)
        else:
            attrs_to_add = dict_sub(get_edge(c, n1, n2),
                                    get_edge(d, d_n1, d_n2))
            add_edge_attrs(d, c_d[n1], c_d[n2], attrs_to_add)
    return (d, b_d, c_d)