Example #1
0
def test_image_rename_map_checks():
    ordering = {'x': 0, 'xp': 1,
                'y': 2, 'yp': 3,
                'z': 4, 'zp': 5}
    bdd = BDD(ordering)
    # non-adjacent
    rename = {0: 2, 3: 4}
    qvars = set()
    r = _bdd.image(1, 1, rename, qvars, bdd)
    assert r == 1, r
    r = _bdd.preimage(1, 1, rename, qvars, bdd)
    assert r == 1, r
    # overlapping keys and values
    rename = {0: 1, 1: 2}
    with nt.assert_raises(AssertionError):
        _bdd.image(1, 1, rename, qvars, bdd)
    with nt.assert_raises(AssertionError):
        _bdd.preimage(1, 1, rename, qvars, bdd)
    # may be in support after quantification ?
    trans = bdd.add_expr('x -> xp')
    source = bdd.add_expr('x & y')
    qvars = {0}
    rename = {1: 0, 3: 2}
    with nt.assert_raises(AssertionError):
        _bdd.image(trans, source, rename, qvars, bdd)
    # in support of `target` ?
    qvars = set()
    target = bdd.add_expr('y & yp')
    rename = {2: 3}
    with nt.assert_raises(AssertionError):
        _bdd.preimage(trans, target, rename, qvars, bdd)
Example #2
0
def test_collect_garbage():
    # all nodes are garbage
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    n = len(g)
    assert n == 4, n
    uref = g._ref[abs(u)]
    assert uref == 0, uref
    _, v, w = g._succ[abs(u)]
    vref = g._ref[abs(v)]
    wref = g._ref[w]
    assert vref == 5, vref
    assert wref == 1, wref
    g.collect_garbage()
    n = len(g)
    assert n == 1, n
    assert u not in g, g._succ
    assert w not in g, g._succ
    # some nodes not garbage
    # projection of x is garbage
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    n = len(g)
    assert n == 4, n
    g._ref[abs(u)] += 1
    uref = g._ref[abs(u)]
    assert uref == 1, uref
    g.collect_garbage()
    n = len(g)
    assert n == 3, n
Example #3
0
def test_level_to_variable():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    assert g.var_at_level(0) == 'x'
    assert g.var_at_level(1) == 'y'
    with nt.assert_raises(AssertionError):
        g.var_at_level(10)
Example #4
0
def test_image_rename_map_checks():
    ordering = {'x': 0, 'xp': 1, 'y': 2, 'yp': 3, 'z': 4, 'zp': 5}
    bdd = BDD(ordering)
    # non-adjacent
    rename = {0: 2, 3: 4}
    qvars = set()
    with nt.assert_raises(AssertionError):
        _bdd.image(1, 1, rename, qvars, bdd)
    with nt.assert_raises(AssertionError):
        _bdd.preimage(1, 1, rename, qvars, bdd)
    # overlapping keys and values
    rename = {0: 1, 1: 2}
    with nt.assert_raises(AssertionError):
        _bdd.image(1, 1, rename, qvars, bdd)
    with nt.assert_raises(AssertionError):
        _bdd.preimage(1, 1, rename, qvars, bdd)
    # may be in support after quantification ?
    trans = bdd.add_expr('x -> xp')
    source = bdd.add_expr('x & y')
    qvars = {0}
    rename = {1: 0, 3: 2}
    with nt.assert_raises(AssertionError):
        _bdd.image(trans, source, rename, qvars, bdd)
    # in support of `target` ?
    qvars = set()
    target = bdd.add_expr('y & yp')
    rename = {2: 3}
    with nt.assert_raises(AssertionError):
        _bdd.preimage(trans, target, rename, qvars, bdd)
Example #5
0
def test_level_to_variable():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    assert g.var_at_level(0) == 'x'
    assert g.var_at_level(1) == 'y'
    with nt.assert_raises(AssertionError):
        g.var_at_level(10)
Example #6
0
def test_elimination():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    g.roots.add(2)
    # high == low, so node 2 is redundant
    g._succ[2] = (0, 3, 3)
    g._succ[3] = (1, -1, 1)
    h = g.reduction()
    assert set(h) == {1, 2}
Example #7
0
def test_elimination():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    g.roots.add(2)
    # high == low, so node 2 is redundant
    g._succ[2] = (0, 3, 3)
    g._succ[3] = (1, -1, 1)
    h = g.reduction()
    assert set(h) == {1, 2}
Example #8
0
def x_and_not_y():
    # remember:
    # 2 = !(x & !y)
    # -2 = x & !y
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    u = 3
    v = -1
    w = 1
    t = (1, v, w)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[abs(v)] += 1
    g._ref[abs(w)] += 1
    g._ref[abs(u)] = 0
    u = 2
    v = 1
    w = 3
    t = (0, v, w)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[abs(v)] += 1
    g._ref[abs(w)] += 1
    g._ref[abs(u)] = 0
    g._min_free = 4
    return g
Example #9
0
def test_add_expr():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # x
    ix = ordering['x']
    u = g.add_expr('x')
    h = ref_var(ix)
    compare(u, g, h)
    # x and y
    u = g.add_expr('x && y')
    h = ref_x_and_y()
    compare(u, g, h)
Example #10
0
def test_add_expr():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # x
    ix = ordering['x']
    u = g.add_expr('x')
    h = ref_var(ix)
    compare(u, g, h)
    # x and y
    u = g.add_expr('x && y')
    h = ref_x_and_y()
    compare(u, g, h)
Example #11
0
def test_isomorphism():
    ordering = {'x': 0}
    g = BDD(ordering)
    g.roots.update([2, 3])
    g._succ[2] = (0, -1, 1)
    g._succ[3] = (0, -1, 1)
    h = g.reduction()
    assert set(h) == {1, 2}, set(h)
    assert 0 not in h
    assert h._succ[1] == (1, None, None)
    assert h._succ[2] == (0, -1, 1)
    assert h.roots == {2}
Example #12
0
def test_isomorphism():
    ordering = {'x': 0}
    g = BDD(ordering)
    g.roots.update([2, 3])
    g._succ[2] = (0, -1, 1)
    g._succ[3] = (0, -1, 1)
    h = g.reduction()
    assert set(h) == {1, 2}, set(h)
    assert 0 not in h
    assert h._succ[1] == (1, None, None)
    assert h._succ[2] == (0, -1, 1)
    assert h.roots == {2}
