Пример #1
0
def test_function_properties():
    bdd = _bdd.BDD()
    bdd.declare('x', 'y')
    order = dict(x=0, y=1)
    bdd.reorder(order)
    u = bdd.add_expr('x \/ y')
    y = bdd.add_expr('y')
    # Assigned first because in presence of a bug
    # different property calls could yield
    # different values.
    level = u.level
    assert level == 0, level
    var = u.var
    assert var == 'x', var
    low = u.low
    assert low == y, low
    high = u.high
    assert high == bdd.true, high
    ref = u.ref
    assert ref == 1, ref
    assert not u.negated
    support = u.support
    assert support == {'x', 'y'}, support
    # terminal
    u = bdd.false
    assert u.var is None, u.var
    assert u.low is None, u.low
    assert u.high is None, u.high
Пример #2
0
def test_sifting():
    # Figs. 6.24, 6.25 Baier 2008
    g = BDD({'z1': 0, 'z2': 1, 'z3': 2, 'y1': 3, 'y2': 4, 'y3': 5})
    u = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    g.collect_garbage()
    n = len(g)
    assert n == 15, n
    _bdd.reorder(g)
    u_ = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    g.collect_garbage()
    g.assert_consistent()
    assert u == u_, (u, u_)
Пример #3
0
def test_sifting():
    # Figs. 6.24, 6.25 Baier 2008
    g = BDD({'z1': 0, 'z2': 1, 'z3': 2,
             'y1': 3, 'y2': 4, 'y3': 5})
    u = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    g.collect_garbage()
    n = len(g)
    assert n == 15, n
    _bdd.reorder(g)
    u_ = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    g.collect_garbage()
    g.assert_consistent()
    assert u == u_, (u, u_)
Пример #4
0
def test_reorder_2():
    bdd = _bdd.BDD()
    vrs = [
        'x', 'y', 'z', 'a', 'b', 'c', 'e', 'z1', 'z2', 'z3', 'y1', 'y2', 'y3'
    ]
    bdd = _bdd.BDD()
    bdd.declare(*vrs)
    expr_1 = '(~ z \/ (c /\ b)) /\ e /\ (a /\ (~ x \/ y))'
    # Figs. 6.24, 6.25 Baier 2008
    expr_2 = '(z1 /\ y1) \/ (z2 /\ y2) \/ (z3 /\ y3)'
    u = bdd.add_expr(expr_1)
    v = bdd.add_expr(expr_2)
    bdd.collect_garbage()
    n = len(bdd)
    assert n == 23, n
    bdd.reorder()
    n_ = len(bdd)
    assert n > n_, (n, n_)
    bdd.assert_consistent()
Пример #5
0
def test_reorder():
    bdd = _bdd.BDD()
    bdd.declare('x', 'y', 'z')
    u = bdd.add_expr('(x /\ y) \/ z')
    bdd.reorder()
    assert u in bdd
Пример #6
0
def reorder(bdd, order=None):
    """Apply Rudell's sifting algorithm to `bdd`."""
    _bdd.reorder(bdd._bdd, order=order)
Пример #7
0
def reorder(bdd, order=None):
    """Apply Rudell's sifting algorithm to `bdd`."""
    _bdd.reorder(bdd._bdd, order=order)
Пример #8
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