def test_copy_bdd_same_indices(): # each va has same index in each `BDD` bdd = cudd.BDD() other = cudd.BDD() assert bdd != other dvars = ['x', 'y', 'z'] for var in dvars: bdd.add_var(var) other.add_var(var) s = '(x & y) | !z' u0 = bdd.add_expr(s) u1 = cudd.copy_bdd(u0, bdd, other) u2 = cudd.copy_bdd(u1, other, bdd) # involution assert u0 == u2, (u0, u2) # confirm w = other.add_expr(s) assert w == u1, (w, u1) # different nodes u3 = cudd.copy_bdd(other. True, other, bdd) assert u3 != u2, (u3, u2) # same bdd with assert_raises(AssertionError): cudd.copy_bdd(u0, bdd, bdd) del u0, u1, u2, u3, w
def test_reorder(): bdd = cudd.BDD() dvars = ['x', 'y', 'z'] for var in dvars: bdd.add_var(var) _confirm_var_order(dvars, bdd) order = dict(y=0, z=1, x=2) bdd.reorder(order) for var in order: level_ = order[var] level = bdd.level_of_var(var) assert level == level_, (var, level, level_) # without args bdd = cudd.BDD() # Figs. 6.24, 6.25 Baier 2008 vrs = ['z1', 'z2', 'z3', 'y1', 'y2', 'y3'] bdd.declare(*vrs) _confirm_var_order(vrs, bdd) expr = '(z1 /\ y1) \/ (z2 /\ y2) \/ (z3 /\ y3)' u = bdd.add_expr(expr) bdd.reorder() levels = {var: bdd.level_of_var(var) for var in vrs} for i in range(1, 4): a = levels['z{i}'.format(i=i)] b = levels['y{i}'.format(i=i)] assert abs(a - b) == 1, levels
def test_contains(): bdd = cudd.BDD() true = bdd.true assert true in bdd bdd.add_var('x') x = bdd.var('x') assert x in bdd # undefined `__contains__` other_bdd = cudd.BDD() other_true = other_bdd.true with assert_raises(AssertionError): other_true in bdd
def test_copy_bdd_different_indices(): # each var has different index in each `BDD` bdd = cudd.BDD() other = cudd.BDD() assert bdd != other dvars = ['x', 'y', 'z'] for var in dvars: bdd.add_var(var) for var in reversed(dvars): other.add_var(var) u0 = bdd.add_expr('(x | !y) & !z') with assert_raises(AssertionError): cudd.copy_bdd(u0, bdd, other)
def test_dump_load(): b = cudd.BDD() b.declare('x', 'y', 'z') u = b.add_expr('x /\ ~ y') # dump fname = 'hoho.json' nodes = [u] _copy.dump_json(nodes, fname) # load target = cudd.BDD() roots = _copy.load_json(fname, target) # assert v, = roots u_ = target.copy(v, b) assert u == u_, (u, u_)
def test_add_expr(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # ((FALSE \/ TRUE) /\ x) \equiv x s = '(True \/ FALSE) /\ x' u = bdd.add_expr(s) x = bdd.var('x') assert u == x, (u, x) # ((x \/ ~ y) /\ x) \equiv x s = '(x \/ ~ y) /\ x' u = bdd.add_expr(s) assert u == x, (u, x) # x /\ y /\ z bdd.add_var('z') z = bdd.var('z') u = bdd.add_expr('x /\ y /\ z') u_ = bdd.cube(dict(x=True, y=True, z=True)) assert u == u_, (u, u_) # x /\ ~ y /\ z u = bdd.add_expr('x /\ ~ y /\ z') u_ = bdd.cube(dict(x=True, y=False, z=True)) assert u == u_, (u, u_) # (\E x: x /\ y) \equiv y y = bdd.var('y') u = bdd.add_expr('\E x: x /\ y') assert u == y, (str(u), str(y)) # (\A x: x \/ ~ x) \equiv TRUE u = bdd.add_expr('\A x: ~ x \/ x') assert u == bdd.true, u
def test_add_expr(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # (0 | 1) & x = x s = '(True | False) & x' u = bdd.add_expr(s) x = bdd.var('x') assert u == x, (u, x) # (x | !y) & x = x s = '(x | !y) & x' u = bdd.add_expr(s) assert u == x, (u, x) # x & y & z bdd.add_var('z') z = bdd.var('z') u = bdd.add_expr('x & y & z') u_ = bdd.cube({'x', 'y', 'z'}) assert u == u_, (u, u_) # x & !y & z u = bdd.add_expr('x & !y & z') u_ = bdd.cube(dict(x=True, y=False, z=True)) assert u == u_, (u, u_) # ? x. x & y = y y = bdd.var('y') u = bdd.add_expr('? x. x & y') assert u == y, (str(u), str(y)) # ! x. x | !x = 1 u = bdd.add_expr('! x. !x | x') assert u == bdd. True, u del x, y, z, u, u_
def test_quantify(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) x = bdd.var('x') # ? x. x = 1 r = bdd.quantify(x, ['x'], forall=False) assert r == bdd. True, r # ! x. x = 0 r = bdd.quantify(x, ['x'], forall=True) assert r == bdd. False, r # ? y. x = x r = bdd.quantify(x, ['y'], forall=False) assert r == x, (r, x) # ! y. x = x r = bdd.quantify(x, ['y'], forall=True) assert r == x, (r, x) # ? x. x & y = y y = bdd.var('y') u = bdd.apply('and', x, y) r = bdd.quantify(u, ['x'], forall=False) assert r == y, (r, y) assert r != x, (r, x) # ! x. x & y = 0 r = bdd.quantify(u, ['x'], forall=True) assert r == bdd. False, r # ! x. !x | y = y not_x = bdd.apply('not', x) u = bdd.apply('or', not_x, y) r = bdd.quantify(u, ['x'], forall=True) assert r == y, (r, y) del x, not_x, y, r, u
def solve_gpg_bdd_partial_multiple_calls(gpg_path, timeout_value): """ Load and solve the generalized parity game whose path is provided in parameter using the bdd implementation of the combination of the recursive algorithm and a partial solver. This implementation performs a call to the partial sover in each recursive call. """ player0_won = "TIMEOUT" winning_0, winning_1 = None, None start_time = time.time() with timeout(timeout_value): manager = _bdd.BDD() arena, all_vertices = bdd_gpg_loader.gpg2bdd(gpg_path, manager) winning_0, winning_1 = bdd_gpg_recursive.generalized_recursive_with_psolver_multiple_calls( arena, manager) vertex_0_dict_rep = next(manager.pick_iter(all_vertices[0])) player0_won = manager.let(vertex_0_dict_rep, winning_0) == manager.true end_time = "%.5f" % (time.time() - start_time) if player0_won == "TIMEOUT": end_time = "TIMEOUT" return player0_won, end_time, winning_0, winning_1
def test_add_expr(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # (0 | 1) & x = x s = '(True | False) & x' u = bdd.add_expr(s) x = bdd.var('x') assert u == x, (u, x) # (x | !y) & x = x s = '(x | !y) & x' u = bdd.add_expr(s) assert u == x, (u, x) # x & y & z bdd.add_var('z') z = bdd.var('z') u = bdd.add_expr('x & y & z') u_ = bdd.cube(dict(x=True, y=True, z=True)) assert u == u_, (u, u_) # x & !y & z u = bdd.add_expr('x & !y & z') u_ = bdd.cube(dict(x=True, y=False, z=True)) assert u == u_, (u, u_) # \E x: x & y = y y = bdd.var('y') u = bdd.add_expr('\E x: x & y') assert u == y, (str(u), str(y)) # \A x: x | !x = 1 u = bdd.add_expr('\A x: !x | x') assert u == bdd.true, u
def test_quantify(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) x = bdd.var('x') # \E x: x = 1 r = bdd.quantify(x, ['x'], forall=False) assert r == bdd.true, r # \A x: x = 0 r = bdd.quantify(x, ['x'], forall=True) assert r == bdd.false, r # \E y: x = x r = bdd.quantify(x, ['y'], forall=False) assert r == x, (r, x) # \A y: x = x r = bdd.quantify(x, ['y'], forall=True) assert r == x, (r, x) # \E x: x & y = y y = bdd.var('y') u = bdd.apply('and', x, y) r = bdd.quantify(u, ['x'], forall=False) assert r == y, (r, y) assert r != x, (r, x) # \A x: x & y = 0 r = bdd.quantify(u, ['x'], forall=True) assert r == bdd.false, r # \A x: !x | y = y not_x = bdd.apply('not', x) u = bdd.apply('or', not_x, y) r = bdd.quantify(u, ['x'], forall=True) assert r == y, (r, y)
def solve_pg_bdd_partial_debug(pg_path, timeout_value): """ Load and solve the parity game whose path is provided in parameter using the bdd implementation of the combination of the recursive algorithm and a partial solver. This is Clement's implementation. """ player0_won = "TIMEOUT" winning_0, winning_1 = None, None start_time = time.time() with timeout(timeout_value): manager = _bdd.BDD() arena, all_vertices = bdd_pg_loader.pg2bdd(pg_path, manager) winning_0, winning_1 = bdd_pg_recursive.recursive_with_buchi( arena, manager) vertex_0_dict_rep = next(manager.pick_iter(all_vertices[0])) player0_won = manager.let(vertex_0_dict_rep, winning_0) == manager.true end_time = "%.5f" % (time.time() - start_time) if player0_won == "TIMEOUT": end_time = "TIMEOUT" return player0_won, end_time, winning_0, winning_1
def test_rename(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # x -> y x = bdd.var('x') supp = bdd.support(x) assert supp == set(['x']), supp d = dict(x='y') f = cudd.rename(x, bdd, d) supp = bdd.support(f) assert supp == set(['y']), supp y = bdd.var('y') assert f == y, (f, y) # x, y -> z, w for var in ['z', 'w']: bdd.add_var(var) not_y = bdd.apply('not', y) u = bdd.apply('or', x, not_y) supp = bdd.support(u) assert supp == set(['x', 'y']), supp d = dict(x='z', w='y') f = cudd.rename(u, bdd, d) supp = bdd.support(f) assert supp == set(['z', 'w']), supp z = bdd.var('z') w = bdd.var('w') not_w = bdd.apply('not', w) f_ = bdd.apply('or', z, not_w) assert f == f_, (f, f_) # x -> x d = dict(x='y', y='x') with assert_raises(AssertionError): cudd.rename(u, bdd, d) del x, y, not_y, z, w, not_w, u, f, f_
def test_compose(): bdd = cudd.BDD() for var in ['x', 'y', 'z']: bdd.add_var(var) u = bdd.add_expr('x /\ ~ y') # x |-> y sub = dict(x=bdd.var('y')) v = bdd.let(sub, u) v_ = bdd.false assert v == v_, v # x |-> y, y |-> x sub = dict(x=bdd.var('y'), y=bdd.var('x')) v = bdd.let(sub, u) v_ = bdd.add_expr('y /\ ~ x') assert v == v_, v # x |-> z sub = dict(x=bdd.var('z')) v = bdd.let(sub, u) v_ = bdd.add_expr('z /\ ~ y') assert v == v_, v # x |-> z, y |-> x sub = dict(x=bdd.var('z'), y=bdd.var('x')) v = bdd.let(sub, u) v_ = bdd.add_expr('z /\ ~ x') assert v == v_, v # x |-> (y \/ z) sub = dict(x=bdd.add_expr('y \/ z')) v = bdd.let(sub, u) v_ = bdd.add_expr('(y \/ z) /\ ~ y') assert v == v_, v
def test_quantify(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) x = bdd.var('x') # (\E x: x) \equiv TRUE r = bdd.quantify(x, ['x'], forall=False) assert r == bdd.true, r # (\A x: x) \equiv FALSE r = bdd.quantify(x, ['x'], forall=True) assert r == bdd.false, r # (\E y: x) \equiv x r = bdd.quantify(x, ['y'], forall=False) assert r == x, (r, x) # (\A y: x) \equiv x r = bdd.quantify(x, ['y'], forall=True) assert r == x, (r, x) # (\E x: x /\ y) \equiv y y = bdd.var('y') u = bdd.apply('and', x, y) r = bdd.quantify(u, ['x'], forall=False) assert r == y, (r, y) assert r != x, (r, x) # (\A x: x /\ y) \equiv FALSE r = bdd.quantify(u, ['x'], forall=True) assert r == bdd.false, r # (\A x: ~ x \/ y) \equiv y not_x = bdd.apply('not', x) u = bdd.apply('or', not_x, y) r = bdd.quantify(u, ['x'], forall=True) assert r == y, (r, y)
def main(): b = cudd.BDD() b.declare('x', 'y', 'z') u = b.add_expr('x & y & z') u = b.add_expr('x | y | ~ z') stats = b.statistics() pprint.pprint(format_dict(stats))
def __init__(self): warnings.warn( 'Deprecated; use the class ' '`omega.symbolic.temporal.Automaton` instead.', category=PendingDeprecationWarning) self.players = dict(env=0, sys=1) # name -> turn self.vars = dict() self.moore = True self.plus_one = True self.qinit = '\A \A' # formulas self.init = dict(env=list(), sys=list()) self.action = dict(env=list(), sys=list()) self.win = {'<>[]': list(), '[]<>': list()} self.acceptance = 'Streett(1)' # auto-populated self.turns = list() # inverse of `self.players` # subsets of bits self.uvars = set() # unprimed env self.upvars = set() # primed env self.ubvars = set() # both primed and unprimed env self.evars = set() # unprimed sys self.epvars = set() # primed sys self.ebvars = set() # both primed and unprimed env self.uevars = set() # all unprimed vars self.uepvars = set() # all primed vars # future: hidden, node vars # map between primed and unprimed self.prime = dict() # unprimed -> primed self.unprime = dict() # primed -> unprimed # aux # init only to aid static analysis self.bdd = _bdd.BDD()
def test_prob_negated_edge_basic(): r_expr = "a & ~b" bdd = _bdd.BDD() bdd.declare('a', 'b') r = bdd.add_expr(r_expr) x = {"a": 0.5, "b": 0.25} assert (bdd_prob(bdd, r, x, dict()) == 0.375)
def test_prob_negated_edge_basic_2(): r_expr = "a & ~(b | ~c)" bdd = _bdd.BDD() bdd.declare('a', 'b', 'c') r = bdd.add_expr(r_expr) x = {"a": 0.5, "b": 0.25, "c": 0.125} assert (bdd_prob(bdd, r, x, dict()) == 0.046875)
def test_true_false(): bdd = cudd.BDD() true = bdd.true false = bdd.false assert false != true assert false == ~true assert false == false & true assert true == true | false
def main(): assert cudd.GB == 2**30, cudd.GB b = cudd.BDD() b.configure( # number of bytes max_memory=2 * cudd.GB, # number of entries, not memory units! max_cache_hard=2**25)
def test_dump_load(): bdd = cudd.BDD() for var in ['x', 'y', 'z', 'w']: bdd.add_var(var) u = bdd.add_expr('(x & !w) | z') fname = 'bdd.txt' bdd.dump(u, fname) u_ = bdd.load(fname) assert u == u_
def test_true_false(): bdd = cudd.BDD() true = bdd. True false = bdd. False assert false != true assert false == ~true assert false == false & true assert true == true | false del true, false
def test_dump_load(): bdd = cudd.BDD() for var in ['x', 'y', 'z', 'w']: bdd.add_var(var) u = bdd.add_expr('(x /\ ~ w) \/ z') fname = 'bdd.txt' bdd.dump(fname, [u], filetype='dddmp') u_ = bdd.load(fname) assert u == u_
def test_function(): bdd = cudd.BDD() bdd.add_var('x') # x x = bdd.var('x') assert not x.negated # ~ x not_x = ~x assert not_x.negated
def _init_bdd(use_cudd): if _bdd is None: raise ImportError('Failed to import `dd.bdd`.\n' 'Install package `dd`.') if not use_cudd: return _bdd.BDD() if cudd is None: raise ImportError('Failed to import module `dd.cudd`.\n' 'Compile the Cython bindings of `dd` to CUDD.') return cudd.BDD()
def test_or_forall(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # \A x y: x | ! y = 0 x = bdd.var('x') not_y = bdd.add_expr('!y') qvars = ['x', 'y'] r = cudd.or_forall(x, not_y, qvars, bdd) assert r == bdd.false, r
def test_or_forall(): bdd = cudd.BDD() for var in ['x', 'y']: bdd.add_var(var) # (\A x, y: x \/ ~ y) \equiv FALSE x = bdd.var('x') not_y = bdd.add_expr('~ y') qvars = ['x', 'y'] r = cudd.or_forall(x, not_y, qvars) assert r == bdd.false, r
def test_var_cofactor(): bdd = cudd.BDD() bdd.add_var('x') x = bdd.var('x') values = dict(x=False) u = bdd.let(values, x) assert u == bdd.false, u values = dict(x=True) u = bdd.let(values, x) assert u == bdd.true, u
def test_function_support(): bdd = cudd.BDD() bdd.add_var('x') u = bdd.var('x') r = u.support assert r == {'x'}, r bdd.add_var('y') u = bdd.add_expr('y /\ x') r = u.support assert r == {'x', 'y'}, r