Spaces:
Sleeping
Sleeping
| """ | |
| Functions and wrapper object to call assumption property and predicate | |
| query with same syntax. | |
| In SymPy, there are two assumption systems. Old assumption system is | |
| defined in sympy/core/assumptions, and it can be accessed by attribute | |
| such as ``x.is_even``. New assumption system is defined in | |
| sympy/assumptions, and it can be accessed by predicates such as | |
| ``Q.even(x)``. | |
| Old assumption is fast, while new assumptions can freely take local facts. | |
| In general, old assumption is used in evaluation method and new assumption | |
| is used in refinement method. | |
| In most cases, both evaluation and refinement follow the same process, and | |
| the only difference is which assumption system is used. This module provides | |
| ``is_[...]()`` functions and ``AssumptionsWrapper()`` class which allows | |
| using two systems with same syntax so that parallel code implementation can be | |
| avoided. | |
| Examples | |
| ======== | |
| For multiple use, use ``AssumptionsWrapper()``. | |
| from sympy import Q, Symbol | |
| from sympy.assumptions.wrapper import AssumptionsWrapper | |
| x = Symbol('x') | |
| _x = AssumptionsWrapper(x, Q.even(x)) | |
| _x.is_integer | |
| True | |
| _x.is_odd | |
| False | |
| For single use, use ``is_[...]()`` functions. | |
| from sympy.assumptions.wrapper import is_infinite | |
| a = Symbol('a') | |
| print(is_infinite(a)) | |
| None | |
| is_infinite(a, Q.finite(a)) | |
| False | |
| """ | |
| from sympy.assumptions import ask, Q | |
| from sympy.core.basic import Basic | |
| from sympy.core.sympify import _sympify | |
| def make_eval_method(fact): | |
| def getit(self): | |
| pred = getattr(Q, fact) | |
| ret = ask(pred(self.expr), self.assumptions) | |
| return ret | |
| return getit | |
| # we subclass Basic to use the fact deduction and caching | |
| class AssumptionsWrapper(Basic): | |
| """ | |
| Wrapper over ``Basic`` instances to call predicate query by | |
| ``.is_[...]`` property | |
| Parameters | |
| ========== | |
| expr : Basic | |
| assumptions : Boolean, optional | |
| Examples | |
| ======== | |
| >>> from sympy import Q, Symbol | |
| >>> from sympy.assumptions.wrapper import AssumptionsWrapper | |
| >>> x = Symbol('x', even=True) | |
| >>> AssumptionsWrapper(x).is_integer | |
| True | |
| >>> y = Symbol('y') | |
| >>> AssumptionsWrapper(y, Q.even(y)).is_integer | |
| True | |
| With ``AssumptionsWrapper``, both evaluation and refinement can be supported | |
| by single implementation. | |
| >>> from sympy import Function | |
| >>> class MyAbs(Function): | |
| ... @classmethod | |
| ... def eval(cls, x, assumptions=True): | |
| ... _x = AssumptionsWrapper(x, assumptions) | |
| ... if _x.is_nonnegative: | |
| ... return x | |
| ... if _x.is_negative: | |
| ... return -x | |
| ... def _eval_refine(self, assumptions): | |
| ... return MyAbs.eval(self.args[0], assumptions) | |
| >>> MyAbs(x) | |
| MyAbs(x) | |
| >>> MyAbs(x).refine(Q.positive(x)) | |
| x | |
| >>> MyAbs(Symbol('y', negative=True)) | |
| -y | |
| """ | |
| def __new__(cls, expr, assumptions=None): | |
| if assumptions is None: | |
| return expr | |
| obj = super().__new__(cls, expr, _sympify(assumptions)) | |
| obj.expr = expr | |
| obj.assumptions = assumptions | |
| return obj | |
| _eval_is_algebraic = make_eval_method("algebraic") | |
| _eval_is_antihermitian = make_eval_method("antihermitian") | |
| _eval_is_commutative = make_eval_method("commutative") | |
| _eval_is_complex = make_eval_method("complex") | |
| _eval_is_composite = make_eval_method("composite") | |
| _eval_is_even = make_eval_method("even") | |
| _eval_is_extended_negative = make_eval_method("extended_negative") | |
| _eval_is_extended_nonnegative = make_eval_method("extended_nonnegative") | |
| _eval_is_extended_nonpositive = make_eval_method("extended_nonpositive") | |
| _eval_is_extended_nonzero = make_eval_method("extended_nonzero") | |
| _eval_is_extended_positive = make_eval_method("extended_positive") | |
| _eval_is_extended_real = make_eval_method("extended_real") | |
| _eval_is_finite = make_eval_method("finite") | |
| _eval_is_hermitian = make_eval_method("hermitian") | |
| _eval_is_imaginary = make_eval_method("imaginary") | |
| _eval_is_infinite = make_eval_method("infinite") | |
| _eval_is_integer = make_eval_method("integer") | |
| _eval_is_irrational = make_eval_method("irrational") | |
| _eval_is_negative = make_eval_method("negative") | |
| _eval_is_noninteger = make_eval_method("noninteger") | |
| _eval_is_nonnegative = make_eval_method("nonnegative") | |
| _eval_is_nonpositive = make_eval_method("nonpositive") | |
| _eval_is_nonzero = make_eval_method("nonzero") | |
| _eval_is_odd = make_eval_method("odd") | |
| _eval_is_polar = make_eval_method("polar") | |
| _eval_is_positive = make_eval_method("positive") | |
| _eval_is_prime = make_eval_method("prime") | |
| _eval_is_rational = make_eval_method("rational") | |
| _eval_is_real = make_eval_method("real") | |
| _eval_is_transcendental = make_eval_method("transcendental") | |
| _eval_is_zero = make_eval_method("zero") | |
| # one shot functions which are faster than AssumptionsWrapper | |
| def is_infinite(obj, assumptions=None): | |
| if assumptions is None: | |
| return obj.is_infinite | |
| return ask(Q.infinite(obj), assumptions) | |
| def is_extended_real(obj, assumptions=None): | |
| if assumptions is None: | |
| return obj.is_extended_real | |
| return ask(Q.extended_real(obj), assumptions) | |
| def is_extended_nonnegative(obj, assumptions=None): | |
| if assumptions is None: | |
| return obj.is_extended_nonnegative | |
| return ask(Q.extended_nonnegative(obj), assumptions) | |