Source code for sympy.assumptions.handlers.ntheory

"""
Handlers for keys related to number theory: prime, even, odd, etc.
"""
from __future__ import print_function, division

from sympy.assumptions import Q, ask
from sympy.assumptions.handlers import CommonHandler
from sympy.ntheory import isprime
from sympy.core import S, Float


[docs]class AskPrimeHandler(CommonHandler): """ Handler for key 'prime' Test that an expression represents a prime number. When the expression is an exact number, the result (when True) is subject to the limitations of isprime() which is used to return the result. """ @staticmethod def Expr(expr, assumptions): return expr.is_prime @staticmethod def _number(expr, assumptions): # helper method exact = not expr.atoms(Float) try: i = int(expr.round()) if (expr - i).equals(0) is False: raise TypeError except TypeError: return False if exact: return isprime(i) # when not exact, we won't give a True or False # since the number represents an approximate value @staticmethod def Basic(expr, assumptions): if expr.is_number: return AskPrimeHandler._number(expr, assumptions) @staticmethod def Mul(expr, assumptions): if expr.is_number: return AskPrimeHandler._number(expr, assumptions) for arg in expr.args: if not ask(Q.integer(arg), assumptions): return None for arg in expr.args: if arg.is_number and arg.is_composite: return False
[docs] @staticmethod def Pow(expr, assumptions): """ Integer**Integer -> !Prime """ if expr.is_number: return AskPrimeHandler._number(expr, assumptions) if ask(Q.integer(expr.exp), assumptions) and \ ask(Q.integer(expr.base), assumptions): return False
@staticmethod def Integer(expr, assumptions): return isprime(expr) Rational, Infinity, NegativeInfinity, ImaginaryUnit = [staticmethod(CommonHandler.AlwaysFalse)]*4 @staticmethod def Float(expr, assumptions): return AskPrimeHandler._number(expr, assumptions) @staticmethod def NumberSymbol(expr, assumptions): return AskPrimeHandler._number(expr, assumptions)
class AskCompositeHandler(CommonHandler): @staticmethod def Expr(expr, assumptions): return expr.is_composite @staticmethod def Basic(expr, assumptions): _positive = ask(Q.positive(expr), assumptions) if _positive: _integer = ask(Q.integer(expr), assumptions) if _integer: _prime = ask(Q.prime(expr), assumptions) if _prime is None: return # Positive integer which is not prime is not # necessarily composite if expr.equals(1): return False return not _prime else: return _integer else: return _positive class AskEvenHandler(CommonHandler): @staticmethod def Expr(expr, assumptions): return expr.is_even @staticmethod def _number(expr, assumptions): # helper method try: i = int(expr.round()) if not (expr - i).equals(0): raise TypeError except TypeError: return False if isinstance(expr, (float, Float)): return False return i % 2 == 0 @staticmethod def Basic(expr, assumptions): if expr.is_number: return AskEvenHandler._number(expr, assumptions) @staticmethod def Mul(expr, assumptions): """ Even * Integer -> Even Even * Odd -> Even Integer * Odd -> ? Odd * Odd -> Odd Even * Even -> Even Integer * Integer -> Even if Integer + Integer = Odd otherwise -> ? """ if expr.is_number: return AskEvenHandler._number(expr, assumptions) even, odd, irrational, acc = False, 0, False, 1 for arg in expr.args: # check for all integers and at least one even if ask(Q.integer(arg), assumptions): if ask(Q.even(arg), assumptions): even = True elif ask(Q.odd(arg), assumptions): odd += 1 elif not even and acc != 1: if ask(Q.odd(acc + arg), assumptions): even = True elif ask(Q.irrational(arg), assumptions): # one irrational makes the result False # two makes it undefined if irrational: break irrational = True else: break acc = arg else: if irrational: return False if even: return True if odd == len(expr.args): return False @staticmethod def Add(expr, assumptions): """ Even + Odd -> Odd Even + Even -> Even Odd + Odd -> Even """ if expr.is_number: return AskEvenHandler._number(expr, assumptions) _result = True for arg in expr.args: if ask(Q.even(arg), assumptions): pass elif ask(Q.odd(arg), assumptions): _result = not _result else: break else: return _result @staticmethod def Pow(expr, assumptions): if expr.is_number: return AskEvenHandler._number(expr, assumptions) if ask(Q.integer(expr.exp), assumptions): if ask(Q.positive(expr.exp), assumptions): return ask(Q.even(expr.base), assumptions) elif ask(~Q.negative(expr.exp) & Q.odd(expr.base), assumptions): return False elif expr.base is S.NegativeOne: return False @staticmethod def Integer(expr, assumptions): return not bool(expr.p & 1) Rational, Infinity, NegativeInfinity, ImaginaryUnit = [staticmethod(CommonHandler.AlwaysFalse)]*4 @staticmethod def NumberSymbol(expr, assumptions): return AskEvenHandler._number(expr, assumptions) @staticmethod def Abs(expr, assumptions): if ask(Q.real(expr.args[0]), assumptions): return ask(Q.even(expr.args[0]), assumptions) @staticmethod def re(expr, assumptions): if ask(Q.real(expr.args[0]), assumptions): return ask(Q.even(expr.args[0]), assumptions) @staticmethod def im(expr, assumptions): if ask(Q.real(expr.args[0]), assumptions): return True
[docs]class AskOddHandler(CommonHandler): """ Handler for key 'odd' Test that an expression represents an odd number """ @staticmethod def Expr(expr, assumptions): return expr.is_odd @staticmethod def Basic(expr, assumptions): _integer = ask(Q.integer(expr), assumptions) if _integer: _even = ask(Q.even(expr), assumptions) if _even is None: return None return not _even return _integer