예제 #1
0
def pullback_pushout(b, c, d, b_d, c_d, pullback_filter=None):
    """Do a pullback and then a pushout."""
    (a, a_b, a_c) = pullback(b, c, d, b_d, c_d)
    if pullback_filter is not None:
        valid_nodes = [n for n in a.nodes()
                       if pullback_filter(a, b, c, d, a_b, a_c, b_d, c_d, n)]
        a = a.subgraph(valid_nodes)
        a_b = restrict_mapping(valid_nodes, a_b)
        a_c = restrict_mapping(valid_nodes, a_c)

    (d2, b_d2, c_d2) = pushout(a, b, c, a_b, a_c)
    d2_d = {}
    for node in b.nodes():
        d2_d[b_d2[node]] = b_d[node]
    for node in c.nodes():
        d2_d[c_d2[node]] = c_d[node]
    return(d2, b_d2, c_d2, d2_d)
예제 #2
0
def pullback_pushout(b, c, d, b_d, c_d, pullback_filter=None):
    """Do a pullback and then a pushout."""
    (a, a_b, a_c) = pullback(b, c, d, b_d, c_d)
    if pullback_filter is not None:
        valid_nodes = [
            n for n in a.nodes()
            if pullback_filter(a, b, c, d, a_b, a_c, b_d, c_d, n)
        ]
        a = a.subgraph(valid_nodes)
        a_b = restrict_mapping(valid_nodes, a_b)
        a_c = restrict_mapping(valid_nodes, a_c)

    (d2, b_d2, c_d2) = pushout(a, b, c, a_b, a_c)
    d2_d = {}
    for node in b.nodes():
        d2_d[b_d2[node]] = b_d[node]
    for node in c.nodes():
        d2_d[c_d2[node]] = c_d[node]
    return (d2, b_d2, c_d2, d2_d)
예제 #3
0
def remove_conflict(hie, ag_id, mm_id, locus, suffix=None):
    """duplicates a locus in order to remove conflicts"""
    ag_gr = hie.node[ag_id].graph
    ag_mm = hie.get_typing(ag_id, mm_id)
    nuggets = [
        nug for nug in tree.get_children_id_by_node(hie, ag_id, locus)
        if hie.node[nug].attrs["type"] == "nugget"
    ]

    # Do not merge nodes that are Not valid
    # As they are removed from the botom graph before the pushout
    not_valid = [locus]

    def valid_pullback_node(a, b, c, d, a_b, a_c, b_d, c_d, n):
        a_d = union_mappings(compose_homomorphisms(b_d, a_b),
                             compose_homomorphisms(c_d, a_c))
        return n not in a_d or a_d[n] not in not_valid

    (pp, pp_ag) = multi_pullback_pushout(
        ag_gr, [(hie.node[nug].graph, hie.get_typing(nug, ag_id))
                for nug in nuggets], valid_pullback_node)

    adj_nodes = [suc for suc in ag_gr.successors(locus)] + [locus]

    lhs = ag_gr.subgraph(adj_nodes)
    new_pp = pp.subgraph(reverse_image(pp_ag, adj_nodes))

    # add regions and agents that do not appear in any nuggets to the
    # preserved part, so we can remove edges from the locus to them
    to_add = {
        suc
        for suc in ag_gr.successors(locus)
        if ag_mm[suc] in ["region", "agent"]
    } - set(pp_ag.values())
    for node in to_add:
        node_id = unique_node_id(new_pp, node)
        add_node(new_pp, node_id)
        pp_ag[node_id] = node

    newpp_lhs = restrict_mapping(new_pp.nodes(), pp_ag)

    # merge loci from preserved part that arr linked to the same other loci
    def linked_to(loc):
        """loc being a locus from new_pp, returns the ag loci linked to loc """
        adj_acts = {
            pp_ag[act]
            for act in new_pp.successors(loc)
            if ag_mm[pp_ag[act]] not in ["region", "agent"]
        }
        return {
            other_loc
            for act in adj_acts for other_loc in ag_gr.predecessors(act)
            if other_loc != locus
        }

    # compute equivalence classes of loci
    loci = [pploc for pploc in new_pp if pp_ag[pploc] == locus]
    classes = [{pploc} for pploc in loci]
    partial_eq = [{loc1, loc2} for loc1 in loci for loc2 in loci
                  if loc1 != loc2 and linked_to(loc1) & linked_to(loc2)]
    for eq in partial_eq:
        classes = merge_classes(eq, classes)

    eq_gr = nx.DiGraph()
    newpp_eq = {}
    for i, cl in enumerate(classes):
        eq_gr.add_node(i)
        for node in cl:
            newpp_eq[node] = i

    (new_pp, newpp_lhs) = pushout_from_partial_mapping(new_pp, eq_gr, newpp_eq,
                                                       newpp_lhs, {})

    lhs_ag = id_of(lhs)
    rhs = copy.deepcopy(new_pp)
    rule = Rule(new_pp, lhs, rhs, newpp_lhs)
    if suffix is None:
        apply_rule_on_parent_inplace(hie, ag_id, rule, lhs_ag)
    else:
        raise ValueError("TODO? rewrite not in place")
