def __init__(self, expression=None, optimization='off', mct_mode='basic'): """ Constructor. Args: expression (str): The string of the desired logical expression. It could be either in the DIMACS CNF format, or a general boolean logical expression, such as 'a ^ b' and 'v[0] & (~v[1] | v[2])' optimization (str): The mode of optimization to use for minimizing the circuit. Currently, besides no optimization ('off'), Aqua also supports an 'espresso' mode <https://en.wikipedia.org/wiki/Espresso_heuristic_logic_minimizer> mct_mode (str): The mode to use for building Multiple-Control Toffoli. """ self.validate(locals()) super().__init__() self._mct_mode = mct_mode self._optimization = optimization if expression is None: raw_expr = expr(None) else: try: raw_expr = expr(expression) except: try: raw_expr = ast2expr(parse_cnf(expression.strip(), varname='v')) except: raise AquaError('Failed to parse the input expression: {}.'.format(expression)) self._expr = raw_expr self._process_expr() self.construct_circuit()
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 solve(s, settings, solver = 'Glucose'): if ClauseHelper.check_clause(s): cnf = ClauseHelper.parse_to_cnf(s,settings) if False == isinstance(cnf[0],expr.Expression): return cnf if isinstance(cnf[0],expr._Zero): return "UNSAT" mapa, dimacs = ClauseHelper.parse_to_dimacs_pyeda(cnf[0]) dimacs = dimacs.__str__() model = SolverHelper.__solvers[solver].solve(dimacs.__str__()) if SolverHelper.__solvers[solver].is_Sat(): result = "SAT\n" ''' for x in model.keys(): result+=str(mapa[x]) + "=" + str(model[x]) + "\n" ''' for x in cnf[1]: if expr.expr(x) in mapa: result += str(x) + "=" + str(model[mapa[expr.expr(x)]]) + "\n" else: result += str(x) + "=" + str(True) + "\n" return result else: return "UNSAT" else: return "Bad clause"
def test_bdd2expr(): ex = bdd2expr(a ^ b ^ c, conj=False) assert ex.equivalent(expr("a ^ b ^ c")) assert type(ex) is OrOp and ex.depth == 2 ex = bdd2expr(a ^ b ^ c, conj=True) assert ex.equivalent(expr("a ^ b ^ c")) assert type(ex) is AndOp and ex.depth == 2
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 sat_measure(formula): cnf = expr(formula).to_cnf() ''' False ''' if str(cnf) == "0": return 0 ''' True ''' if str(cnf) == "1": return 1 else: ''' Sat? ''' file = open('input.cnf', 'w') litmap, nvars, clauses = cnf.encode_cnf() dimacs = str(DimacsCNF(nvars, clauses)) if cache.get(dimacs) != None and do_memoize: return cache[dimacs] else: file.write(dimacs) file.close() output = check_output(["bin/sharpSAT", "input.cnf"]) m = re.search(r"# solutions \n([0-9]+)\n# END", output.decode('UTF-8')) #print(m.group(1)) print("vars: " + str(nvars)) print("clauses: " + (str(len(clauses)))) # print(str(DimacsCNF(nvars, clauses))) cache[dimacs] = int(m.group(1)) / 2**nvars return cache[dimacs]
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_misc(): a, b, c = map(exprvar, 'abc') a0 = exprvar('a', 0) b0 = exprvar('b', 0) assert expr("a & b & c").equivalent(a & b & c) assert expr("a ^ b ^ c").equivalent(a ^ b ^ c) assert expr("a | b | c").equivalent(a | b | c) assert expr("a & (b | c)").equivalent(a & (b | c)) assert expr("a | (b & c)").equivalent(a | b & c) assert expr("Or()").is_zero() assert expr("a[0] | b[0]").equivalent(a0 | b0)
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_misc(): a, b, c = map(exprvar, 'abc') a0 = exprvar('a', 0) b0 = exprvar('b', 0) assert expr("a * b * c").equivalent(a * b * c) assert expr("a + b + c").equivalent(a + b + c) assert expr("a * (b + c)").equivalent(a * (b + c)) assert expr("a + (b * c)").equivalent(a + b * c) assert expr("Or()").is_zero() assert expr("a[0] + b[0]").equivalent(a0 + b0)
def test_misc(): a, b, c = map(exprvar, 'abc') assert expr("a & b & c").equivalent(a & b & c) assert expr("a ^ b ^ c").equivalent(a ^ b ^ c) assert expr("a | b | c").equivalent(a | b | c) assert expr("a & (b | c)").equivalent(a & (b | c)) assert expr("a | (b & c)").equivalent(a | b & c) assert expr("Or()").is_zero() a_0 = exprvar('a', 0) b_a = exprvar(('a', 'b')) a_0_1 = exprvar('a', (0, 1)) b_a_0_1 = exprvar(('a', 'b'), (0, 1)) assert expr("a[0] | b.a | a[0,1] | b.a[0,1]").equivalent(a_0 | b_a | a_0_1 | b_a_0_1)
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_basic(): a, b, c, p, q, s = map(exprvar, 'abcpqs') assert expr("a * -b + b * -c").equivalent(a * -b + b * -c) assert expr("p => q").equivalent(-p + q) assert expr("a <=> b").equivalent(-a * -b + a * b) assert expr("s ? a : b").equivalent(s * a + -s * b) assert expr("Not(a)").equivalent(Not(a)) assert expr("Or(a, b, c)").equivalent(Or(a, b, c)) assert expr("And(a, b, c)").equivalent(And(a, b, c)) assert expr("Xor(a, b, c)").equivalent(Xor(a, b, c)) assert expr("Xnor(a, b, c)").equivalent(Xnor(a, b, c)) assert expr("Equal(a, b, c)").equivalent(Equal(a, b, c)) assert expr("Unequal(a, b, c)").equivalent(Unequal(a, b, c)) assert expr("Implies(p, q)").equivalent(Implies(p, q)) assert expr("ITE(s, a, b)").equivalent(ITE(s, a, b)) assert expr("Nor(a, b, c)").equivalent(Nor(a, b, c)) assert expr("Nand(a, b, c)").equivalent(Nand(a, b, c)) assert expr("OneHot0(a, b, c)").equivalent(OneHot0(a, b, c)) assert expr("OneHot(a, b, c)").equivalent(OneHot(a, b, c)) assert expr("Majority(a, b, c)").equivalent(Majority(a, b, c))
def test_satisfy_one(): _, cnf = expr2dimacscnf(expr("And(a, b, c)")) assert picosat.satisfy_one(cnf.nvars, cnf.clauses) == (1, 1, 1) assert list(picosat.satisfy_all(cnf.nvars, cnf.clauses)) == [(1, 1, 1)]
def test_expr(): f = a & ~b | c ^ ~d assert expr(Zero) is Zero assert expr(a) is a assert expr(f) is f assert expr(False) is Zero assert expr(True) is One assert expr(0) is Zero assert expr(1) is One assert expr('0') is Zero assert expr('1') is One assert expr([]) is Zero assert expr(['foo', 'bar']) is One assert str(expr("a & ~b | c ^ ~d")) == "Or(And(a, ~b), Xor(c, ~d))" assert str(expr("a & 0 | 1 ^ ~d", simplify=False)) == "Or(And(a, 0), Xor(1, ~d))"
def test_basic(): a, b, c, d, p, q, s = map(exprvar, 'abcdpqs') assert expr("a & ~b | b & ~c").equivalent(a & ~b | b & ~c) assert expr("p => q").equivalent(~p | q) assert expr("a <=> b").equivalent(~a & ~b | a & b) assert expr("s ? a : b").equivalent(s & a | ~s & b) assert expr("Not(a)").equivalent(Not(a)) assert expr("Or(a, b, c)").equivalent(Or(a, b, c)) assert expr("And(a, b, c)").equivalent(And(a, b, c)) assert expr("Xor(a, b, c)").equivalent(Xor(a, b, c)) assert expr("Xnor(a, b, c)").equivalent(Xnor(a, b, c)) assert expr("Equal(a, b, c)").equivalent(Equal(a, b, c)) assert expr("Unequal(a, b, c)").equivalent(Unequal(a, b, c)) assert expr("Implies(p, q)").equivalent(Implies(p, q)) assert expr("ITE(s, a, b)").equivalent(ITE(s, a, b)) assert expr("Nor(a, b, c)").equivalent(Nor(a, b, c)) assert expr("Nand(a, b, c)").equivalent(Nand(a, b, c)) assert expr("OneHot0(a, b, c)").equivalent(OneHot0(a, b, c)) assert expr("OneHot(a, b, c)").equivalent(OneHot(a, b, c)) assert expr("Majority(a, b, c)").equivalent(Majority(a, b, c)) assert expr("AchillesHeel(a, b, c, d)").equivalent(AchillesHeel( a, b, c, d))
def cnf_to_dimacs(cnf_input): clause = expr(cnf_input, False) cnf = clause.to_cnf() map, dimacs = expr2dimacscnf(cnf) return dimacs, map
# -*- coding: utf-8 -*- from pyeda.boolalg.expr import ( Not, And, Or, expr, exprvar as var, Constant, Literal, Variable, Complement, NotOp, AndOp, OrOp, OrAndOp) ZERO = expr(False) ONE = expr(True)
def test_expr(): assert expr(a) is a f = a & ~b | c ^ ~d assert expr(f) is f assert expr(False) is Zero assert expr(0) is Zero assert expr('0') is Zero assert expr([]) is Zero assert expr(True) is One assert expr(1) is One assert expr('1') is One assert expr(['foo', 'bar']) is One assert expr("a ^ b").to_nnf().equivalent(~a & b | a & ~b) assert str(expr("a ^ 0", simplify=False)) == "Xor(a, 0)"
def test_bdd2expr(): assert bdd2expr(a & ~a).is_zero() assert bdd2expr(a | ~a).is_one() f = a & b | a & c | b & c assert bdd2expr(f).equivalent(expr("Majority(a, b, c)")) assert bdd2expr(f, conj=True).equivalent(expr("Majority(a, b, c)"))
def test_expr(): assert expr(a) is a f = a & ~b | c ^ ~d assert expr(f) is f assert expr(False) is EXPRZERO assert expr(0) is EXPRZERO assert expr('0') is EXPRZERO assert expr([]) is EXPRZERO assert expr(True) is EXPRONE assert expr(1) is EXPRONE assert expr('1') is EXPRONE assert expr(['foo', 'bar']) is EXPRONE assert str(expr("a ^ b").to_nnf()) == "Or(And(~a, b), And(a, ~b))" assert str(expr("a ^ 0", simplify=False)) == "Xor(0, a)"
def test_expr(): assert expr(a) is a f = a & ~b | c ^ ~d assert expr(f) is f assert expr(False) is EXPRZERO assert expr(0) is EXPRZERO assert expr('0') is EXPRZERO assert expr([]) is EXPRZERO assert expr(True) is EXPRONE assert expr(1) is EXPRONE assert expr('1') is EXPRONE assert expr(['foo', 'bar']) is EXPRONE assert str(expr("a ^ b", factor=True)) == "Or(And(~a, b), And(a, ~b))" assert str(expr("a ^ 0", simplify=False)) == "Xor(0, a)"
def test_basic(): a, b, c, p, q, s = map(exprvar, 'abcpqs') assert expr("a & ~b | b & ~c").equivalent(a & ~b | b & ~c) assert expr("p => q").equivalent(~p | q) assert expr("a <=> b").equivalent(~a & ~b | a & b) assert expr("s ? a : b").equivalent(s & a | ~s & b) assert expr("Not(a)").equivalent(Not(a)) assert expr("Or(a, b, c)").equivalent(Or(a, b, c)) assert expr("And(a, b, c)").equivalent(And(a, b, c)) assert expr("Xor(a, b, c)").equivalent(Xor(a, b, c)) assert expr("Xnor(a, b, c)").equivalent(Xnor(a, b, c)) assert expr("Equal(a, b, c)").equivalent(Equal(a, b, c)) assert expr("Unequal(a, b, c)").equivalent(Unequal(a, b, c)) assert expr("Implies(p, q)").equivalent(Implies(p, q)) assert expr("ITE(s, a, b)").equivalent(ITE(s, a, b)) assert expr("Nor(a, b, c)").equivalent(Nor(a, b, c)) assert expr("Nand(a, b, c)").equivalent(Nand(a, b, c)) assert expr("OneHot0(a, b, c)").equivalent(OneHot0(a, b, c)) assert expr("OneHot(a, b, c)").equivalent(OneHot(a, b, c)) assert expr("Majority(a, b, c)").equivalent(Majority(a, b, c))
def main(): #Parse the command line arguments provided at run time. parser = argparse.ArgumentParser(description='ROBDD') parser.add_argument('-b', '--boolean_expr', dest='expr_1', metavar='B', type=str, nargs='?', help='Provide a boolean expression') parser.add_argument('-b2', '--boolean_expr2', dest='expr_2', metavar='B2', type=str, nargs='?', help='Provide a boolean expression') parser.add_argument( '-a', '--apply', dest='apply_expr', metavar='A', type=str, nargs='?', help='Provide the operation to apply (And, Or, Equal, Implies)') parser.add_argument('-r', '--restrict', dest='restrict_expr', metavar='R', type=str, nargs='?', help='Provide the restriction "var,val"') parser.add_argument('-s', '--sat', dest='sat', action='store_true', help='Return SAT on ROBDD') # Parse the input arguments args = parser.parse_args() if args.expr_1 is not None: expression1 = str(expr(args.expr_1)) print("Expression1: " + expression1) r1 = Robdd(find_large_var(expression1)) r1.build(expression1) r1.print_graph("r1") if args.expr_2 is not None: expression2 = str(expr(args.expr_2)) print("Expression2: " + expression2) r2 = Robdd(find_large_var(expression2)) r2.build(expression2) r2.print_graph("r2") if args.apply_expr is not None: r3 = Robdd_apply( max(find_large_var(expression1), find_large_var(expression2))) r3.apply(convert_apply(args.apply_expr), r1, r2) r3.print_graph("r3_apply") if args.restrict_expr is not None: r4 = Robdd_restrict(r1) r4.restrict(int(args.restrict_expr.split(',')[0]), int(args.restrict_expr.split(',')[1])) r4.print_graph('r4_restrict') if args.sat: r4 = Robdd_sat(r1) r4.print_SAT()