Esempio n. 1
0
    def inject_remove_node(self, lhs_node_id):
        """Inject a new node removal to the rule.

        This method removes from `p` all the nodes that map
        to the node with the id `lhs_node_id`. In addition,
        all the nodes from `rhs` that are mapped by the nodes
        removed in `p` are also removed.

        Parameters
        ----------
        lhs_node_id
            Id of the node in `lhs` that should be removed
            by the rule.
        """
        # remove corresponding nodes from p and rhs
        p_keys = keys_by_value(self.p_lhs, lhs_node_id)
        for k in p_keys:
            if k in self.p.nodes():
                primitives.remove_node(self.p, k)
            if self.p_rhs[k] in self.rhs.nodes():
                primitives.remove_node(self.rhs, self.p_rhs[k])
                affected_nodes = keys_by_value(self.p_rhs, self.p_rhs[k])
                for node in affected_nodes:
                    del self.p_rhs[node]
            del self.p_lhs[k]
        return
Esempio n. 2
0
    def added_edge_attrs(self):
        """Get edge attributes added by the rule.

        Returns
        -------
        attrs : dict
            Dictionary where keys are edges from `rhs`
            and values are attribute dictionaries to add.
        """
        attrs = dict()
        for s, t in self.rhs.edges():
            s_p_nodes = keys_by_value(self.p_rhs, s)
            t_p_nodes = keys_by_value(self.p_rhs, t)
            new_attrs = {}
            for s_p_node in s_p_nodes:
                for t_p_node in t_p_nodes:
                    if (s_p_node, t_p_node) in self.p.edges():
                        new_attrs = attrs_union(
                            new_attrs,
                            dict_sub(
                                self.rhs.edge[s][t],
                                self.p.edge[s_p_node][t_p_node]
                            )
                        )
        return attrs
Esempio n. 3
0
 def _remove_edge_rhs(self, node1, node2):
     """Remove edge from the rhs of the graph."""
     primitives.remove_edge(self.rhs, node1, node2)
     for pn1 in keys_by_value(self.p_rhs, node1):
         for pn2 in keys_by_value(self.p_rhs, node2):
             if (pn1, pn2) in self.p.edges():
                 primitives.remove_edge(self.p, pn1, pn2)
Esempio n. 4
0
    def merge_nodes(self, n1, n2, node_id=None):
        """Merge two nodes of the graph."""
        # Update graphs
        new_name = None
        p_keys_1 = keys_by_value(self.p_lhs, n1)
        p_keys_2 = keys_by_value(self.p_lhs, n2)

        nodes_to_merge = set()
        for k1 in p_keys_1:
            if k1 not in self.p.nodes():
                raise RuleError(
                    "Node with the id '%s' does not exist in the "
                    "preserved part of the rule" % k1
                )
            for k2 in p_keys_2:
                if k2 not in self.p.nodes():
                    raise RuleError(
                        "Node with the id '%s' does not exist in "
                        "the preserved part of the rule" % k2
                    )
                nodes_to_merge.add(self.p_rhs[k1])
                nodes_to_merge.add(self.p_rhs[k2])
        new_name = primitives.merge_nodes(
            self.rhs,
            list(nodes_to_merge),
            node_id=node_id
        )
        # Update mappings
        keys = p_keys_1 + p_keys_2
        for k in keys:
            self.p_rhs[k] = new_name
        return new_name
Esempio n. 5
0
    def removed_edge_attrs(self):
        """Get edge attributes removed by the rule.

        Returns
        -------
        attrs : dict
            Dictionary where keys are edges from `lhs`
            and values are attribute dictionaries to remove.
        """
        attrs = dict()
        for s, t in self.lhs.edges():
            s_p_nodes = keys_by_value(self.p_lhs, s)
            t_p_nodes = keys_by_value(self.p_lhs, t)
            new_attrs = {}
            for s_p_node in s_p_nodes:
                for t_p_node in t_p_nodes:
                    if (s_p_node, t_p_node) in self.p.edges():
                        new_attrs = attrs_union(
                            new_attrs,
                            dict_sub(
                                self.lhs.edge[s][t],
                                self.p.edge[s_p_node][t_p_node]
                            )
                        )
            if len(new_attrs) > 0:
                attrs[(s, t)] = new_attrs
        return attrs
Esempio n. 6
0
def get_unique_map_to_pullback_complement_full(a_p, p_c, a_prime_a, a_prime_z,
                                               z_c):
    """Find morphism z->p using the UP of PBC."""
    # Preliminary checks
    if not is_monic(a_p):
        raise ReGraphError("Morphism 'a_p' is required to be a mono "
                           "to use the UP of the pullback complement")
    z_p = {}
    for z_element, c_element in z_c.items():
        a_prime_elements = keys_by_value(a_prime_z, z_element)
        p_elements1 = set()  # candidate p elements
        for a_prime_element in a_prime_elements:
            p_elements1.add(a_p[a_prime_a[a_prime_element]])
        # resolve ambiguity going the other way
        p_elements2 = keys_by_value(p_c, c_element)
        if len(p_elements1) == 0:
            if len(p_elements2) == 1:
                z_p[z_element] = list(p_elements2)[0]
            else:
                raise ValueError("Something is wrong")
        else:
            intersection = p_elements1.intersection(p_elements2)
            if len(intersection) == 1:
                z_p[z_element] = list(intersection)[0]
            else:
                raise ValueError("Something is wrong")
    return z_p
