def test_pullback_complement(self): C, homAC, homCD = pullback_complement(self.A, self.B, self.D, self.homAB, self.homBD) assert_equals(type(C), nx.DiGraph) test_graph = get_relabeled_graph(self.C, { 2: "circle", 3: "dark_circle", "dark_square": "dark_square" }) assert_graph_eq(test_graph, C) assert (id(self.D) != id(C))
def test_pullpack_complement_inplace(self): D_copy = copy.deepcopy(self.D) C, homAC, homCD = pullback_complement( self.A, self.B, D_copy, self.homAB, self.homBD, inplace=True ) assert_equals(type(C), NXGraph) test_graph = self.C.get_relabeled_graph( {2: "circle", 3: "dark_circle", "dark_square": "dark_square"} ) assert(test_graph == C) assert(id(D_copy) == id(C))
def apply_to(self, graph, instance, inplace=False): """Perform graph rewriting with the rule. Parameters ---------- graph : nx.(Di)Graph Graph to rewrite with the rule. instance : dict Instance of the `lhs` pattern in the graph defined by a dictionary where keys are nodes of `lhs` and values are nodes of the graph. inplace : bool, optional If `True`, the rewriting will be performed in-place by applying primitve transformations to the graph object, otherwise the result of the rewriting is a new graph object. Default value is `False`. Returns ------- g_prime : nx.(Di)Graph Result of the rewriting. If parameter `inplace` was `True`, `g_prime` is exactly the (transformed) input graph object `graph`. rhs_g_prime : dict Matching of the `rhs` in `g_prime`, a dictionary, where keys are nodes of `rhs` and values are nodes of `g_prime`. """ g_m, p_g_m, g_m_g = pullback_complement( self.p, self.lhs, graph, self.p_lhs, instance, inplace ) g_prime, g_m_g_prime, rhs_g_prime = pushout( self.p, g_m, self.rhs, p_g_m, self.p_rhs, inplace) return (g_prime, rhs_g_prime)
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 }