You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.0 KiB

5 months ago
"""
This module defines base class for handlers and some core handlers:
``Q.commutative`` and ``Q.is_true``.
"""
from sympy.assumptions import Q, ask, AppliedPredicate
from sympy.core import Basic, Symbol
from sympy.core.logic import _fuzzy_group
from sympy.core.numbers import NaN, Number
from sympy.logic.boolalg import (And, BooleanTrue, BooleanFalse, conjuncts,
Equivalent, Implies, Not, Or)
from sympy.utilities.exceptions import sympy_deprecation_warning
from ..predicates.common import CommutativePredicate, IsTruePredicate
class AskHandler:
"""Base class that all Ask Handlers must inherit."""
def __new__(cls, *args, **kwargs):
sympy_deprecation_warning(
"""
The AskHandler system is deprecated. The AskHandler class should
be replaced with the multipledispatch handler of Predicate
""",
deprecated_since_version="1.8",
active_deprecations_target='deprecated-askhandler',
)
return super().__new__(cls, *args, **kwargs)
class CommonHandler(AskHandler):
# Deprecated
"""Defines some useful methods common to most Handlers. """
@staticmethod
def AlwaysTrue(expr, assumptions):
return True
@staticmethod
def AlwaysFalse(expr, assumptions):
return False
@staticmethod
def AlwaysNone(expr, assumptions):
return None
NaN = AlwaysFalse
# CommutativePredicate
@CommutativePredicate.register(Symbol)
def _(expr, assumptions):
"""Objects are expected to be commutative unless otherwise stated"""
assumps = conjuncts(assumptions)
if expr.is_commutative is not None:
return expr.is_commutative and not ~Q.commutative(expr) in assumps
if Q.commutative(expr) in assumps:
return True
elif ~Q.commutative(expr) in assumps:
return False
return True
@CommutativePredicate.register(Basic)
def _(expr, assumptions):
for arg in expr.args:
if not ask(Q.commutative(arg), assumptions):
return False
return True
@CommutativePredicate.register(Number)
def _(expr, assumptions):
return True
@CommutativePredicate.register(NaN)
def _(expr, assumptions):
return True
# IsTruePredicate
@IsTruePredicate.register(bool)
def _(expr, assumptions):
return expr
@IsTruePredicate.register(BooleanTrue)
def _(expr, assumptions):
return True
@IsTruePredicate.register(BooleanFalse)
def _(expr, assumptions):
return False
@IsTruePredicate.register(AppliedPredicate)
def _(expr, assumptions):
return ask(expr, assumptions)
@IsTruePredicate.register(Not)
def _(expr, assumptions):
arg = expr.args[0]
if arg.is_Symbol:
# symbol used as abstract boolean object
return None
value = ask(arg, assumptions=assumptions)
if value in (True, False):
return not value
else:
return None
@IsTruePredicate.register(Or)
def _(expr, assumptions):
result = False
for arg in expr.args:
p = ask(arg, assumptions=assumptions)
if p is True:
return True
if p is None:
result = None
return result
@IsTruePredicate.register(And)
def _(expr, assumptions):
result = True
for arg in expr.args:
p = ask(arg, assumptions=assumptions)
if p is False:
return False
if p is None:
result = None
return result
@IsTruePredicate.register(Implies)
def _(expr, assumptions):
p, q = expr.args
return ask(~p | q, assumptions=assumptions)
@IsTruePredicate.register(Equivalent)
def _(expr, assumptions):
p, q = expr.args
pt = ask(p, assumptions=assumptions)
if pt is None:
return None
qt = ask(q, assumptions=assumptions)
if qt is None:
return None
return pt == qt
#### Helper methods
def test_closed_group(expr, assumptions, key):
"""
Test for membership in a group with respect
to the current operation.
"""
return _fuzzy_group(
(ask(key(a), assumptions) for a in expr.args), quick_exit=True)