Esempio n. 7
0
 def remove_edge_rhs(self, node1, node2):
     """Remove edge from the rhs of the graph."""
     primitives.remove_edge(self.rhs, node1, node2)
     for pn1 in keys_by_value(self.p_rhs, node1):
         for pn2 in keys_by_value(self.p_rhs, node2):
             print(pn1, pn2)
             try:
                 primitives.remove_edge(self.p, pn1, pn2)
             except GraphError:
                 continue
Esempio n. 8
0
 def removed_edges(self):
     """."""
     edges = set()
     for s, t in self.lhs.edges():
         s_p_nodes = keys_by_value(self.p_lhs, s)
         t_p_nodes = keys_by_value(self.p_lhs, t)
         if len(s_p_nodes) != 0 and len(t_p_nodes) != 0:
             for s_p_node in s_p_nodes:
                 for t_p_node in t_p_nodes:
                     if (s_p_node, t_p_node) not in self.p.edges():
                         edges.add((s_p_node, t_p_node))
     return edges
Esempio n. 9
0
def subtract(a, b, ba_mapping):
    """Subtract graphs provided node mapping.

    Subtract graph B from A having mapping of nodes from B to
    nodes from A specified.

    Parameters
    ----------
    a : networkx.(Di)Graph
    b : networkx.(Di)Graph
    ba_mapping : dict

    Returns
    -------
    Graph representing the difference a - b.

    Examples
    --------
    >>> a = nx.DiGraph()
    >>> add_nodes_from(a, [1, 2, 3])
    >>> add_edges_from(a, [(1, 2), (2, 2), (2, 3)])
    >>> b = nx.DiGraph()
    >>> add_nodes_from(b, ['x', 'y'])
    >>> ba_mapping = {'x': 1, 'y': 3}
    >>> diff = subtract(a, b, ba_mapping)
    >>> diff.nodes()
    [2]
    >>> diff.edges()
    [(2, 2)]
    """
    res = type(a)()
    f = ba_mapping

    for n in a.nodes():
        if n not in f.values():
            add_node(res,
                     n,
                     a.node[n])
    for (n1, n2) in a.edges():
        if n1 in res.nodes() and n2 in res.nodes():
            b_keys_1 = keys_by_value(f, n1)
            b_keys_2 = keys_by_value(f, n2)
            if len(b_keys_1) == 0 or len(b_keys_2) == 0:
                add_edge(res, n1, n2, get_edge(a, n1, n2))
            else:
                for k1 in b_keys_1:
                    for k2 in b_keys_2:
                        if (k1, k2) not in b.edges():
                            add_edge(res,
                                     n1,
                                     n2,
                                     get_edge(a, n1, n2))
    return res
Esempio n. 10
0
def subtract(a, b, ba_mapping):
    """Subtract graphs provided node mapping.

    Subtract graph B from A having mapping of nodes from B to
    nodes from A specified.

    Parameters
    ----------
    a : networkx.(Di)Graph
    b : networkx.(Di)Graph
    ba_mapping : dict

    Returns
    -------
    Graph representing the difference a - b.

    Examples
    --------
    >>> a = nx.DiGraph()
    >>> add_nodes_from(a, [1, 2, 3])
    >>> add_edges_from(a, [(1, 2), (2, 2), (2, 3)])
    >>> b = nx.DiGraph()
    >>> add_nodes_from(b, ['x', 'y'])
    >>> ba_mapping = {'x': 1, 'y': 3}
    >>> diff = subtract(a, b, ba_mapping)
    >>> diff.nodes()
    [2]
    >>> diff.edges()
    [(2, 2)]
    """
    res = type(a)()
    f = ba_mapping

    for n in a.nodes():
        if n not in f.values():
            add_node(res,
                     n,
                     a.node[n])
    for (n1, n2) in a.edges():
        if n1 in res.nodes() and n2 in res.nodes():
            b_keys_1 = keys_by_value(f, n1)
            b_keys_2 = keys_by_value(f, n2)
            if len(b_keys_1) == 0 or len(b_keys_2) == 0:
                add_edge(res, n1, n2, get_edge(a, n1, n2))
            else:
                for k1 in b_keys_1:
                    for k2 in b_keys_2:
                        if (k1, k2) not in b.edges():
                            add_edge(res,
                                     n1,
                                     n2,
                                     get_edge(a, n1, n2))
    return res
Esempio n. 11
0
 def remove_node(self, n):
     """Remove a node in the graph."""
     # remove corresponding nodes from p and rhs
     p_keys = keys_by_value(self.p_lhs, n)
     for k in p_keys:
         if k in self.p.nodes():
             primitives.remove_node(self.p, k)
         if self.p_rhs[k] in self.rhs.nodes():
             primitives.remove_node(self.rhs, self.p_rhs[k])
             affected_nodes = keys_by_value(self.p_rhs, self.p_rhs[k])
             for node in affected_nodes:
                 del self.p_rhs[node]
         del self.p_lhs[k]
     return
