Esempio n. 1
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)
Esempio n. 2
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)
Esempio n. 3
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)
Esempio n. 4
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)
Esempio n. 5
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
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
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
Esempio n. 9
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
Esempio n. 10
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