def test_pl_true(): assert pl_true(True) is True assert pl_true( A & B, {A: True, B: True}) is True assert pl_true( A | B, {A: True}) is True assert pl_true( A | B, {B: True}) is True assert pl_true( A | B, {A: None, B: True}) is True assert pl_true( A >> B, {A: False}) is True assert pl_true( A | B | ~C, {A: False, B: True, C: True}) is True assert pl_true(Equivalent(A, B), {A: False, B: False}) is True # test for false assert pl_true(False) is False assert pl_true( A & B, {A: False, B: False}) is False assert pl_true( A & B, {A: False}) is False assert pl_true( A & B, {B: False}) is False assert pl_true( A | B, {A: False, B: False}) is False # test for None assert pl_true(B, {B: None}) is None assert pl_true( A & B, {A: True, B: None}) is None assert pl_true( A >> B, {A: True, B: None}) is None assert pl_true(Equivalent(A, B), {A: None}) is None assert pl_true(Equivalent(A, B), {A: True, B: None}) is None # Test for deep assert pl_true(A | B, {A: False}, deep=True) is None assert pl_true(~A & ~B, {A: False}, deep=True) is None assert pl_true(A | B, {A: False, B: False}, deep=True) is False assert pl_true(A & B & (~A | ~B), {A: True}, deep=True) is False assert pl_true((C >> A) >> (B >> A), {C: True}, deep=True) is True
def test_to_nnf(): assert to_nnf(true) is true assert to_nnf(false) is false assert to_nnf(a) == a assert to_nnf(~a) == ~a class Foo(BooleanFunction): pass pytest.raises(ValueError, lambda: to_nnf(~Foo(a))) assert to_nnf(a | ~a | b) is true assert to_nnf(a & ~a & b) is false assert to_nnf(a >> b) == ~a | b assert to_nnf(Implies(a, b, evaluate=False)) == ~a | b assert to_nnf(a >> (c >> ~b)) == (~b | ~c) | ~a assert to_nnf(Equivalent(a, b)) == (a | ~b) & (b | ~a) assert to_nnf(Equivalent(a, b, c)) == (~a | b) & (~b | c) & (~c | a) assert to_nnf(Equivalent(a, b, c, d)) == (~a | b) & (~b | c) & (~c | d) & (~d | a) assert to_nnf(a ^ b ^ c) == (a | b | c) & (~a | ~b | c) & (a | ~b | ~c) & (~a | b | ~c) assert to_nnf(ITE(a, b, c)) == (~a | b) & (a | c) assert to_nnf(~(a | b | c)) == ~a & ~b & ~c assert to_nnf(~(a & b & c)) == ~a | ~b | ~c assert to_nnf(~(a >> b)) == a & ~b assert to_nnf(~(Equivalent(a, b, c))) == (a | b | c) & (~a | ~b | ~c) assert to_nnf(~(a ^ b ^ c)) == (~a | b | c) & (a | ~b | c) & (a | b | ~c) & (~a | ~b | ~c) assert to_nnf(~(ITE(a, b, c))) == (~a | ~b) & (a | ~c) assert to_nnf((a >> b) ^ (b >> a)) == (a & ~b) | (~a & b) assert to_nnf((a >> b) ^ (b >> a), False) == (~a | ~b | a | b) & ((a & ~b) | (~a & b))
def test_to_nnf(): assert to_nnf(true) is true assert to_nnf(false) is false assert to_nnf(A) == A assert (~A).to_nnf() == ~A class Boo(BooleanFunction): pass pytest.raises(ValueError, lambda: to_nnf(~Boo(A))) assert to_nnf(A | ~A | B) is true assert to_nnf(A & ~A & B) is false assert to_nnf(A >> B) == ~A | B assert to_nnf(Equivalent(A, B, C)) == (~A | B) & (~B | C) & (~C | A) assert to_nnf(A ^ B ^ C) == \ (A | B | C) & (~A | ~B | C) & (A | ~B | ~C) & (~A | B | ~C) assert to_nnf(ITE(A, B, C)) == (~A | B) & (A | C) assert to_nnf(Not(A | B | C)) == ~A & ~B & ~C assert to_nnf(Not(A & B & C)) == ~A | ~B | ~C assert to_nnf(Not(A >> B)) == A & ~B assert to_nnf(Not(Equivalent(A, B, C))) == And(Or(A, B, C), Or(~A, ~B, ~C)) assert to_nnf(Not(A ^ B ^ C)) == \ (~A | B | C) & (A | ~B | C) & (A | B | ~C) & (~A | ~B | ~C) assert to_nnf(Not(ITE(A, B, C))) == (~A | ~B) & (A | ~C) assert to_nnf((A >> B) ^ (B >> A)) == (A & ~B) | (~A & B) assert to_nnf((A >> B) ^ (B >> A), False) == \ (~A | ~B | A | B) & ((A & ~B) | (~A & B))
def test_pl_true(): assert pl_true(True) is True assert pl_true(a & b, {a: True, b: True}) is True assert pl_true(a | b, {a: True}) is True assert pl_true(a | b, {b: True}) is True assert pl_true(a | b, {a: None, b: True}) is True assert pl_true(a >> b, {a: False}) is True assert pl_true(a | b | ~c, {a: False, b: True, c: True}) is True assert pl_true(Equivalent(a, b), {a: False, b: False}) is True assert pl_true(False) is False assert pl_true(a & b, {a: False, b: False}) is False assert pl_true(a & b, {a: False}) is False assert pl_true(a & b, {b: False}) is False assert pl_true(a | b, {a: False, b: False}) is False assert pl_true(b, {b: None}) is None assert pl_true(a & b, {a: True, b: None}) is None assert pl_true(a >> b, {a: True, b: None}) is None assert pl_true(Equivalent(a, b), {a: None}) is None assert pl_true(Equivalent(a, b), {a: True, b: None}) is None assert pl_true(a | b, {a: False}, deep=True) is None assert pl_true(~a & ~b, {a: False}, deep=True) is None assert pl_true(a | b, {a: False, b: False}, deep=True) is False assert pl_true(a & b & (~a | ~b), {a: True}, deep=True) is False assert pl_true((c >> a) >> (b >> a), {c: True}, deep=True) is True pytest.raises(ValueError, lambda: pl_true('John Cleese')) pytest.raises(ValueError, lambda: pl_true(42 + pi)) pytest.raises(ValueError, lambda: pl_true(42))
def test_to_dnf(): assert to_dnf(true) == true assert to_dnf(~b & ~c) == ~b & ~c assert to_dnf(~(b | c)) == ~b & ~c assert to_dnf(a & (b | c)) == (a & b) | (a & c) assert to_dnf((~a | b) & c) == (b & c) | (c & ~a) assert to_dnf(a >> b) == ~a | b assert to_dnf(a >> (b & c)) == (~a) | (b & c) assert to_dnf(Equivalent(a, b), True) == (a & b) | (~a & ~b) assert to_dnf(Equivalent(a, b & c), True) == ((a & b & c) | (~a & ~b) | (~a & ~c))
def test_to_dnf(): assert to_dnf(true) == true assert to_dnf((~B) & (~C)) == (~B) & (~C) assert to_dnf(~(B | C)) == And(Not(B), Not(C)) assert to_dnf(A & (B | C)) == Or(And(A, B), And(A, C)) assert to_dnf(A >> B) == (~A) | B assert to_dnf(A >> (B & C)) == (~A) | (B & C) assert to_dnf(Equivalent(A, B), True) == \ Or(And(A, B), And(Not(A), Not(B))) assert to_dnf(Equivalent(A, B & C), True) == \ Or(And(A, B, C), And(Not(A), Not(B)), And(Not(A), Not(C)))
def test_to_cnf(): assert to_cnf(~(b | c)) == ~b & ~c assert to_cnf((a & b) | c) == (a | c) & (b | c) assert to_cnf(a >> b) == ~a | b assert to_cnf(a >> (b & c)) == (~a | b) & (~a | c) assert to_cnf(a & (b | c) | ~a & (b | c), True) == b | c assert to_cnf(a | (~b & ~c)) == (a | ~b) & (a | ~c) assert to_cnf(Equivalent(a, b)) == (a | ~b) & (b | ~a) assert to_cnf(Equivalent(a, b & c)) == (~a | b) & (~a | c) & (~b | ~c | a) assert to_cnf(Equivalent(a, b | c), True) == (~b | a) & (~c | a) & (b | c | ~a) assert to_cnf(~(a | b) | c) == (~a | c) & (~b | c) assert to_cnf((a & b) | c) == (a | c) & (b | c)
def test_dpll_satisfiable(): assert dpll_satisfiable(false) is False assert dpll_satisfiable( A & ~A ) is False assert dpll_satisfiable( A & ~B ) == {A: True, B: False} assert dpll_satisfiable( A | B ) in ({A: True}, {B: True}, {A: True, B: True}) assert dpll_satisfiable( (~A | B) & (~B | A) ) in ({A: True, B: True}, {A: False, B: False}) assert dpll_satisfiable( (A | B) & (~B | C) ) in ({A: True, B: False}, {A: True, C: True}, {B: True, C: True}) assert dpll_satisfiable( A & B & C ) == {A: True, B: True, C: True} assert dpll_satisfiable( (A | B) & (A >> B) ) == {B: True} assert dpll_satisfiable( Equivalent(A, B) & A ) == {A: True, B: True} assert dpll_satisfiable( Equivalent(A, B) & ~A ) == {A: False, B: False}
def test_to_cnf(): assert to_cnf(~(B | C)) == And(Not(B), Not(C)) assert to_cnf((A & B) | C) == And(Or(A, C), Or(B, C)) assert to_cnf(A >> B) == (~A) | B assert to_cnf(A >> (B & C)) == (~A | B) & (~A | C) assert to_cnf(A & (B | C) | ~A & (B | C), True) == B | C assert to_cnf(Equivalent(A, B)) == And(Or(A, Not(B)), Or(B, Not(A))) assert to_cnf(Equivalent(A, B & C)) == \ (~A | B) & (~A | C) & (~B | ~C | A) assert to_cnf(Equivalent(A, B | C), True) == \ And(Or(Not(B), A), Or(Not(C), A), Or(B, C, Not(A))) assert to_cnf(~(A | B) | C) == And(Or(Not(A), C), Or(Not(B), C))
def test_equals(): assert (~(a | b)).equals(~a & ~b) is True assert Equivalent(a, b).equals((a >> b) & (b >> a)) is True assert ((a | ~b) & (~a | b)).equals((~a & ~b) | (a & b)) is True assert (a >> b).equals(~a >> ~b) is False assert (a >> (b >> a)).equals(a >> (c >> a)) is False pytest.raises(NotImplementedError, lambda: (a & (a < b)).equals(a & (b > a)))
def test_satisfiable_all_models(): assert next(satisfiable(False, all_models=True)) is False assert list(satisfiable((A >> ~A) & A, all_models=True)) == [False] assert list(satisfiable(True, all_models=True)) == [{true: true}] models = [{A: True, B: False}, {A: False, B: True}] result = satisfiable(A ^ B, all_models=True) models.remove(next(result)) models.remove(next(result)) pytest.raises(StopIteration, lambda: next(result)) assert not models assert list(satisfiable(Equivalent(A, B), all_models=True)) == \ [{A: False, B: False}, {A: True, B: True}] models = [{A: False, B: False}, {A: False, B: True}, {A: True, B: True}] for model in satisfiable(A >> B, all_models=True): models.remove(model) assert not models # This is a santiy test to check that only the required number # of solutions are generated. The expr below has 2**100 - 1 models # which would time out the test if all are generated at once. sym = numbered_symbols() X = [next(sym) for i in range(100)] result = satisfiable(Or(*X), all_models=True) for i in range(10): assert next(result)
def test_simplification(): """Test working of simplification methods.""" set1 = [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 0]] set2 = [[0, 0, 0], [0, 1, 0], [1, 0, 1], [1, 1, 1]] assert SOPform([x, y, z], set1) == Or(And(Not(x), z), And(Not(z), x)) assert Not(SOPform([x, y, z], set2)) == Not(Or(And(Not(x), Not(z)), And(x, z))) assert POSform([x, y, z], set1 + set2) is true assert SOPform([x, y, z], set1 + set2) is true assert SOPform([Dummy(), Dummy(), Dummy()], set1 + set2) is true minterms = [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1]] dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]] assert ( SOPform([w, x, y, z], minterms, dontcares) == Or(And(Not(w), z), And(y, z))) assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z) # test simplification ans = And(A, Or(B, C)) assert simplify_logic(A & (B | C)) == ans assert simplify_logic((A & B) | (A & C)) == ans assert simplify_logic(Implies(A, B)) == Or(Not(A), B) assert simplify_logic(Equivalent(A, B)) == \ Or(And(A, B), And(Not(A), Not(B))) assert simplify_logic(And(Equality(A, 2), C)) == And(Equality(A, 2), C) assert simplify_logic(And(Equality(A, 2), A)) == And(Equality(A, 2), A) assert simplify_logic(And(Equality(A, B), C)) == And(Equality(A, B), C) assert simplify_logic(Or(And(Equality(A, 3), B), And(Equality(A, 3), C))) \ == And(Equality(A, 3), Or(B, C)) e = And(A, x**2 - x) assert simplify_logic(e) == And(A, x*(x - 1)) assert simplify_logic(e, deep=False) == e pytest.raises(ValueError, lambda: simplify_logic(A & (B | C), form='spam')) e = x & y ^ z | (z ^ x) res = [(x & ~z) | (z & ~x) | (z & ~y), (x & ~y) | (x & ~z) | (z & ~x)] assert simplify_logic(e) in res assert SOPform([z, y, x], [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0]]) == res[1] # check input ans = SOPform([x, y], [[1, 0]]) assert SOPform([x, y], [[1, 0]]) == ans assert POSform([x, y], [[1, 0]]) == ans pytest.raises(ValueError, lambda: SOPform([x], [[1]], [[1]])) assert SOPform([x], [[1]], [[0]]) is true assert SOPform([x], [[0]], [[1]]) is true assert SOPform([x], [], []) is false pytest.raises(ValueError, lambda: POSform([x], [[1]], [[1]])) assert POSform([x], [[1]], [[0]]) is true assert POSform([x], [[0]], [[1]]) is true assert POSform([x], [], []) is false # check working of simplify assert simplify((A & B) | (A & C)) == And(A, Or(B, C)) assert simplify(And(x, Not(x))) is false assert simplify(Or(x, Not(x))) is true
def test_equals(): assert Not(Or(A, B)).equals( And(Not(A), Not(B)) ) is True assert Equivalent(A, B).equals((A >> B) & (B >> A)) is True assert ((A | ~B) & (~A | B)).equals((~A & ~B) | (A & B)) is True assert (A >> B).equals(~A >> ~B) is False assert (A >> (B >> A)).equals(A >> (C >> A)) is False pytest.raises(NotImplementedError, lambda: And(A, A < B).equals(And(A, B > A)))
def test_satisfiable_all_models(): assert next(satisfiable(False, all_models=True)) is False assert list(satisfiable((a >> ~a) & a, all_models=True)) == [False] assert list(satisfiable(True, all_models=True)) == [{true: true}] assert next(satisfiable(a & ~a, all_models=True)) is False models = [{a: True, b: False}, {a: False, b: True}] result = satisfiable(a ^ b, all_models=True) models.remove(next(result)) models.remove(next(result)) pytest.raises(StopIteration, lambda: next(result)) assert not models assert list(satisfiable(Equivalent(a, b), all_models=True)) == [{a: False, b: False}, {a: True, b: True}] models = [{a: False, b: False}, {a: False, b: True}, {a: True, b: True}] for model in satisfiable(a >> b, all_models=True): models.remove(model) assert not models # This is a santiy test to check that only the required number # of solutions are generated. The expr below has 2**100 - 1 models # which would time out the test if all are generated at once. X = [Symbol(f'x{i}') for i in range(100)] result = satisfiable(Or(*X), all_models=True) for _ in range(10): assert next(result)
def test_dpll2_satisfiable(): assert dpll2_satisfiable( A & ~A ) is False assert dpll2_satisfiable( A & ~B ) == {A: True, B: False} assert dpll2_satisfiable( A | B ) in ({A: True}, {B: True}, {A: True, B: True}) assert dpll2_satisfiable( (~A | B) & (~B | A) ) in ({A: True, B: True}, {A: False, B: False}) assert dpll2_satisfiable( (A | B) & (~B | C) ) in ({A: True, B: False, C: True}, {A: True, B: True, C: True}) assert dpll2_satisfiable( A & B & C ) == {A: True, B: True, C: True} assert dpll2_satisfiable( (A | B) & (A >> B) ) in ({B: True, A: False}, {B: True, A: True}) assert dpll2_satisfiable( Equivalent(A, B) & A ) == {A: True, B: True} assert dpll2_satisfiable( Equivalent(A, B) & ~A ) == {A: False, B: False} l = SATSolver([], set(), set()) assert l.lit_heap == [] assert l._vsids_calculate() == 0 l0 = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2}, {3, -2}], {1, 2, 3}, set()) l = copy.deepcopy(l0) assert l.num_learned_clauses == 0 assert l.lit_scores == {-3: -2.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -2.0, 3: -2.0} l._vsids_clause_added({2, -3}) assert l.num_learned_clauses == 1 assert l.lit_scores == {-3: -1.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -1.0, 3: -2.0} l = copy.deepcopy(l0) assert l.num_learned_clauses == 0 assert l.clauses == [[2, -3], [1], [3, -3], [2, -2], [3, -2]] assert l.sentinels == {-3: {0, 2}, -2: {3, 4}, 2: {0, 3}, 3: {2, 4}} l._simple_add_learned_clause([3]) assert l.clauses == [[2, -3], [1], [3, -3], [2, -2], [3, -2], [3]] assert l.sentinels == {-3: {0, 2}, -2: {3, 4}, 2: {0, 3}, 3: {2, 4, 5}} l = copy.deepcopy(l0) assert l.lit_scores == {-3: -2.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -2.0, 3: -2.0} l._vsids_decay() assert l.lit_scores == {-3: -1.0, -2: -1.0, -1: 0.0, 1: 0.0, 2: -1.0, 3: -1.0} l = copy.deepcopy(l0) assert next(l._find_model()) == {1: True, 2: False, 3: False} assert l._simple_compute_conflict() == [3]
def test_fcode_precedence(): assert fcode(And(x < y, y < x + 1), source_format='free') == \ 'x < y .and. y < x + 1' assert fcode(Or(x < y, y < x + 1), source_format='free') == \ 'x < y .or. y < x + 1' assert fcode(Xor(x < y, y < x + 1, evaluate=False), source_format='free') == 'x < y .neqv. y < x + 1' assert fcode(Equivalent(x < y, y < x + 1), source_format='free') == \ 'x < y .eqv. y < x + 1'
def test_simplification(): set1 = [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 0]] set2 = [[0, 0, 0], [0, 1, 0], [1, 0, 1], [1, 1, 1]] assert _SOPform([x, y, z], set1) == (~x & z) | (~z & x) assert ~_SOPform([x, y, z], set2) == ~((~x & ~z) | (x & z)) assert _POSform([x, y, z], set1 + set2) is true assert _SOPform([x, y, z], set1 + set2) is true assert _SOPform([w, x, y, z], set1 + set2) is true minterms = [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1]] dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]] assert _SOPform([w, x, y, z], minterms, dontcares) == (~w & z) | (y & z) assert _POSform([w, x, y, z], minterms, dontcares) == (~w | y) & z # test simplification assert (a & (b | c)).simplify() == a & (b | c) assert ((a & b) | (a & c)).simplify() == a & (b | c) assert (a >> b).simplify() == ~a | b assert to_dnf(Equivalent(a, b), simplify=True) == (a & b) | (~a & ~b) assert (Equality(a, 2) & c).simplify() == Equality(a, 2) & c assert (Equality(a, 2) & a).simplify() == Equality(a, 2) & a assert (Equality(a, b) & c).simplify() == Equality(a, b) & c assert ((Equality(a, 3) & b) | (Equality(a, 3) & c)).simplify() == Equality(a, 3) & (b | c) e = a & (x**2 - x) assert e.simplify() == a & x*(x - 1) assert simplify_logic(e, deep=False) == e pytest.raises(ValueError, lambda: simplify_logic(a & (b | c), form='spam')) e = x & y ^ z | (z ^ x) res = [(x & ~z) | (z & ~x) | (z & ~y), (x & ~y) | (x & ~z) | (z & ~x)] assert to_dnf(e, simplify=True) in res assert _SOPform([z, y, x], [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0]]) == res[1] # check input ans = _SOPform([x, y], [[1, 0]]) assert _SOPform([x, y], [[1, 0]]) == ans assert _POSform([x, y], [[1, 0]]) == ans pytest.raises(ValueError, lambda: _SOPform([x], [[1]], [[1]])) assert _SOPform([x], [[1]], [[0]]) is true assert _SOPform([x], [[0]], [[1]]) is true assert _SOPform([x], [], []) is false pytest.raises(ValueError, lambda: _POSform([x], [[1]], [[1]])) assert _POSform([x], [[1]], [[0]]) is true assert _POSform([x], [[0]], [[1]]) is true assert _POSform([x], [], []) is false # check working of simplify assert ((a & b) | (a & c)).simplify() == a & (b | c) assert (x & ~x).simplify() is false assert (x | ~x).simplify() is true
def test_ccode_boolean(): assert ccode(x & y) == 'x && y' assert ccode(x | y) == 'x || y' assert ccode(~x) == '!x' assert ccode(x & y & z) == 'x && y && z' assert ccode(x | y | z) == 'x || y || z' assert ccode((x & y) | z) == 'z || x && y' assert ccode((x | y) & z) == 'z && (x || y)' assert ccode(x ^ y) == '// Not supported in C:\n// Xor\nXor(x, y)' assert ccode(Equivalent(x, y)) == ('// Not supported in C:\n// ' 'Equivalent\nEquivalent(x, y)')
def test_satisfiable(algorithm): assert satisfiable(true, algorithm=algorithm) == {true: true} assert satisfiable(false, algorithm=algorithm) is False assert satisfiable(a & ~a, algorithm=algorithm) is False assert satisfiable(a & ~b, algorithm=algorithm) == {a: True, b: False} assert satisfiable(a | b, algorithm=algorithm) in ({a: True}, {b: True}, {a: True, b: True}) assert satisfiable((~a | b) & (~b | a), algorithm=algorithm) in ({a: True, b: True}, {a: False, b: False}) assert satisfiable((a | b) & (~b | c), algorithm=algorithm) in ({a: True, b: False}, {a: True, c: True}, {b: True, c: True}, {a: True, c: True, b: False}) assert satisfiable(a & (a >> b) & ~b, algorithm=algorithm) is False assert satisfiable(a & b & c, algorithm=algorithm) == {a: True, b: True, c: True} assert satisfiable((a | b) & (a >> b), algorithm=algorithm) in ({b: True}, {b: True, a: False}) assert satisfiable(Equivalent(a, b) & a, algorithm=algorithm) == {a: True, b: True} assert satisfiable(Equivalent(a, b) & ~a, algorithm=algorithm) == {a: False, b: False} class Zero(Boolean): pass assumptions = Zero(x*y) facts = Zero(x*y) >> (Zero(x) | Zero(y)) query = ~Zero(x) & ~Zero(y) refutations = [{Zero(x): True, Zero(x*y): True}, {Zero(y): True, Zero(x*y): True}, {Zero(x): True, Zero(y): True, Zero(x*y): True}, {Zero(x): True, Zero(y): False, Zero(x*y): True}, {Zero(x): False, Zero(y): True, Zero(x*y): True}] assert not satisfiable(assumptions & facts & query, algorithm=algorithm) assert satisfiable(assumptions & facts & ~query, algorithm=algorithm) in refutations
def test_count_ops_non_visual(): def count(val): return count_ops(val, visual=False) assert count(x) == 0 assert count(x) is not Integer(0) assert count(x + y) == 1 assert count(x + y) is not Integer(1) assert count(x + y*x + 2*y) == 4 assert count({x + y: x}) == 1 assert count({x + y: 2 + x}) is not Integer(1) assert count(Or(x, y)) == 1 assert count(And(x, y)) == 1 assert count(Not(x)) == 1 assert count(Nor(x, y)) == 2 assert count(Nand(x, y)) == 2 assert count(Xor(x, y)) == 1 assert count(Implies(x, y)) == 1 assert count(Equivalent(x, y)) == 1 assert count(ITE(x, y, z)) == 1 assert count(ITE(True, x, y)) == 0
def test_count_ops_visual(): ADD, MUL, POW, SIN, COS, AND, D, G = symbols( 'Add Mul Pow sin cos And Derivative Integral'.upper()) DIV, SUB, NEG = symbols('DIV SUB NEG') NOT, OR, AND, XOR, IMPLIES, EQUIVALENT, _ITE, BASIC, TUPLE = symbols( 'Not Or And Xor Implies Equivalent ITE Basic Tuple'.upper()) def count(val): return count_ops(val, visual=True) assert count(7) is Integer(0) assert count(-1) == NEG assert count(-2) == NEG assert count(Rational(2, 3)) == DIV assert count(pi / 3) == DIV assert count(-pi / 3) == DIV + NEG assert count(I - 1) == SUB assert count(1 - I) == SUB assert count(1 - 2 * I) == SUB + MUL assert count(x) is Integer(0) assert count(-x) == NEG assert count(-2 * x / 3) == NEG + DIV + MUL assert count(1 / x) == DIV assert count(1 / (x * y)) == DIV + MUL assert count(-1 / x) == NEG + DIV assert count(-2 / x) == NEG + DIV assert count(x / y) == DIV assert count(-x / y) == NEG + DIV assert count(x**2) == POW assert count(-x**2) == POW + NEG assert count(-2 * x**2) == POW + MUL + NEG assert count(x + pi / 3) == ADD + DIV assert count(x + Rational(1, 3)) == ADD + DIV assert count(x + y) == ADD assert count(x - y) == SUB assert count(y - x) == SUB assert count(-1 / (x - y)) == DIV + NEG + SUB assert count(-1 / (y - x)) == DIV + NEG + SUB assert count(1 + x**y) == ADD + POW assert count(1 + x + y) == 2 * ADD assert count(1 + x + y + z) == 3 * ADD assert count(1 + x**y + 2 * x * y + y**2) == 3 * ADD + 2 * POW + 2 * MUL assert count(2 * z + y + x + 1) == 3 * ADD + MUL assert count(2 * z + y**17 + x + 1) == 3 * ADD + MUL + POW assert count(2 * z + y**17 + x + sin(x)) == 3 * ADD + POW + MUL + SIN assert count(2 * z + y**17 + x + sin(x**2)) == 3 * ADD + MUL + 2 * POW + SIN assert count(2 * z + y**17 + x + sin(x**2) + exp(cos(x))) == 4 * ADD + MUL + 3 * POW + COS + SIN assert count(Derivative(x, x)) == D assert count(Integral(x, x) + 2 * x / (1 + x)) == G + DIV + MUL + 2 * ADD assert count(Basic()) is Integer(0) assert count({x + 1: sin(x)}) == ADD + SIN assert count([x + 1, sin(x) + y, None]) == ADD + SIN + ADD assert count({x + 1: sin(x), y: cos(x) + 1}) == SIN + COS + 2 * ADD assert count({}) is Integer(0) assert count([x + 1, sin(x) * y, None]) == SIN + ADD + MUL assert count([]) is Integer(0) assert count(Basic()) == 0 assert count(Basic(Basic(), Basic(x, x + y))) == ADD + 2 * BASIC assert count(Basic(x, x + y)) == ADD + BASIC assert count(Or(x, y)) == OR assert count(And(x, y)) == AND assert count(And(x**y, z)) == AND + POW assert count(Or(x, Or(y, And(z, a)))) == AND + OR assert count(Nor(x, y)) == NOT + OR assert count(Nand(x, y)) == NOT + AND assert count(Xor(x, y)) == XOR assert count(Implies(x, y)) == IMPLIES assert count(Equivalent(x, y)) == EQUIVALENT assert count(ITE(x, y, z)) == _ITE assert count([Or(x, y), And(x, y), Basic(x + y)]) == ADD + AND + BASIC + OR assert count(Basic(Tuple(x))) == BASIC + TUPLE # It checks that TUPLE is counted as an operation. assert count(Eq(x + y, 2)) == ADD
def test_Equivalent(): assert str(Equivalent(y, x)) == "Equivalent(x, y)"
def test_true_false(): # pylint: disable=singleton-comparison,comparison-with-itself assert true is true assert false is false assert true is not True assert false is not False assert true assert not false assert true == True # noqa: E712 assert false == False # noqa: E712 assert not true == False # noqa: E712 assert not false == True # noqa: E712 assert not true == false assert hash(true) == hash(True) assert hash(false) == hash(False) assert len({true, True}) == len({false, False}) == 1 assert int(true) == 1 assert int(false) == 0 assert isinstance(true, BooleanAtom) assert isinstance(false, BooleanAtom) assert not isinstance(true, bool) assert not isinstance(false, bool) assert ~true is false assert Not(True) is false assert ~false is true assert Not(False) is true for T, F in itertools.product([True, true], [False, false]): assert And(T, F) is false assert And(F, T) is false assert And(F, F) is false assert And(T, T) is true assert And(T, x) == x assert And(F, x) is false if not (T is True and F is False): assert T & F is false assert F & T is false if F is not False: assert F & F is false if T is not True: assert T & T is true assert Or(T, F) is true assert Or(F, T) is true assert Or(F, F) is false assert Or(T, T) is true assert Or(T, x) is true assert Or(F, x) == x if not (T is True and F is False): assert T | F is true assert F | T is true if F is not False: assert F | F is false if T is not True: assert T | T is true assert Xor(T, F) is true assert Xor(F, T) is true assert Xor(F, F) is false assert Xor(T, T) is false assert Xor(T, x) == ~x assert Xor(F, x) == x if not (T is True and F is False): assert T ^ F is true assert F ^ T is true if F is not False: assert F ^ F is false if T is not True: assert T ^ T is false assert Nand(T, F) is true assert Nand(F, T) is true assert Nand(F, F) is true assert Nand(T, T) is false assert Nand(T, x) == ~x assert Nand(F, x) is true assert Nor(T, F) is false assert Nor(F, T) is false assert Nor(F, F) is true assert Nor(T, T) is false assert Nor(T, x) is false assert Nor(F, x) == ~x assert Implies(T, F) is false assert Implies(F, T) is true assert Implies(F, F) is true assert Implies(T, T) is true assert Implies(T, x) == x assert Implies(F, x) is true assert Implies(x, T) is true assert Implies(x, F) == ~x if not (T is True and F is False): assert T >> F is false assert F << T is false assert F >> T is true assert T << F is true if F is not False: assert F >> F is true assert F << F is true if T is not True: assert T >> T is true assert T << T is true assert Equivalent(T, F) is false assert Equivalent(F, T) is false assert Equivalent(F, F) is true assert Equivalent(T, T) is true assert Equivalent(T, x) == x assert Equivalent(F, x) == ~x assert Equivalent(x, T) == x assert Equivalent(x, F) == ~x assert ITE(T, T, T) is true assert ITE(T, T, F) is true assert ITE(T, F, T) is false assert ITE(T, F, F) is false assert ITE(F, T, T) is true assert ITE(F, T, F) is false assert ITE(F, F, T) is true assert ITE(F, F, F) is false
def test_Equivalent(): assert Equivalent(A, B) == Equivalent(B, A) == Equivalent(A, B, A) assert Equivalent() is true assert Equivalent(A, A) == Equivalent(A) is true assert Equivalent(True, True) == Equivalent(False, False) is true assert Equivalent(True, False) == Equivalent(False, True) is false assert Equivalent(A, True) == A assert Equivalent(A, False) == Not(A) assert Equivalent(A, B, True) == A & B assert Equivalent(A, B, False) == ~A & ~B assert Equivalent(1, A) == A assert Equivalent(0, A) == Not(A) assert Equivalent(A, Equivalent(B, C)) != Equivalent(Equivalent(A, B), C) assert Equivalent(A < 1, A >= 1) is false assert Equivalent(A < 1, A >= 1, 0) is false assert Equivalent(A < 1, A >= 1, 1) is false assert Equivalent(A < 1, Integer(1) > A) == Equivalent(1, 1) == Equivalent(0, 0) assert Equivalent(A < 1, B >= 1) == Equivalent(B >= 1, A < 1, evaluate=False)
def test_true_false(): assert true is true assert false is false assert true is not True assert false is not False assert true assert not false assert true == True # noqa: E712 assert false == False # noqa: E712 assert not (true == False) # noqa: E712 assert not (false == True) # noqa: E712 assert not (true == false) assert hash(true) == hash(True) assert hash(false) == hash(False) assert len({true, True}) == len({false, False}) == 1 assert isinstance(true, BooleanAtom) assert isinstance(false, BooleanAtom) # We don't want to subclass from bool, because bool subclasses from # int. But operators like &, |, ^, <<, >>, and ~ act differently on 0 and # 1 then we want them to on true and false. See the docstrings of the # various And, Or, etc. functions for examples. assert not isinstance(true, bool) assert not isinstance(false, bool) # Note: using 'is' comparison is important here. We want these to return # true and false, not True and False assert Not(true) is false assert Not(True) is false assert Not(false) is true assert Not(False) is true assert ~true is false assert ~false is true for T, F in itertools.product([True, true], [False, false]): assert And(T, F) is false assert And(F, T) is false assert And(F, F) is false assert And(T, T) is true assert And(T, x) == x assert And(F, x) is false if not (T is True and F is False): assert T & F is false assert F & T is false if F is not False: assert F & F is false if T is not True: assert T & T is true assert Or(T, F) is true assert Or(F, T) is true assert Or(F, F) is false assert Or(T, T) is true assert Or(T, x) is true assert Or(F, x) == x if not (T is True and F is False): assert T | F is true assert F | T is true if F is not False: assert F | F is false if T is not True: assert T | T is true assert Xor(T, F) is true assert Xor(F, T) is true assert Xor(F, F) is false assert Xor(T, T) is false assert Xor(T, x) == ~x assert Xor(F, x) == x if not (T is True and F is False): assert T ^ F is true assert F ^ T is true if F is not False: assert F ^ F is false if T is not True: assert T ^ T is false assert Nand(T, F) is true assert Nand(F, T) is true assert Nand(F, F) is true assert Nand(T, T) is false assert Nand(T, x) == ~x assert Nand(F, x) is true assert Nor(T, F) is false assert Nor(F, T) is false assert Nor(F, F) is true assert Nor(T, T) is false assert Nor(T, x) is false assert Nor(F, x) == ~x assert Implies(T, F) is false assert Implies(F, T) is true assert Implies(F, F) is true assert Implies(T, T) is true assert Implies(T, x) == x assert Implies(F, x) is true assert Implies(x, T) is true assert Implies(x, F) == ~x if not (T is True and F is False): assert T >> F is false assert F << T is false assert F >> T is true assert T << F is true if F is not False: assert F >> F is true assert F << F is true if T is not True: assert T >> T is true assert T << T is true assert Equivalent(T, F) is false assert Equivalent(F, T) is false assert Equivalent(F, F) is true assert Equivalent(T, T) is true assert Equivalent(T, x) == x assert Equivalent(F, x) == ~x assert Equivalent(x, T) == x assert Equivalent(x, F) == ~x assert ITE(T, T, T) is true assert ITE(T, T, F) is true assert ITE(T, F, T) is false assert ITE(T, F, F) is false assert ITE(F, T, T) is true assert ITE(F, T, F) is false assert ITE(F, F, T) is true assert ITE(F, F, F) is false
def test_entails(): assert entails(A, [A >> B, ~B]) is False assert entails(B, [Equivalent(A, B), A]) is True assert entails((A >> B) >> (~A >> ~B)) is False assert entails((A >> B) >> (~B >> ~A)) is True
def test_entails(): assert entails(a, [a >> b, ~b]) is False assert entails(b, [Equivalent(a, b), a]) is True assert entails((a >> b) >> (~a >> ~b)) is False assert entails((a >> b) >> (~b >> ~a)) is True
def test_fcode_Xlogical(): # binary Xor assert fcode(Xor(x, y, evaluate=False), source_format='free') == \ 'x .neqv. y' assert fcode(Xor(x, Not(y), evaluate=False), source_format='free') == \ 'x .neqv. .not. y' assert fcode(Xor(Not(x), y, evaluate=False), source_format='free') == \ 'y .neqv. .not. x' assert fcode(Xor(Not(x), Not(y), evaluate=False), source_format='free') == '.not. x .neqv. .not. y' assert fcode(Not(Xor(x, y, evaluate=False), evaluate=False), source_format='free') == '.not. (x .neqv. y)' # binary Equivalent assert fcode(Equivalent(x, y), source_format='free') == 'x .eqv. y' assert fcode(Equivalent(x, Not(y)), source_format='free') == \ 'x .eqv. .not. y' assert fcode(Equivalent(Not(x), y), source_format='free') == \ 'y .eqv. .not. x' assert fcode(Equivalent(Not(x), Not(y)), source_format='free') == \ '.not. x .eqv. .not. y' assert fcode(Not(Equivalent(x, y), evaluate=False), source_format='free') == '.not. (x .eqv. y)' # mixed And/Equivalent assert fcode(Equivalent(And(y, z), x), source_format='free') == \ 'x .eqv. y .and. z' assert fcode(Equivalent(And(z, x), y), source_format='free') == \ 'y .eqv. x .and. z' assert fcode(Equivalent(And(x, y), z), source_format='free') == \ 'z .eqv. x .and. y' assert fcode(And(Equivalent(y, z), x), source_format='free') == \ 'x .and. (y .eqv. z)' assert fcode(And(Equivalent(z, x), y), source_format='free') == \ 'y .and. (x .eqv. z)' assert fcode(And(Equivalent(x, y), z), source_format='free') == \ 'z .and. (x .eqv. y)' # mixed Or/Equivalent assert fcode(Equivalent(Or(y, z), x), source_format='free') == \ 'x .eqv. y .or. z' assert fcode(Equivalent(Or(z, x), y), source_format='free') == \ 'y .eqv. x .or. z' assert fcode(Equivalent(Or(x, y), z), source_format='free') == \ 'z .eqv. x .or. y' assert fcode(Or(Equivalent(y, z), x), source_format='free') == \ 'x .or. (y .eqv. z)' assert fcode(Or(Equivalent(z, x), y), source_format='free') == \ 'y .or. (x .eqv. z)' assert fcode(Or(Equivalent(x, y), z), source_format='free') == \ 'z .or. (x .eqv. y)' # mixed Xor/Equivalent assert fcode(Equivalent(Xor(y, z, evaluate=False), x), source_format='free') == 'x .eqv. (y .neqv. z)' assert fcode(Equivalent(Xor(z, x, evaluate=False), y), source_format='free') == 'y .eqv. (x .neqv. z)' assert fcode(Equivalent(Xor(x, y, evaluate=False), z), source_format='free') == 'z .eqv. (x .neqv. y)' assert fcode(Xor(Equivalent(y, z), x, evaluate=False), source_format='free') == 'x .neqv. (y .eqv. z)' assert fcode(Xor(Equivalent(z, x), y, evaluate=False), source_format='free') == 'y .neqv. (x .eqv. z)' assert fcode(Xor(Equivalent(x, y), z, evaluate=False), source_format='free') == 'z .neqv. (x .eqv. y)' # mixed And/Xor assert fcode(Xor(And(y, z), x, evaluate=False), source_format='free') == \ 'x .neqv. y .and. z' assert fcode(Xor(And(z, x), y, evaluate=False), source_format='free') == \ 'y .neqv. x .and. z' assert fcode(Xor(And(x, y), z, evaluate=False), source_format='free') == \ 'z .neqv. x .and. y' assert fcode(And(Xor(y, z, evaluate=False), x), source_format='free') == \ 'x .and. (y .neqv. z)' assert fcode(And(Xor(z, x, evaluate=False), y), source_format='free') == \ 'y .and. (x .neqv. z)' assert fcode(And(Xor(x, y, evaluate=False), z), source_format='free') == \ 'z .and. (x .neqv. y)' # mixed Or/Xor assert fcode(Xor(Or(y, z), x, evaluate=False), source_format='free') == \ 'x .neqv. y .or. z' assert fcode(Xor(Or(z, x), y, evaluate=False), source_format='free') == \ 'y .neqv. x .or. z' assert fcode(Xor(Or(x, y), z, evaluate=False), source_format='free') == \ 'z .neqv. x .or. y' assert fcode(Or(Xor(y, z, evaluate=False), x), source_format='free') == \ 'x .or. (y .neqv. z)' assert fcode(Or(Xor(z, x, evaluate=False), y), source_format='free') == \ 'y .or. (x .neqv. z)' assert fcode(Or(Xor(x, y, evaluate=False), z), source_format='free') == \ 'z .or. (x .neqv. y)' # trinary Xor assert fcode(Xor(x, y, z, evaluate=False), source_format='free') == \ 'x .neqv. y .neqv. z' assert fcode(Xor(x, y, Not(z), evaluate=False), source_format='free') == \ 'x .neqv. y .neqv. .not. z' assert fcode(Xor(x, Not(y), z, evaluate=False), source_format='free') == \ 'x .neqv. z .neqv. .not. y' assert fcode(Xor(Not(x), y, z, evaluate=False), source_format='free') == \ 'y .neqv. z .neqv. .not. x'
def test_Equivalent(): assert Equivalent(a, b) == Equivalent(b, a) == Equivalent(a, b, a) assert Equivalent() is true assert Equivalent(a, a) == Equivalent(a) is true assert Equivalent(True, True) == Equivalent(False, False) is true assert Equivalent(True, False) == Equivalent(False, True) is false assert Equivalent(a, True) == a assert Equivalent(a, False) == ~a assert Equivalent(a, b, True) == a & b assert Equivalent(a, b, False) == ~a & ~b assert Equivalent(1, a) == a assert Equivalent(0, a) == Not(a) assert Equivalent(a, Equivalent(b, c)) != Equivalent(Equivalent(a, b), c) assert Equivalent(a < 1, a >= 1) is false assert Equivalent(a < 1, a >= 1, 0) is false assert Equivalent(a < 1, a >= 1, 1) is false assert Equivalent(a < 1, 1 > a) == Equivalent(1, 1) == Equivalent(0, 0) assert Equivalent(a < 1, Integer(1) > a) == Equivalent(1, 1) == Equivalent(0, 0) assert Equivalent(a < 1, b >= 1) == Equivalent(b >= 1, a < 1, evaluate=False)
def test_eliminate_implications(): assert eliminate_implications(Implies(A, B, evaluate=False)) == (~A) | B assert eliminate_implications(A >> (C >> Not(B))) == Or( Or(Not(B), Not(C)), Not(A)) assert eliminate_implications(Equivalent(A, B, C, D)) == \ (~A | B) & (~B | C) & (~C | D) & (~D | A)