Example #13
0
def test_rename():
    ordering = {'x': 0, 'xp': 1}
    g = BDD(ordering)
    x = g.add_expr('x')
    xp = g.add_expr('xp')
    dvars = {'x': 'xp'}
    xrenamed = _bdd.rename(x, g, dvars)
    assert xrenamed == xp, xrenamed
    ordering = {'x': 0, 'xp': 1, 'y': 2, 'yp': 3, 'z': 4, 'zp': 5}
    g = BDD(ordering)
    u = g.add_expr('x && y && ! z')
    dvars = {'x': 'xp', 'y': 'yp', 'z': 'zp'}
    urenamed = _bdd.rename(u, g, dvars)
    up = g.add_expr('xp && yp && ! zp')
    assert urenamed == up, urenamed
    # assertion violations
    # non-neighbors
    dvars = {'x': 'yp'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(u, g, dvars)
    # u not in bdd
    dvars = {'x': 'xp'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(15, g, dvars)
    # y essential for u
    dvars = {'xp': 'y'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(u, g, dvars)
    # old and new vars intersect
    dvars = {'x': 'x'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(u, g, dvars)
Example #14
0
def x_and_not_y():
    # remember:
    # 2 = !(x & !y)
    # -2 = x & !y
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    u = 3
    v = -1
    w = 1
    t = (1, v, w)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[abs(v)] += 1
    g._ref[abs(w)] += 1
    g._ref[abs(u)] = 0
    u = 2
    v = 1
    w = 3
    t = (0, v, w)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[abs(v)] += 1
    g._ref[abs(w)] += 1
    g._ref[abs(u)] = 0
    g._min_free = 4
    return g
Example #15
0
def test_collect_garbage():
    # all nodes are garbage
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    n = len(g)
    assert n == 4, n
    uref = g._ref[abs(u)]
    assert uref == 0, uref
    _, v, w = g._succ[abs(u)]
    vref = g._ref[abs(v)]
    wref = g._ref[w]
    assert vref == 5, vref
    assert wref == 1, wref
    g.collect_garbage()
    n = len(g)
    assert n == 1, n
    assert u not in g, g._succ
    assert w not in g, g._succ
    # some nodes not garbage
    # projection of x is garbage
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    n = len(g)
    assert n == 4, n
    g._ref[abs(u)] += 1
    uref = g._ref[abs(u)]
    assert uref == 1, uref
    g.collect_garbage()
    n = len(g)
    assert n == 3, n
Example #16
0
def test_reduce_combined():
    """Fig.5 in 1986 Bryant TOC"""
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    g.roots.add(2)
    g._succ[2] = (0, 3, 4)
    g._succ[3] = (1, -1, 5)
    g._succ[4] = (1, 5, 6)
    g._succ[5] = (2, -1, 1)
    g._succ[6] = (2, -1, 1)
    h = g.reduction()
    assert 1 in h
    assert ordering == h.ordering

    r = nx.MultiDiGraph()
    r.add_node(1, level=3)
    r.add_node(2, level=0)
    r.add_node(3, level=1)
    r.add_node(4, level=2)

    r.add_edge(2, 3, value=False, complement=False)
    r.add_edge(2, 4, value=True, complement=False)
    r.add_edge(3, 4, value=True, complement=False)
    r.add_edge(3, 1, value=False, complement=True)
    r.add_edge(4, 1, value=False, complement=True)
    r.add_edge(4, 1, value=True, complement=False)

    (u, ) = h.roots
    compare(u, h, r)
Example #17
0
def test_dump_load_manager():
    prefix = 'test_dump_load_manager'
    g = BDD({'x': 0, 'y': 1})
    e = 'x & !y'
    u = g.add_expr(e)
    g.incref(u)
    fname = prefix + '.p'
    g._dump_manager(fname)
    h = g._load_manager(fname)
    assert g.assert_consistent()
    u_ = h.add_expr(e)
    assert u == u_, (u, u_)
Example #18
0
def test_reduce_combined():
    """Fig.5 in 1986 Bryant TOC"""
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    g.roots.add(2)
    g._succ[2] = (0, 3, 4)
    g._succ[3] = (1, -1, 5)
    g._succ[4] = (1, 5, 6)
    g._succ[5] = (2, -1, 1)
    g._succ[6] = (2, -1, 1)
    h = g.reduction()
    assert 1 in h
    assert ordering == h.ordering

    r = nx.MultiDiGraph()
    r.add_node(1, level=3)
    r.add_node(2, level=0)
    r.add_node(3, level=1)
    r.add_node(4, level=2)

    r.add_edge(2, 3, value=False, complement=False)
    r.add_edge(2, 4, value=True, complement=False)
    r.add_edge(3, 4, value=True, complement=False)
    r.add_edge(3, 1, value=False, complement=True)
    r.add_edge(4, 1, value=False, complement=True)
    r.add_edge(4, 1, value=True, complement=False)

    (u, ) = h.roots
    compare(u, h, r)
Example #19
0
def test_descendants():
    ordering = dict(x=0, y=1)
    b = BDD(ordering)
    u = b.add_expr('x && y')
    v = b.add_expr('x | y')
    roots = [u, v]
    nodes = b.descendants(roots)
    nodes_u = b.descendants([u])
    nodes_v = b.descendants([v])
    assert u in nodes_u, nodes_u
    assert v in nodes_v, nodes_v
    assert u in nodes, nodes
    assert v in nodes, nodes
    assert 1 in nodes_u, nodes_u
    assert 1 in nodes_v, nodes_v
    assert 1 in nodes, nodes
    assert len(nodes_u) == 3, nodes_u
    assert len(nodes_v) == 3, nodes_v
    assert nodes_u != nodes_v, (nodes_u, nodes_v)
    assert len(nodes) == 4, nodes
    assert nodes == nodes_u.union(nodes_v), (nodes, b._succ)
    # no roots
    roots = []
    nodes = b.descendants(roots)
    assert len(nodes) == 0, nodes
Example #20
0
def test_rename():
    ordering = {'x': 0, 'xp': 1}
    g = BDD(ordering)
    x = g.add_expr('x')
    xp = g.add_expr('xp')
    dvars = {'x': 'xp'}
    xrenamed = _bdd.rename(x, g, dvars)
    assert xrenamed == xp, xrenamed
    ordering = {'x': 0, 'xp': 1,
                'y': 2, 'yp': 3,
                'z': 4, 'zp': 5}
    g = BDD(ordering)
    u = g.add_expr('x && y && ! z')
    dvars = {'x': 'xp', 'y': 'yp', 'z': 'zp'}
    urenamed = _bdd.rename(u, g, dvars)
    up = g.add_expr('xp && yp && ! zp')
    assert urenamed == up, urenamed
    # assertion violations
    # non-neighbors
    dvars = {'x': 'yp'}
    r = _bdd.rename(u, g, dvars)
    r_ = g.add_expr('yp && y && ! z')
    assert r == r_, (r, r_)
    # u not in bdd
    dvars = {'x': 'xp'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(1000, g, dvars)
    # y essential for u
    dvars = {'xp': 'y'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(u, g, dvars)
    # old and new vars intersect
    dvars = {'x': 'x'}
    with nt.assert_raises(AssertionError):
        _bdd.rename(u, g, dvars)
Example #21
0
def two_vars_xy():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    u = 2
    t = (0, -1, 1)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[u] = 1
    u = 3
    t = (1, -1, 1)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[u] = 1
    g._min_free = u + 1
    return g
Example #22
0
def test_dump_load_manager():
    prefix = 'test_dump_load_manager'
    g = BDD({'x': 0, 'y': 1})
    e = 'x & !y'
    u = g.add_expr(e)
    g.incref(u)
    fname = prefix + '.p'
    g._dump_manager(fname)
    h = g._load_manager(fname)
    assert g.assert_consistent()
    u_ = h.add_expr(e)
    assert u == u_, (u, u_)
Example #23
0
def test_bdd_to_mdd():
    from dd.bdd import BDD

    ordering = {'x': 0, 'y': 1}
    bdd = BDD(ordering)
    u = bdd.add_expr('x & ! y')
    bdd.incref(u)
    # BDD -> MDD
    dvars = dict(
        x=dict(level=1, len=2, bitnames=['x']),
        y=dict(level=0, len=2, bitnames=['y']))
    mdd, umap = dd.mdd.bdd_to_mdd(bdd, dvars)
    # pd = dd.mdd.to_pydot(mdd)
    # pd.write_pdf('mdd.pdf')
    # bdd.dump('bdd.pdf')
    v = umap[abs(u)]
    if u < 0:
        v = -v
    print(v)
Example #24
0
def test_pick_iter():
    # x & y
    g = x_and_y()
    u = 4
    bits = {'x', 'y'}
    s = [{'x': 1, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    # care_bits == support (default)
    bits = None
    compare_iter_to_list_of_sets(u, g, s, bits)
    #
    # x | y
    g = x_or_y()
    u = 4
    # support
    bits = None
    s = [{'x': 1, 'y': 0}, {'x': 1, 'y': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    # only what appears along traversal
    bits = set()
    s = [{'x': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    # bits < support
    bits = {'x'}
    s = [{'x': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    bits = {'y'}
    s = [{'x': 1, 'y': 0}, {'x': 1, 'y': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    #
    # x & !y
    g = x_and_not_y()
    u = -2
    bits = {'x', 'y'}
    s = [{'x': 1, 'y': 0}]
    compare_iter_to_list_of_sets(u, g, s, bits)
    # gaps in order
    order = {'x': 0, 'y': 1, 'z': 2}
    bdd = BDD(order)
    u = bdd.add_expr('x & z')
    (m, ) = bdd.pick_iter(u)
    assert m == {'x': 1, 'z': 1}, m
Example #25
0
def test_dump_load():
    prefix = 'test_dump_load'
    g = BDD({'x': 0, 'y': 1})
    e = 'x & !y'
    u = g.add_expr(e)
    g.incref(u)
    fname = prefix + '.p'
    g.dump(fname)
    h = BDD.load(fname)
    assert h.assert_consistent()
    u_ = h.add_expr(e)
    assert u == u_, (u, u_)
    h.dump(prefix + '.pdf')
Example #26
0
def test_descendants():
    ordering = dict(x=0, y=1)
    b = BDD(ordering)
    u = b.add_expr('x && y')
    v = b.add_expr('x | y')
    roots = [u, v]
    nodes = b.descendants(roots)
    nodes_u = b.descendants([u])
    nodes_v = b.descendants([v])
    assert u in nodes_u, nodes_u
    assert v in nodes_v, nodes_v
    assert u in nodes, nodes
    assert v in nodes, nodes
    assert 1 in nodes_u, nodes_u
    assert 1 in nodes_v, nodes_v
    assert 1 in nodes, nodes
    assert len(nodes_u) == 3, nodes_u
    assert len(nodes_v) == 3, nodes_v
    assert nodes_u != nodes_v, (nodes_u, nodes_v)
    assert len(nodes) == 4, nodes
    assert nodes == nodes_u.union(nodes_v), (
        nodes, b._succ)
    # no roots
    roots = []
    nodes = b.descendants(roots)
    assert len(nodes) == 0, nodes
Example #27
0
def test_sat_iter():
    # x & y
    g = x_and_y()
    u = 2
    s = [{'x': 1, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s)
    # x | y
    g = x_or_y()
    u = 2
    s = [{'x': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s)
    # x & !y
    g = x_and_not_y()
    u = -2
    s = [{'x': 1, 'y': 0}]
    compare_iter_to_list_of_sets(u, g, s)
    # gaps in order
    order = {'x': 0, 'y': 1, 'z': 2}
    bdd = BDD(order)
    u = bdd.add_expr('x & z')
    (m,) = bdd.sat_iter(u)
    assert m == {'x': 1, 'z': 1}, m
Example #28
0
def test_sat_iter():
    # x & y
    g = x_and_y()
    u = 2
    s = [{'x': 1, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s)
    # x | y
    g = x_or_y()
    u = 2
    s = [{'x': 1}, {'x': 0, 'y': 1}]
    compare_iter_to_list_of_sets(u, g, s)
    # x & !y
    g = x_and_not_y()
    u = -2
    s = [{'x': 1, 'y': 0}]
    compare_iter_to_list_of_sets(u, g, s)
    # gaps in order
    order = {'x': 0, 'y': 1, 'z': 2}
    bdd = BDD(order)
    u = bdd.add_expr('x & z')
    (m, ) = bdd.sat_iter(u)
    assert m == {'x': 1, 'z': 1}, m
Example #29
0
def test_top_cofactor():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    x = ordering['x']
    y = ordering['y']
    u = g.find_or_add(y, -1, 1)
    assert g._top_cofactor(u, x) == (u, u)
    assert g._top_cofactor(u, y) == (-1, 1)
    u = g.find_or_add(x, -1, 1)
    assert g._top_cofactor(u, x) == (-1, 1)
    assert g._top_cofactor(-u, x) == (1, -1)
Example #30
0
def test_var():
    b = BDD()
    with nt.assert_raises(AssertionError):
        b.var('x')
    j = b.add_var('x')
    u = b.var('x')
    assert u > 0, u
    level, low, high = b.succ(u)
    assert level == j, (level, j)
    assert low == b.false, low
    assert high == b.true, high
Example #31
0
def two_vars_xy():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    u = 2
    t = (0, -1, 1)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[u] = 1
    u = 3
    t = (1, -1, 1)
    g._succ[u] = t
    g._pred[t] = u
    g._ref[u] = 1
    g._min_free = u + 1
    return g
Example #32
0
def load(fname):
    """Return a `BDD` loaded from DDDMP file `fname`.

    If no `.orderedvarnames` appear in the file,
    then `.suppvarnames` and `.permids` are used instead.
    In the second case, the variable levels contains blanks.
    To avoid blanks, the levels are re-indexed here.
    This has no effect if `.orderedvarnames` appears in the file.

    DDDMP files are dumped by [CUDD](http://vlsi.colorado.edu/~fabio/CUDD/).
    """
    parser = Parser()
    bdd_succ, n_vars, ordering, roots = parser.parse(fname)
    # reindex to ensure no blanks
    perm = {k: var for var, k in ordering.iteritems()}
    perm = {i: perm[k] for i, k in enumerate(sorted(perm))}
    new_ordering = {var: k for k, var in perm.iteritems()}
    old2new = {ordering[var]: new_ordering[var] for var in ordering}
    # convert
    bdd = BDD(new_ordering)
    umap = {-1: -1, 1: 1}
    for j in xrange(len(new_ordering) - 1, -1, -1):
        for u, (k, v, w) in bdd_succ.iteritems():
            # terminal ?
            if v is None:
                assert w is None, w
                continue
            # non-terminal
            i = old2new[k]
            if i != j:
                continue
            p, q = umap[abs(v)], umap[w]
            if v < 0:
                p = -p
            r = bdd.find_or_add(i, p, q)
            umap[abs(u)] = r
    bdd.roots.update(roots)
    return bdd
Example #33
0
def load(fname):
    """Return a `BDD` loaded from DDDMP file `fname`.

    If no `.orderedvarnames` appear in the file,
    then `.suppvarnames` and `.permids` are used instead.
    In the second case, the variable levels contains blanks.
    To avoid blanks, the levels are re-indexed here.
    This has no effect if `.orderedvarnames` appears in the file.

    DDDMP files are dumped by [CUDD](http://vlsi.colorado.edu/~fabio/CUDD/).
    """
    parser = Parser()
    bdd_succ, n_vars, ordering, roots = parser.parse(fname)
    # reindex to ensure no blanks
    perm = {k: var for var, k in ordering.iteritems()}
    perm = {i: perm[k] for i, k in enumerate(sorted(perm))}
    new_ordering = {var: k for k, var in perm.iteritems()}
    old2new = {ordering[var]: new_ordering[var] for var in ordering}
    # convert
    bdd = BDD(new_ordering)
    umap = {-1: -1, 1: 1}
    for j in xrange(len(new_ordering) - 1, -1, -1):
        for u, (k, v, w) in bdd_succ.iteritems():
            # terminal ?
            if v is None:
                assert w is None, w
                continue
            # non-terminal
            i = old2new[k]
            if i != j:
                continue
            p, q = umap[abs(v)], umap[w]
            if v < 0:
                p = -p
            r = bdd.find_or_add(i, p, q)
            umap[abs(u)] = r
    bdd.roots.update(roots)
    return bdd
Example #34
0
def test_top_cofactor():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    x = ordering['x']
    y = ordering['y']
    u = g.find_or_add(y, -1, 1)
    assert g._top_cofactor(u, x) == (u, u)
    assert g._top_cofactor(u, y) == (-1, 1)
    u = g.find_or_add(x, -1, 1)
    assert g._top_cofactor(u, x) == (-1, 1)
    assert g._top_cofactor(-u, x) == (1, -1)
Example #35
0
def test_bdd_to_mdd():
    from dd.bdd import BDD

    ordering = {'x': 0, 'y': 1}
    bdd = BDD(ordering)
    u = bdd.add_expr('x & ! y')
    bdd.incref(u)
    # BDD -> MDD
    dvars = dict(x=dict(level=1, len=2, bitnames=['x']),
                 y=dict(level=0, len=2, bitnames=['y']))
    mdd, umap = dd.mdd.bdd_to_mdd(bdd, dvars)
    pd = dd.mdd.to_pydot(mdd)
    pd.write_pdf('mdd.pdf')
    bdd.dump('bdd.pdf')
    v = umap[abs(u)]
    if u < 0:
        v = -v
    print(v)
Example #36
0
def test_ite():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # x
    ix = ordering['x']
    x = g.find_or_add(ix, -1, 1)
    h = ref_var(ix)
    compare(x, g, h)
    # y
    iy = ordering['y']
    y = g.find_or_add(iy, -1, 1)
    h = ref_var(iy)
    compare(y, g, h)
    # x and y
    u = g.ite(x, y, -1)
    h = ref_x_and_y()
    compare(u, g, h)
    # x or y
    u = g.ite(x, 1, y)
    h = ref_x_or_y()
    compare(u, g, h)
    # negation
    assert g.ite(x, -1, 1) == -x, g._succ
    assert g.ite(-x, -1, 1) == x, g._succ
Example #37
0
def test_ite():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # x
    ix = ordering['x']
    x = g.find_or_add(ix, -1, 1)
    h = ref_var(ix)
    compare(x, g, h)
    # y
    iy = ordering['y']
    y = g.find_or_add(iy, -1, 1)
    h = ref_var(iy)
    compare(y, g, h)
    # x and y
    u = g.ite(x, y, -1)
    h = ref_x_and_y()
    compare(u, g, h)
    # x or y
    u = g.ite(x, 1, y)
    h = ref_x_or_y()
    compare(u, g, h)
    # negation
    assert g.ite(x, -1, 1) == -x, g._succ
    assert g.ite(-x, -1, 1) == x, g._succ
Example #38
0
def test_swap():
    # x, y
    g = BDD({'x': 0, 'y': 1})
    x = g.add_expr('x')
    y = g.add_expr('y')
    g.incref(x)
    g.incref(y)
    n = len(g)
    assert n == 3, n
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'y': 0, 'x': 1}, g.ordering
    assert g.assert_consistent()
    # functions remain invariant
    x_ = g.add_expr('x')
    y_ = g.add_expr('y')
    assert x == x_, (x, x_, g._succ)
    assert y == y_, (y, y_, g._succ)
    # external reference counts remain unchanged
    assert g._ref[abs(x)] == 1
    assert g._ref[abs(y)] == 1
    # x & y
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    g.incref(u)
    nold, n = g.swap('x', 'y')
    assert nold == n, (nold, n)
    assert g.ordering == {'y': 0, 'x': 1}, g.ordering
    u_ = g.add_expr('x & y')
    assert u == u_, (u, u_)
    assert g.assert_consistent()
    # reference counts unchanged
    assert g._ref[abs(u)] == 1
    # x & !y
    # tests handling of complement edges
    e = 'x & !y'
    g = x_and_not_y()
    u = g.add_expr(e)
    g.incref(u)
    g.collect_garbage()
    n = len(g)
    assert n == 3, n
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'x': 1, 'y': 0}
    assert g.assert_consistent()
    u_ = g.add_expr(e)
    # function u must have remained unaffected
    assert u_ == u, (u, u_, g._succ)
    # invert swap of:
    # x & !y
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'x': 0, 'y': 1}
    assert g.assert_consistent()
    u_ = g.add_expr(e)
    assert u_ == u, (u, u_, g._succ)
    # Figs. 6.24, 6.25 Baier 2008
    g = BDD({'z1': 0, 'y1': 1, 'z2': 2, 'y2': 3, 'z3': 4, 'y3': 5})
    u = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    n = len(g)
    assert n == 16, n
    g.collect_garbage()
    n = len(g)
    assert n == 7, n
    # sift to inefficient order
    g.swap('y1', 'z2')  # z1, z2, y1, y2, z3, y3
    g.swap('y2', 'z3')  # z1, z2, y1, z3, y2, y3
    g.swap('y1', 'z3')  # z1, z2, z3, y1, y2, y3
    n = len(g)
    assert n == 15, n
    assert g.assert_consistent()
    new_ordering = {'z1': 0, 'z2': 1, 'z3': 2, 'y1': 3, 'y2': 4, 'y3': 5}
    assert g.ordering == new_ordering, g.ordering
    u_ = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    assert u_ == u, (u, u_, g._succ)
Example #39
0
def test_cofactor():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # u not in g
    with nt.assert_raises(AssertionError):
        g.cofactor(5, {'x': 0, 'y': 1, 'z': 0})
    # x & y
    e = g.add_expr('x && y')
    x = g.add_expr('x')
    assert g.cofactor(x, {'x': 0}) == -1
    assert g.cofactor(x, {'x': 1}) == 1
    assert g.cofactor(-x, {'x': 0}) == 1
    assert g.cofactor(-x, {'x': 1}) == -1
    y = g.add_expr('y')
    assert g.cofactor(e, {'x': 1}) == y
    assert g.cofactor(e, {'x': 0}) == -1
    assert g.cofactor(e, {'y': 1}) == x
    assert g.cofactor(e, {'y': 0}) == -1

    assert g.cofactor(-e, {'x': 0}) == 1
    assert g.cofactor(-e, {'x': 1}) == -y
    assert g.cofactor(-e, {'y': 0}) == 1
    assert g.cofactor(-e, {'y': 1}) == -x
Example #40
0
def test_compose():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # x & (x | z)
    a = g.add_expr('x && y')
    b = g.add_expr('x || z')
    c = g.compose(a, 'y', b)
    d = g.add_expr('x && (x || z)')
    assert c == d, (c, d)
    # (y | z) & x
    ordering = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
    g = BDD(ordering)
    a = g.add_expr('(x && y) || z')
    b = g.add_expr('(y || z) && x')
    c = g.compose(a, 'z', b)
    assert c == b, (c, b)
    # long expr
    ordering = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
    g = BDD(ordering)
    a = g.add_expr('(x && y) || (!z || (w && y && x))')
    b = g.add_expr('(y || z) && x')
    c = g.compose(a, 'y', b)
    d = g.add_expr('(x && ((y || z) && x)) ||'
                   ' (!z || (w && ((y || z) && x) && x))')
    assert c == d, (c, d)
    # complemented edges
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    f = g.add_expr('x <-> y')
    var = 'y'
    new_level = 0
    var_node = g.find_or_add(new_level, -1, 1)
    u = g.compose(f, var, var_node)
    assert u == 1, g.to_expr(u)
Example #41
0
def test_find_or_add():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # init
    n = len(g)
    m = g._min_free
    assert n == 1, n
    assert m == 2, m
    # elimination rule
    i = 0
    v = -1
    w = 1
    n = len(g)
    u = g.find_or_add(i, v, v)
    n_ = len(g)
    assert n == n_, (n, n_)
    assert u == v, (u, v)
    assert not g._pred, g._pred
    # unchanged min_free
    v = 1
    m = g._min_free
    g.find_or_add(i, v, v)
    m_ = g._min_free
    assert m_ == m, (m_, m)
    # add new node
    g = BDD(ordering)
    v = -1
    w = 1
    n = len(g)
    m = g._min_free
    assert n == 1, n
    u = g.find_or_add(i, v, w)
    n_ = len(g)
    m_ = g._min_free
    assert u != v, (u, v)
    assert n_ == n + 1, (n, n_)
    assert m_ == m + 1, (m, m_)
    assert g._succ[u] == (i, -1, 1)
    assert (i, v, w) in g._pred
    assert abs(u) in g._ref
    assert g._ref[abs(u)] == 0
    assert g._ref[abs(v)] == 2, g._ref
    # independent increase of reference counters
    v = u
    w = w
    refv = g._ref[abs(v)]
    refw = g._ref[w]
    u = g.find_or_add(i, v, w)
    refv_ = g._ref[abs(v)]
    refw_ = g._ref[w]
    assert refv + 1 == refv_, (refv, refv_)
    assert refw + 1 == refw_, (refw, refw_)
    # add existing
    n = len(g)
    m = g._min_free
    refv = g._ref[abs(v)]
    refw = g._ref[w]
    r = g.find_or_add(i, v, w)
    n_ = len(g)
    m_ = g._min_free
    refv_ = g._ref[abs(v)]
    refw_ = g._ref[w]
    assert n == n_, (n, n_)
    assert m == m_, (m, m_)
    assert u == r, u
    assert refv == refv_, (refv, refv_)
    assert refw == refw_, (refw, refw_)
    # only non-terminals can be added
    with nt.assert_raises(AssertionError):
        g.find_or_add(2, -1, 1)
    # low and high must already exist
    with nt.assert_raises(AssertionError):
        g.find_or_add(0, 3, 4)
    # canonicity of complemented edges
    # v < 0, w > 0
    g = BDD(ordering)
    i = 0
    v = -1
    w = 1
    u = g.find_or_add(i, v, w)
    assert u > 0, u
    # v > 0, w < 0
    v = 1
    w = -1
    u = g.find_or_add(i, v, w)
    assert u < 0, u
    assert abs(u) in g._succ, u
    _, v, w = g._succ[abs(u)]
    assert v < 0, v
    assert w > 0, w
    # v < 0, w < 0
    v = -1
    w = -2
    u = g.find_or_add(i, v, w)
    assert u < 0, u
    _, v, w = g._succ[abs(u)]
    assert v > 0, v
    assert w > 0, w
Example #42
0
def test_next_free_int():
    g = BDD()
    # contiguous
    g._succ = {1, 2, 3}
    n = g._next_free_int(start=1, debug=True)
    assert n == 4, n
    n = g._next_free_int(start=3, debug=True)
    assert n == 4, n
    # with blanks
    g._succ = {1, 3}
    n = g._next_free_int(start=1, debug=True)
    assert n == 2, n
    n = g._next_free_int(start=3)
    assert n == 4, n
    # full
    g._succ = {1, 2, 3}
    g.max_nodes = 3
    with nt.assert_raises(Exception):
        g._next_free_int(start=1)
Example #43
0
def test_compose():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # x & (x | z)
    a = g.add_expr('x && y')
    b = g.add_expr('x || z')
    c = g.compose(a, 'y', b)
    d = g.add_expr('x && (x || z)')
    assert c == d, (c, d)
    # (y | z) & x
    ordering = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
    g = BDD(ordering)
    a = g.add_expr('(x && y) || z')
    b = g.add_expr('(y || z) && x')
    c = g.compose(a, 'z', b)
    assert c == b, (c, b)
    # long expr
    ordering = {'x': 0, 'y': 1, 'z': 2, 'w': 3}
    g = BDD(ordering)
    a = g.add_expr('(x && y) || (!z || (w && y && x))')
    b = g.add_expr('(y || z) && x')
    c = g.compose(a, 'y', b)
    d = g.add_expr(
        '(x && ((y || z) && x)) ||'
        ' (!z || (w && ((y || z) && x) && x))')
    assert c == d, (c, d)
    # complemented edges
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    f = g.add_expr('x <-> y')
    var = 'y'
    new_level = 0
    var_node = g.find_or_add(new_level, -1, 1)
    u = g.compose(f, var, var_node)
    assert u == 1, g.to_expr(u)
Example #44
0
def test_quantify():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # x & y
    e = g.add_expr('x && ! y')
    x = g.add_expr('x')
    not_y = g.add_expr('! y')
    assert g.quantify(e, {'x'}) == not_y
    assert g.quantify(e, {'x'}, forall=True) == -1
    assert g.quantify(e, {'y'}) == x
    assert g.quantify(e, {'x'}, forall=True) == -1
    # x | y | z
    e = g.add_expr('x || y || z')
    xy = g.add_expr('x || y')
    yz = g.add_expr('y || z')
    zx = g.add_expr('z || x')
    assert g.quantify(e, {'x'})
    assert g.quantify(e, {'y'})
    assert g.quantify(e, {'z'})
    assert g.quantify(e, {'z'}, forall=True) == xy
    assert g.quantify(e, {'x'}, forall=True) == yz
    assert g.quantify(e, {'y'}, forall=True) == zx
    # complement edges
    u = -x
    v = g.quantify(u, {'y'}, forall=True)
    assert v == -x, g.to_expr(v)
    # multiple values: test recursion
    e = g.add_expr('x & y & z')
    x = g.add_expr('x')
    r = g.quantify(e, {'y', 'z'})
    assert r == x, r
Example #45
0
def test_next_free_int():
    g = BDD()
    # contiguous
    g._succ = {1, 2, 3}
    n = g._next_free_int(start=1, debug=True)
    assert n == 4, n
    n = g._next_free_int(start=3, debug=True)
    assert n == 4, n
    # with blanks
    g._succ = {1, 3}
    n = g._next_free_int(start=1, debug=True)
    assert n == 2, n
    n = g._next_free_int(start=3)
    assert n == 4, n
    # full
    g._succ = {1, 2, 3}
    g.max_nodes = 3
    with nt.assert_raises(Exception):
        g._next_free_int(start=1)
Example #46
0
def test_rename_syntax():
    b = BDD()
    [b.add_var(var) for var in ['x', 'y', 'z', 'w']]
    # single substitution
    u = b.add_expr('\S y / x: True')
    assert u == b.true, u
    u = b.add_expr('\S y / x: False')
    assert u == b.false, u
    u = b.add_expr('\S y / x: x')
    u_ = b.add_expr('y')
    assert u == u_, (u, u_)
    u = b.add_expr('\S y / x: z')
    u_ = b.add_expr('z')
    assert u == u_, (u, u_)
    u = b.add_expr('\S y / x: x & z')
    u_ = b.add_expr('y & z')
    assert u == u_, (u, u_)
    # multiple substitution
    u = b.add_expr('\S y / x,  w / z: x & z')
    u_ = b.add_expr('y & w')
    assert u == u_, (u, u_)
    u = b.add_expr('\S y / x,  w / z: z | ! x')
    u_ = b.add_expr('w | ! y')
    assert u == u_, (u, u_)
Example #47
0
def test_find_or_add():
    ordering = {'x': 0, 'y': 1}
    g = BDD(ordering)
    # init
    n = len(g)
    m = g._min_free
    assert n == 1, n
    assert m == 2, m
    # elimination rule
    i = 0
    v = -1
    w = 1
    n = len(g)
    u = g.find_or_add(i, v, v)
    n_ = len(g)
    assert n == n_, (n, n_)
    assert u == v, (u, v)
    assert not g._pred, g._pred
    # unchanged min_free
    v = 1
    m = g._min_free
    g.find_or_add(i, v, v)
    m_ = g._min_free
    assert m_ == m, (m_, m)
    # add new node
    g = BDD(ordering)
    v = -1
    w = 1
    n = len(g)
    m = g._min_free
    assert n == 1, n
    u = g.find_or_add(i, v, w)
    n_ = len(g)
    m_ = g._min_free
    assert u != v, (u, v)
    assert n_ == n + 1, (n, n_)
    assert m_ == m + 1, (m, m_)
    assert g._succ[u] == (i, -1, 1)
    assert (i, v, w) in g._pred
    assert abs(u) in g._ref
    assert g._ref[abs(u)] == 0
    assert g._ref[abs(v)] == 2, g._ref
    # independent increase of reference counters
    v = u
    w = w
    refv = g._ref[abs(v)]
    refw = g._ref[w]
    u = g.find_or_add(i, v, w)
    refv_ = g._ref[abs(v)]
    refw_ = g._ref[w]
    assert refv + 1 == refv_, (refv, refv_)
    assert refw + 1 == refw_, (refw, refw_)
    # add existing
    n = len(g)
    m = g._min_free
    refv = g._ref[abs(v)]
    refw = g._ref[w]
    r = g.find_or_add(i, v, w)
    n_ = len(g)
    m_ = g._min_free
    refv_ = g._ref[abs(v)]
    refw_ = g._ref[w]
    assert n == n_, (n, n_)
    assert m == m_, (m, m_)
    assert u == r, u
    assert refv == refv_, (refv, refv_)
    assert refw == refw_, (refw, refw_)
    # only non-terminals can be added
    with nt.assert_raises(AssertionError):
        g.find_or_add(2, -1, 1)
    # low and high must already exist
    with nt.assert_raises(AssertionError):
        g.find_or_add(0, 3, 4)
    # canonicity of complemented edges
    # v < 0, w > 0
    g = BDD(ordering)
    i = 0
    v = -1
    w = 1
    u = g.find_or_add(i, v, w)
    assert u > 0, u
    # v > 0, w < 0
    v = 1
    w = -1
    u = g.find_or_add(i, v, w)
    assert u < 0, u
    assert abs(u) in g._succ, u
    _, v, w = g._succ[abs(u)]
    assert v < 0, v
    assert w > 0, w
    # v < 0, w < 0
    v = -1
    w = -2
    u = g.find_or_add(i, v, w)
    assert u < 0, u
    _, v, w = g._succ[abs(u)]
    assert v > 0, v
    assert w > 0, w
Example #48
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_)
Example #49
0
def test_dump_load():
    prefix = 'test_dump_load'
    fname = prefix + '.p'
    dvars = dict(x=0, y=1)
    # dump
    b = BDD(dvars)
    e = 'x & !y'
    u_dumped = b.add_expr(e)
    b.dump(fname, [u_dumped])
    b.dump(fname)  # no roots
    # load
    b = BDD(dvars)
    b.add_expr('x | y')
    u_new = b.add_expr(e)
    umap = b.load(fname)
    u_loaded = umap[abs(u_dumped)]
    if u_dumped < 0:
        u_loaded = -u_loaded
    assert u_loaded == u_new, (
        u_dumped, u_loaded, u_new, umap)
    assert b.assert_consistent()
Example #50
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_)
Example #51
0
def test_cofactor():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # u not in g
    with nt.assert_raises(AssertionError):
        g.cofactor(5, {'x': 0, 'y': 1, 'z': 0})
    # x & y
    e = g.add_expr('x && y')
    x = g.add_expr('x')
    assert g.cofactor(x, {'x': 0}) == -1
    assert g.cofactor(x, {'x': 1}) == 1
    assert g.cofactor(-x, {'x': 0}) == 1
    assert g.cofactor(-x, {'x': 1}) == -1
    y = g.add_expr('y')
    assert g.cofactor(e, {'x': 1}) == y
    assert g.cofactor(e, {'x': 0}) == -1
    assert g.cofactor(e, {'y': 1}) == x
    assert g.cofactor(e, {'y': 0}) == -1

    assert g.cofactor(-e, {'x': 0}) == 1
    assert g.cofactor(-e, {'x': 1}) == -y
    assert g.cofactor(-e, {'y': 0}) == 1
    assert g.cofactor(-e, {'y': 1}) == -x
Example #52
0
def test_quantifier_syntax():
    b = BDD()
    [b.add_var(var) for var in ['x', 'y']]
    # constants
    u = b.add_expr('\E x: True')
    assert u == b.true, u
    u = b.add_expr('\E x, y: True')
    assert u == b.true, u
    u = b.add_expr('\E x: False')
    assert u == b.false, u
    u = b.add_expr('\A x: True')
    assert u == b.true, u
    u = b.add_expr('\A x: False')
    assert u == b.false, u
    u = b.add_expr('\A x, y: False')
    assert u == b.false, u
    # variables
    u = b.add_expr('\E x: x')
    assert u == b.true, u
    u = b.add_expr('\A x: x')
    assert u == b.false, u
    u = b.add_expr('\E x, y: x')
    assert u == b.true, u
    u = b.add_expr('\E x, y: y')
    assert u == b.true, u
    u = b.add_expr('\A x: y')
    assert u == b.var('y'), u
    u = b.add_expr('\A x: ! y')
    u_ = b.apply('not', b.var('y'))
    assert u == u_, (u, u_)
Example #53
0
def test_quantifier_syntax():
    b = BDD()
    [b.add_var(var) for var in ['x', 'y']]
    # constants
    u = b.add_expr('\E x: True')
    assert u == b.true, u
    u = b.add_expr('\E x, y: True')
    assert u == b.true, u
    u = b.add_expr('\E x: False')
    assert u == b.false, u
    u = b.add_expr('\A x: True')
    assert u == b.true, u
    u = b.add_expr('\A x: False')
    assert u == b.false, u
    u = b.add_expr('\A x, y: False')
    assert u == b.false, u
    # variables
    u = b.add_expr('\E x: x')
    assert u == b.true, u
    u = b.add_expr('\A x: x')
    assert u == b.false, u
    u = b.add_expr('\E x, y: x')
    assert u == b.true, u
    u = b.add_expr('\E x, y: y')
    assert u == b.true, u
    u = b.add_expr('\A x: y')
    assert u == b.var('y'), u
    u = b.add_expr('\A x: ! y')
    u_ = b.apply('not', b.var('y'))
    assert u == u_, (u, u_)
Example #54
0
def test_swap():
    # x, y
    g = BDD({'x': 0, 'y': 1})
    x = g.add_expr('x')
    y = g.add_expr('y')
    g.incref(x)
    g.incref(y)
    n = len(g)
    assert n == 3, n
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'y': 0, 'x': 1}, g.ordering
    assert g.assert_consistent()
    # functions remain invariant
    x_ = g.add_expr('x')
    y_ = g.add_expr('y')
    assert x == x_, (x, x_, g._succ)
    assert y == y_, (y, y_, g._succ)
    # external reference counts remain unchanged
    assert g._ref[abs(x)] == 1
    assert g._ref[abs(y)] == 1
    # x & y
    g = BDD({'x': 0, 'y': 1})
    u = g.add_expr('x & y')
    g.incref(u)
    nold, n = g.swap('x', 'y')
    assert nold == n, (nold, n)
    assert g.ordering == {'y': 0, 'x': 1}, g.ordering
    u_ = g.add_expr('x & y')
    assert u == u_, (u, u_)
    assert g.assert_consistent()
    # reference counts unchanged
    assert g._ref[abs(u)] == 1
    # x & !y
    # tests handling of complement edges
    e = 'x & !y'
    g = x_and_not_y()
    u = g.add_expr(e)
    g.incref(u)
    g.collect_garbage()
    n = len(g)
    assert n == 3, n
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'x': 1, 'y': 0}
    assert g.assert_consistent()
    u_ = g.add_expr(e)
    # function u must have remained unaffected
    assert u_ == u, (u, u_, g._succ)
    # invert swap of:
    # x & !y
    nold, n = g.swap('x', 'y')
    assert n == 3, n
    assert nold == n, nold
    assert g.ordering == {'x': 0, 'y': 1}
    assert g.assert_consistent()
    u_ = g.add_expr(e)
    assert u_ == u, (u, u_, g._succ)
    # Figs. 6.24, 6.25 Baier 2008
    g = BDD({'z1': 0, 'y1': 1, 'z2': 2,
             'y2': 3, 'z3': 4, 'y3': 5})
    u = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    g.incref(u)
    n = len(g)
    assert n == 16, n
    g.collect_garbage()
    n = len(g)
    assert n == 7, n
    # sift to inefficient order
    g.swap('y1', 'z2')  # z1, z2, y1, y2, z3, y3
    g.swap('y2', 'z3')  # z1, z2, y1, z3, y2, y3
    g.swap('y1', 'z3')  # z1, z2, z3, y1, y2, y3
    n = len(g)
    assert n == 15, n
    assert g.assert_consistent()
    new_ordering = {
        'z1': 0, 'z2': 1, 'z3': 2,
        'y1': 3, 'y2': 4, 'y3': 5}
    assert g.ordering == new_ordering, g.ordering
    u_ = g.add_expr('(z1 & y1) | (z2 & y2) | (z3 & y3)')
    assert u_ == u, (u, u_, g._succ)
Example #55
0
def test_preimage():
    # exists: x, y
    # forall: z
    ordering = {'x': 0, 'xp': 1, 'y': 2, 'yp': 3, 'z': 4, 'zp': 5}
    rename = {0: 1, 2: 3, 4: 5}
    g = BDD(ordering)
    f = g.add_expr('!x')
    t = g.add_expr('x <-> !xp')
    qvars = {1, 3}
    p = preimage(t, f, rename, qvars, g)
    x = g.add_expr('x')
    assert x == p, (x, p)
    # a cycle
    # (x & y) -> (!x & y) ->
    # (!x & !y) -> (x & !y) -> wrap around
    t = g.add_expr('((x & y) -> (!xp & yp)) && '
                   '((!x & y) -> (!xp & !yp)) && '
                   '((!x & !y) -> (xp & !yp)) && '
                   '((x & !y) -> (xp & yp))')
    f = g.add_expr('x && y')
    p = preimage(t, f, rename, qvars, g)
    assert p == g.add_expr('x & !y')
    f = g.add_expr('x && !y')
    p = preimage(t, f, rename, qvars, g)
    assert p == g.add_expr('!x & !y')
    # backward reachable set
    f = g.add_expr('x & y')
    oldf = None
    while oldf != f:
        p = preimage(t, f, rename, qvars, g)
        oldf = f
        f = g.apply('or', p, oldf)
    assert f == 1
    # go around once
    f = g.add_expr('x & y')
    start = f
    for i in xrange(4):
        f = preimage(t, f, rename, qvars, g)
    end = f
    assert start == end
    # forall z exists x, y
    t = g.add_expr('('
                   '    ((x & y) -> (zp & xp & !yp)) | '
                   '    ((x & y) -> (!zp & !xp & yp))'
                   ') & '
                   '(!(x & y) -> False)')
    f = g.add_expr('x && !y')
    ep = preimage(t, f, rename, qvars, g)
    p = g.quantify(ep, {'zp'}, forall=True)
    assert p == -1
    f = g.add_expr('(x & !y) | (!x & y)')
    ep = preimage(t, f, rename, qvars, g)
    p = g.quantify(ep, {'zp'}, forall=True)
    assert p == g.add_expr('x & y')
Example #56
0
def test_rename():
    ordering = {'x': 0, 'xp': 1}
    g = BDD(ordering)
    x = g.add_expr('x')
    xp = g.add_expr('xp')
    dvars = {'x': 'xp'}
    xrenamed = g.let(dvars, x)
    assert xrenamed == xp, xrenamed
    ordering = {'x': 0, 'xp': 1, 'y': 2, 'yp': 3, 'z': 4, 'zp': 5}
    g = BDD(ordering)
    u = g.add_expr('x && y && ! z')
    dvars = {'x': 'xp', 'y': 'yp', 'z': 'zp'}
    urenamed = g.let(dvars, u)
    up = g.add_expr('xp && yp && ! zp')
    assert urenamed == up, urenamed
    # assertion violations
    # non-neighbors
    dvars = {'x': 'yp'}
    r = g.let(dvars, u)
    r_ = g.add_expr('yp && y && ! z')
    assert r == r_, (r, r_)
    # u not in bdd
    dvars = {'x': 'xp'}
    with nt.assert_raises(AssertionError):
        g.let(dvars, 1000)
    # y essential for u
    dvars = {'xp': 'y'}
    with nt.assert_raises(AssertionError):
        g.let(dvars, u)
    # old and new vars intersect
    dvars = {'x': 'x'}
    with nt.assert_raises(AssertionError):
        g.let(dvars, u)
Example #57
0
def test_quantify():
    ordering = {'x': 0, 'y': 1, 'z': 2}
    g = BDD(ordering)
    # x & y
    e = g.add_expr('x && ! y')
    x = g.add_expr('x')
    not_y = g.add_expr('! y')
    assert g.quantify(e, {'x'}) == not_y
    assert g.quantify(e, {'x'}, forall=True) == -1
    assert g.quantify(e, {'y'}) == x
    assert g.quantify(e, {'x'}, forall=True) == -1
    # x | y | z
    e = g.add_expr('x || y || z')
    xy = g.add_expr('x || y')
    yz = g.add_expr('y || z')
    zx = g.add_expr('z || x')
    assert g.quantify(e, {'x'})
    assert g.quantify(e, {'y'})
    assert g.quantify(e, {'z'})
    assert g.quantify(e, {'z'}, forall=True) == xy
    assert g.quantify(e, {'x'}, forall=True) == yz
    assert g.quantify(e, {'y'}, forall=True) == zx
    # complement edges
    u = -x
    v = g.quantify(u, {'y'}, forall=True)
    assert v == -x, g.to_expr(v)
    # multiple values: test recursion
    e = g.add_expr('x & y & z')
    x = g.add_expr('x')
    r = g.quantify(e, {'y', 'z'})
    assert r == x, r
Example #58
0
def test_preimage():
    # exists: x, y
    # forall: z
    ordering = {'x': 0, 'xp': 1,
                'y': 2, 'yp': 3,
                'z': 4, 'zp': 5}
    rename = {0: 1, 2: 3, 4: 5}
    g = BDD(ordering)
    f = g.add_expr('!x')
    t = g.add_expr('x <-> !xp')
    qvars = {1, 3}
    p = preimage(t, f, rename, qvars, g)
    x = g.add_expr('x')
    assert x == p, (x, p)
    # a cycle
    # (x & y) -> (!x & y) ->
    # (!x & !y) -> (x & !y) -> wrap around
    t = g.add_expr(
        '((x & y) -> (!xp & yp)) && '
        '((!x & y) -> (!xp & !yp)) && '
        '((!x & !y) -> (xp & !yp)) && '
        '((x & !y) -> (xp & yp))')
    f = g.add_expr('x && y')
    p = preimage(t, f, rename, qvars, g)
    assert p == g.add_expr('x & !y')
    f = g.add_expr('x && !y')
    p = preimage(t, f, rename, qvars, g)
    assert p == g.add_expr('!x & !y')
    # backward reachable set
    f = g.add_expr('x & y')
    oldf = None
    while oldf != f:
        p = preimage(t, f, rename, qvars, g)
        oldf = f
        f = g.apply('or', p, oldf)
    assert f == 1
    # go around once
    f = g.add_expr('x & y')
    start = f
    for i in range(4):
        f = preimage(t, f, rename, qvars, g)
    end = f
    assert start == end
    # forall z exists x, y
    t = g.add_expr(
        '('
        '    ((x & y) -> (zp & xp & !yp)) | '
        '    ((x & y) -> (!zp & !xp & yp))'
        ') & '
        '(!(x & y) -> False)')
    f = g.add_expr('x && !y')
    ep = preimage(t, f, rename, qvars, g)
    p = g.quantify(ep, {'zp'}, forall=True)
    assert p == -1
    f = g.add_expr('(x & !y) | (!x & y)')
    ep = preimage(t, f, rename, qvars, g)
    p = g.quantify(ep, {'zp'}, forall=True)
    assert p == g.add_expr('x & y')