Esempio n. 12
0
    def inject_remove_edge(self, n1, n2):
        """Inject removal of an edge by the rule.

        Parameters
        ----------
        n1 : hashable
            Id of an edge's source node in `lhs`.
        n2 : hashable
            Id of an edge's target node in `lhs`.

        Raises
        ------
        RuleError
            If some of the nodes are not found in neither
            `lhs` nor `p`, or if a corresponding edge in
            `p` does not exist.
        """
        # Find nodes in p mapping to n1 & n2
        p_keys_1 = keys_by_value(self.p_lhs, n1)
        p_keys_2 = keys_by_value(self.p_lhs, n2)

        # n1 is actually a node from `p`
        if len(p_keys_1) == 0:
            if n1 in self.p.nodes():
                p_keys_1 = [n1]
            else:
                raise RuleError(
                    "Node '%s' is not found in neither left-hand "
                    "side nor preserved part" % n2)

        if len(p_keys_2) == 0:
            if n2 in self.p.nodes():
                p_keys_2 = [n2]
            else:
                raise RuleError(
                    "Node '%s' is not found in neither left-hand "
                    "side nor preserved part" % str(n2))

        for k1 in p_keys_1:
            for k2 in p_keys_2:
                if (k1, k2) in self.p.edges():
                    primitives.remove_edge(self.p, k1, k2)
                    primitives.remove_edge(self.rhs, self.p_rhs[k1], self.p_rhs[k2])
                else:
                    raise RuleError(
                        "Edge '%s->%s' does not exist in the preserved part"
                        % (k1, k2))

        return
Esempio n. 13
0
    def remove_edge(self, n1, n2):
        """Remove edge from the graph."""
        # Find nodes in p mapping to n1 & n2
        p_keys_1 = keys_by_value(self.p_lhs, n1)
        p_keys_2 = keys_by_value(self.p_lhs, n2)

        # Remove edge from the preserved part & rhs of the rule
        for k1 in p_keys_1:
            if k1 not in self.p.nodes():
                raise RuleError(
                    "Node with the id '%s' does not exist in "
                    "the preserved part" % k1
                )
            for k2 in p_keys_2:
                if k2 not in self.p.nodes():
                    raise RuleError(
                        "Node with the id '%s' does not exist in "
                        "the preserved part" % k2
                    )
                rhs_key_1 = self.p_rhs[k1]
                rhs_key_2 = self.p_rhs[k2]
                if self.p.is_directed():
                    if (k1, k2) not in self.p.edges():
                        raise RuleError(
                            "Edge '%s->%s' does not exist in the preserved "
                            "part of the rule " % (k1, k2)
                        )
                    if (rhs_key_1, rhs_key_2) not in self.rhs.edges():
                        raise RuleError(
                            "Edge '%s->%s' does not exist in the right hand "
                            "side of the rule " % (rhs_key_1, rhs_key_2)
                        )
                    primitives.remove_edge(self.p, k1, k2)
                    primitives.remove_edge(self.rhs, rhs_key_1, rhs_key_2)
                else:
                    if (k1, k2) not in self.p.edges() and\
                       (k2, k1) not in self.p.edges():
                        raise RuleError(
                            "Edge '%s->%s' does not exist in the "
                            "preserved part of the rule " % (k1, k2)
                        )
                    if (rhs_key_1, rhs_key_2) not in self.rhs.edges() and\
                       (rhs_key_2, rhs_key_1) not in self.rhs.edges():
                        raise RuleError(
                            "Edge '%s->%s' does not exist in the right "
                            "hand side of the rule " % (rhs_key_1, rhs_key_2)
                        )
                    primitives.remove_edge(self.p, k1, k2)
        return
Esempio n. 14
0
def get_unique_map_to_pullback_complement(a_p, p_c, a_prime_a, a_prime_z, z_c):
    """Find morphism z->p using the UP of PBC."""
    # Preliminary checks
    if not is_monic(a_p):
        raise ReGraphError("Morphism 'a_p' is required to be a mono "
                           "to use the UP of the pullback complement")
    z_p = {}
    for z_element, c_element in z_c.items():
        a_prime_elements = keys_by_value(a_prime_z, z_element)
        p_elements1 = set()  # candidate p elements
        for a_prime_element in a_prime_elements:
            p_elements1.add(a_p[a_prime_a[a_prime_element]])
        # resolve ambiguity going the other way
        p_elements2 = keys_by_value(p_c, c_element)
        if len(p_elements1) == 0:
            if len(p_elements2) == 1:
                z_p[z_element] = list(p_elements2)[0]
            else:
                raise ValueError(
                    "Cannot apply the universal property, " +
                    "check if the conditions to apply it are satisfied, " +
                    "problem: element '{}' from Z ".format(z_element) +
                    "corresponds to more than one element " +
                    "from P (i.e. corresponds to {}) and A'->A->P doesn't ".
                    format(p_elements2) + "resolve the conflict")
        else:
            intersection = p_elements1.intersection(p_elements2)
            if len(intersection) == 1:
                z_p[z_element] = list(intersection)[0]
            elif len(intersection) == 0:
                raise ValueError(
                    "Cannot apply the universal property, " +
                    "check if the conditions to apply it are satisfied, " +
                    "problem: element '{}' from Z ".format(z_element) +
                    "corresponds to '{}' ".format(p_elements1) +
                    "from P following A'->A->P ".format(intersection) +
                    "to '{}' following (P->C)^{{-1}} composed with (Z -> C)".
                    format(p_elements2))
            else:
                raise ValueError(
                    "Cannot apply the universal property, " +
                    "check if the conditions to apply it are satisfied, " +
                    "problem: element '{}' from Z ".format(z_element) +
                    "doesn't corresponds to exactly one element " +
                    "from P (i.e. corresponds to {}) in both A'->A->P ".format(
                        intersection) +
                    "and (P->C)^{{-1}} composed with (Z -> C)")
    return z_p
Esempio n. 15
0
    def inject_update_node_attrs(self, n, attrs):
        """Inject an update of node attrs by the rule.

        Parameters
        ----------
        n : hashable
            Id of a node from the left-hand side whose attrs
            should be updated
        attrs : dict
            Dictionary of new attrs that will replace the old ones

        Raises
        ------
        RuleError
            If node `n` does not exist in the left-hand side or
            is being removed by the rule.
        """
        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 update attributes" % n)
        for k in p_keys:
            self.p.node[k] = None
            primitives.update_node_attrs(self.rhs, self.p_rhs[k], attrs)
        return
