Source code for sympy.assumptions.handlers.sets

"""
Handlers for predicates related to set membership: integer, rational, etc.
"""
from __future__ import print_function, division

from sympy.assumptions.handlers import CommonHandler, test_closed_group
from sympy.core.numbers import pi
from sympy.functions.elementary.exponential import exp, log
from sympy import I

"""
Handler for Q.integer
Test that an expression belongs to the field of integer numbers
"""

@staticmethod
def Expr(expr, assumptions):
return expr.is_integer

@staticmethod
def _number(expr, assumptions):
# helper method
try:
i = int(expr.round())
if not (expr - i).equals(0):
raise TypeError
return True
except TypeError:
return False

[docs]    @staticmethod
"""
Integer + Integer       -> Integer
Integer + !Integer      -> !Integer
!Integer + !Integer -> ?
"""
if expr.is_number:
return test_closed_group(expr, assumptions, Q.integer)

[docs]    @staticmethod
def Mul(expr, assumptions):
"""
Integer*Integer      -> Integer
Integer*Irrational   -> !Integer
Odd/Even             -> !Integer
Integer*Rational     -> ?
"""
if expr.is_number:
_output = True
for arg in expr.args:
if arg.is_Rational:
if arg.q == 2:
if ~(arg.q & 1):
return None
if _output:
_output = False
else:
return
else:
return
else:
return _output

int, Integer = [staticmethod(CommonHandler.AlwaysTrue)]*2

Pi, Exp1, GoldenRatio, TribonacciConstant, Infinity, NegativeInfinity, ImaginaryUnit = \
[staticmethod(CommonHandler.AlwaysFalse)]*7

@staticmethod
def Rational(expr, assumptions):
# rationals with denominator one get
# evaluated to Integers
return False

@staticmethod
def Abs(expr, assumptions):

@staticmethod
def MatrixElement(expr, assumptions):

Determinant = Trace = MatrixElement

"""
Handler for Q.rational
Test that an expression belongs to the field of rational numbers
"""

@staticmethod
def Expr(expr, assumptions):
return expr.is_rational

