def test_odd_even_merge(): for n in [1, 2, 4, 8, 16]: A = list(range(1, n + 1)) B = list(range(n + 1, 2 * n + 1)) C = Clauses(n) merged = C.odd_even_merge(A, B) for i in range(n + 1): for j in range(n + 1): # Test all possible mergings of sorted lists, like [1, 1, 0, # 0] and [1, 0, 0, 0] -> [1, 1, 1, 0, 0, 0, 0, 0]. Asigns = [1] * i + [-1] * (n - i) Bsigns = [1] * j + [-1] * (n - j) As = {(s * a, ) for s, a in zip(Asigns, A)} Bs = {(s * b, ) for s, b in zip(Bsigns, B)} for sol in my_itersolve(C.clauses | As | Bs): a = [i in sol for i in A] b = [i in sol for i in B] m = [i in sol for i in merged] # Check we did the above correctly assert a == sorted(a, reverse=True) assert b == sorted(b, reverse=True) # And check that the merge is correct assert m == sorted(a + b, reverse=True) assert raises(ValueError, lambda: Clauses(4).odd_even_merge([1, 2], [2, 3, 4]))
def test_ITE(): # Note, pycosat will automatically include all smaller numbers in models, # e.g., itersolve([[2]]) gives [[1, 2], [-1, 2]]. This should not be an # issue here. for c in [true, false, 1]: for t in [true, false, 2]: for f in [true, false, 3]: Cl = Clauses(3) x = Cl.ITE(c, t, f) if x in [true, false]: if t == f: # In this case, it doesn't matter if c is not boolizable assert boolize(x) == boolize(t) else: assert boolize(x) == (boolize(t) if boolize(c) else boolize(f)), (c, t, f) else: for sol in my_itersolve({(x,)} | Cl.clauses): C = boolize(c) if c in [true, false] else (1 in sol) T = boolize(t) if t in [true, false] else (2 in sol) F = boolize(f) if f in [true, false] else (3 in sol) assert T if C else F, (T, C, F, sol, t, c, f) for sol in my_itersolve({(-x,)} | Cl.clauses): C = boolize(c) if c in [true, false] else (1 in sol) T = boolize(t) if t in [true, false] else (2 in sol) F = boolize(f) if f in [true, false] else (3 in sol) assert not (T if C else F)
def test_odd_even_merge(): for n in [1, 2, 4, 8, 16]: A = list(range(1, n+1)) B = list(range(n+1, 2*n+1)) C = Clauses(n) merged = C.odd_even_merge(A, B) for i in range(n+1): for j in range(n+1): # Test all possible mergings of sorted lists, like [1, 1, 0, # 0] and [1, 0, 0, 0] -> [1, 1, 1, 0, 0, 0, 0, 0]. Asigns = [1]*i + [-1]*(n - i) Bsigns = [1]*j + [-1]*(n - j) As = {(s*a,) for s, a in zip(Asigns, A)} Bs = {(s*b,) for s, b in zip(Bsigns, B)} for sol in my_itersolve(C.clauses | As | Bs): a = [i in sol for i in A] b = [i in sol for i in B] m = [i in sol for i in merged] # Check we did the above correctly assert a == sorted(a, reverse=True) assert b == sorted(b, reverse=True) # And check that the merge is correct assert m == sorted(a + b, reverse=True) assert raises(ValueError, lambda: Clauses(4).odd_even_merge([1, 2], [2, 3, 4]))
def gen_clauses(self, groups, trackers, specs): C = Clauses() def push_MatchSpec(ms): name = self.ms_to_v(ms) m = C.from_name(name) if m is None: libs = [fn for fn in self.find_matches_group(ms, groups, trackers)] m = C.Any(libs, polarity=None if ms.optional else True, name=name) return m # Create package variables for group in itervalues(groups): for fn in group: C.new_var(fn) # Create spec variables for ms in specs: push_MatchSpec(ms) # Create feature variables for name in iterkeys(trackers): push_MatchSpec(MatchSpec('@' + name)) # Add dependency relationships for group in itervalues(groups): C.Require(C.AtMostOne_NSQ, group) for fn in group: for ms in self.ms_depends(fn): if not ms.optional: C.Require(C.Or, C.Not(fn), push_MatchSpec(ms)) return C
def test_cmp_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) x, y = C.Cmp(i * 1, j * 2) for sol in my_itersolve(C.clauses): f = i * 1 in sol g = j * 2 in sol M = x in sol m = y in sol assert M == max(f, g) assert m == min(f, g) C = Clauses(1) x, y = C.Cmp(1, -1) assert x, y == [true, false] # true > false assert C.clauses == set([]) C = Clauses(1) x, y = C.Cmp(1, 1) for sol in my_itersolve(C.clauses): f = 1 in sol M = x in sol m = y in sol assert M == max(f, f) assert m == min(f, f)
def test_Cmp_bools(): for f in [true, false]: for g in [true, false]: C = Clauses(2) x, y = C.Cmp(f, g) assert x == max(f, g) assert y == min(f, g) assert C.clauses == set([]) C = Clauses(1) x, y = C.Cmp(f, 1) fb = boolize(f) # No better way to test this without defining true >= 1, which seems # like a bad idea. Should represent the order true >= 1 >= false. if fb: assert [x, y] == [true, 1] else: assert [x, y] == [1, false] C = Clauses(1) x, y = C.Cmp(1, f) fb = boolize(f) if fb: assert [x, y] == [true, 1] else: assert [x, y] == [1, false]
def test_And_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) x = C.And(i*1, j*2) for sol in my_itersolve({(x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert f and g for sol in my_itersolve({(-x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert not (f and g) C = Clauses(1) x = C.And(1, -1) assert x == false # x and ~x assert C.clauses == set([]) C = Clauses(1) x = C.And(1, 1) for sol in my_itersolve({(x,)} | C.clauses): f = 1 in sol assert (f and f) for sol in my_itersolve({(-x,)} | C.clauses): f = 1 in sol assert not (f and f)
def test_Xor_bools(): for f in [true, false]: for g in [true, false]: C = Clauses(2) x = C.Xor(f, g) assert x == (true if (boolize(f) != boolize(g)) else false) assert C.clauses == set([]) C = Clauses(1) x = C.Xor(f, 1) fb = boolize(f) if x in [true, false]: assert False else: for sol in my_itersolve({(x,)} | C.clauses): a = 1 in sol assert (fb != a) for sol in my_itersolve({(-x,)} | C.clauses): a = 1 in sol assert not (fb != a) C = Clauses(1) x = C.Xor(1, f) if x in [true, false]: assert False else: for sol in my_itersolve({(x,)} | C.clauses): a = 1 in sol assert not (fb == a) for sol in my_itersolve({(-x,)} | C.clauses): a = 1 in sol assert not not (fb == a)
def test_Or_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) x = C.Or(i*1, j*2) for sol in my_itersolve({(x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert f or g for sol in my_itersolve({(-x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert not (f or g) C = Clauses(1) x = C.Or(1, -1) assert x == true # x or ~x assert C.clauses == set([]) C = Clauses(1) x = C.Or(1, 1) for sol in my_itersolve({(x,)} | C.clauses): f = 1 in sol assert (f or f) for sol in my_itersolve({(-x,)} | C.clauses): f = 1 in sol assert not (f or f)
def test_minimize(): # minimize x1 + 2 x2 + 3 x3 + ... + 10 x10 # subject to x1 + x2 + x3 + x4 + x5 == 1 # x6 + x7 + x8 + x9 + x10 == 1 C = Clauses(10) C.Require(C.ExactlyOne, range(1, 6)) C.Require(C.ExactlyOne, range(6, 11)) objective = [(k, k) for k in range(1, 11)] sol = C.sat() C.unsat = True assert C.minimize(objective, sol)[1] == 56 C.unsat = False sol2, sval = C.minimize(objective, sol) assert C.minimize(objective, sol)[1] == 7, (objective, sol2, sval)
def test_sat(): C = Clauses() C.new_var('x1') C.new_var('x2') assert C.sat([(+1, ), (+2, )], names=True) == {'x1', 'x2'} assert C.sat([(-1, ), (+2, )], names=True) == {'x2'} assert C.sat([(-1, ), (-2, )], names=True) == set() assert C.sat([(+1, ), (-1, )], names=True) is None C.unsat = True assert C.sat() is None assert len(Clauses(10).sat([[1]])) == 10
def gen_clauses(self, specs): C = Clauses() # Creates a variable that represents the proposition: # Does the package set include package "fn"? for name, group in iteritems(self.groups): for fkey in group: C.new_var(fkey) # Install no more than one version of each package C.Require(C.AtMostOne, group) # Create an on/off variable for the entire group name = self.ms_to_v(name) C.name_var(C.Any(group, polarity=None, name=name), name+'?') # Creates a variable that represents the proposition: # Does the package set include track_feature "feat"? for name, group in iteritems(self.trackers): name = self.ms_to_v('@' + name) C.name_var(C.Any(group, polarity=None, name=name), name+'?') # Create propositions that assert: # If package "fn" is installed, its dependencie must be satisfied for group in itervalues(self.groups): for fkey in group: nkey = C.Not(fkey) for ms in self.ms_depends(fkey): if not ms.optional: C.Require(C.Or, nkey, self.push_MatchSpec(C, ms)) return C
def gen_clauses(self, groups, trackers, specs): C = Clauses() # Creates a variable that represents the proposition: # Does the package set include a package that matches MatchSpec "ms"? def push_MatchSpec(ms): name = self.ms_to_v(ms) m = C.from_name(name) if m is None: libs = [fn for fn in self.find_matches_group(ms, groups, trackers)] # If the MatchSpec is optional, then there may be cases where we want # to assert that it is *not* True. This requires polarity=None. m = C.Any(libs, polarity=None if ms.optional else True, name=name) return m # Creates a variable that represents the proposition: # Does the package set include package "fn"? for group in itervalues(groups): for fn in group: C.new_var(fn) # Install no more than one version of each package C.Require(C.AtMostOne, group) # Create a variable that represents the proposition: # Is the feature "name" active in this package set? # We mark this as "optional" below because sometimes we need to be able to # assert the proposition is False during the feature minimization pass. for name in iterkeys(trackers): ms = MatchSpec('@' + name) ms.optional = True push_MatchSpec(ms) # Create a variable that represents the proposition: # Is the MatchSpec "ms" satisfied by the current package set? for ms in specs: push_MatchSpec(ms) # Create propositions that assert: # If package "fn" is installed, its dependencie must be satisfied for group in itervalues(groups): for fn in group: for ms in self.ms_depends(fn): if not ms.optional: C.Require(C.Or, C.Not(fn), push_MatchSpec(ms)) return C
def test_odd_even_mergesort(): for n in [1, 2, 4, 8]: A = list(range(1, n+1)) C = Clauses(n) S = C.odd_even_mergesort(A) # Note, the zero-one principle states we only need to test lists of # 0's and # 1's. https://en.wikipedia.org/wiki/Sorting_network#Zero-one_principle. for sol in my_itersolve(C.clauses): a = [i in sol for i in A] s = [i in sol for i in S] assert s == sorted(a, reverse=True) # TODO: n > 8 takes too long to test all combinations, but maybe we should test # some random combinations. assert raises(ValueError, lambda: Clauses(5).odd_even_mergesort([1, 2, 3, 4, 5])) # Make sure it works with booleans for n in [1, 2, 4]: for item in product(*[[true, false]]*n): assert list(Clauses(0).odd_even_mergesort(item)) == sorted(item, reverse=True) # The most important use-case is extending a non-power of 2 length list # with false. for n in range(1, 9): next_power_of_2 = 2**ceil(log2(n)) assert n <= next_power_of_2 for item in product(*[[true, false]]*(next_power_of_2 - n)): A = list(range(1, n + 1)) + list(item) C = Clauses(n) S = C.odd_even_mergesort(A) for sol in my_itersolve(C.clauses): a = [boolize(i) if isinstance(boolize(i), bool) else i in sol for i in A] s = [boolize(i) if isinstance(boolize(i), bool) else i in sol for i in S] assert s == sorted(a, reverse=True), (a, s, sol)
def test_BDD(): L = [ ([(1, 1), (2, 2)], [0, 2], 10000), ([(1, 1), (2, -2)], [0, 2], 10000), ([(1, 1), (2, 2), (3, 3)], [3, 3], 10000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2], 10000), ([(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), ([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40], 1000) ] for eq, rhs, max_iter in L: N = max(a for c,a in eq) C = Clauses(N) Cneg = Clauses(N) Cpos = Clauses(N) x = C.build_BDD(eq, rhs[0], rhs[1]) xneg = Cneg.build_BDD(eq, rhs[0], rhs[1], polarity=False) xpos = Cpos.build_BDD(eq, rhs[0], rhs[1], polarity=True) for _, sol in zip(range(max_iter), my_itersolve([(x,)] + C.clauses)): assert rhs[0] <= evaluate_eq(eq,sol) <= rhs[1] for _, sol in zip(range(max_iter), my_itersolve([(xpos,)] + Cpos.clauses)): assert rhs[0] <= evaluate_eq(eq,sol) <= rhs[1] for _, sol in zip(range(max_iter), my_itersolve([(-x,)] + C.clauses)): assert not(rhs[0] <= evaluate_eq(eq,sol) <= rhs[1]) for _, sol in zip(range(max_iter), my_itersolve([(-xneg,)] + Cneg.clauses)): assert not(rhs[0] <= evaluate_eq(eq,sol) <= rhs[1])
def test_sat(): C = Clauses() C.new_var('x1') C.new_var('x2') assert C.sat([(+1,),(+2,)], names=True) == {'x1','x2'} assert C.sat([(-1,),(+2,)], names=True) == {'x2'} assert C.sat([(-1,),(-2,)], names=True) == set() assert C.sat([(+1,),(-1,)], names=True) is None C.unsat = True assert C.sat() is None assert len(Clauses(10).sat([[1]])) == 10
def test_odd_even_mergesort(): for n in [1, 2, 4, 8]: A = list(range(1, n + 1)) C = Clauses(n) S = C.odd_even_mergesort(A) # Note, the zero-one principle states we only need to test lists of # 0's and # 1's. https://en.wikipedia.org/wiki/Sorting_network#Zero-one_principle. for sol in my_itersolve(C.clauses): a = [i in sol for i in A] s = [i in sol for i in S] assert s == sorted(a, reverse=True) # TODO: n > 8 takes too long to test all combinations, but maybe we should test # some random combinations. assert raises(ValueError, lambda: Clauses(5).odd_even_mergesort([1, 2, 3, 4, 5])) # Make sure it works with booleans for n in [1, 2, 4]: for item in product(*[[true, false]] * n): assert list(Clauses(0).odd_even_mergesort(item)) == sorted( item, reverse=True) # The most important use-case is extending a non-power of 2 length list # with false. for n in range(1, 9): next_power_of_2 = 2**ceil(log2(n)) assert n <= next_power_of_2 for item in product(*[[true, false]] * (next_power_of_2 - n)): A = list(range(1, n + 1)) + list(item) C = Clauses(n) S = C.odd_even_mergesort(A) for sol in my_itersolve(C.clauses): a = [ boolize(i) if isinstance(boolize(i), bool) else i in sol for i in A ] s = [ boolize(i) if isinstance(boolize(i), bool) else i in sol for i in S ] assert s == sorted(a, reverse=True), (a, s, sol)
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.clauses == C2.clauses
def test_minimize(): # minimize x1 + 2 x2 + 3 x3 + ... + 10 x10 # subject to x1 + x2 + x3 + x4 + x5 == 1 # x6 + x7 + x8 + x9 + x10 == 1 C = Clauses(10) C.Require(C.ExactlyOne, range(1,6)) C.Require(C.ExactlyOne, range(6,11)) objective = [(k,k) for k in range(1,11)] sol = C.sat() C.unsat = True assert C.minimize(objective, sol)[1] == 56 C.unsat = False sol2, sval = C.minimize(objective, sol) assert C.minimize(objective, sol)[1] == 7, (objective, sol2, sval)
def gen_clauses(self, groups, trackers, specs): C = Clauses() # Creates a variable that represents the proposition: # Does the package set include a package that matches MatchSpec "ms"? def push_MatchSpec(ms): name = self.ms_to_v(ms) m = C.from_name(name) if m is None: libs = [ fn for fn in self.find_matches_group(ms, groups, trackers) ] # If the MatchSpec is optional, then there may be cases where we want # to assert that it is *not* True. This requires polarity=None. m = C.Any(libs, polarity=None if ms.optional else True, name=name) return m # Creates a variable that represents the proposition: # Does the package set include package "fn"? for group in itervalues(groups): for fn in group: C.new_var(fn) # Install no more than one version of each package C.Require(C.AtMostOne, group) # Create a variable that represents the proposition: # Is the feature "name" active in this package set? # We mark this as "optional" below because sometimes we need to be able to # assert the proposition is False during the feature minimization pass. for name in iterkeys(trackers): ms = MatchSpec('@' + name) ms.optional = True push_MatchSpec(ms) # Create a variable that represents the proposition: # Is the MatchSpec "ms" satisfied by the current package set? for ms in specs: push_MatchSpec(ms) # Create propositions that assert: # If package "fn" is installed, its dependencie must be satisfied for group in itervalues(groups): for fn in group: for ms in self.ms_depends(fn): if not ms.optional: C.Require(C.Or, C.Not(fn), push_MatchSpec(ms)) return C
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 test_Xor_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) x = C.Xor(i*1, j*2) for sol in my_itersolve({(x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert (f != g) for sol in my_itersolve({(-x,)} | C.clauses): f = i*1 in sol g = j*2 in sol assert not (f != g) C = Clauses(1) x = C.Xor(1, 1) assert x == false # x xor x assert C.clauses == set([]) C = Clauses(1) x = C.Xor(1, -1) assert x == true # x xor -x assert C.clauses == set([])
def test_And_bools(): for f in [true, false]: for g in [true, false]: C = Clauses(2) x = C.And(f, g) assert x == (true if (boolize(f) and boolize(g)) else false) assert C.clauses == set([]) C = Clauses(1) x = C.And(f, 1) fb = boolize(f) if x in [true, false]: assert C.clauses == set([]) xb = boolize(x) assert xb == (fb and NoBool()) else: for sol in my_itersolve({(x,)} | C.clauses): a = 1 in sol assert (fb and a) for sol in my_itersolve({(-x,)} | C.clauses): a = 1 in sol assert not (fb and a) C = Clauses(1) x = C.And(1, f) if x in [true, false]: assert C.clauses == set([]) xb = boolize(x) assert xb == (fb and NoBool()) else: for sol in my_itersolve({(x,)} | C.clauses): a = 1 in sol assert (fb and a) for sol in my_itersolve({(-x,)} | C.clauses): a = 1 in sol assert not (fb and a)
def gen_clauses(self, groups, trackers, specs): C = Clauses() polarities = {} def push_MatchSpec(ms, polarity=None): name = self.ms_to_v(ms) m = C.from_name(name) if m is None: m = C.Any(self.find_matches_group(ms, groups, trackers), polarity=polarity, name=name) return m # Create package variables for group in itervalues(groups): for fn in group: C.new_var(fn) # Create spec variables for ms in specs: push_MatchSpec(ms, polarity=None if ms.optional else True) # Create feature variables for name in iterkeys(trackers): push_MatchSpec(MatchSpec('@' + name), polarity=True) # Add dependency relationships for group in itervalues(groups): C.Require(C.AtMostOne_NSQ, group) for fn in group: for ms in self.ms_depends(fn): if not ms.optional: C.Require(C.Or, C.Not(fn), push_MatchSpec(ms, polarity=True)) return C
def sat(val, m=1): return Clauses(m).sat(val)
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)
def test_sorter(): L = [ Linear([(1, 1), (2, 2)], [0, 2]), Linear([(1, 1), (2, -2)], [0, 2]), Linear([(1, 1), (2, 2), (3, 3)], [3, 3]), Linear([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2]) ] for l in L: C = Clauses(max(l.atoms)) m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0]-1],), (-m[l.rhs[1]],)} nx = {(-m[l.rhs[0]-1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]],)} nx = {(m[l.rhs[1]],)} for sol in my_itersolve(x | C.clauses): assert l(sol) for sol in my_itersolve(nx | C.clauses): assert not l(sol) l = Linear([(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]) C = Clauses(max(l.atoms)) m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0]-1],), (-m[l.rhs[1]],)} nx = {(-m[l.rhs[0]-1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]],)} nx = {(m[l.rhs[1]],)} for sol, _ in zip(my_itersolve(x | C.clauses), range(2)): assert l(sol) for sol, _ in zip(my_itersolve(nx | C.clauses), range(2)): assert not l(sol) l = Linear([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40]) C = Clauses(max(l.atoms)) print('building sorter') m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0]-1],), (-m[l.rhs[1]],)} nx = {(-m[l.rhs[0]-1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]],)} nx = {(m[l.rhs[1]],)} print('checking positive solutions') for sol, _ in zip(my_itersolve(x | C.clauses), range(2)): assert l(sol) print('checking negative solutions') for sol, _ in zip(my_itersolve(nx | C.clauses), range(2)): assert not l(sol) C = Clauses(0) assert C.build_sorter([]) == [] assert not C.clauses
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 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 test_BDD(): L = [ Linear([(1, 1), (2, 2)], [0, 2]), Linear([(1, 1), (2, -2)], [0, 2]), Linear([(1, 1), (2, 2), (3, 3)], [3, 3]), Linear([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2]) ] for l in L: Cr = Clauses(max(l.atoms)) Crneg = Clauses(max(l.atoms)) Crpos = Clauses(max(l.atoms)) xr = Cr.build_BDD_recursive(l) xrneg = Crneg.build_BDD_recursive(l, polarity=False) xrpos = Crpos.build_BDD_recursive(l, polarity=True) C = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) x = C.build_BDD(l) xneg = Cneg.build_BDD(l, polarity=False) xpos = Cpos.build_BDD(l, polarity=True) assert x == xr assert xneg == xrneg assert xpos == xrpos assert C.clauses == Cr.clauses assert Cneg.clauses == Crneg.clauses assert Cpos.clauses == Crpos.clauses for sol in chain(my_itersolve({(x,)} | C.clauses), my_itersolve({(xpos,)} | Cpos.clauses)): assert l(sol) for sol in chain(my_itersolve({(-x,)} | C.clauses), my_itersolve({(-xneg,)} | Cneg.clauses)): assert not l(sol) # Real life example. There are too many solutions to check them all, just # check that building the BDD doesn't take forever l = Linear([(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]) Cr = Clauses(max(l.atoms)) Crneg = Clauses(max(l.atoms)) Crpos = Clauses(max(l.atoms)) xr = Cr.build_BDD_recursive(l) xrneg = Crneg.build_BDD_recursive(l, polarity=False) xrpos = Crpos.build_BDD_recursive(l, polarity=True) C = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) x = C.build_BDD(l) xneg = Cneg.build_BDD(l, polarity=False) xpos = Cpos.build_BDD(l, polarity=True) assert x == xr assert xneg == xrneg assert xpos == xrpos assert C.clauses == Cr.clauses assert Cneg.clauses == Crneg.clauses assert Cpos.clauses == Crpos.clauses for _, sol in zip(range(20), my_itersolve({(x,)} | C.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-x,)} | C.clauses)): assert not l(sol) for _, sol in zip(range(20), my_itersolve({(xpos,)} | Cpos.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-xneg,)} | Cneg.clauses)): assert not l(sol) # Another real-life example. This one is too big to be built recursively # unless the recursion limit is increased. l = Linear([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40]) C = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) x = C.build_BDD(l) xpos = Cpos.build_BDD(l, polarity=True) xneg = Cneg.build_BDD(l, polarity=False) for _, sol in zip(range(20), my_itersolve({(x,)} | C.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-x,)} | C.clauses)): assert not l(sol) for _, sol in zip(range(20), my_itersolve({(xpos,)} | Cpos.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-xneg,)} | Cneg.clauses)): assert not l(sol)
def test_And_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) Cpos = Clauses(2) Cneg = Clauses(2) x = C.And(i * 1, j * 2) xpos = Cpos.And(i * 1, j * 2, polarity=True) xneg = Cneg.And(i * 1, j * 2, polarity=False) for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): f = i * 1 in sol g = j * 2 in sol assert f and g for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): f = i * 1 in sol g = j * 2 in sol assert not (f and g) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.And(1, -1) xpos = Cpos.And(1, -1, polarity=True) xneg = Cneg.And(1, -1, polarity=False) assert x == xneg == xpos == false # x and ~x assert C.clauses == Cpos.clauses == Cneg.clauses == set([]) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.And(1, 1) xpos = Cpos.And(1, 1, polarity=True) xneg = Cneg.And(1, 1, polarity=False) for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): f = 1 in sol assert (f and f) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): f = 1 in sol assert not (f and f)
def test_sorter(): L = [ Linear([(1, 1), (2, 2)], [0, 2]), Linear([(1, 1), (2, -2)], [0, 2]), Linear([(1, 1), (2, 2), (3, 3)], [3, 3]), Linear([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2]) ] for l in L: C = Clauses(max(l.atoms)) m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0] - 1], ), (-m[l.rhs[1]], )} nx = {(-m[l.rhs[0] - 1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]], )} nx = {(m[l.rhs[1]], )} for sol in my_itersolve(x | C.clauses): assert l(sol) for sol in my_itersolve(nx | C.clauses): assert not l(sol) l = Linear([(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]) C = Clauses(max(l.atoms)) m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0] - 1], ), (-m[l.rhs[1]], )} nx = {(-m[l.rhs[0] - 1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]], )} nx = {(m[l.rhs[1]], )} for sol, _ in zip(my_itersolve(x | C.clauses), range(2)): assert l(sol) for sol, _ in zip(my_itersolve(nx | C.clauses), range(2)): assert not l(sol) l = Linear([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40]) C = Clauses(max(l.atoms)) print('building sorter') m = C.build_sorter(l) if l.rhs[0]: x = {(m[l.rhs[0] - 1], ), (-m[l.rhs[1]], )} nx = {(-m[l.rhs[0] - 1], m[l.rhs[1]])} else: x = {(-m[l.rhs[1]], )} nx = {(m[l.rhs[1]], )} print('checking positive solutions') for sol, _ in zip(my_itersolve(x | C.clauses), range(2)): assert l(sol) print('checking negative solutions') for sol, _ in zip(my_itersolve(nx | C.clauses), range(2)): assert not l(sol) C = Clauses(0) assert C.build_sorter([]) == [] assert not C.clauses
def test_LinearBound(): L = [ ([], [0, 1], True), ([], [1, 2], False), ([(2, 1), (2, 2)], [3, 3], False), ([(2, 1), (2, 2)], [0, 1], 1000), ([(1, 1), (2, 2)], [0, 2], 1000), ([(1, 1), (2, -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: 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) 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 type(max_iter) is bool: assert x is max_iter, (ij, Cfunc.__name__, C.clauses) assert Cpos.unsat == (not max_iter) and not Cpos.clauses, ( ij, 'Require(%s)') assert Cneg.unsat == max_iter and not Cneg.clauses, (ij, 'Prevent(%s)') continue for _, sol in zip(range(max_iter), C.itersolve([(x, )], N)): assert rhs[0] <= my_EVAL(eq, sol) <= rhs[1], C.clauses for _, sol in zip(range(max_iter), C.itersolve([(C.Not(x), )], N)): assert not (rhs[0] <= my_EVAL(eq, sol) <= rhs[1]), C.clauses for _, sol in zip(range(max_iter), Cpos.itersolve([], N)): assert rhs[0] <= my_EVAL(eq, sol) <= rhs[1], ('Cpos', Cpos.clauses) for _, sol in zip(range(max_iter), Cneg.itersolve([], N)): assert not (rhs[0] <= my_EVAL(eq, sol) <= rhs[1]), ('Cneg', Cneg.clauses)
def test_BDD(): L = [ ([(1, 1), (2, 2)], [0, 2], 10000), ([(1, 1), (2, -2)], [0, 2], 10000), ([(1, 1), (2, 2), (3, 3)], [3, 3], 10000), ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2], 10000), ([(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), ([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40], 1000) ] for eq, rhs, max_iter in L: N = max(a for c, a in eq) C = Clauses(N) Cneg = Clauses(N) Cpos = Clauses(N) x = C.build_BDD(eq, rhs[0], rhs[1]) xneg = Cneg.build_BDD(eq, rhs[0], rhs[1], polarity=False) xpos = Cpos.build_BDD(eq, rhs[0], rhs[1], polarity=True) for _, sol in zip(range(max_iter), my_itersolve([(x, )] + C.clauses)): assert rhs[0] <= evaluate_eq(eq, sol) <= rhs[1] for _, sol in zip(range(max_iter), my_itersolve([(xpos, )] + Cpos.clauses)): assert rhs[0] <= evaluate_eq(eq, sol) <= rhs[1] for _, sol in zip(range(max_iter), my_itersolve([(-x, )] + C.clauses)): assert not (rhs[0] <= evaluate_eq(eq, sol) <= rhs[1]) for _, sol in zip(range(max_iter), my_itersolve([(-xneg, )] + Cneg.clauses)): assert not (rhs[0] <= evaluate_eq(eq, sol) <= rhs[1])
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)
def sat(val): return Clauses().sat(val)
def test_BDD(): L = [ Linear([(1, 1), (2, 2)], [0, 2]), Linear([(1, 1), (2, -2)], [0, 2]), Linear([(1, 1), (2, 2), (3, 3)], [3, 3]), Linear([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2]) ] for l in L: Cr = Clauses(max(l.atoms)) Crneg = Clauses(max(l.atoms)) Crpos = Clauses(max(l.atoms)) xr = Cr.build_BDD_recursive(l) xrneg = Crneg.build_BDD_recursive(l, polarity=False) xrpos = Crpos.build_BDD_recursive(l, polarity=True) C = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) x = C.build_BDD(l) xneg = Cneg.build_BDD(l, polarity=False) xpos = Cpos.build_BDD(l, polarity=True) assert x == xr assert xneg == xrneg assert xpos == xrpos assert C.clauses == Cr.clauses assert Cneg.clauses == Crneg.clauses assert Cpos.clauses == Crpos.clauses for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): assert l(sol) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): assert not l(sol) # Real life example. There are too many solutions to check them all, just # check that building the BDD doesn't take forever l = Linear([(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]) Cr = Clauses(max(l.atoms)) Crneg = Clauses(max(l.atoms)) Crpos = Clauses(max(l.atoms)) xr = Cr.build_BDD_recursive(l) xrneg = Crneg.build_BDD_recursive(l, polarity=False) xrpos = Crpos.build_BDD_recursive(l, polarity=True) C = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) x = C.build_BDD(l) xneg = Cneg.build_BDD(l, polarity=False) xpos = Cpos.build_BDD(l, polarity=True) assert x == xr assert xneg == xrneg assert xpos == xrpos assert C.clauses == Cr.clauses assert Cneg.clauses == Crneg.clauses assert Cpos.clauses == Crpos.clauses for _, sol in zip(range(20), my_itersolve({(x, )} | C.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-x, )} | C.clauses)): assert not l(sol) for _, sol in zip(range(20), my_itersolve({(xpos, )} | Cpos.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-xneg, )} | Cneg.clauses)): assert not l(sol) # Another real-life example. This one is too big to be built recursively # unless the recursion limit is increased. l = Linear([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90), (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82), (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75), (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124), (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108), (57, 107), (58, 106)], [21, 40]) C = Clauses(max(l.atoms)) Cpos = Clauses(max(l.atoms)) Cneg = Clauses(max(l.atoms)) x = C.build_BDD(l) xpos = Cpos.build_BDD(l, polarity=True) xneg = Cneg.build_BDD(l, polarity=False) for _, sol in zip(range(20), my_itersolve({(x, )} | C.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-x, )} | C.clauses)): assert not l(sol) for _, sol in zip(range(20), my_itersolve({(xpos, )} | Cpos.clauses)): assert l(sol) for _, sol in zip(range(20), my_itersolve({(-xneg, )} | Cneg.clauses)): assert not l(sol)
def sat(val): return Clauses(max(abs(v) for v in chain(*val))).sat(val)
def test_Or_bools(): for f in [true, false]: for g in [true, false]: C = Clauses(2) Cpos = Clauses(2) Cneg = Clauses(2) x = C.Or(f, g) xpos = Cpos.Or(f, g, polarity=True) xneg = Cneg.Or(f, g, polarity=False) assert x == xpos == xneg == (true if (boolize(f) or boolize(g)) else false) assert C.clauses == Cpos.clauses == Cneg.clauses == set([]) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Or(f, 1) xpos = Cpos.Or(f, 1, polarity=True) xneg = Cneg.Or(f, 1, polarity=False) fb = boolize(f) if x in [true, false]: assert C.clauses == Cpos.clauses == Cneg.clauses == set([]) xb = boolize(x) xbpos = boolize(xpos) xbneg = boolize(xneg) assert xb == xbpos == xbneg == (fb or NoBool()) else: for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): a = 1 in sol assert (fb or a) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): a = 1 in sol assert not (fb or a) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Or(1, f) xpos = Cpos.Or(1, f, polarity=True) xneg = Cneg.Or(1, f, polarity=False) if x in [true, false]: assert C.clauses == Cpos.clauses == Cneg.clauses == set([]) xb = boolize(x) xbpos = boolize(xpos) xbneg = boolize(xneg) assert xb == xbpos == xbneg == (fb or NoBool()) else: for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): a = 1 in sol assert (fb or a) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): a = 1 in sol assert not (fb or a)
def test_Xor_bools(): for f in [true, false]: for g in [true, false]: C = Clauses(2) Cpos = Clauses(2) Cneg = Clauses(2) x = C.Xor(f, g) xpos = Cpos.Xor(f, g, polarity=True) xneg = Cneg.Xor(f, g, polarity=False) assert x == xpos == xneg == (true if (boolize(f) != boolize(g)) else false) assert C.clauses == Cpos.clauses == Cneg.clauses == set([]) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Xor(f, 1) xpos = Cpos.Xor(f, 1, polarity=True) xneg = Cneg.Xor(f, 1, polarity=False) fb = boolize(f) if x in [true, false] or xpos in [true, false ] or xneg in [true, false]: assert False else: for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): a = 1 in sol assert (fb != a) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): a = 1 in sol assert not (fb != a) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Xor(1, f) xpos = Cpos.Xor(1, f, polarity=True) xneg = Cneg.Xor(1, f, polarity=False) if x in [true, false] or xpos in [true, false ] or xneg in [true, false]: assert False else: for sol in chain(my_itersolve({(x, )} | C.clauses), my_itersolve({(xpos, )} | Cpos.clauses)): a = 1 in sol assert not (fb == a) for sol in chain(my_itersolve({(-x, )} | C.clauses), my_itersolve({(-xneg, )} | Cneg.clauses)): a = 1 in sol assert not not (fb == a)
def test_Xor_clauses(): # XXX: Is this i, j stuff necessary? for i in range(-1, 2, 2): # [-1, 1] for j in range(-1, 2, 2): C = Clauses(2) Cpos = Clauses(2) Cneg = Clauses(2) x = C.Xor(i * 1, j * 2) xpos = Cpos.Xor(i * 1, j * 2, polarity=True) xneg = Cneg.Xor(i * 1, j * 2, polarity=False) for sol in chain(my_itersolve([(x, )] + C.clauses), my_itersolve([(xpos, )] + Cpos.clauses)): f = i * 1 in sol g = j * 2 in sol assert (f != g) for sol in chain(my_itersolve([(-x, )] + C.clauses), my_itersolve([(-xneg, )] + Cneg.clauses)): f = i * 1 in sol g = j * 2 in sol assert not (f != g) C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Xor(1, 1) xpos = Cpos.Xor(1, 1, polarity=True) xneg = Cneg.Xor(1, 1, polarity=False) assert x == xpos == xneg == false # x xor x assert C.clauses == Cpos.clauses == Cneg.clauses == [] C = Clauses(1) Cpos = Clauses(1) Cneg = Clauses(1) x = C.Xor(1, -1) xpos = Cpos.Xor(1, -1, polarity=True) xneg = Cneg.Xor(1, -1, polarity=False) assert x == xpos == xneg == true # x xor -x assert C.clauses == Cpos.clauses == Cneg.clauses == []