Esempio n. 16
0
 def _refine_delta(self, delta):
     lhs = delta["rule"].refine(self.graph, delta["lhs_instance"])
     delta["lhs_instance"] = lhs
     for n in delta["rule"].rhs.nodes():
         if n not in delta["rhs_instance"].keys():
             delta["rhs_instance"][n] = lhs[
                 delta["rule"].p_lhs[keys_by_value(delta["rule"].p_rhs, n)[0]]]
Esempio n. 17
0
def _check_totality(hierarchy, graph_id, rule, instance, lhs_typing,
                    rhs_typing):
    """"Check that everything is typed at the end of the rewriting."""
    for node in rule.rhs.nodes():
        p_nodes = keys_by_value(rule.p_rhs, node)
        for typing_graph in hierarchy.successors(graph_id):
            typing = hierarchy.edge[graph_id][typing_graph].mapping
            # Totality can be broken in two cases
            if len(p_nodes) > 1:
                # node will be merged
                all_untyped = True
                for p_node in p_nodes:
                    if instance[rule.p_lhs[p_node]] in typing.keys():
                        all_untyped = False
                        break
                if all_untyped:
                    continue

            if typing_graph in rhs_typing.keys() and\
               node in rhs_typing[typing_graph].keys():
                continue
            else:
                raise RewritingError(
                    "Rewriting is strict (no propagation of types is "
                    "allowed), typing of the node `%s` "
                    "in rhs is required (typing by the following "
                    "graph stays unresolved: '%s')!" % (node, typing_graph))
Esempio n. 18
0
 def test_inject_clone_node(self):
     pattern = nx.DiGraph()
     prim.add_nodes_from(pattern, [1, 2, 3])
     prim.add_edges_from(pattern, [(1, 2), (3, 2)])
     rule = Rule.from_transform(pattern)
     new_p_node, new_rhs_node = rule.inject_clone_node(2)
     check_homomorphism(rule.p, rule.lhs, rule.p_lhs)
     check_homomorphism(rule.p, rule.rhs, rule.p_rhs)
     assert (new_p_node in rule.p.nodes())
     assert (new_rhs_node in rule.rhs.nodes())
     assert (rule.p_rhs[new_p_node] == new_rhs_node)
     assert ((1, new_p_node) in rule.p.edges())
     assert ((3, new_p_node) in rule.p.edges())
     assert ((1, new_rhs_node) in rule.rhs.edges())
     assert ((3, new_rhs_node) in rule.rhs.edges())
     new_p_node, new_rhs_node = rule.inject_clone_node(2)
     assert (len(keys_by_value(rule.p_lhs, 2)) == 3)
     check_homomorphism(rule.p, rule.lhs, rule.p_lhs)
     check_homomorphism(rule.p, rule.rhs, rule.p_rhs)
     rule.inject_remove_node(3)
     try:
         rule.inject_clone_node(3)
         raise ValueError("Cloning of removed node was not caught")
     except:
         pass
Esempio n. 19
0
    def add_node(self, node_id, attrs=None):
        """Add node to the graph.

        Parameters
        ----------
        node_id : hashable
            Id of a node to add
        attrs : dict, optional
            Attributes of the node.

        Raises
        ------
        RuleError
            If node with this id already exists in the `rhs`.
        """
        if node_id not in self.rhs.nodes():
            p_keys = keys_by_value(self.p_rhs, node_id)
            # here we check for the nodes with the same name in the lhs
            for k in p_keys:
                lhs_key = self.p_lhs[k]
                if lhs_key == node_id:
                    raise RuleError(
                        "Node with the id '%s' already exists in the "
                        "left hand side of the rule" %
                        node_id
                    )
            primitives.add_node(self.rhs, node_id, attrs)
        else:
            raise RuleError(
                "Node with the id '%s' already exists in the "
                "right hand side of the rule" %
                node_id
            )
Esempio n. 20
0
def _check_totality(hierarchy, graph_id, rule, instance,
                    lhs_typing, rhs_typing):
    """"Check that everything is typed at the end of the rewriting."""
    for node in rule.rhs.nodes():
        p_nodes = keys_by_value(rule.p_rhs, node)
        for typing_graph in hierarchy.successors(graph_id):
            typing = hierarchy.edge[graph_id][typing_graph].mapping
            # Totality can be broken in two cases
            if len(p_nodes) > 1:
                # node will be merged
                all_untyped = True
                for p_node in p_nodes:
                    if instance[rule.p_lhs[p_node]] in typing.keys():
                        all_untyped = False
                        break
                if all_untyped:
                    continue

            if typing_graph in rhs_typing.keys() and\
               node in rhs_typing[typing_graph].keys():
                continue
            else:
                raise RewritingError(
                    "Rewriting is strict (no propagation of types is "
                    "allowed), typing of the node `%s` "
                    "in rhs is required (typing by the following "
                    "graph stays unresolved: '%s')!" %
                    (node, typing_graph))
Esempio n. 21
0
def get_unique_map(a, b, c, d, a_b, b_d, c_d):
    """Get a map a->c that makes a square commute."""
    a_c = dict()
    for node in b.nodes():
        a_keys = keys_by_value(a_b, node)
        if len(a_keys) > 0:
            # node stayed in the rule
            if node in b_d.keys():
                d_node = b_d[node]
                c_keys = keys_by_value(c_d, d_node)
                if len(a_keys) != len(c_keys):
                    raise ReGraphError("Map is not unique!")
                else:
                    for i, a_key in enumerate(a_keys):
                        a_c[a_key] = c_keys[i]
    return a_c
