%PDF- %PDF-
| Direktori : /proc/thread-self/root/usr/lib/python3/dist-packages/sympy/assumptions/handlers/ |
| Current File : //proc/thread-self/root/usr/lib/python3/dist-packages/sympy/assumptions/handlers/sets.py |
"""
Handlers for predicates related to set membership: integer, rational, etc.
"""
from sympy.assumptions import Q, ask
from sympy.core import Add, Basic, Expr, Mul, Pow
from sympy.core.numbers import (AlgebraicNumber, ComplexInfinity, Exp1, Float,
GoldenRatio, ImaginaryUnit, Infinity, Integer, NaN, NegativeInfinity,
Number, NumberSymbol, Pi, pi, Rational, TribonacciConstant, E)
from sympy.core.logic import fuzzy_bool
from sympy.functions import (Abs, acos, acot, asin, atan, cos, cot, exp, im,
log, re, sin, tan)
from sympy import I, Eq, conjugate
from sympy.matrices import Determinant, MatrixBase, Trace
from sympy.matrices.expressions.matexpr import MatrixElement
from sympy.multipledispatch import MDNotImplementedError
from .common import test_closed_group
from ..predicates.sets import (IntegerPredicate, RationalPredicate,
IrrationalPredicate, RealPredicate, ExtendedRealPredicate,
HermitianPredicate, ComplexPredicate, ImaginaryPredicate,
AntihermitianPredicate, AlgebraicPredicate)
# IntegerPredicate
def _IntegerPredicate_number(expr, assumptions):
# helper function
try:
i = int(expr.round())
if not (expr - i).equals(0):
raise TypeError
return True
except TypeError:
return False
@IntegerPredicate.register_many(int, Integer)
def _(expr, assumptions):
return True
@IntegerPredicate.register_many(Exp1, GoldenRatio, ImaginaryUnit, Infinity,
NegativeInfinity, Pi, Rational, TribonacciConstant)
def _(expr, assumptions):
return False
@IntegerPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_integer
if ret is None:
raise MDNotImplementedError
return ret
@IntegerPredicate.register_many(Add, Pow)
def _(expr, assumptions):
"""
* Integer + Integer -> Integer
* Integer + !Integer -> !Integer
* !Integer + !Integer -> ?
"""
if expr.is_number:
return _IntegerPredicate_number(expr, assumptions)
return test_closed_group(expr, assumptions, Q.integer)
@IntegerPredicate.register(Mul)
def _(expr, assumptions):
"""
* Integer*Integer -> Integer
* Integer*Irrational -> !Integer
* Odd/Even -> !Integer
* Integer*Rational -> ?
"""
if expr.is_number:
return _IntegerPredicate_number(expr, assumptions)
_output = True
for arg in expr.args:
if not ask(Q.integer(arg), assumptions):
if arg.is_Rational:
if arg.q == 2:
return ask(Q.even(2*expr), assumptions)
if ~(arg.q & 1):
return None
elif ask(Q.irrational(arg), assumptions):
if _output:
_output = False
else:
return
else:
return
return _output
@IntegerPredicate.register(Abs)
def _(expr, assumptions):
return ask(Q.integer(expr.args[0]), assumptions)
@IntegerPredicate.register_many(Determinant, MatrixElement, Trace)
def _(expr, assumptions):
return ask(Q.integer_elements(expr.args[0]), assumptions)
# RationalPredicate
@RationalPredicate.register(Rational)
def _(expr, assumptions):
return True
@RationalPredicate.register(Float)
def _(expr, assumptions):
return None
@RationalPredicate.register_many(Exp1, GoldenRatio, ImaginaryUnit, Infinity,
NegativeInfinity, Pi, TribonacciConstant)
def _(expr, assumptions):
return False
@RationalPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_rational
if ret is None:
raise MDNotImplementedError
return ret
@RationalPredicate.register_many(Add, Mul)
def _(expr, assumptions):
"""
* Rational + Rational -> Rational
* Rational + !Rational -> !Rational
* !Rational + !Rational -> ?
"""
if expr.is_number:
if expr.as_real_imag()[1]:
return False
return test_closed_group(expr, assumptions, Q.rational)
@RationalPredicate.register(Pow)
def _(expr, assumptions):
"""
* Rational ** Integer -> Rational
* Irrational ** Rational -> Irrational
* Rational ** Irrational -> ?
"""
if expr.base == E:
x = expr.exp
if ask(Q.rational(x), assumptions):
return ask(~Q.nonzero(x), assumptions)
return
if ask(Q.integer(expr.exp), assumptions):
return ask(Q.rational(expr.base), assumptions)
elif ask(Q.rational(expr.exp), assumptions):
if ask(Q.prime(expr.base), assumptions):
return False
@RationalPredicate.register_many(asin, atan, cos, sin, tan)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.rational(x), assumptions):
return ask(~Q.nonzero(x), assumptions)
@RationalPredicate.register(exp)
def _(expr, assumptions):
x = expr.exp
if ask(Q.rational(x), assumptions):
return ask(~Q.nonzero(x), assumptions)
@RationalPredicate.register_many(acot, cot)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.rational(x), assumptions):
return False
@RationalPredicate.register_many(acos, log)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.rational(x), assumptions):
return ask(~Q.nonzero(x - 1), assumptions)
# IrrationalPredicate
@IrrationalPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_irrational
if ret is None:
raise MDNotImplementedError
return ret
@IrrationalPredicate.register(Basic)
def _(expr, assumptions):
_real = ask(Q.real(expr), assumptions)
if _real:
_rational = ask(Q.rational(expr), assumptions)
if _rational is None:
return None
return not _rational
else:
return _real
# RealPredicate
def _RealPredicate_number(expr, assumptions):
# let as_real_imag() work first since the expression may
# be simpler to evaluate
i = expr.as_real_imag()[1].evalf(2)
if i._prec != 1:
return not i
# allow None to be returned if we couldn't show for sure
# that i was 0
@RealPredicate.register_many(Abs, Exp1, Float, GoldenRatio, im, Pi, Rational,
re, TribonacciConstant)
def _(expr, assumptions):
return True
@RealPredicate.register_many(ImaginaryUnit, Infinity, NegativeInfinity)
def _(expr, assumptions):
return False
@RealPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_real
if ret is None:
raise MDNotImplementedError
return ret
@RealPredicate.register(Add)
def _(expr, assumptions):
"""
* Real + Real -> Real
* Real + (Complex & !Real) -> !Real
"""
if expr.is_number:
return _RealPredicate_number(expr, assumptions)
return test_closed_group(expr, assumptions, Q.real)
@RealPredicate.register(Mul)
def _(expr, assumptions):
"""
* Real*Real -> Real
* Real*Imaginary -> !Real
* Imaginary*Imaginary -> Real
"""
if expr.is_number:
return _RealPredicate_number(expr, assumptions)
result = True
for arg in expr.args:
if ask(Q.real(arg), assumptions):
pass
elif ask(Q.imaginary(arg), assumptions):
result = result ^ True
else:
break
else:
return result
@RealPredicate.register(Pow)
def _(expr, assumptions):
"""
* Real**Integer -> Real
* Positive**Real -> Real
* Real**(Integer/Even) -> Real if base is nonnegative
* Real**(Integer/Odd) -> Real
* Imaginary**(Integer/Even) -> Real
* Imaginary**(Integer/Odd) -> not Real
* Imaginary**Real -> ? since Real could be 0 (giving real)
or 1 (giving imaginary)
* b**Imaginary -> Real if log(b) is imaginary and b != 0
and exponent != integer multiple of
I*pi/log(b)
* Real**Real -> ? e.g. sqrt(-1) is imaginary and
sqrt(2) is not
"""
if expr.is_number:
return _RealPredicate_number(expr, assumptions)
if expr.base == E:
return ask(
Q.integer(expr.exp/I/pi) | Q.real(expr.exp), assumptions
)
if expr.base.func == exp or (expr.base.is_Pow and expr.base.base == E):
if ask(Q.imaginary(expr.base.exp), assumptions):
if ask(Q.imaginary(expr.exp), assumptions):
return True
# If the i = (exp's arg)/(I*pi) is an integer or half-integer
# multiple of I*pi then 2*i will be an integer. In addition,
# exp(i*I*pi) = (-1)**i so the overall realness of the expr
# can be determined by replacing exp(i*I*pi) with (-1)**i.
i = expr.base.exp/I/pi
if ask(Q.integer(2*i), assumptions):
return ask(Q.real(((-1)**i)**expr.exp), assumptions)
return
if ask(Q.imaginary(expr.base), assumptions):
if ask(Q.integer(expr.exp), assumptions):
odd = ask(Q.odd(expr.exp), assumptions)
if odd is not None:
return not odd
return
if ask(Q.imaginary(expr.exp), assumptions):
imlog = ask(Q.imaginary(log(expr.base)), assumptions)
if imlog is not None:
# I**i -> real, log(I) is imag;
# (2*I)**i -> complex, log(2*I) is not imag
return imlog
if ask(Q.real(expr.base), assumptions):
if ask(Q.real(expr.exp), assumptions):
if expr.exp.is_Rational and \
ask(Q.even(expr.exp.q), assumptions):
return ask(Q.positive(expr.base), assumptions)
elif ask(Q.integer(expr.exp), assumptions):
return True
elif ask(Q.positive(expr.base), assumptions):
return True
elif ask(Q.negative(expr.base), assumptions):
return False
@RealPredicate.register_many(cos, sin)
def _(expr, assumptions):
if ask(Q.real(expr.args[0]), assumptions):
return True
@RealPredicate.register(exp)
def _(expr, assumptions):
return ask(
Q.integer(expr.exp/I/pi) | Q.real(expr.exp), assumptions
)
@RealPredicate.register(log)
def _(expr, assumptions):
return ask(Q.positive(expr.args[0]), assumptions)
@RealPredicate.register_many(Determinant, MatrixElement, Trace)
def _(expr, assumptions):
return ask(Q.real_elements(expr.args[0]), assumptions)
# ExtendedRealPredicate
@ExtendedRealPredicate.register(object)
def _(expr, assumptions):
return ask(Q.negative_infinite(expr)
| Q.negative(expr)
| Q.zero(expr)
| Q.positive(expr)
| Q.positive_infinite(expr),
assumptions)
@ExtendedRealPredicate.register_many(Infinity, NegativeInfinity)
def _(expr, assumptions):
return True
@ExtendedRealPredicate.register_many(Add, Mul, Pow)
def _(expr, assumptions):
return test_closed_group(expr, assumptions, Q.extended_real)
# HermitianPredicate
@HermitianPredicate.register(object)
def _(expr, assumptions):
if isinstance(expr, MatrixBase):
return None
return ask(Q.real(expr), assumptions)
@HermitianPredicate.register(Add)
def _(expr, assumptions):
"""
* Hermitian + Hermitian -> Hermitian
* Hermitian + !Hermitian -> !Hermitian
"""
if expr.is_number:
raise MDNotImplementedError
return test_closed_group(expr, assumptions, Q.hermitian)
@HermitianPredicate.register(Mul)
def _(expr, assumptions):
"""
As long as there is at most only one noncommutative term:
* Hermitian*Hermitian -> Hermitian
* Hermitian*Antihermitian -> !Hermitian
* Antihermitian*Antihermitian -> Hermitian
"""
if expr.is_number:
raise MDNotImplementedError
nccount = 0
result = True
for arg in expr.args:
if ask(Q.antihermitian(arg), assumptions):
result = result ^ True
elif not ask(Q.hermitian(arg), assumptions):
break
if ask(~Q.commutative(arg), assumptions):
nccount += 1
if nccount > 1:
break
else:
return result
@HermitianPredicate.register(Pow)
def _(expr, assumptions):
"""
* Hermitian**Integer -> Hermitian
"""
if expr.is_number:
raise MDNotImplementedError
if expr.base == E:
if ask(Q.hermitian(expr.exp), assumptions):
return True
raise MDNotImplementedError
if ask(Q.hermitian(expr.base), assumptions):
if ask(Q.integer(expr.exp), assumptions):
return True
raise MDNotImplementedError
@HermitianPredicate.register_many(cos, sin)
def _(expr, assumptions):
if ask(Q.hermitian(expr.args[0]), assumptions):
return True
raise MDNotImplementedError
@HermitianPredicate.register(exp)
def _(expr, assumptions):
if ask(Q.hermitian(expr.exp), assumptions):
return True
raise MDNotImplementedError
@HermitianPredicate.register(MatrixBase)
def _(mat, assumptions):
rows, cols = mat.shape
ret_val = True
for i in range(rows):
for j in range(i, cols):
cond = fuzzy_bool(Eq(mat[i, j], conjugate(mat[j, i])))
if cond is None:
ret_val = None
if cond == False:
return False
if ret_val is None:
raise MDNotImplementedError
return ret_val
# ComplexPredicate
@ComplexPredicate.register_many(Abs, cos, exp, im, ImaginaryUnit, log, Number,
NumberSymbol, re, sin)
def _(expr, assumptions):
return True
@ComplexPredicate.register_many(Infinity, NegativeInfinity)
def _(expr, assumptions):
return False
@ComplexPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_complex
if ret is None:
raise MDNotImplementedError
return ret
@ComplexPredicate.register_many(Add, Mul)
def _(expr, assumptions):
return test_closed_group(expr, assumptions, Q.complex)
@ComplexPredicate.register(Pow)
def _(expr, assumptions):
if expr.base == E:
return True
return test_closed_group(expr, assumptions, Q.complex)
@ComplexPredicate.register_many(Determinant, MatrixElement, Trace)
def _(expr, assumptions):
return ask(Q.complex_elements(expr.args[0]), assumptions)
@ComplexPredicate.register(NaN)
def _(expr, assumptions):
return None
# ImaginaryPredicate
def _Imaginary_number(expr, assumptions):
# let as_real_imag() work first since the expression may
# be simpler to evaluate
r = expr.as_real_imag()[0].evalf(2)
if r._prec != 1:
return not r
# allow None to be returned if we couldn't show for sure
# that r was 0
@ImaginaryPredicate.register(ImaginaryUnit)
def _(expr, assumptions):
return True
@ImaginaryPredicate.register(Expr)
def _(expr, assumptions):
ret = expr.is_imaginary
if ret is None:
raise MDNotImplementedError
return ret
@ImaginaryPredicate.register(Add)
def _(expr, assumptions):
"""
* Imaginary + Imaginary -> Imaginary
* Imaginary + Complex -> ?
* Imaginary + Real -> !Imaginary
"""
if expr.is_number:
return _Imaginary_number(expr, assumptions)
reals = 0
for arg in expr.args:
if ask(Q.imaginary(arg), assumptions):
pass
elif ask(Q.real(arg), assumptions):
reals += 1
else:
break
else:
if reals == 0:
return True
if reals == 1 or (len(expr.args) == reals):
# two reals could sum 0 thus giving an imaginary
return False
@ImaginaryPredicate.register(Mul)
def _(expr, assumptions):
"""
* Real*Imaginary -> Imaginary
* Imaginary*Imaginary -> Real
"""
if expr.is_number:
return _Imaginary_number(expr, assumptions)
result = False
reals = 0
for arg in expr.args:
if ask(Q.imaginary(arg), assumptions):
result = result ^ True
elif not ask(Q.real(arg), assumptions):
break
else:
if reals == len(expr.args):
return False
return result
@ImaginaryPredicate.register(Pow)
def _(expr, assumptions):
"""
* Imaginary**Odd -> Imaginary
* Imaginary**Even -> Real
* b**Imaginary -> !Imaginary if exponent is an integer
multiple of I*pi/log(b)
* Imaginary**Real -> ?
* Positive**Real -> Real
* Negative**Integer -> Real
* Negative**(Integer/2) -> Imaginary
* Negative**Real -> not Imaginary if exponent is not Rational
"""
if expr.is_number:
return _Imaginary_number(expr, assumptions)
if expr.base == E:
a = expr.exp/I/pi
return ask(Q.integer(2*a) & ~Q.integer(a), assumptions)
if expr.base.func == exp or (expr.base.is_Pow and expr.base.base == E):
if ask(Q.imaginary(expr.base.exp), assumptions):
if ask(Q.imaginary(expr.exp), assumptions):
return False
i = expr.base.exp/I/pi
if ask(Q.integer(2*i), assumptions):
return ask(Q.imaginary(((-1)**i)**expr.exp), assumptions)
if ask(Q.imaginary(expr.base), assumptions):
if ask(Q.integer(expr.exp), assumptions):
odd = ask(Q.odd(expr.exp), assumptions)
if odd is not None:
return odd
return
if ask(Q.imaginary(expr.exp), assumptions):
imlog = ask(Q.imaginary(log(expr.base)), assumptions)
if imlog is not None:
# I**i -> real; (2*I)**i -> complex ==> not imaginary
return False
if ask(Q.real(expr.base) & Q.real(expr.exp), assumptions):
if ask(Q.positive(expr.base), assumptions):
return False
else:
rat = ask(Q.rational(expr.exp), assumptions)
if not rat:
return rat
if ask(Q.integer(expr.exp), assumptions):
return False
else:
half = ask(Q.integer(2*expr.exp), assumptions)
if half:
return ask(Q.negative(expr.base), assumptions)
return half
@ImaginaryPredicate.register(log)
def _(expr, assumptions):
if ask(Q.real(expr.args[0]), assumptions):
if ask(Q.positive(expr.args[0]), assumptions):
return False
return
# XXX it should be enough to do
# return ask(Q.nonpositive(expr.args[0]), assumptions)
# but ask(Q.nonpositive(exp(x)), Q.imaginary(x)) -> None;
# it should return True since exp(x) will be either 0 or complex
if expr.args[0].func == exp or (expr.args[0].is_Pow and expr.args[0].base == E):
if expr.args[0].exp in [I, -I]:
return True
im = ask(Q.imaginary(expr.args[0]), assumptions)
if im is False:
return False
@ImaginaryPredicate.register(exp)
def _(expr, assumptions):
a = expr.exp/I/pi
return ask(Q.integer(2*a) & ~Q.integer(a), assumptions)
@ImaginaryPredicate.register_many(Number, NumberSymbol)
def _(expr, assumptions):
return not (expr.as_real_imag()[1] == 0)
@ImaginaryPredicate.register(NaN)
def _(expr, assumptions):
return None
# AntihermitianPredicate
@AntihermitianPredicate.register(object)
def _(expr, assumptions):
if isinstance(expr, MatrixBase):
return None
if ask(Q.zero(expr), assumptions):
return True
return ask(Q.imaginary(expr), assumptions)
@AntihermitianPredicate.register(Add)
def _(expr, assumptions):
"""
* Antihermitian + Antihermitian -> Antihermitian
* Antihermitian + !Antihermitian -> !Antihermitian
"""
if expr.is_number:
raise MDNotImplementedError
return test_closed_group(expr, assumptions, Q.antihermitian)
@AntihermitianPredicate.register(Mul)
def _(expr, assumptions):
"""
As long as there is at most only one noncommutative term:
* Hermitian*Hermitian -> !Antihermitian
* Hermitian*Antihermitian -> Antihermitian
* Antihermitian*Antihermitian -> !Antihermitian
"""
if expr.is_number:
raise MDNotImplementedError
nccount = 0
result = False
for arg in expr.args:
if ask(Q.antihermitian(arg), assumptions):
result = result ^ True
elif not ask(Q.hermitian(arg), assumptions):
break
if ask(~Q.commutative(arg), assumptions):
nccount += 1
if nccount > 1:
break
else:
return result
@AntihermitianPredicate.register(Pow)
def _(expr, assumptions):
"""
* Hermitian**Integer -> !Antihermitian
* Antihermitian**Even -> !Antihermitian
* Antihermitian**Odd -> Antihermitian
"""
if expr.is_number:
raise MDNotImplementedError
if ask(Q.hermitian(expr.base), assumptions):
if ask(Q.integer(expr.exp), assumptions):
return False
elif ask(Q.antihermitian(expr.base), assumptions):
if ask(Q.even(expr.exp), assumptions):
return False
elif ask(Q.odd(expr.exp), assumptions):
return True
raise MDNotImplementedError
@AntihermitianPredicate.register(MatrixBase)
def _(mat, assumptions):
rows, cols = mat.shape
ret_val = True
for i in range(rows):
for j in range(i, cols):
cond = fuzzy_bool(Eq(mat[i, j], -conjugate(mat[j, i])))
if cond is None:
ret_val = None
if cond == False:
return False
if ret_val is None:
raise MDNotImplementedError
return ret_val
# AlgebraicPredicate
@AlgebraicPredicate.register_many(AlgebraicNumber, Float, GoldenRatio,
ImaginaryUnit, TribonacciConstant)
def _(expr, assumptions):
return True
@AlgebraicPredicate.register_many(ComplexInfinity, Exp1, Infinity,
NegativeInfinity, Pi)
def _(expr, assumptions):
return False
@AlgebraicPredicate.register_many(Add, Mul)
def _(expr, assumptions):
return test_closed_group(expr, assumptions, Q.algebraic)
@AlgebraicPredicate.register(Pow)
def _(expr, assumptions):
if expr.base == E:
if ask(Q.algebraic(expr.exp), assumptions):
return ask(~Q.nonzero(expr.exp), assumptions)
return
return expr.exp.is_Rational and ask(Q.algebraic(expr.base), assumptions)
@AlgebraicPredicate.register(Rational)
def _(expr, assumptions):
return expr.q != 0
@AlgebraicPredicate.register_many(asin, atan, cos, sin, tan)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.algebraic(x), assumptions):
return ask(~Q.nonzero(x), assumptions)
@AlgebraicPredicate.register(exp)
def _(expr, assumptions):
x = expr.exp
if ask(Q.algebraic(x), assumptions):
return ask(~Q.nonzero(x), assumptions)
@AlgebraicPredicate.register_many(acot, cot)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.algebraic(x), assumptions):
return False
@AlgebraicPredicate.register_many(acos, log)
def _(expr, assumptions):
x = expr.args[0]
if ask(Q.algebraic(x), assumptions):
return ask(~Q.nonzero(x - 1), assumptions)