Skip to content

Evaluate #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
/dist/
/tmp/
/.cache/
/.idea/
33 changes: 33 additions & 0 deletions boolean/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,21 @@

import inspect
import itertools
from operator import and_ as and_operator
from operator import or_ as or_operator


try:
basestring # Python 2
except NameError:
basestring = str # Python 3

try:
reduce # Python 2
except NameError:
from functools import reduce # Python 3


# Set to True to enable tracing for parsing
TRACE_PARSE = False

Expand Down Expand Up @@ -849,6 +858,10 @@ def __init__(self, obj):
self.iscanonical = True
self.isliteral = True

def __call__(self, **kwargs):
""" returns the value for this symbol from kwargs """
return kwargs[self.obj]

def __hash__(self):
if self.obj is None: # Anonymous Symbol.
return id(self)
Expand Down Expand Up @@ -1052,6 +1065,10 @@ def demorgan(self):
op = expr.args[0]
return op.dual(*(self.__class__(arg).cancel() for arg in op.args))

def __call__(self, **kwargs):
""" negates the value returned from self.args[0].__call__ """
return not self.args[0](**kwargs)

def __lt__(self, other):
return self.args[0] < other

Expand Down Expand Up @@ -1407,6 +1424,14 @@ def __init__(self, arg1, arg2, *args):
self.dual = self.OR
self.operator = '&'

def __call__(self, **kwargs):
"""
Calls arg.__call__ for each arg in self.args and applies python 'and' operator.

reduce is used as in e.g. AND(a, b, c, d) == AND(a, AND(b, AND(c, d)))
"""
return reduce(and_operator, (a(**kwargs) for a in self.args))


class OR(DualBase):
"""
Expand All @@ -1430,3 +1455,11 @@ def __init__(self, arg1, arg2, *args):
self.annihilator = self.TRUE
self.dual = self.AND
self.operator = '|'

def __call__(self, **kwargs):
"""
Calls arg.__call__ for each arg in self.args and applies python 'or' operator.

reduce is used as in e.g. OR(a, b, c, d) == OR(a, OR(b, OR(c, d)))
"""
return reduce(or_operator, (a(**kwargs) for a in self.args))
46 changes: 46 additions & 0 deletions boolean/test_boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,5 +1073,51 @@ def __init__(self, name, value='value'):
self.fail(e)


class CallabilityTestCase(unittest.TestCase):

def test_and(self):
algebra = BooleanAlgebra()
exp = algebra.parse("a&b&c")
for a in [True, False]:
for b in [True, False]:
for c in [True, False]:
self.assertEqual(exp(a=a, b=b, c=c), a and b and c)

def test_or(self):
algebra = BooleanAlgebra()
exp = algebra.parse("a|b|c")
for a in [True, False]:
for b in [True, False]:
for c in [True, False]:
self.assertEqual(exp(a=a, b=b, c=c), a or b or c)

def test_not(self):
algebra = BooleanAlgebra()
exp = algebra.parse("!a")
for a in [True, False]:
self.assertEqual(exp(a=a), not a)

def test_symbol(self):
algebra = BooleanAlgebra()
exp = algebra.parse("a")
for a in [True, False]:
self.assertEqual(exp(a=a), a)

def test_composite(self):
algebra = BooleanAlgebra()
exp = algebra.parse("!(a|b&(a|!c))")
for a in [True, False]:
for b in [True, False]:
for c in [True, False]:
self.assertEqual(exp(a=a, b=b, c=c), not(a or b and (a or not c)))

def test_negate_A_or_B(self):
algebra = BooleanAlgebra()
exp = algebra.parse("!(a|b)")
for a in [True, False]:
for b in [True, False]:
self.assertEqual(exp(a=a, b=b), not(a or b))


if __name__ == '__main__':
unittest.main()