Esempio n. 22
0
def _autocomplete_typing(hierarchy, graph_id, instance, lhs_typing, p_typing,
                         rhs_typing_rel, p_lhs, p_rhs):
    if lhs_typing is None:
        new_lhs_typing = dict()
    else:
        new_lhs_typing = format_typing(lhs_typing)
    if p_typing is None:
        new_p_typing = dict()
    else:
        new_p_typing = normalize_typing_relation(p_typing)
    if rhs_typing_rel is None:
        new_rhs_typing_rel = dict()
    else:
        new_rhs_typing_rel = normalize_typing_relation(rhs_typing_rel)
    successors = list(hierarchy.successors(graph_id))
    if len(successors) > 0:
        ancestors = hierarchy.get_descendants(graph_id)
        for anc, anc_typing in ancestors.items():
            if anc not in new_rhs_typing_rel.keys():
                new_rhs_typing_rel[anc] = dict()

        merged_nodes = set()
        for r_node in p_rhs.values():
            p_nodes = keys_by_value(p_rhs, r_node)
            if len(p_nodes) > 1:
                merged_nodes.add(r_node)

        for typing_graph in hierarchy.successors(graph_id):
            typing = hierarchy.typing[graph_id][typing_graph]
            # Autocomplete lhs and rhs typings
            # by immediate successors induced by an instance
            if typing_graph not in new_lhs_typing.keys():
                new_lhs_typing[typing_graph] = dict()
            for (source, target) in instance.items():
                if source not in new_lhs_typing[typing_graph].keys():
                    if target in typing.keys():
                        new_lhs_typing[typing_graph][source] = typing[target]

            for (p_node, l_node) in p_lhs.items():
                if l_node in new_lhs_typing[typing_graph].keys():
                    if p_rhs[p_node] not in new_rhs_typing_rel[
                            typing_graph].keys():
                        new_rhs_typing_rel[typing_graph][p_rhs[p_node]] = set()

                    new_rhs_typing_rel[typing_graph][p_rhs[p_node]].add(
                        new_lhs_typing[typing_graph][l_node])

        # Second step of autocompletion of rhs typing
        for graph, typing in new_rhs_typing_rel.items():
            ancestors = hierarchy.get_descendants(graph)
            for ancestor, ancestor_typing in ancestors.items():
                dif = set(typing.keys()) -\
                    set(new_rhs_typing_rel[ancestor].keys())
                for node in dif:
                    type_set = set()
                    for el in new_rhs_typing_rel[graph][node]:
                        type_set.add(ancestor_typing[el])
                    new_rhs_typing_rel[ancestor][node] = type_set
    return (new_lhs_typing, new_p_typing, new_rhs_typing_rel)
Esempio n. 23
0
 def added_edges(self):
     """."""
     edges = set()
     for s, t in self.rhs.edges():
         s_p_nodes = keys_by_value(self.p_rhs, s)
         t_p_nodes = keys_by_value(self.p_rhs, t)
         if len(s_p_nodes) == 0 or len(t_p_nodes) == 0:
             edges.add((s, t))
         else:
             found_edge = False
             for s_p_node in s_p_nodes:
                 for t_p_node in t_p_nodes:
                     if (s_p_node, t_p_node) in self.p.edges():
                         found_edge = True
             if not found_edge:
                 edges.add((s, t))
     return edges
Esempio n. 24
0
 def remove_node_rhs(self, n):
     """Remove a node from a rhs."""
     p_keys = keys_by_value(self.p_rhs, n)
     for p_node in p_keys:
         primitives.remove_node(self.p, p_node)
         del self.p_rhs[p_node]
         del self.p_lhs[p_node]
     primitives.remove_node(self.rhs, n)
Esempio n. 25
0
 def added_nodes(self):
     """A set of nodes from rhs which are added by a rule."""
     nodes = set()
     for r_node in self.rhs.nodes():
         p_nodes = keys_by_value(self.p_rhs, r_node)
         if len(p_nodes) == 0:
             nodes.add(r_node)
     return nodes
Esempio n. 26
0
 def removed_nodes(self):
     """."""
     nodes = set()
     for node in self.lhs.nodes():
         p_nodes = keys_by_value(self.p_lhs, node)
         if len(p_nodes) == 0:
             nodes.add(node)
     return nodes
Esempio n. 27
0
 def cloned_nodes(self):
     """."""
     nodes = dict()
     for node in self.lhs.nodes():
         p_nodes = keys_by_value(self.p_lhs, node)
         if len(p_nodes) > 1:
             nodes[node] = set(p_nodes)
     return nodes
