def test_expr2bdd(): assert expr2bdd(expr("a ^ b ^ c")) is a ^ b ^ c assert expr2bdd(expr("~a & ~b | a & ~b | ~a & b | a & b")) is one assert expr2bdd(expr("~(~a & ~b | a & ~b | ~a & b | a & b)")) is zero f = expr2bdd(expr("~a & ~b & c | ~a & b & ~c | a & ~b & ~c | a & b & c")) g = expr2bdd(expr("a ^ b ^ c")) assert f is g assert f.node.root == a.uniqid assert f.node.lo.root == b.uniqid assert f.node.hi.root == b.uniqid assert f.node.lo.lo.root == c.uniqid assert f.node.lo.hi.root == c.uniqid assert f.node.hi.lo.root == c.uniqid assert f.node.hi.hi.root == c.uniqid assert f.node.lo.lo.lo == BDDNODEZERO assert f.node.lo.lo.hi == BDDNODEONE assert f.node.lo.hi.lo == BDDNODEONE assert f.node.lo.hi.hi == BDDNODEZERO assert f.node.hi.lo.lo == BDDNODEONE assert f.node.hi.lo.hi == BDDNODEZERO assert f.node.hi.hi.lo == BDDNODEZERO assert f.node.hi.hi.hi == BDDNODEONE
def test_satisfy(): f = a & b | a & c | b & c ff = expr2bdd(f) assert [p for p in ff.satisfy_all()] == [{aa: 0, bb: 1, cc: 1}, {aa: 1, bb: 0, cc: 1}, {aa: 1, bb: 1}] assert ff.satisfy_count() == 3 assert ff.satisfy_one() == {aa: 0, bb: 1, cc: 1} assert expr2bdd(EXPRZERO).satisfy_one() is None assert expr2bdd(EXPRONE).satisfy_one() == {}
def test_bdd2expr(): f = a & b | a & c | b & c zero = bdd(BDDNODEZERO) one = bdd(BDDNODEONE) assert bdd2expr(zero) is EXPRZERO assert bdd2expr(one) is EXPRONE assert bdd2expr(expr2bdd(f)).equivalent(f) assert bdd2expr(expr2bdd(f), conj=True).equivalent(f)
def __init__(self, varcount=0, auto_gc=True): """Create a new BDD manager. :param varcount: number of initial variables :type varcount: int :param auto_gc: use automatic garbage collection and minimization :type auto_gc: bool """ DDManager.__init__(self) self.varcount = 1 self.ZERO = bdd.expr2bdd(bdd_expr.expr("0")) self.ONE = bdd.expr2bdd(bdd_expr.expr("1"))
def test_misc(): f = a * b + a * c + b * c ff = expr2bdd(f) assert ff.smoothing(aa).equivalent(bb + cc) assert ff.consensus(aa).equivalent(bb * cc) assert ff.derivative(aa).equivalent(bb.xor(cc))
def test_misc(): f = a & b | a & c | b & c ff = expr2bdd(f) assert ff.smoothing(aa).equivalent(bb | cc) assert ff.consensus(aa).equivalent(bb & cc) assert ff.derivative(aa).equivalent(bb ^ cc)
def test_restrict(): ff = expr2bdd(a * b + a * c + b * c) assert ff.restrict({}).equivalent(ff) assert ff.restrict({aa: 0}).equivalent(expr2bdd(b * c)) assert ff.restrict({aa: 1}).equivalent(expr2bdd(b + c)) assert ff.restrict({bb: 0}).equivalent(expr2bdd(a * c)) assert ff.restrict({bb: 1}).equivalent(expr2bdd(a + c)) assert ff.restrict({cc: 0}).equivalent(expr2bdd(a * b)) assert ff.restrict({cc: 1}).equivalent(expr2bdd(a + b)) assert ff.restrict({aa: 0, bb: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 1}) == cc assert ff.restrict({aa: 1, bb: 0}) == cc assert ff.restrict({aa: 1, bb: 1}) is BDDONE assert ff.restrict({aa: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, cc: 1}) == bb assert ff.restrict({aa: 1, cc: 0}) == bb assert ff.restrict({aa: 1, cc: 1}) is BDDONE assert ff.restrict({bb: 0, cc: 0}) is BDDZERO assert ff.restrict({bb: 0, cc: 1}) == aa assert ff.restrict({bb: 1, cc: 0}) == aa assert ff.restrict({bb: 1, cc: 1}) is BDDONE assert ff.restrict({aa: 0, bb: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 0, cc: 1}) is BDDZERO assert ff.restrict({aa: 0, bb: 1, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 1, cc: 1}) is BDDONE assert ff.restrict({aa: 1, bb: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 1, bb: 0, cc: 1}) is BDDONE assert ff.restrict({aa: 1, bb: 1, cc: 0}) is BDDONE assert ff.restrict({aa: 1, bb: 1, cc: 1}) is BDDONE
def test_restrict(): ff = expr2bdd(a & b | a & c | b & c) assert ff.restrict({}).equivalent(ff) assert ff.restrict({aa: 0}).equivalent(expr2bdd(b & c)) assert ff.restrict({aa: 1}).equivalent(expr2bdd(b | c)) assert ff.restrict({bb: 0}).equivalent(expr2bdd(a & c)) assert ff.restrict({bb: 1}).equivalent(expr2bdd(a | c)) assert ff.restrict({cc: 0}).equivalent(expr2bdd(a & b)) assert ff.restrict({cc: 1}).equivalent(expr2bdd(a | b)) assert ff.restrict({aa: 0, bb: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 1}) == cc assert ff.restrict({aa: 1, bb: 0}) == cc assert ff.restrict({aa: 1, bb: 1}) is BDDONE assert ff.restrict({aa: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, cc: 1}) == bb assert ff.restrict({aa: 1, cc: 0}) == bb assert ff.restrict({aa: 1, cc: 1}) is BDDONE assert ff.restrict({bb: 0, cc: 0}) is BDDZERO assert ff.restrict({bb: 0, cc: 1}) == aa assert ff.restrict({bb: 1, cc: 0}) == aa assert ff.restrict({bb: 1, cc: 1}) is BDDONE assert ff.restrict({aa: 0, bb: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 0, cc: 1}) is BDDZERO assert ff.restrict({aa: 0, bb: 1, cc: 0}) is BDDZERO assert ff.restrict({aa: 0, bb: 1, cc: 1}) is BDDONE assert ff.restrict({aa: 1, bb: 0, cc: 0}) is BDDZERO assert ff.restrict({aa: 1, bb: 0, cc: 1}) is BDDONE assert ff.restrict({aa: 1, bb: 1, cc: 0}) is BDDONE assert ff.restrict({aa: 1, bb: 1, cc: 1}) is BDDONE
def recursive_build(a, b): """ Recursively create BDD from edge expressions """ if a == b: r = __edge_expressions[a] return expr2bdd(r) split_index = math.floor((b + a) / 2) return recursive_build(a, split_index) | recursive_build(split_index + 1, b)
def test_boolfunc(): # __invert__, __or__, __and__, __xor__ f = ~a | b & c ^ d assert expr2bdd(expr("~a | b & c ^ d")) is f # support, usupport, inputs assert f.support == {a, b, c, d} assert f.usupport == {a.uniqid, b.uniqid, c.uniqid, d.uniqid} # restrict assert f.restrict({}) is f assert f.restrict({a: 0}) is one assert f.restrict({a: 1, b: 1}) is c ^ d assert f.restrict({a: 1, b: 1, c: 0}) is d assert f.restrict({a: 1, b: 1, c: 0, d: 0}) is zero # compose assert f.compose({a: w}) is ~w | b & c ^ d assert f.compose({ a: w, b: x & y, c: y | z, d: x ^ z }) is ~w | x ^ z ^ x & y & (y | z) # satisfy_one, satisfy_all assert zero.satisfy_one() is None assert one.satisfy_one() == {} g = a & b | a & c | b & c assert list(g.satisfy_all()) == [{ a: 0, b: 1, c: 1 }, { a: 1, b: 0, c: 1 }, { a: 1, b: 1 }] assert g.satisfy_count() == 3 assert g.satisfy_one() == {a: 0, b: 1, c: 1} # is_zero, is_one assert zero.is_zero() assert one.is_one() # box, unbox assert BinaryDecisionDiagram.box('0') is zero assert BinaryDecisionDiagram.box('1') is one assert BinaryDecisionDiagram.box("") is zero assert BinaryDecisionDiagram.box("foo") is one
def test_expr2bdd(): assert expr2bdd(a) is aa assert expr2bdd(~a & ~b | a & ~b | ~a & b | a & b).node is BDDNODEONE assert expr2bdd(~(~a & ~b | a & ~b | ~a & b | a & b)).node is BDDNODEZERO ff = expr2bdd(a & b | a & c | b & c) gg = expr2bdd(a & b | a & c | b & c) assert ff is gg assert ff.node.root == a.uniqid assert ff.node.lo.root == b.uniqid assert ff.node.hi.root == b.uniqid assert ff.node.lo.lo is BDDNODEZERO assert ff.node.lo.hi.root == c.uniqid assert ff.node.hi.lo.root == c.uniqid assert ff.node.hi.hi is BDDNODEONE assert ff.node.lo.hi.lo is BDDNODEZERO assert ff.node.hi.lo.hi is BDDNODEONE assert ff.support == {aa, bb, cc} assert ff.inputs == (aa, bb, cc)
def test_expr2bdd(): assert expr2bdd(expr("a ^ b ^ c")) is a ^ b ^ c assert expr2bdd(expr("~a & ~b | a & ~b | ~a & b | a & b")).is_one() assert expr2bdd(expr("~(~a & ~b | a & ~b | ~a & b | a & b)")).is_zero() f = expr2bdd(expr("a & b | a & c | b & c")) g = expr2bdd(expr("Majority(a, b, c)")) assert f is g assert f.node.root == a.uniqid assert f.node.lo.root == b.uniqid assert f.node.hi.root == b.uniqid assert f.node.lo.lo is BDDNODEZERO assert f.node.lo.hi.root == c.uniqid assert f.node.hi.lo.root == c.uniqid assert f.node.hi.hi is BDDNODEONE assert f.node.lo.hi.lo is BDDNODEZERO assert f.node.hi.lo.hi is BDDNODEONE assert f.support == {a, b, c} assert f.inputs == (a, b, c)
def test_expr2bdd(): assert expr2bdd(a) == aa assert expr2bdd(~a & ~b | a & ~b | ~a & b | a & b).node is BDDNODEONE assert expr2bdd(~(~a & ~b | a & ~b | ~a & b | a & b)).node is BDDNODEZERO ff = expr2bdd(a & b | a & c | b & c) gg = expr2bdd(a & b | a & c | b & c) assert ff == gg assert ff.node.root == a.uniqid assert ff.node.low.root == b.uniqid assert ff.node.high.root == b.uniqid assert ff.node.low.low is BDDNODEZERO assert ff.node.low.high.root == c.uniqid assert ff.node.high.low.root == c.uniqid assert ff.node.high.high is BDDNODEONE assert ff.node.low.high.low is BDDNODEZERO assert ff.node.high.low.high is BDDNODEONE assert ff.support == {aa, bb, cc} assert ff.inputs == (aa, bb, cc)
def test_expr2bdd(): assert expr2bdd(a) == aa assert expr2bdd(-a * -b + a * -b + -a * b + a * b).node is BDDNODEONE assert expr2bdd(-(-a * -b + a * -b + -a * b + a * b)).node is BDDNODEZERO ff = expr2bdd(a * b + a * c + b * c) gg = expr2bdd(a * b + a * c + b * c) assert ff == gg assert ff.node.root == a.uniqid assert ff.node.low.root == b.uniqid assert ff.node.high.root == b.uniqid assert ff.node.low.low is BDDNODEZERO assert ff.node.low.high.root == c.uniqid assert ff.node.high.low.root == c.uniqid assert ff.node.high.high is BDDNODEONE assert ff.node.low.high.low is BDDNODEZERO assert ff.node.high.low.high is BDDNODEONE assert ff.support == {aa, bb, cc} assert ff.inputs == (aa, bb, cc)
def test_boolfunc(): # __invert__, __or__, __and__, __xor__ f = ~a | b & c ^ d assert expr2bdd(expr("~a | b & c ^ d")) is f # support, usupport, inputs assert f.support == {a, b, c, d} assert f.usupport == {a.uniqid, b.uniqid, c.uniqid, d.uniqid} # restrict assert f.restrict({}) is f assert f.restrict({a: 0}) is one assert f.restrict({a: 1, b: 1}) is c ^ d assert f.restrict({a: 1, b: 1, c: 0}) is d assert f.restrict({a: 1, b: 1, c: 0, d: 0}) is zero # compose assert f.compose({a: w}) is ~w | b & c ^ d assert f.compose({a: w, b: x&y, c: y|z, d: x^z}) is ~w | x ^ z ^ x & y & (y | z) # satisfy_one, satisfy_all assert zero.satisfy_one() is None assert one.satisfy_one() == {} g = a & b | a & c | b & c assert list(g.satisfy_all()) == [ {a: 0, b: 1, c: 1}, {a: 1, b: 0, c: 1}, {a: 1, b: 1} ] assert g.satisfy_count() == 3 assert g.satisfy_one() == {a: 0, b: 1, c: 1} # is_zero, is_one assert zero.is_zero() assert one.is_one() # box, unbox assert BinaryDecisionDiagram.box('0') is zero assert BinaryDecisionDiagram.box('1') is one assert BinaryDecisionDiagram.box("") is zero assert BinaryDecisionDiagram.box("foo") is one
def test_compose(): f = a * b + a * c + b * c ff = expr2bdd(a * b + a * c + b * c) assert ff.compose({aa: bb, cc: dd*ee}).equivalent(expr2bdd(f.compose({a: b, c: d*e})))
edges = getEdges() print (edges); print ("Mapping boolean variables ... ") x1, x2, y1, y2, z1, z2 = map(exprvar, 'abcdef') print ("Mapping BDD variables ... ") xx1, xx2, yy1, yy2, zz1, zz2 = map(bddvar, 'abcdef') #translating edges to bool formulas and bdds print ("Translating edges to boolean formulas and BDDs ... ") #first edge 0-->1, i.e., 00 --> 01 r= ~x1 & ~x2 & ~y1 & y2 rr= expr2bdd(r) #second edge 1-->2; i.e., 01-->10 r= ( ~x1 & x2 & y1 & ~y2 ) rr= rr | expr2bdd(r) #third edge 2-->3; i.e., 10-->11 r= ( x1 & ~x2 & y1 & y2 ) rr= rr | expr2bdd(r) #fourth edge 3-->0; i.e., 11-->00 r= ( x1 & x2 & ~y1 & ~y2 ) rr= rr | expr2bdd(r) #five step reachability
def fivestep(node1, node2): n1 = str(bin(int(node1))[2:].zfill(10)) n2 = str(bin(int(node2))[2:].zfill(10)) a = [] #to store the binary ints of node1 b = [] #to store the binary ints of node2 i = 0 for c in n1: a.append(int(c)) i += 1 i = 0 for c in n2: b.append(int(c)) i += 1 x = [] #to store the static x expvars y = [] #to store the static y expvars z = [] x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 = map(exprvar, 'abcdefghij') x.append(x1) x.append(x2) x.append(x3) x.append(x4) x.append(x5) x.append(x6) x.append(x7) x.append(x8) x.append(x9) x.append(x10) y1, y2, y3, y4, y5, y6, y7, y8, y9, y10 = map(exprvar, 'klmnopqrst') y.append(y1) y.append(y2) y.append(y3) y.append(y4) y.append(y5) y.append(y6) y.append(y7) y.append(y8) y.append(y9) y.append(y10) z1, z2, z3, z4, z5, z6, z7, z8, z9, z10 = map(exprvar, 'ABCDEFGHIJ') xx1, xx2, xx3, xx4, xx5, xx6, xx7, xx8, xx9, xx10 = map( bddvar, 'klmnopqrst') yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10 = map( bddvar, 'abcdefghij') zz1, zz2, zz3, zz4, zz5, zz6, zz7, zz8, zz9, zz10 = map( bddvar, 'ABCDEFGHIJ') file = open("translate.txt", "r") contents = file.read() file.close() nums = contents.split() i = 0 j = 0 #r = x1 & y1 rr = None #expr2bdd(r) exp = [] #translating edges to bool formulas and bdds print("Building BDD") for node in nums: if i % 2 == 0: j = 0 for c in node: if c == '0': exp.append(~x[j]) else: exp.append(x[j]) j += 1 else: j = 0 for c in node: if c == '0': exp.append(~y[j]) else: exp.append(y[j]) j += 1 r = exp[0] & exp[1] & exp[2] & exp[3] & exp[4] & exp[5] & exp[ 6] & exp[7] & exp[8] & exp[9] & exp[10] & exp[11] & exp[ 12] & exp[13] & exp[14] & exp[15] & exp[16] & exp[ 17] & exp[18] & exp[19] rr = rr | expr2bdd(r) exp = [] #print(j) j = 0 i += 1 #Start searching for 5 step. i = 0 hh = rr print("Finding 5 step.") while i < 4: hh = (rr.compose({ yy1: zz1, yy2: zz2, yy3: zz3, yy4: zz4, yy5: zz5, yy6: zz6, yy7: zz7, yy8: zz8, yy9: zz9, yy10: zz10 }) & hh.compose({ xx1: zz1, xx2: zz2, xx3: zz3, xx4: zz4, xx5: zz5, xx6: zz6, xx7: zz7, xx8: zz8, xx9: zz9, xx10: zz10 })).smoothing({zz1, zz2, zz3, zz4, zz5, zz6, zz7, zz8, zz9, zz10}) | hh i += 1 if (hh.restrict({ xx1: a[0], xx2: a[1], xx3: a[2], xx4: a[3], xx5: a[4], xx6: a[5], xx7: a[6], xx8: a[7], xx9: a[8], xx10: a[9], yy1: b[0], yy2: b[1], yy3: b[2], yy4: b[3], yy5: b[4], yy6: b[5], yy7: b[6], yy8: b[7], yy9: b[8], yy10: b[9] }) == 1): return True else: return False
def test_negate(): f = a * b + a * c + b * c ff = expr2bdd(f) assert bdd2expr(-ff).equivalent(-f)
def fivestep(node1, node2): x = [] y = [] z = [] x1, x2, x3, x4 = map( exprvar, 'abcd') # x5, x6, x7, x8, x9, x10 = map(exprvar, 'abcdefghij') x.append(x1) x.append(x2) x.append(x3) x.append(x4) y1, y2, y3, y4 = map( exprvar, 'efgh') # y5, y6, y7, y8, y9, y10 = map(exprvar, 'abcdefghij') y.append(y1) y.append(y2) y.append(y3) y.append(y4) z1, z2, z3, z4 = map( exprvar, 'ijkl') #z5, z6, z7, z8, z9, z10 = map(exprvar, 'abcdefghij') xx1, xx2, xx3, xx4 = map( bddvar, 'abcd') #xx5, xx6, xx7, xx8, xx9, xx10 = map(bddvar, 'abcdefghij') yy1, yy2, yy3, yy4 = map( bddvar, 'efgh') #yy5, yy6, yy7, yy8, yy9, yy10 = map(bddvar, 'abcdefghij') zz1, zz2, zz3, zz4 = map( bddvar, 'ijkl') #zz5, zz6, zz7, zz8, zz9, zz10 = map(bddvar, 'abcdefghij') # file = open("translate.txt", "r") # contents = file.read() # file.close() # nums = contents.split() nums = [ '000', '001', '001', '100', '010', '011', '100', '101', '101', '010', '011', '110' ] print(nums) i = 0 j = 0 # r = x1 & y1 rr = None #expr2bdd(r) a = [] #translating edges to bool formulas and bdds for node in nums: if i % 2 == 0: j = 0 for c in node: if c == '0': #if j == 0: # a.append(~x[j]) #else: a.append(~x[j]) else: a.append(x[j]) j += 1 else: j = 0 for c in node: if c == '0': #if j == 0: # a.append(~y[j]) #else: a.append(~y[j]) else: #if c == '1': a.append(y[j]) j += 1 #if i == 1:# & j == 3: # r = a[0] & a[1] & a[2] & a[3] & a[4] & a[5] #& a[6] & a[7] # print(r) # rr = expr2bdd(r) #else: #if j == 3: r = a[0] & a[1] & a[2] & a[3] & a[4] & a[5] #& a[6] & a[7] print(r) rr = rr | expr2bdd(r) a = [] j = 0 i += 1 i = 0 hh = rr while i < 4: hh = (rr.compose({ yy1: zz1, yy2: zz2, yy3: zz3, yy4: zz4 }) & hh.compose({ xx1: zz1, xx2: zz2, xx3: zz3, xx4: zz4 })).smoothing({zz1, zz2, zz3, zz4}) | hh i += 1 #print(hh.restrict({xx1:0, xx2:0, xx3:0, xx4:0, yy1:0, yy2:0, yy3:1, yy4:0})) #assert hh.restrict({xx1:0, xx2:0, xx3:0, xx4:0, yy1:1, yy2:0, yy3:0, yy4:0}) return hh.restrict({xx1: 0, xx2: 0, xx3: 0, yy1: 1, yy2: 1, yy3: 0})
def test_equivalent(): ff = expr2bdd(a & ~b | ~a & b) gg = expr2bdd((~a | ~b) & (a | b)) assert ff.equivalent(ff) assert gg.equivalent(ff)
def test_traverse(): ff = expr2bdd(a & b | a & c | b & c) path = [node.root for node in ff.traverse()] # 0, 1, c, b(0, c), b(c, 1), a assert path == [-2, -1, c.uniqid, b.uniqid, b.uniqid, a.uniqid]
def test_equivalent(): ff = expr2bdd(a * -b + -a * b) gg = expr2bdd((-a + -b) * (a + b)) assert ff.equivalent(ff) assert gg.equivalent(ff)
def test_compose(): f = a & b | a & c | b & c ff = expr2bdd(a & b | a & c | b & c) assert ff.compose({aa: bb, cc: dd&ee}).equivalent(expr2bdd(f.compose({a: b, c: d&e})))
def test_negate(): f = a & b | a & c | b & c ff = expr2bdd(f) assert bdd2expr(~ff).equivalent(~f)