def test_AMONE(): my_TEST(my_AMONE, Clauses.AtMostOne_NSQ, 0,3, True) my_TEST(my_AMONE, Clauses.AtMostOne_BDD, 0,3, True) my_TEST(my_AMONE, Clauses.AtMostOne, 0,3, True) C1 = Clauses(10) x1 = C1.AtMostOne_BDD((1,2,3,4,5,6,7,8,9,10)) C2 = Clauses(10) x2 = C2.AtMostOne((1,2,3,4,5,6,7,8,9,10)) assert x1 == x2 and C1.as_list() == C2.as_list()
def test_AMONE(): my_TEST(my_AMONE, Clauses.AtMostOne_NSQ, 0, 3, True) my_TEST(my_AMONE, Clauses.AtMostOne_BDD, 0, 3, True) my_TEST(my_AMONE, Clauses.AtMostOne, 0, 3, True) C1 = Clauses(10) x1 = C1.AtMostOne_BDD((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) C2 = Clauses(10) x2 = C2.AtMostOne((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) assert x1 == x2 and C1.as_list() == C2.as_list()
def test_AMONE(): my_TEST(my_AMONE, Clauses.AtMostOne_NSQ, 0, 3, True) my_TEST(my_AMONE, Clauses.AtMostOne_BDD, 0, 3, True) my_TEST(my_AMONE, Clauses.AtMostOne, 0, 3, True) C1 = Clauses(10) x1 = C1.AtMostOne_BDD(tuple(range(1, 11))) C2 = Clauses(10) x2 = C2.AtMostOne(tuple(range(1, 11))) assert x1 == x2 and C1.as_list() == C2.as_list()
def test_minimize(): # minimize x1 + 2 x2 + 3 x3 + 4 x4 + 5 x5 # subject to x1 + x2 + x3 + x4 + x5 == 1 C = Clauses(15) C.Require(C.ExactlyOne, range(1, 6)) sol = C.sat() C._clauses.unsat = True # Unsatisfiable constraints assert C.minimize([(k, k) for k in range(1, 6)], sol)[1] == 16 C._clauses.unsat = False sol, sval = C.minimize([(k, k) for k in range(1, 6)], sol) assert sval == 1 C.Require(C.ExactlyOne, range(6, 11)) # Supply an initial vector that is too short, forcing recalculation sol, sval = C.minimize([(k, k) for k in range(6, 11)], sol) assert sval == 6 C.Require(C.ExactlyOne, range(11, 16)) # Don't supply an initial vector sol, sval = C.minimize([(k, k) for k in range(11, 16)]) assert sval == 11
def test_minimize(): # minimize x1 + 2 x2 + 3 x3 + 4 x4 + 5 x5 # subject to x1 + x2 + x3 + x4 + x5 == 1 C = Clauses(15) C.Require(C.ExactlyOne, range(1,6)) sol = C.sat() C.unsat = True # Unsatisfiable constraints assert C.minimize([(k,k) for k in range(1,6)], sol)[1] == 16 C.unsat = False sol, sval = C.minimize([(k,k) for k in range(1,6)], sol) assert sval == 1 C.Require(C.ExactlyOne, range(6,11)) # Supply an initial vector that is too short, forcing recalculation sol, sval = C.minimize([(k,k) for k in range(6,11)], sol) assert sval == 6 C.Require(C.ExactlyOne, range(11,16)) # Don't supply an initial vector sol, sval = C.minimize([(k,k) for k in range(11,16)]) assert sval == 11
def sat(val): return Clauses(max(abs(v) for v in chain(*val))).sat(val)
def test_sat(): C = Clauses() C.new_var('x1') C.new_var('x2') assert C.sat() is not None assert C.sat([]) is not None assert C.sat([()]) is None assert C.sat([(False, )]) is None assert C.sat([(True, ), ()]) is None assert C.sat([(True, False, -1)]) is not None assert C.sat([(+1, False), (+2, ), (True, )], names=True) == {'x1', 'x2'} assert C.sat([(-1, False), (True, ), (+2, )], names=True) == {'x2'} assert C.sat([(True, ), (-1, ), (-2, False)], names=True) == set() assert C.sat([(+1, ), (-1, False)], names=True) is None C.unsat = True assert C.sat() is None assert C.sat([]) is None assert C.sat([(True, )]) is None assert len(Clauses(10).sat([[1]])) == 10
def test_LinearBound(): L = [ ([], [0, 1], 10), ([], [1, 2], 10), ({ 'x1': 2, 'x2': 2 }, [3, 3], 10), ({ 'x1': 2, 'x2': 2 }, [0, 1], 1000), ({ 'x1': 1, 'x2': 2 }, [0, 2], 1000), ({ 'x1': 2, '!x2': 2 }, [0, 2], 1000), ([(1, 1), (2, 2), (3, 3)], [3, 3], 1000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2], 1000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7), (3, False), (2, True)], [2, 4], 1000), ([(1, 15), (2, 16), (3, 17), (4, 18), (5, 6), (5, 19), (6, 7), (6, 20), (7, 8), (7, 21), (7, 28), (8, 9), (8, 22), (8, 29), (8, 41), (9, 10), (9, 23), (9, 30), (9, 42), (10, 1), (10, 11), (10, 24), (10, 31), (10, 34), (10, 37), (10, 43), (10, 46), (10, 50), (11, 2), (11, 12), (11, 25), (11, 32), (11, 35), (11, 38), (11, 44), (11, 47), (11, 51), (12, 3), (12, 4), (12, 5), (12, 13), (12, 14), (12, 26), (12, 27), (12, 33), (12, 36), (12, 39), (12, 40), (12, 45), (12, 48), (12, 49), (12, 52), (12, 53), (12, 54)], [192, 204], 100), ] for eq, rhs, max_iter in L: if isinstance(eq, dict): N = len(eq) else: N = max([0] + [a for c, a in eq if a is not True and a is not False]) C = Clauses(N) Cpos = Clauses(N) Cneg = Clauses(N) if isinstance(eq, dict): for k in range(1, N + 1): nm = 'x%d' % k C.name_var(k, nm) Cpos.name_var(k, nm) Cneg.name_var(k, nm) eq2 = [(v, C.from_name(c)) for c, v in iteritems(eq)] else: eq2 = eq x = C.LinearBound(eq, rhs[0], rhs[1]) Cpos.Require(Cpos.LinearBound, eq, rhs[0], rhs[1]) Cneg.Prevent(Cneg.LinearBound, eq, rhs[0], rhs[1]) if x is not False: for _, sol in zip(range(max_iter), C.itersolve([] if x is True else [(x, )], N)): assert rhs[0] <= my_EVAL(eq2, sol) <= rhs[1], C.as_list() if x is not True: for _, sol in zip( range(max_iter), C.itersolve([] if x is True else [(C.Not(x), )], N)): assert not (rhs[0] <= my_EVAL(eq2, sol) <= rhs[1]), C.as_list() for _, sol in zip(range(max_iter), Cpos.itersolve([], N)): assert rhs[0] <= my_EVAL(eq2, sol) <= rhs[1], ('Cpos', Cpos.as_list()) for _, sol in zip(range(max_iter), Cneg.itersolve([], N)): assert not (rhs[0] <= my_EVAL(eq2, sol) <= rhs[1]), ( 'Cneg', Cneg.as_list())
def my_TEST(Mfunc, Cfunc, mmin, mmax, is_iter): for m in range(mmin, mmax + 1): if m == 0: ijprod = [()] else: ijprod = (True, False) + sum( ((k, my_NOT(k)) for k in range(1, m + 1)), ()) ijprod = product(ijprod, repeat=m) for ij in ijprod: C = Clauses() Cpos = Clauses() Cneg = Clauses() for k in range(1, m + 1): nm = 'x%d' % k C.new_var(nm) Cpos.new_var(nm) Cneg.new_var(nm) ij2 = tuple(C.from_index(k) if type(k) is int else k for k in ij) if is_iter: x = Cfunc.__get__(C, Clauses)(ij2) Cpos.Require(Cfunc.__get__(Cpos, Clauses), ij) Cneg.Prevent(Cfunc.__get__(Cneg, Clauses), ij) else: x = Cfunc.__get__(C, Clauses)(*ij2) Cpos.Require(Cfunc.__get__(Cpos, Clauses), *ij) Cneg.Prevent(Cfunc.__get__(Cneg, Clauses), *ij) tsol = Mfunc(*ij) if type(tsol) is bool: assert x is tsol, (ij2, Cfunc.__name__, C.as_list()) assert Cpos.unsat == (not tsol) and not Cpos.as_list(), ( ij, 'Require(%s)') assert Cneg.unsat == tsol and not Cneg.as_list(), ( ij, 'Prevent(%s)') continue for sol in C.itersolve([(x, )]): qsol = Mfunc(*my_SOL(ij, sol)) assert qsol is True, (ij2, sol, Cfunc.__name__, C.as_list()) for sol in Cpos.itersolve([]): qsol = Mfunc(*my_SOL(ij, sol)) assert qsol is True, (ij, sol, 'Require(%s)' % Cfunc.__name__, Cpos.as_list()) for sol in C.itersolve([(C.Not(x), )]): qsol = Mfunc(*my_SOL(ij, sol)) assert qsol is False, (ij2, sol, Cfunc.__name__, C.as_list()) for sol in Cneg.itersolve([]): qsol = Mfunc(*my_SOL(ij, sol)) assert qsol is False, (ij, sol, 'Prevent(%s)' % Cfunc.__name__, Cneg.as_list())
def test_sat(): C = Clauses() C.new_var('x1') C.new_var('x2') assert C.sat() is not None assert C.sat([]) is not None assert C.sat([()]) is None assert C.sat([(False,)]) is None assert C.sat([(True,),()]) is None assert C.sat([(True,False,-1)]) is not None assert C.sat([(+1,False),(+2,),(True,)], names=True) == {'x1','x2'} assert C.sat([(-1,False),(True,),(+2,)], names=True) == {'x2'} assert C.sat([(True,),(-1,),(-2,False)], names=True) == set() assert C.sat([(+1,),(-1,False)], names=True) is None C.unsat = True assert C.sat() is None assert C.sat([]) is None assert C.sat([(True,)]) is None assert len(Clauses(10).sat([[1]])) == 10
def test_LinearBound(): L = [ ([], [0, 1], 10), ([], [1, 2], 10), ({'x1':2, 'x2':2}, [3, 3], 10), ({'x1':2, 'x2':2}, [0, 1], 1000), ({'x1':1, 'x2':2}, [0, 2], 1000), ({'x1':2, '!x2':2}, [0, 2], 1000), ([(1, 1), (2, 2), (3, 3)], [3, 3], 1000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2], 1000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7), (3, False), (2, True)], [2, 4], 1000), ([(1, 15), (2, 16), (3, 17), (4, 18), (5, 6), (5, 19), (6, 7), (6, 20), (7, 8), (7, 21), (7, 28), (8, 9), (8, 22), (8, 29), (8, 41), (9, 10), (9, 23), (9, 30), (9, 42), (10, 1), (10, 11), (10, 24), (10, 31), (10, 34), (10, 37), (10, 43), (10, 46), (10, 50), (11, 2), (11, 12), (11, 25), (11, 32), (11, 35), (11, 38), (11, 44), (11, 47), (11, 51), (12, 3), (12, 4), (12, 5), (12, 13), (12, 14), (12, 26), (12, 27), (12, 33), (12, 36), (12, 39), (12, 40), (12, 45), (12, 48), (12, 49), (12, 52), (12, 53), (12, 54)], [192, 204], 100), ] for eq, rhs, max_iter in L: if isinstance(eq, dict): N = len(eq) else: N = max([0]+[a for c,a in eq if a is not True and a is not False]) C = Clauses(N) Cpos = Clauses(N) Cneg = Clauses(N) if isinstance(eq, dict): for k in range(1,N+1): nm = 'x%d'%k C.name_var(k, nm) Cpos.name_var(k, nm) Cneg.name_var(k, nm) eq2 = [(v,C.from_name(c)) for c,v in iteritems(eq)] else: eq2 = eq x = C.LinearBound(eq, rhs[0], rhs[1]) Cpos.Require(Cpos.LinearBound, eq, rhs[0], rhs[1]) Cneg.Prevent(Cneg.LinearBound, eq, rhs[0], rhs[1]) if x is not False: for _, sol in zip(range(max_iter), C.itersolve([] if x is True else [(x,)],N)): assert rhs[0] <= my_EVAL(eq2,sol) <= rhs[1], C.clauses if x is not True: for _, sol in zip(range(max_iter), C.itersolve([] if x is True else [(C.Not(x),)],N)): assert not(rhs[0] <= my_EVAL(eq2,sol) <= rhs[1]), C.clauses for _, sol in zip(range(max_iter), Cpos.itersolve([],N)): assert rhs[0] <= my_EVAL(eq2,sol) <= rhs[1], ('Cpos',Cpos.clauses) for _, sol in zip(range(max_iter), Cneg.itersolve([],N)): assert not(rhs[0] <= my_EVAL(eq2,sol) <= rhs[1]), ('Cneg',Cneg.clauses)
def my_TEST(Mfunc, Cfunc, mmin, mmax, is_iter): for m in range(mmin,mmax+1): if m == 0: ijprod = [()] else: ijprod = (True,False)+sum(((k,my_NOT(k)) for k in range(1,m+1)),()) ijprod = product(ijprod, repeat=m) for ij in ijprod: C = Clauses() Cpos = Clauses() Cneg = Clauses() for k in range(1,m+1): nm = 'x%d' % k C.new_var(nm) Cpos.new_var(nm) Cneg.new_var(nm) ij2 = tuple(C.from_index(k) if type(k) is int else k for k in ij) if is_iter: x = Cfunc.__get__(C,Clauses)(ij2) Cpos.Require(Cfunc.__get__(Cpos,Clauses), ij) Cneg.Prevent(Cfunc.__get__(Cneg,Clauses), ij) else: x = Cfunc.__get__(C,Clauses)(*ij2) Cpos.Require(Cfunc.__get__(Cpos,Clauses), *ij) Cneg.Prevent(Cfunc.__get__(Cneg,Clauses), *ij) tsol = Mfunc(*ij) if type(tsol) is bool: assert x is tsol, (ij2, Cfunc.__name__, C.clauses) assert Cpos.unsat == (not tsol) and not Cpos.clauses, (ij, 'Require(%s)') assert Cneg.unsat == tsol and not Cneg.clauses, (ij, 'Prevent(%s)') continue for sol in C.itersolve([(x,)]): qsol = Mfunc(*my_SOL(ij,sol)) assert qsol is True, (ij2, sol, Cfunc.__name__, C.clauses) for sol in Cpos.itersolve([]): qsol = Mfunc(*my_SOL(ij,sol)) assert qsol is True, (ij, sol,'Require(%s)' % Cfunc.__name__, Cpos.clauses) for sol in C.itersolve([(C.Not(x),)]): qsol = Mfunc(*my_SOL(ij,sol)) assert qsol is False, (ij2, sol, Cfunc.__name__, C.clauses) for sol in Cneg.itersolve([]): qsol = Mfunc(*my_SOL(ij,sol)) assert qsol is False, (ij, sol,'Prevent(%s)' % Cfunc.__name__, Cneg.clauses)