34
47
"""Overloading for <<"""
35
48
return Implies(other, self)
50
__rrshift__ = __lshift__
51
__rlshift__ = __rshift__
37
53
def __xor__(self, other):
38
54
return Xor(self, other)
58
def equals(self, other):
60
Returns if the given formulas have the same truth table.
61
For two formulas to be equal they must have the same literals.
66
>>> from sympy.abc import A, B, C
67
>>> from sympy.logic.boolalg import And, Or, Not
68
>>> (A >> B).equals(~B >> ~A)
70
>>> Not(And(A, B, C)).equals(And(Not(A), Not(B), Not(C)))
72
>>> Not(And(A, Not(A))).equals(Or(B, Not(B)))
76
from sympy.logic.inference import satisfiable
77
return self.atoms() == other.atoms() and \
78
not satisfiable(Not(Equivalent(self, other)))
81
# Developer note: There is liable to be some confusion as to when True should
82
# be used and when S.true should be used in various contexts throughout SymPy.
83
# An important thing to remember is that sympify(True) returns S.true. This
84
# means that for the most part, you can just use True and it will
85
# automatically be converted to S.true when necessary, similar to how you can
86
# generally use 1 instead of S.One.
88
# The rule of thumb is:
90
# "If the boolean in question can be replaced by an arbitrary symbolic
91
# Boolean, like Or(x, y) or x > 1, use S.true. Otherwise, use True"
93
# In other words, use S.true only on those contexts where the boolean is being
94
# used as a symbolic representation of truth. For example, if the object ends
95
# up in the .args of any expression, then it must necessarily be S.true
96
# instead of True, as elements of .args must be Basic. On the other hand, ==
97
# is not a symbolic operation in SymPy, since it always returns True or False,
98
# and does so in terms of structural equality rather than mathematical, so it
99
# should return True. The assumptions system should use True and False. Aside
100
# from not satisfying the above rule of thumb, the assumptions system uses a
101
# three-valued logic (True, False, None), whereas S.true and S.false represent
102
# a two-valued logic. When it doubt, use True.
104
# 2. "S.true == True" is True.
106
# While "S.true is True" is False, "S.true == True" is True, so if there is
107
# any doubt over whether a function or expression will return S.true or True,
108
# just use "==" instead of "is" to do the comparison, and it will work in
109
# either case. Finally, for boolean flags, it's better to just use "if x"
110
# instead of "if x is True". To quote PEP 8:
112
# Don't compare boolean values to True or False using ==.
115
# No: if greeting == True:
116
# Worse: if greeting is True:
118
class BooleanAtom(Boolean):
120
Base class of BooleanTrue and BooleanFalse.
123
class BooleanTrue(with_metaclass(Singleton, BooleanAtom)):
125
SymPy version of True.
127
The instances of this class are singletonized and can be accessed via
130
This is the SymPy version of True, for use in the logic module. The
131
primary advantage of using true instead of True is that shorthand boolean
132
operations like ~ and >> will work as expected on this class, whereas with
133
True they act bitwise on 1. Functions in the logic module will return this
134
class when they evaluate to true.
139
>>> from sympy import sympify, true, Or
151
sympy.logic.boolalg.BooleanFalse
154
def __nonzero__(self):
157
__bool__ = __nonzero__
164
Rewrite logic operators and relationals in terms of real sets.
169
>>> from sympy import true
173
return S.UniversalSet
176
class BooleanFalse(with_metaclass(Singleton, BooleanAtom)):
178
SymPy version of False.
180
The instances of this class are singletonized and can be accessed via
183
This is the SymPy version of False, for use in the logic module. The
184
primary advantage of using false instead of False is that shorthand boolean
185
operations like ~ and >> will work as expected on this class, whereas with
186
False they act bitwise on 0. Functions in the logic module will return this
187
class when they evaluate to false.
192
>>> from sympy import sympify, false, Or, true
204
sympy.logic.boolalg.BooleanTrue
207
def __nonzero__(self):
210
__bool__ = __nonzero__
217
Rewrite logic operators and relationals in terms of real sets.
222
>>> from sympy import false
226
from sympy.sets.sets import EmptySet
230
false = BooleanFalse()
231
# We want S.true and S.false to work, rather than S.BooleanTrue and
232
# S.BooleanFalse, but making the class and instance names the same causes some
233
# major issues (like the inability to import the class directly from this
238
converter[bool] = lambda x: S.true if x else S.false
41
240
class BooleanFunction(Application, Boolean):
42
241
"""Boolean function is a function that lives in a boolean space
134
378
newargs.append(x)
135
379
return LatticeOp._new_args_filter(newargs, Or)
383
Rewrite logic operators and relationals in terms of real sets.
388
>>> from sympy import Or, Symbol
389
>>> x = Symbol('x', real=True)
390
>>> Or(x>2, x<-2).as_set()
393
from sympy.sets.sets import Union
394
if len(self.free_symbols) == 1:
395
return Union(*[arg.as_set() for arg in self.args])
397
raise NotImplementedError("Sorry, Or.as_set has not yet been"
398
" implemented for multivariate"
138
402
class Not(BooleanFunction):
140
404
Logical Not function (negation)
407
Returns True if the statement is False
408
Returns False if the statement is True
413
>>> from sympy.logic.boolalg import Not, And, Or
414
>>> from sympy.abc import x, A, B
419
>>> Not(And(True, False))
421
>>> Not(Or(True, False))
423
>>> Not(And(And(True, x), Or(x, False)))
427
>>> Not(And(Or(A, B), Or(~A, ~B)))
428
Not(And(Or(A, B), Or(Not(A), Not(B))))
145
De Morgan rules are applied automatically.
433
- The ``~`` operator is provided as a convenience, but note that its use
434
here is different from its normal use in Python, which is bitwise
435
not. In particular, ``~a`` and ``Not(a)`` will be different if ``a`` is
436
an integer. Furthermore, since bools in Python subclass from ``int``,
437
``~True`` is the same as ``~1`` which is ``-2``, which has a boolean
438
value of True. To avoid this issue, use the SymPy boolean types
439
``true`` and ``false``.
441
>>> from sympy import true
151
452
def eval(cls, arg):
153
Logical Not function (negation)
155
Returns True if the statement is False
156
Returns False if the statement is True
161
>>> from sympy.logic.boolalg import Not, And, Or
162
>>> from sympy.abc import x
167
>>> Not(And(True, False))
169
>>> Not(Or(True, False))
171
>>> Not(And(And(True, x), Or(x, False)))
174
if isinstance(arg, Number) or arg in (0, 1):
175
return False if arg else True
176
# apply De Morgan Rules
178
return Or(*[Not(a) for a in arg.args])
180
return And(*[Not(a) for a in arg.args])
453
if isinstance(arg, Number) or arg in (True, False):
454
return false if arg else true
182
456
return arg.args[0]
457
# Simplify Relational objects.
458
if isinstance(arg, C.Equality):
459
return C.Unequality(*arg.args)
460
if isinstance(arg, C.Unequality):
461
return C.Equality(*arg.args)
462
if isinstance(arg, C.StrictLessThan):
463
return C.GreaterThan(*arg.args)
464
if isinstance(arg, C.StrictGreaterThan):
465
return C.LessThan(*arg.args)
466
if isinstance(arg, C.LessThan):
467
return C.StrictGreaterThan(*arg.args)
468
if isinstance(arg, C.GreaterThan):
469
return C.StrictLessThan(*arg.args)
473
Rewrite logic operators and relationals in terms of real sets.
478
>>> from sympy import Not, Symbol
479
>>> x = Symbol('x', real=True)
480
>>> Not(x>0).as_set()
483
if len(self.free_symbols) == 1:
484
return self.args[0].as_set().complement
486
raise NotImplementedError("Sorry, Not.as_set has not yet been"
487
" implemented for mutivariate"
490
def to_nnf(self, simplify=True):
496
func, args = expr.func, expr.args
499
return Or._to_nnf(*[~arg for arg in args], simplify=simplify)
502
return And._to_nnf(*[~arg for arg in args], simplify=simplify)
506
return And._to_nnf(a, ~b, simplify=simplify)
508
if func == Equivalent:
509
return And._to_nnf(Or(*args), Or(*[~arg for arg in args]), simplify=simplify)
513
for i in xrange(1, len(args)+1, 2):
514
for neg in combinations(args, i):
515
clause = [~s if s in neg else s for s in args]
516
result.append(Or(*clause))
517
return And._to_nnf(*result, simplify=simplify)
521
return And._to_nnf(Or(a, ~c), Or(~a, ~b), simplify=simplify)
523
raise ValueError("Illegal operator %s in expression" % func)
185
526
class Xor(BooleanFunction):
187
528
Logical XOR (exclusive OR) function.
531
Returns True if an odd number of the arguments are True and the rest are
534
Returns False if an even number of the arguments are True and the rest are
540
>>> from sympy.logic.boolalg import Xor
541
>>> from sympy import symbols
542
>>> x, y = symbols('x y')
547
>>> Xor(True, False, True, True, False)
549
>>> Xor(True, False, True, False)
557
The ``^`` operator is provided as a convenience, but note that its use
558
here is different from its normal use in Python, which is bitwise xor. In
559
particular, ``a ^ b`` and ``Xor(a, b)`` will be different if ``a`` and
562
>>> Xor(x, y).subs(y, 0)
190
def eval(cls, *args):
192
Logical XOR (exclusive OR) function.
194
Returns True if an odd number of the arguments are True
195
and the rest are False.
196
Returns False if an even number of the arguments are True
197
and the rest are False.
202
>>> from sympy.logic.boolalg import Xor
208
>>> Xor(True, False, True, True, False)
210
>>> Xor(True, False, True, False)
219
A = Or(And(A, Not(B)), And(Not(A), B))
566
def __new__(cls, *args, **kwargs):
568
obj = super(Xor, cls).__new__(cls, *args, **kwargs)
569
for arg in obj._args:
570
if isinstance(arg, Number) or arg in (True, False):
575
if isinstance(arg, Xor):
577
argset.remove(a) if a in argset else argset.add(a)
584
elif len(argset) == 1:
588
return Not(Xor(*argset))
590
obj._args = tuple(ordered(argset))
591
obj._argset = frozenset(argset)
597
return tuple(ordered(self._argset))
599
def to_nnf(self, simplify=True):
601
for i in xrange(0, len(self.args)+1, 2):
602
for neg in combinations(self.args, i):
603
clause = [~s if s in neg else s for s in self.args]
604
args.append(Or(*clause))
605
return And._to_nnf(*args, simplify=simplify)
223
608
class Nand(BooleanFunction):
318
730
raise ValueError(
319
731
"%d operand(s) used for an Implies "
320
732
"(pairs are required): %s" % (len(args), str(args)))
321
if A is True or A is False or B is True or B is False:
733
if A == True or A == False or B == True or B == False:
322
734
return Or(Not(A), B)
324
736
return Basic.__new__(cls, *args)
738
def to_nnf(self, simplify=True):
740
return Or._to_nnf(~a, b, simplify=simplify)
327
743
class Equivalent(BooleanFunction):
329
745
Equivalence relation.
331
747
Equivalent(A, B) is True iff A and B are both True or both False
749
Returns True if all of the arguments are logically equivalent.
750
Returns False otherwise.
755
>>> from sympy.logic.boolalg import Equivalent, And
756
>>> from sympy.abc import x, y
757
>>> Equivalent(False, False, False)
759
>>> Equivalent(True, False, False)
761
>>> Equivalent(x, And(x, True))
334
def eval(cls, *args):
336
Equivalence relation.
338
Returns True if all of the arguments are logically equivalent.
339
Returns False otherwise.
344
>>> from sympy.logic.boolalg import Equivalent, And
345
>>> from sympy.abc import x
346
>>> Equivalent(False, False, False)
348
>>> Equivalent(True, False, False)
350
>>> Equivalent(x, And(x, True))
764
def __new__(cls, *args, **options):
765
args = [_sympify(arg) for arg in args]
357
if isinstance(x, Number) or x in (0, 1):
358
newargs.append(True if x else False)
361
argset = set(newargs)
769
if isinstance(x, Number) or x in [True, False]: # Includes 0, 1
771
argset.add(True if x else False)
362
772
if len(argset) <= 1:
364
774
if True in argset:
365
775
argset.discard(True)
366
776
return And(*argset)
367
777
if False in argset:
368
778
argset.discard(False)
370
return Basic.__new__(cls, *set(args))
779
return And(*[~arg for arg in argset])
780
_args = frozenset(argset)
781
obj = super(Equivalent, cls).__new__(cls, _args)
788
return tuple(ordered(self._argset))
790
def to_nnf(self, simplify=True):
792
for a, b in zip(self.args, self.args[1:]):
793
args.append(Or(~a, b))
794
args.append(Or(~self.args[-1], self.args[0]))
795
return And._to_nnf(*args, simplify=simplify)
373
798
class ITE(BooleanFunction):
375
800
If then else clause.
802
ITE(A, B, C) evaluates and returns the result of B if A is true
803
else it returns the result of C
808
>>> from sympy.logic.boolalg import ITE, And, Xor, Or
809
>>> from sympy.abc import x, y, z
810
>>> ITE(True, False, True)
812
>>> ITE(Or(True, False), And(True, True), Xor(True, True))
378
824
def eval(cls, *args):
382
ITE(A, B, C) evaluates and returns the result of B if A is true
383
else it returns the result of C
388
>>> from sympy.logic.boolalg import ITE, And, Xor, Or
389
>>> from sympy.abc import x, y, z
395
>>> ITE(Or(x, y), And(x, z), Xor(z, x))
400
return Or(And(args[0], args[1]), And(Not(args[0]), args[2]))
401
raise ValueError("ITE expects 3 arguments, but got %d: %s" %
402
(len(args), str(args)))
828
raise ValueError("ITE expects exactly 3 arguments")
836
def to_nnf(self, simplify=True):
838
return And._to_nnf(Or(~a, b), Or(a, c), simplify=simplify)
404
840
### end class definitions. Some useful methods
486
922
rest = info[2](*[a for a in info[0].args if a is not conj])
487
923
return info[1](*list(map(_distribute,
488
[(info[2](c, rest), info[1], info[2]) for c in conj.args])))
924
[(info[2](c, rest), info[1], info[2]) for c in conj.args])))
489
925
elif info[0].func is info[1]:
490
926
return info[1](*list(map(_distribute,
491
[(x, info[1], info[2]) for x in info[0].args])))
927
[(x, info[1], info[2]) for x in info[0].args])))
932
def to_nnf(expr, simplify=True):
934
Converts expr to Negation Normal Form.
935
A logical expression is in Negation Normal Form (NNF) if it
936
contains only And, Or and Not, and Not is applied only to literals.
937
If simpify is True, the result contains no redundant clauses.
942
>>> from sympy.abc import A, B, C, D
943
>>> from sympy.logic.boolalg import Not, Equivalent, to_nnf
944
>>> to_nnf(Not((~A & ~B) | (C & D)))
945
And(Or(A, B), Or(Not(C), Not(D)))
946
>>> to_nnf(Equivalent(A >> B, B >> A))
947
And(Or(A, And(A, Not(B)), Not(B)), Or(And(B, Not(A)), B, Not(A)))
949
if is_nnf(expr, simplify):
951
return expr.to_nnf(simplify)
496
954
def to_cnf(expr, simplify=False):
498
956
Convert a propositional logical sentence s to conjunctive normal form.
499
957
That is, of the form ((A | ~B | ...) & (B | C | ...) & ...)
958
If simplify is True, the expr is evaluated to its simplest CNF form.
667
1169
>>> eliminate_implications(Equivalent(A, B))
668
1170
And(Or(A, Not(B)), Or(B, Not(A)))
672
return expr # (Atoms are unchanged.)
673
args = list(map(eliminate_implications, expr.args))
674
if expr.func is Implies:
675
a, b = args[0], args[-1]
677
elif expr.func is Equivalent:
678
a, b = args[0], args[-1]
679
return (a | Not(b)) & (b | Not(a))
1171
>>> eliminate_implications(Equivalent(A, B, C))
1172
And(Or(A, Not(C)), Or(B, Not(A)), Or(C, Not(B)))
1177
def is_literal(expr):
1179
Returns True if expr is a literal, else False.
1184
>>> from sympy import Or, Q
1185
>>> from sympy.abc import A, B
1186
>>> from sympy.logic.boolalg import is_literal
1191
>>> is_literal(Q.zero(A))
1193
>>> is_literal(A + B)
1195
>>> is_literal(Or(A, B))
1198
if isinstance(expr, Not):
1199
return not isinstance(expr.args[0], BooleanFunction)
681
return expr.func(*args)
1201
return not isinstance(expr, BooleanFunction)
685
useinstead="sympify", issue=3451, deprecated_since_version="0.7.3")
1205
useinstead="sympify", issue=6550, deprecated_since_version="0.7.3")
686
1206
def compile_rule(s):
688
1208
Transforms a rule into a SymPy expression
1026
def bool_equal(bool1, bool2, info=False):
1027
"""Return True if the two expressions represent the same logical
1028
behavior for some correspondence between the variables of each
1029
(which may be different). For example, And(x, y) is logically
1030
equivalent to And(a, b) for {x: a, y: b} (or vice versa). If the
1031
mapping is desired, then set ``info`` to True and the simplified
1032
form of the functions and the mapping of variables will be
1573
def bool_map(bool1, bool2):
1575
Return the simplified version of bool1, and the mapping of variables
1576
that makes the two expressions bool1 and bool2 represent the same
1577
logical behaviour for some correspondence between the variables
1579
If more than one mappings of this sort exist, one of them
1581
For example, And(x, y) is logically equivalent to And(a, b) for
1582
the mapping {x: a, y:b} or {x: b, y:a}.
1583
If no such mapping exists, return False.
1038
>>> from sympy import SOPform, bool_equal, Or, And, Not, Xor
1588
>>> from sympy import SOPform, bool_map, Or, And, Not, Xor
1039
1589
>>> from sympy.abc import w, x, y, z, a, b, c, d
1040
1590
>>> function1 = SOPform(['x','z','y'],[[1, 0, 1], [0, 0, 1]])
1041
1591
>>> function2 = SOPform(['a','b','c'],[[1, 0, 1], [1, 0, 0]])
1042
>>> bool_equal(function1, function2, info=True)
1592
>>> bool_map(function1, function2)
1043
1593
(And(Not(z), y), {y: a, z: b})
1045
1595
The results are not necessarily unique, but they are canonical. Here,