예제 #4
0
def unfold_locus(hie, ag_id, mm_id, locus, suffix=None):
    """duplicate a locus that is shared between agents"""
    ag_gr = hie.node[ag_id].graph
    ag_mm = hie.get_typing(ag_id, mm_id)
    nuggets = [
        nug for nug in tree.get_children_id_by_node(hie, ag_id, locus)
        if hie.node[nug].attrs["type"] == "nugget"
    ]
    # Do not merge nodes that are Not valid
    # As they are removed from the botom graph before the pushout
    not_valid = [locus] + [
        node
        for node in ag_gr[locus] if ag_mm[node] not in ["region", "agent"]
    ]

    def valid_pullback_node(a, b, c, d, a_b, a_c, b_d, c_d, n):
        a_d = union_mappings(compose_homomorphisms(b_d, a_b),
                             compose_homomorphisms(c_d, a_c))
        return n not in a_d or a_d[n] not in not_valid

    (pp, pp_ag) = multi_pullback_pushout(
        ag_gr, [(hie.node[nug].graph, hie.get_typing(nug, ag_id))
                for nug in nuggets], valid_pullback_node)

    adj_nodes = [suc for suc in ag_gr.successors(locus)] + [locus]

    lhs = ag_gr.subgraph(adj_nodes)
    new_pp = pp.subgraph(reverse_image(pp_ag, adj_nodes))

    # add regions and agents that do not appear in any nuggets to the
    # preserved part, so we can remove edges from the locus to them
    to_add = {
        suc
        for suc in ag_gr.successors(locus)
        if ag_mm[suc] in ["region", "agent"]
    } - set(pp_ag.values())
    for node in to_add:
        node_id = unique_node_id(new_pp, node)
        add_node(new_pp, node_id)
        pp_ag[node_id] = node

    newpp_lhs = restrict_mapping(new_pp.nodes(), pp_ag)

    # merge loci that have a shared successor component
    def common_comp(loc1, loc2):
        comps1 = {
            c
            for c in new_pp.successors(loc1)
            if ag_mm[pp_ag[c]] in ["region", "agent"]
        }
        comps2 = {
            c
            for c in new_pp.successors(loc2)
            if ag_mm[pp_ag[c]] in ["region", "agent"]
        }
        return comps1 & comps2

    # compute equivalence classes of loci
    loci = [pploc for pploc in new_pp if pp_ag[pploc] == locus]
    classes = [{pploc} for pploc in loci]
    partial_eq = [{loc1, loc2} for (loc1, loc2) in combinations(loci, 2)
                  if loc1 != loc2 and common_comp(loc1, loc2)]
    for eq in partial_eq:
        classes = merge_classes(eq, classes)

    # compute equivalence classes of action nodes
    def equiv_acts(act1, act2):
        def equiv_loci(locs1, locs2):
            if len(locs1) != 1:
                raise ValueError(
                    "should have exactly one locus next to action")
            if len(locs2) != 1:
                raise ValueError(
                    "should have exactly one locus next to action")
            return any(set(locs1) | set(locs2) <= cl for cl in classes)

        return (pp_ag[act1] == pp_ag[act2] and equiv_loci(
            new_pp.predecessors(act1), new_pp.predecessors(act2)))

    actions = [
        act for act in new_pp
        if ag_mm[pp_ag[act]] in ["is_bnd", "bnd", "is_free", "brk"]
    ]
    action_classes = [{act} for act in actions]
    for (act1, act2) in combinations(actions, 2):
        if equiv_acts(act1, act2):
            action_classes = merge_classes({act1, act2}, action_classes)

    eq_gr = nx.DiGraph()
    newpp_eq = {}
    for i, cl in enumerate(classes + action_classes):
        eq_gr.add_node(i)
        for node in cl:
            newpp_eq[node] = i

    (new_pp, newpp_lhs) = pushout_from_partial_mapping(new_pp, eq_gr, newpp_eq,
                                                       newpp_lhs, {})

    lhs_ag = id_of(lhs)
    rhs = copy.deepcopy(new_pp)
    rule = Rule(new_pp, lhs, rhs, newpp_lhs)
    if suffix is None:
        apply_rule_on_parent_inplace(hie, ag_id, rule, lhs_ag)
    else:
        raise ValueError("TODO? rewrite not in place")