Esempio n. 28
0
def _autocomplete_typing(hierarchy, graph_id, instance,
                         lhs_typing, rhs_typing_rel, p_lhs, p_rhs):
    successors = list(hierarchy.successors(graph_id))
    if len(successors) > 0:
        if lhs_typing is None:
            new_lhs_typing = dict()
        else:
            new_lhs_typing = format_typing(lhs_typing)
        if rhs_typing_rel is None:
            new_rhs_typing_rel = dict()
        else:
            new_rhs_typing_rel = normalize_typing_relation(rhs_typing_rel)

        ancestors = hierarchy.get_ancestors(graph_id)
        for anc, anc_typing in ancestors.items():
            if anc not in new_rhs_typing_rel.keys():
                new_rhs_typing_rel[anc] = dict()

        merged_nodes = set()
        for r_node in p_rhs.values():
            p_nodes = keys_by_value(p_rhs, r_node)
            if len(p_nodes) > 1:
                merged_nodes.add(r_node)

        for typing_graph in hierarchy.successors(graph_id):
            typing = hierarchy.typing[graph_id][typing_graph]
            # Autocomplete lhs and rhs typings
            # by immediate successors induced by an instance
            if typing_graph not in new_lhs_typing.keys():
                new_lhs_typing[typing_graph] = dict()
            for (source, target) in instance.items():
                if source not in new_lhs_typing[typing_graph].keys():
                    if target in typing.keys():
                        new_lhs_typing[typing_graph][source] = typing[target]

            for (p_node, l_node) in p_lhs.items():
                if l_node in new_lhs_typing[typing_graph].keys():
                    if p_rhs[p_node] not in new_rhs_typing_rel[typing_graph].keys():
                        new_rhs_typing_rel[typing_graph][p_rhs[p_node]] = set()

                    new_rhs_typing_rel[typing_graph][p_rhs[p_node]].add(
                        new_lhs_typing[typing_graph][l_node])

        # Second step of autocompletion of rhs typing
        for graph, typing in new_rhs_typing_rel.items():
            ancestors = hierarchy.get_ancestors(graph)
            for ancestor, ancestor_typing in ancestors.items():
                dif = set(typing.keys()) -\
                    set(new_rhs_typing_rel[ancestor].keys())
                for node in dif:
                    type_set = set()
                    for el in new_rhs_typing_rel[graph][node]:
                        type_set.add(ancestor_typing[el])
                    new_rhs_typing_rel[ancestor][node] = type_set

        return (new_lhs_typing, new_rhs_typing_rel)
    else:
        return (None, None)
Esempio n. 29
0
 def added_edge_attrs(self):
     """."""
     attrs = dict()
     for s, t in self.rhs.edges():
         s_p_nodes = keys_by_value(self.p_rhs, s)
         t_p_nodes = keys_by_value(self.p_rhs, t)
         new_attrs = {}
         for s_p_node in s_p_nodes:
             for t_p_node in t_p_nodes:
                 if (s_p_node, t_p_node) in self.p.edges():
                     new_attrs = attrs_union(
                         new_attrs,
                         dict_sub(
                             self.rhs.edge[s][t],
                             self.p.edge[s_p_node][t_p_node]
                         )
                     )
     return attrs
Esempio n. 30
0
    def removed_edges(self):
        """Get edges removed by the rule.

        Returns
        -------
        edges : set
            Set of edges from `lhs` removed by the rule.
        """
        edges = set()
        for s, t in self.lhs.edges():
            s_p_nodes = keys_by_value(self.p_lhs, s)
            t_p_nodes = keys_by_value(self.p_lhs, t)
            if len(s_p_nodes) != 0 and len(t_p_nodes) != 0:
                for s_p_node in s_p_nodes:
                    for t_p_node in t_p_nodes:
                        if (s_p_node, t_p_node) not in self.p.edges():
                            edges.add((s_p_node, t_p_node))
        return edges
Esempio n. 31
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)
Esempio n. 32
0
def get_unique_map(a, b, c, d, a_b, b_d, c_d):
    """Get a map a->c that makes a square commute."""
    a_c = dict()
    for node in b.nodes():
        a_keys = keys_by_value(a_b, node)
        if len(a_keys) > 0:
            # node stayed in the rule
            if node in b_d.keys():
                d_node = b_d[node]
                c_keys = keys_by_value(
                    c_d,
                    d_node
                )
                if len(a_keys) != len(c_keys):
                    raise ReGraphError("Map is not unique!")
                else:
                    for i, a_key in enumerate(a_keys):
                        a_c[a_key] = c_keys[i]
    return a_c
Esempio n. 33
0
def get_unique_map_to_pullback(p, p_a, p_b, z_a, z_b):
    """Find a unique map to pullback."""
    z_p = dict()
    for value in p:
        z_keys_from_a = set()
        if value in p_a.keys():
            a_value = p_a[value]
            z_keys_from_a = set(keys_by_value(z_a, a_value))

        z_keys_from_b = set()
        if value in p_b.keys():
            b_value = p_b[value]
            z_keys_from_b.update(keys_by_value(z_b, b_value))

        z_keys = z_keys_from_a.intersection(z_keys_from_b)
        for z_key in z_keys:
            z_p[z_key] = value

    return z_p
Esempio n. 34
0
def get_unique_map_to_pullback(p, p_a, p_b, z_a, z_b):
    """Find a unique map to pullback."""
    z_p = dict()
    for value in p:
        z_keys_from_a = set()
        if value in p_a.keys():
            a_value = p_a[value]
            z_keys_from_a = set(keys_by_value(z_a, a_value))

        z_keys_from_b = set()
        if value in p_b.keys():
            b_value = p_b[value]
            z_keys_from_b.update(keys_by_value(z_b, b_value))

        z_keys = z_keys_from_a.intersection(z_keys_from_b)
        for z_key in z_keys:
            z_p[z_key] = value

    return z_p
Esempio n. 35
0
 def removed_edge_attrs(self):
     """."""
     attrs = dict()
     for s, t in self.lhs.edges():
         s_p_nodes = keys_by_value(self.p_lhs, s)
         t_p_nodes = keys_by_value(self.p_lhs, t)
         new_attrs = {}
         for s_p_node in s_p_nodes:
             for t_p_node in t_p_nodes:
                 if (s_p_node, t_p_node) in self.p.edges():
                     new_attrs = attrs_union(
                         new_attrs,
                         dict_sub(
                             self.lhs.edge[s][t],
                             self.p.edge[s_p_node][t_p_node]
                         )
                     )
         if len(new_attrs) > 0:
             attrs[(s, t)] = new_attrs
     return attrs