[docs]    @staticmethod
"""
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)

[docs]    @staticmethod
def Pow(expr, assumptions):
"""
Rational ** Integer      -> Rational
Irrational ** Rational   -> Irrational
Rational ** Irrational   -> ?
"""
return False

Rational = staticmethod(CommonHandler.AlwaysTrue)

Float = staticmethod(CommonHandler.AlwaysNone)

ImaginaryUnit, Infinity, NegativeInfinity, Pi, Exp1, GoldenRatio, TribonacciConstant = \
[staticmethod(CommonHandler.AlwaysFalse)]*7

@staticmethod
def exp(expr, assumptions):
x = expr.args[0]

@staticmethod
def cot(expr, assumptions):
x = expr.args[0]
return False

@staticmethod
def log(expr, assumptions):
x = expr.args[0]

sin, cos, tan, asin, atan = [exp]*5
acos, acot = log, cot

@staticmethod
def Expr(expr, assumptions):
return expr.is_irrational

@staticmethod
def Basic(expr, assumptions):
if _real:
if _rational is None:
return None
return not _rational
else:
return _real

"""
Handler for Q.real
Test that an expression belongs to the field of real numbers
"""

@staticmethod
def Expr(expr, assumptions):
return expr.is_real

@staticmethod
def _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

[docs]    @staticmethod
"""
Real + Real              -> Real
Real + (Complex & !Real) -> !Real
"""
if expr.is_number:
return test_closed_group(expr, assumptions, Q.real)

[docs]    @staticmethod
def Mul(expr, assumptions):
"""
Real*Real               -> Real
Real*Imaginary          -> !Real
Imaginary*Imaginary     -> Real
"""
if expr.is_number:
result = True
for arg in expr.args:
pass
result = result ^ True
else:
break
else:
return result

[docs]    @staticmethod
def Pow(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:

if expr.base.func == exp:
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.args[0]/I/pi
return

if odd is not None:
return not odd
return

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 expr.exp.is_Rational and \
return True
return True
return False

Rational, Float, Pi, Exp1, GoldenRatio, TribonacciConstant, Abs, re, im = \
[staticmethod(CommonHandler.AlwaysTrue)]*9

ImaginaryUnit, Infinity, NegativeInfinity = \
[staticmethod(CommonHandler.AlwaysFalse)]*3

@staticmethod
def sin(expr, assumptions):
return True

cos = sin

@staticmethod
def exp(expr, assumptions):

@staticmethod
def log(expr, assumptions):

@staticmethod
def MatrixElement(expr, assumptions):

Determinant = Trace = MatrixElement

"""
Handler for Q.extended_real
Test that an expression belongs to the field of extended real numbers,
that is real numbers union {Infinity, -Infinity}
"""

@staticmethod
return test_closed_group(expr, assumptions, Q.extended_real)

Infinity, NegativeInfinity = [staticmethod(CommonHandler.AlwaysTrue)]*2

"""
Handler for Q.hermitian
Test that an expression belongs to the field of Hermitian operators
"""

[docs]    @staticmethod
"""
Hermitian + Hermitian  -> Hermitian
Hermitian + !Hermitian -> !Hermitian
"""
if expr.is_number:
return test_closed_group(expr, assumptions, Q.hermitian)

[docs]    @staticmethod
def Mul(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:
nccount = 0
result = True
for arg in expr.args:
result = result ^ True
break
nccount += 1
if nccount > 1:
break
else:
return result

[docs]    @staticmethod
def Pow(expr, assumptions):
"""
Hermitian**Integer -> Hermitian
"""
if expr.is_number:
return True

@staticmethod
def sin(expr, assumptions):
return True

cos, exp = [sin]*2

"""
Handler for Q.complex
Test that an expression belongs to the field of complex numbers
"""

@staticmethod
def Expr(expr, assumptions):
return expr.is_complex

@staticmethod
return test_closed_group(expr, assumptions, Q.complex)

Number, sin, cos, log, exp, re, im, NumberSymbol, Abs, ImaginaryUnit = \
[staticmethod(CommonHandler.AlwaysTrue)]*10 # they are all complex functions or expressions

Infinity, NegativeInfinity = [staticmethod(CommonHandler.AlwaysFalse)]*2

@staticmethod
def MatrixElement(expr, assumptions):

Determinant = Trace = MatrixElement

"""
Handler for Q.imaginary
Test that an expression belongs to the field of imaginary numbers,
that is, numbers in the form x*I, where x is real
"""

@staticmethod
def Expr(expr, assumptions):
return expr.is_imaginary

@staticmethod
def _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

[docs]    @staticmethod
"""
Imaginary + Imaginary -> Imaginary
Imaginary + Complex   -> ?
Imaginary + Real      -> !Imaginary
"""
if expr.is_number:

reals = 0
for arg in expr.args:
pass
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

[docs]    @staticmethod
def Mul(expr, assumptions):
"""
Real*Imaginary      -> Imaginary
Imaginary*Imaginary -> Real
"""
if expr.is_number:
result = False
reals = 0
for arg in expr.args:
result = result ^ True
break
else:
if reals == len(expr.args):
return False
return result

[docs]    @staticmethod
def Pow(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:

if expr.base.func == exp:
return False
i = expr.base.args[0]/I/pi

if odd is not None:
return odd
return

if imlog is not None:
return False  # I**i -> real; (2*I)**i -> complex ==> not imaginary

return False
else:
if not rat:
return rat
return False
else:
if half:
return half

@staticmethod
def log(expr, assumptions):
return False
return
# XXX it should be enough to do
# 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:
if expr.args[0].args[0] in [I, -I]:
return True
if im is False:
return False

@staticmethod
def exp(expr, assumptions):
a = expr.args[0]/I/pi

@staticmethod
def Number(expr, assumptions):
return not (expr.as_real_imag()[1] == 0)

NumberSymbol = Number

ImaginaryUnit = staticmethod(CommonHandler.AlwaysTrue)

"""
Handler for Q.antihermitian
Test that an expression belongs to the field of anti-Hermitian operators,
that is, operators in the form x*I, where x is Hermitian
"""

[docs]    @staticmethod
"""
Antihermitian + Antihermitian  -> Antihermitian
Antihermitian + !Antihermitian -> !Antihermitian
"""
if expr.is_number:
return test_closed_group(expr, assumptions, Q.antihermitian)

[docs]    @staticmethod
def Mul(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:
nccount = 0
result = False
for arg in expr.args:
result = result ^ True
break
nccount += 1
if nccount > 1:
break
else:
return result

[docs]    @staticmethod
def Pow(expr, assumptions):
"""
Hermitian**Integer  -> !Antihermitian
Antihermitian**Even -> !Antihermitian
Antihermitian**Odd  -> Antihermitian
"""
if expr.is_number:
return False
return False
return True

"""Handler for Q.algebraic key. """

@staticmethod
return test_closed_group(expr, assumptions, Q.algebraic)

@staticmethod
def Mul(expr, assumptions):
return test_closed_group(expr, assumptions, Q.algebraic)

@staticmethod
def Pow(expr, assumptions):
Q.algebraic(expr.base), assumptions)

@staticmethod
def Rational(expr, assumptions):
return expr.q != 0

Float, GoldenRatio, TribonacciConstant, ImaginaryUnit, AlgebraicNumber = \
[staticmethod(CommonHandler.AlwaysTrue)]*5

Infinity, NegativeInfinity, ComplexInfinity, Pi, Exp1 = \
[staticmethod(CommonHandler.AlwaysFalse)]*5

@staticmethod
def exp(expr, assumptions):
x = expr.args[0]

@staticmethod
def cot(expr, assumptions):
x = expr.args[0]