Example #1
0
def compare(u, bdd, h):
    g = _bdd.to_nx(bdd, [u])
    # nx.drawing.nx_pydot.to_pydot(g).write_pdf('g.pdf')
    post = nx.descendants(g, u)
    post.add(u)
    r = g.subgraph(post)
    # nx.drawing.nx_pydot.to_pydot(r).write_pdf('r.pdf')
    # nx.drawing.nx_pydot.to_pydot(h).write_pdf('h.pdf')
    gm = iso.GraphMatcher(r, h, node_match=_nm, edge_match=_em)
    assert gm.is_isomorphic()
    d = gm.mapping
    assert d[1] == 1
Example #2
0
def compare(u, bdd, h):
    g = _bdd.to_nx(bdd, [u])
    # nx.drawing.nx_pydot.to_pydot(g).write_pdf('g.pdf')
    post = nx.descendants(g, u)
    post.add(u)
    r = g.subgraph(post)
    # nx.drawing.nx_pydot.to_pydot(r).write_pdf('r.pdf')
    # nx.drawing.nx_pydot.to_pydot(h).write_pdf('h.pdf')
    gm = iso.GraphMatcher(r, h, node_match=_nm, edge_match=_em)
    assert gm.is_isomorphic()
    d = gm.mapping
    assert d[1] == 1
Example #3
0
def bdd_to_mdd(bdd, dvars):
    """Return MDD for given BDD.

    Caution: collects garbage.

    `dvars` must map each MDD variable to the
    corresponding bits in BDD.
    Also, it should give the order as "level" keys.
    """
    # i = level in BDD
    # j = level in MDD
    # bit = BDD variable
    # var = MDD variable
    #
    # map from bits to integers
    bit_to_var = dict()
    for var, d in dvars.iteritems():
        bits = d['bitnames']
        b = {bit: var for bit in bits}
        bit_to_var.update(b)
    # find target bit ordering
    ordering = list()  # target
    levels = {d['level']: var for var, d in dvars.iteritems()}
    m = len(levels)
    for j in xrange(m):
        var = levels[j]
        bits = dvars[var]['bitnames']
        ordering.extend(bits)
    bit_to_sort = {bit: k for k, bit in enumerate(ordering)}
    # reorder
    bdd.collect_garbage()
    _bdd.reorder(bdd, order=bit_to_sort)
    # BDD -> MDD
    mdd = MDD(dvars)
    # zones of bits per integer var
    zones = dict()
    for var, d in dvars.iteritems():
        bits = d['bitnames']
        lsb = bits[0]
        msb = bits[-1]
        min_level = bit_to_sort[lsb]
        max_level = bit_to_sort[msb]
        zones[var] = (min_level, max_level)
    # reverse edges
    pred = {u: set() for u in bdd}
    for u, (_, v, w) in bdd._succ.iteritems():
        assert u > 0, u
        # terminal ?
        if u == 1:
            continue
        # non-terminal
        pred[abs(v)].add(u)
        pred[abs(w)].add(u)
    # find BDD nodes mentioned from above
    rm = set()
    for u, p in pred.iteritems():
        rc = bdd.ref(u)
        k = len(p)  # number of predecessors
        # has external refs ?
        if rc > k:
            continue
        # has refs from outside zone ?
        i, _, _ = bdd._succ[u]
        bit = bdd.var_at_level(i)
        var = bit_to_var[bit]
        min_level, _ = zones[var]
        pred_levels = {bdd._succ[v][0] for v in p}
        min_pred_level = min(pred_levels)
        if min_pred_level < min_level:
            continue
        # referenced only from inside zone
        rm.add(u)
    pred = {u: p for u, p in pred.iteritems() if u not in rm}
    # build layer by layer
    # TODO: use bins, instad of iterating through all nodes
    bdd.assert_consistent()
    g = to_nx(bdd, roots=[u])
    for u in pred:
        g.add_node(u, color='red')
    for u in g:
        if u == 1:
            continue
        i, _, _ = bdd._succ[u]
        var = bdd.var_at_level(i)
        label = '{var}-{u}'.format(var=var, u=u)
        g.add_node(u, label=label)
    pd = nx.to_pydot(g)
    pd.write_pdf('bdd_colored.pdf')
    bdd.dump('bdd.pdf')
    umap = dict()
    umap[1] = 1
    for u, i, v, w in bdd.levels(skip_terminals=True):
        # ignore function ?
        if u not in pred:
            continue
        # keep `u`
        bit = bdd.var_at_level(i)
        var = bit_to_var[bit]
        bits = dvars[var]['bitnames']
        bit_succ = list()
        for d in _enumerate_integer(bits):
            x = bdd.cofactor(u, d)
            bit_succ.append(x)
        # map edges
        int_succ = [umap[abs(z)] if z > 0 else -umap[abs(z)]
                    for z in bit_succ]
        # add new MDD node at level j
        j = dvars[var]['level']
        r = mdd.find_or_add(j, *int_succ)
        # cache
        # signed r, because low never inverted,
        # opposite to canonicity chosen for BDDs
        umap[u] = r
    return mdd, umap