bastikr / boolean.py

Implements boolean algebra in one module.
BSD 2-Clause "Simplified" License
78 stars 34 forks source link

`subs` raises assertion when substituting with constant #118

Open jgoeders opened 11 months ago

jgoeders commented 11 months ago
>>> eq = boolean.BooleanAlgebra().parse("A OR (A & ~B)")
>>> eq
OR(Symbol('A'), AND(Symbol('A'), NOT(Symbol('B'))))
>>> eq.subs({boolean.Symbol("B"):True})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 743, in subs
    expr = self._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 781, in _subs
    new_arg = arg._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 781, in _subs
    new_arg = arg._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 796, in _subs
    newexpr = self.__class__(*new_arguments)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1138, in __init__
    super(NOT, self).__init__(arg1)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1042, in __init__
    assert all(
AssertionError: Bad arguments: all arguments must be an Expression: (True,)

>>> eq = eq.simplify()
>>> eq
Symbol('A')
>>> eq.subs({boolean.Symbol("B"):True})
Symbol('A')
jgoeders commented 11 months ago

Actually is seems that simplify() doesn't always fix the issue:

>>> eq = boolean.BooleanAlgebra().parse("(I0&I1&~I2&~I4&I5)|(I0&~I1&I2&I5)|(I0&~I1&I4)|(I0&I2&I4&~I5)|(~I0&~I1&I2&~I4&~I5)|(I1&I2&I4&I5)")
>>> eq.subs({boolean.Symbol("I5"):True})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 743, in subs
    expr = self._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 781, in _subs
    new_arg = arg._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 796, in _subs
    newexpr = self.__class__(*new_arguments)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1569, in __init__
    super(AND, self).__init__(arg1, arg2, *args)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1236, in __init__
    super(DualBase, self).__init__(arg1, arg2, *args)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1042, in __init__
    assert all(
AssertionError: Bad arguments: all arguments must be an Expression: (Symbol('I0'), Symbol('I1'), NOT(Symbol('I2')), NOT(Symbol('I4')), True)
>>> eq = eq.simplify()
>>> eq.subs({boolean.Symbol("I5"):True})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 743, in subs
    expr = self._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 781, in _subs
    new_arg = arg._subs(substitutions, default, simplify)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 796, in _subs
    newexpr = self.__class__(*new_arguments)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1569, in __init__
    super(AND, self).__init__(arg1, arg2, *args)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1236, in __init__
    super(DualBase, self).__init__(arg1, arg2, *args)
  File "/home/jgoeders/bfasst/.venv/lib/python3.10/site-packages/boolean/boolean.py", line 1042, in __init__
    assert all(
AssertionError: Bad arguments: all arguments must be an Expression: (Symbol('I0'), Symbol('I1'), NOT(Symbol('I2')), NOT(Symbol('I4')), True)
jgoeders commented 11 months ago

Ok, it seems I'm not supposed to use the Python True/False constants directly.

Is this then the preferred way to access the class-level TRUE/FALSE?

>>> eq = boolean.BooleanAlgebra().parse("A|B|C")
>>> eq.subs({boolean.Symbol("A"):eq.TRUE}).simplify()
TRUE