Esempio n. 36
0
    def remove_node_attrs_rhs(self, n, attrs):
        """Remove attrs of 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)

        p_keys = keys_by_value(self.p_rhs, n)
        for p_node in p_keys:
            primitives.remove_node_attrs(self.p, p_node, attrs)
        primitives.remove_node_attrs(self.rhs, n, attrs)
Esempio n. 37
0
 def removed_node_attrs(self):
     """."""
     attrs = dict()
     for node in self.lhs.nodes():
         p_nodes = keys_by_value(self.p_lhs, node)
         new_attrs = {}
         for p_node in p_nodes:
             new_attrs = attrs_union(new_attrs, dict_sub(
                 self.lhs.node[node], self.p.node[p_node]))
         if len(new_attrs) > 0:
             attrs[node] = new_attrs
     return attrs
Esempio n. 38
0
def get_unique_map_from_pushout(p, a_p, b_p, a_z, b_z):
    """Find a unique map to pushout."""
    p_z = dict()
    for value in p:
        z_values = set()

        a_values = set(keys_by_value(a_p, value))
        for a_value in a_values:
            if a_value in a_z.keys():
                z_values.add(a_z[a_value])

        b_values = set(keys_by_value(b_p, value))
        for b_value in b_values:
            if b_value in b_z.keys():
                z_values.add(b_z[b_value])

        if len(z_values) > 0:
            if len(z_values) > 1:
                raise ReGraphError("Cannot construct a unique map!")
            p_z[value] = z_values.pop()
    return p_z
Esempio n. 39
0
 def clone_node(self, n, node_name=None):
     """Clone a node of the graph."""
     p_new_nodes = []
     rhs_new_nodes = []
     p_keys = keys_by_value(self.p_lhs, n)
     for k in p_keys:
         p_new_node = primitives.clone_node(self.p, k)
         p_new_nodes.append(p_new_node)
         rhs_new_node = primitives.clone_node(self.rhs, self.p_rhs[k])
         rhs_new_nodes.append(rhs_new_node)
         # self.p_lhs[k] = n
         self.p_lhs[p_new_node] = n
         self.p_rhs[p_new_node] = rhs_new_node
     return (p_new_nodes, rhs_new_nodes)
Esempio n. 40
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
Esempio n. 41
0
 def added_node_attrs(self):
     """."""
     attrs = dict()
     for node in self.rhs.nodes():
         p_nodes = keys_by_value(self.p_rhs, node)
         # if len(p_nodes) == 0:
         #     attrs[node] = self.rhs.node[node]
         new_attrs = {}
         for p_node in p_nodes:
             new_attrs = attrs_union(new_attrs, dict_sub(
                 self.rhs.node[node], self.p.node[p_node]))
         if len(new_attrs) > 0:
             attrs[node] = new_attrs
     return attrs
Esempio n. 42
0
 def add_edge(self, n1, n2, attrs=None):
     """Add an edge in the graph."""
     # Find nodes in p mapping to n1 & n2
     p_keys_1 = keys_by_value(self.p_lhs, n1)
     p_keys_2 = keys_by_value(self.p_lhs, n2)
     for k1 in p_keys_1:
         if k1 not in self.p.nodes():
             raise RuleError(
                 "Node with the id '%s' does not exist in the "
                 "preserved part of the rule" % k1
             )
         for k2 in p_keys_2:
             if k2 not in self.p.nodes():
                 raise RuleError(
                     "Node with the id '%s' does not exist in the "
                     "preserved part of the rule" % k2
                 )
             rhs_key_1 = self.p_rhs[k1]
             rhs_key_2 = self.p_rhs[k2]
             if self.rhs.is_directed():
                 if (rhs_key_1, rhs_key_2) in self.rhs.edges():
                     raise RuleError(
                         "Edge '%s->%s' already exists in the right "
                         "hand side of the rule" %
                         (rhs_key_1, rhs_key_2)
                     )
                 primitives.add_edge(self.rhs, rhs_key_1, rhs_key_2, attrs)
             else:
                 if (rhs_key_1, rhs_key_2) in self.rhs.edges() or\
                    (rhs_key_2, rhs_key_1) in self.rhs.edges():
                     raise RuleError(
                         "Edge '%s->%s' already exists in the right "
                         "hand side of the rule" %
                         (rhs_key_1, rhs_key_2)
                     )
                 primitives.add_edge(self.rhs, rhs_key_1, rhs_key_2, attrs)
     return
Esempio n. 43
0
    def update_node_attrs(self, n, attrs):
        """Update attributes of a node."""
        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 update attributes" % n)
        for k in p_keys:
            self.p.node[k] = None
            primitives.update_node_attrs(self.rhs, self.p_rhs[k], attrs)
        return
Esempio n. 44
0
 def clone_rhs_node(self, node, new_name=None):
     """Clone an rhs node."""
     if node not in self.rhs.nodes():
         raise RuleError(
             "Node '%s' is not a node of right hand side" %
             node
         )
     p_keys = keys_by_value(self.p_rhs, node)
     if len(p_keys) == 0:
         primitives.clone_node(self.rhs, node, new_name)
     elif len(p_keys) == 1:
         primitives.clone_node(self.rhs, node, new_name)
         new_p_node = primitives.clone_node(self.p, p_keys[0])
         self.p_rhs[new_p_node] = new_name
         self.p_lhs[new_p_node] = self.p_lhs[p_keys[0]]
     else:
         raise RuleError("Cannot clone node that is result of merge!")
Esempio n. 45
0
    def update_edge_attrs(self, n1, n2, attrs):
        """Update the attributes of an edge with a new set `attrs`."""
        if n1 not in self.lhs.nodes():
            raise RuleError(
                "Node '%s' does not exist in the left hand side of the rule" %
                n1
            )
        if n2 not in self.lhs.nodes():
            raise RuleError(
                "Node '%s' does not exist in the left hand side of the rule" %
                n2
            )
        normalize_attrs(attrs)
        if self.lhs.is_directed():
            if (n1, n2) not in self.lhs.edges():
                raise RuleError(
                    "Edge '%s->%s' does not exist in the left hand "
                    "side of the rule" % (n1, n2)
                )

            p_keys_1 = keys_by_value(self.p_lhs, n1)
            p_keys_2 = keys_by_value(self.p_lhs, n2)

            if len(p_keys_1) == 0:
                raise RuleError(
                    "Node '%s' is being removed by the rule, cannot update "
                    "attributes from the incident edge" %
                    n2
                )
            if len(p_keys_2) == 0:
                raise RuleError(
                    "Node '%s' is being removed by the rule, cannot update "
                    "attributes from the incident edge" %
                    n1
                )
            for k1 in p_keys_1:
                for k2 in p_keys_2:
                    self.p.edge[k1][k2] = None
                    primitives.update_edge_attrs(
                        self.rhs,
                        self.p_rhs[k1],
                        self.p_rhs[k2],
                        attrs
                    )
        else:
            if (n1, n2) not in self.lhs.edges() and\
               (n2, n1) not in self.lhs.edges():
                raise RuleError(
                    "Edge '%s->%s' does not exist in the "
                    "left hand side of the rule" %
                    (n1, n2)
                )

            p_keys_1 = keys_by_value(self.p_lhs, n1)
            p_keys_2 = keys_by_value(self.p_lhs, n2)
            if len(p_keys_1) == 0:
                raise RuleError(
                    "Node '%s' is being removed by the rule, cannot update "
                    "attributes from the incident edge" %
                    n1
                )
            if len(p_keys_2) == 0:
                raise RuleError(
                    "Node '%s' is being removed by the rule, cannot update "
                    "attributes from the incident edge" %
                    n2
                )
            for k1 in p_keys_1:
                for k2 in p_keys_2:
                    self.p.edge[k1][k2] = None
                    primitives.update_edge_attrs(
                        self.rhs,
                        self.p_rhs[k1],
                        self.p_rhs[k2],
                        attrs
                    )
        return
Esempio n. 46
0
def _rewrite_base(hierarchy, graph_id, rule, instance,
                  lhs_typing, rhs_typing, inplace=False):
    g_m, p_g_m, g_m_g =\
        pullback_complement(rule.p, rule.lhs, hierarchy.node[graph_id].graph,
                            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.edge[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
    }
Esempio n. 47
0
def _propagate_rule_to(graph, origin_typing, rule, instance, p_origin,
                       inplace=False):

    if inplace is True:
        graph_prime = graph
    else:
        graph_prime = copy.deepcopy(graph)

    lhs_removed_nodes = rule.removed_nodes()
    lhs_removed_node_attrs = rule.removed_node_attrs()
    p_removed_edges = rule.removed_edges()
    p_removed_edge_attrs = rule.removed_edge_attrs()
    lhs_cloned_nodes = rule.cloned_nodes()

    graph_prime_graph = id_of(graph.nodes())
    graph_prime_origin = dict()

    for lhs_node in rule.lhs.nodes():
        origin_node = instance[lhs_node]
        g_nodes = keys_by_value(
            origin_typing, origin_node)
        for node in g_nodes:
            if lhs_node in lhs_removed_nodes:
                primitives.remove_node(
                    graph_prime, node)
                del graph_prime_graph[node]
            else:
                graph_prime_origin[node] = origin_node

    for lhs_node, p_nodes in lhs_cloned_nodes.items():
        nodes_to_clone = keys_by_value(origin_typing, instance[lhs_node])
        for node in nodes_to_clone:
            for i, p_node in enumerate(p_nodes):
                if i == 0:
                    graph_prime_origin[node] = p_origin[p_node]
                    graph_prime_graph[node] = node
                else:
                    new_name = primitives.clone_node(
                        graph_prime,
                        node)
                    graph_prime_origin[new_name] = p_origin[p_node]
                    graph_prime_graph[new_name] = node

    for lhs_node, attrs in lhs_removed_node_attrs.items():
        nodes_to_remove_attrs = keys_by_value(
            origin_typing, instance[lhs_node])
        for node in nodes_to_remove_attrs:
            primitives.remove_node_attrs(
                graph_prime,
                node, attrs)

    for p_u, p_v in p_removed_edges:
        us = keys_by_value(graph_prime_origin, p_origin[p_u])
        vs = keys_by_value(graph_prime_origin, p_origin[p_v])
        for u in us:
            for v in vs:
                if (u, v) in graph_prime.edges():
                    primitives.remove_edge(
                        graph_prime, u, v)

    for (p_u, p_v), attrs in p_removed_edge_attrs.items():
        us = keys_by_value(origin_typing, p_origin[p_u])
        vs = keys_by_value(origin_typing, p_origin[p_v])
        for u in us:
            for v in vs:
                primitives.removed_edge_attrs(
                    graph_prime, u, v, attrs)

    return (graph_prime, graph_prime_graph, graph_prime_origin)