Spaces:
Sleeping
Sleeping
""" | |
Handlers related to order relations: positive, negative, etc. | |
""" | |
from sympy.assumptions import Q, ask | |
from sympy.core import Add, Basic, Expr, Mul, Pow | |
from sympy.core.logic import fuzzy_not, fuzzy_and, fuzzy_or | |
from sympy.core.numbers import E, ImaginaryUnit, NaN, I, pi | |
from sympy.functions import Abs, acos, acot, asin, atan, exp, factorial, log | |
from sympy.matrices import Determinant, Trace | |
from sympy.matrices.expressions.matexpr import MatrixElement | |
from sympy.multipledispatch import MDNotImplementedError | |
from ..predicates.order import (NegativePredicate, NonNegativePredicate, | |
NonZeroPredicate, ZeroPredicate, NonPositivePredicate, PositivePredicate, | |
ExtendedNegativePredicate, ExtendedNonNegativePredicate, | |
ExtendedNonPositivePredicate, ExtendedNonZeroPredicate, | |
ExtendedPositivePredicate,) | |
# NegativePredicate | |
def _NegativePredicate_number(expr, assumptions): | |
r, i = expr.as_real_imag() | |
# If the imaginary part can symbolically be shown to be zero then | |
# we just evaluate the real part; otherwise we evaluate the imaginary | |
# part to see if it actually evaluates to zero and if it does then | |
# we make the comparison between the real part and zero. | |
if not i: | |
r = r.evalf(2) | |
if r._prec != 1: | |
return r < 0 | |
else: | |
i = i.evalf(2) | |
if i._prec != 1: | |
if i != 0: | |
return False | |
r = r.evalf(2) | |
if r._prec != 1: | |
return r < 0 | |
def _(expr, assumptions): | |
if expr.is_number: | |
return _NegativePredicate_number(expr, assumptions) | |
def _(expr, assumptions): | |
ret = expr.is_negative | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
def _(expr, assumptions): | |
""" | |
Positive + Positive -> Positive, | |
Negative + Negative -> Negative | |
""" | |
if expr.is_number: | |
return _NegativePredicate_number(expr, assumptions) | |
r = ask(Q.real(expr), assumptions) | |
if r is not True: | |
return r | |
nonpos = 0 | |
for arg in expr.args: | |
if ask(Q.negative(arg), assumptions) is not True: | |
if ask(Q.positive(arg), assumptions) is False: | |
nonpos += 1 | |
else: | |
break | |
else: | |
if nonpos < len(expr.args): | |
return True | |
def _(expr, assumptions): | |
if expr.is_number: | |
return _NegativePredicate_number(expr, assumptions) | |
result = None | |
for arg in expr.args: | |
if result is None: | |
result = False | |
if ask(Q.negative(arg), assumptions): | |
result = not result | |
elif ask(Q.positive(arg), assumptions): | |
pass | |
else: | |
return | |
return result | |
def _(expr, assumptions): | |
""" | |
Real ** Even -> NonNegative | |
Real ** Odd -> same_as_base | |
NonNegative ** Positive -> NonNegative | |
""" | |
if expr.base == E: | |
# Exponential is always positive: | |
if ask(Q.real(expr.exp), assumptions): | |
return False | |
return | |
if expr.is_number: | |
return _NegativePredicate_number(expr, assumptions) | |
if ask(Q.real(expr.base), assumptions): | |
if ask(Q.positive(expr.base), assumptions): | |
if ask(Q.real(expr.exp), assumptions): | |
return False | |
if ask(Q.even(expr.exp), assumptions): | |
return False | |
if ask(Q.odd(expr.exp), assumptions): | |
return ask(Q.negative(expr.base), assumptions) | |
def _(expr, assumptions): | |
return False | |
def _(expr, assumptions): | |
if ask(Q.real(expr.exp), assumptions): | |
return False | |
raise MDNotImplementedError | |
# NonNegativePredicate | |
def _(expr, assumptions): | |
if expr.is_number: | |
notnegative = fuzzy_not(_NegativePredicate_number(expr, assumptions)) | |
if notnegative: | |
return ask(Q.real(expr), assumptions) | |
else: | |
return notnegative | |
def _(expr, assumptions): | |
ret = expr.is_nonnegative | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
# NonZeroPredicate | |
def _(expr, assumptions): | |
ret = expr.is_nonzero | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
def _(expr, assumptions): | |
if ask(Q.real(expr)) is False: | |
return False | |
if expr.is_number: | |
# if there are no symbols just evalf | |
i = expr.evalf(2) | |
def nonz(i): | |
if i._prec != 1: | |
return i != 0 | |
return fuzzy_or(nonz(i) for i in i.as_real_imag()) | |
def _(expr, assumptions): | |
if all(ask(Q.positive(x), assumptions) for x in expr.args) \ | |
or all(ask(Q.negative(x), assumptions) for x in expr.args): | |
return True | |
def _(expr, assumptions): | |
for arg in expr.args: | |
result = ask(Q.nonzero(arg), assumptions) | |
if result: | |
continue | |
return result | |
return True | |
def _(expr, assumptions): | |
return ask(Q.nonzero(expr.base), assumptions) | |
def _(expr, assumptions): | |
return ask(Q.nonzero(expr.args[0]), assumptions) | |
def _(expr, assumptions): | |
return None | |
# ZeroPredicate | |
def _(expr, assumptions): | |
ret = expr.is_zero | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
def _(expr, assumptions): | |
return fuzzy_and([fuzzy_not(ask(Q.nonzero(expr), assumptions)), | |
ask(Q.real(expr), assumptions)]) | |
def _(expr, assumptions): | |
# TODO: This should be deducible from the nonzero handler | |
return fuzzy_or(ask(Q.zero(arg), assumptions) for arg in expr.args) | |
# NonPositivePredicate | |
def _(expr, assumptions): | |
ret = expr.is_nonpositive | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
def _(expr, assumptions): | |
if expr.is_number: | |
notpositive = fuzzy_not(_PositivePredicate_number(expr, assumptions)) | |
if notpositive: | |
return ask(Q.real(expr), assumptions) | |
else: | |
return notpositive | |
# PositivePredicate | |
def _PositivePredicate_number(expr, assumptions): | |
r, i = expr.as_real_imag() | |
# If the imaginary part can symbolically be shown to be zero then | |
# we just evaluate the real part; otherwise we evaluate the imaginary | |
# part to see if it actually evaluates to zero and if it does then | |
# we make the comparison between the real part and zero. | |
if not i: | |
r = r.evalf(2) | |
if r._prec != 1: | |
return r > 0 | |
else: | |
i = i.evalf(2) | |
if i._prec != 1: | |
if i != 0: | |
return False | |
r = r.evalf(2) | |
if r._prec != 1: | |
return r > 0 | |
def _(expr, assumptions): | |
ret = expr.is_positive | |
if ret is None: | |
raise MDNotImplementedError | |
return ret | |
def _(expr, assumptions): | |
if expr.is_number: | |
return _PositivePredicate_number(expr, assumptions) | |
def _(expr, assumptions): | |
if expr.is_number: | |
return _PositivePredicate_number(expr, assumptions) | |
result = True | |
for arg in expr.args: | |
if ask(Q.positive(arg), assumptions): | |
continue | |
elif ask(Q.negative(arg), assumptions): | |
result = result ^ True | |
else: | |
return | |
return result | |
def _(expr, assumptions): | |
if expr.is_number: | |
return _PositivePredicate_number(expr, assumptions) | |
r = ask(Q.real(expr), assumptions) | |
if r is not True: | |
return r | |
nonneg = 0 | |
for arg in expr.args: | |
if ask(Q.positive(arg), assumptions) is not True: | |
if ask(Q.negative(arg), assumptions) is False: | |
nonneg += 1 | |
else: | |
break | |
else: | |
if nonneg < len(expr.args): | |
return True | |
def _(expr, assumptions): | |
if expr.base == E: | |
if ask(Q.real(expr.exp), assumptions): | |
return True | |
if ask(Q.imaginary(expr.exp), assumptions): | |
return ask(Q.even(expr.exp/(I*pi)), assumptions) | |
return | |
if expr.is_number: | |
return _PositivePredicate_number(expr, assumptions) | |
if ask(Q.positive(expr.base), assumptions): | |
if ask(Q.real(expr.exp), assumptions): | |
return True | |
if ask(Q.negative(expr.base), assumptions): | |
if ask(Q.even(expr.exp), assumptions): | |
return True | |
if ask(Q.odd(expr.exp), assumptions): | |
return False | |
def _(expr, assumptions): | |
if ask(Q.real(expr.exp), assumptions): | |
return True | |
if ask(Q.imaginary(expr.exp), assumptions): | |
return ask(Q.even(expr.exp/(I*pi)), assumptions) | |
def _(expr, assumptions): | |
r = ask(Q.real(expr.args[0]), assumptions) | |
if r is not True: | |
return r | |
if ask(Q.positive(expr.args[0] - 1), assumptions): | |
return True | |
if ask(Q.negative(expr.args[0] - 1), assumptions): | |
return False | |
def _(expr, assumptions): | |
x = expr.args[0] | |
if ask(Q.integer(x) & Q.positive(x), assumptions): | |
return True | |
def _(expr, assumptions): | |
return False | |
def _(expr, assumptions): | |
return ask(Q.nonzero(expr), assumptions) | |
def _(expr, assumptions): | |
if ask(Q.positive_definite(expr.arg), assumptions): | |
return True | |
def _(expr, assumptions): | |
if ask(Q.positive_definite(expr.arg), assumptions): | |
return True | |
def _(expr, assumptions): | |
if (expr.i == expr.j | |
and ask(Q.positive_definite(expr.parent), assumptions)): | |
return True | |
def _(expr, assumptions): | |
return ask(Q.positive(expr.args[0]), assumptions) | |
def _(expr, assumptions): | |
x = expr.args[0] | |
if ask(Q.positive(x) & Q.nonpositive(x - 1), assumptions): | |
return True | |
if ask(Q.negative(x) & Q.nonnegative(x + 1), assumptions): | |
return False | |
def _(expr, assumptions): | |
x = expr.args[0] | |
if ask(Q.nonpositive(x - 1) & Q.nonnegative(x + 1), assumptions): | |
return True | |
def _(expr, assumptions): | |
return ask(Q.real(expr.args[0]), assumptions) | |
def _(expr, assumptions): | |
return None | |
# ExtendedNegativePredicate | |
def _(expr, assumptions): | |
return ask(Q.negative(expr) | Q.negative_infinite(expr), assumptions) | |
# ExtendedPositivePredicate | |
def _(expr, assumptions): | |
return ask(Q.positive(expr) | Q.positive_infinite(expr), assumptions) | |
# ExtendedNonZeroPredicate | |
def _(expr, assumptions): | |
return ask( | |
Q.negative_infinite(expr) | Q.negative(expr) | Q.positive(expr) | Q.positive_infinite(expr), | |
assumptions) | |
# ExtendedNonPositivePredicate | |
def _(expr, assumptions): | |
return ask( | |
Q.negative_infinite(expr) | Q.negative(expr) | Q.zero(expr), | |
assumptions) | |
# ExtendedNonNegativePredicate | |
def _(expr, assumptions): | |
return ask( | |
Q.zero(expr) | Q.positive(expr) | Q.positive_infinite(expr), | |
assumptions) | |