Repository: sympy/sympy
File: sympy/assumptions/handlers/sets.py (Python)

Code before:
    * !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):
        is_base_rational = ask(Q.rational(expr.base),assumptions)
        if is_base_rational is True:
            if ask(Q.ne(expr.base,0),assumptions):
                return True
            if ask(Q.eq(expr.base,0),assumptions) and ask(Q.positive(expr.exp)) is True:
                return True
            return
        return is_base_rational
    elif ask(Q.rational(expr.exp), assumptions):
        if ask(Q.prime(expr.base), assumptions):
            return False
        if ask(Q.rational(expr.base),assumptions) is False:
            return False
        if ask(Q.eq(expr.base,1) | Q.eq(expr.base,-1)):
            return True
        if ask(Q.eq(expr.base,0)) and ask(Q.positive(expr.exp)) is True:
            return True

@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)

Review comment (bug):
I'm pretty sure you don't need to make both of these checks
- ask(Q.ne(expr.base,0),assumptions)
- ask(Q.eq(expr.base,0),assumptions)

If you saved the result of one of them, you'd know what the result of the other would be. (Although, I suppose there might be a quirk with `ask` where one of these returns None but the other doesn't. That would not lead to wrong results though.)

Code after:
    * !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.zero(x), assumptions)
        return

    is_exp_integer = ask(Q.integer(expr.exp), assumptions)
    if is_exp_integer:
        is_base_rational = ask(Q.rational(expr.base),assumptions)
        if is_base_rational:
            is_base_zero = ask(Q.zero(expr.base),assumptions)
            if is_base_zero is False:
                return True
            if is_base_zero and ask(Q.positive(expr.exp)):
                return True
        if ask(Q.algebraic(expr.base),assumptions) is False:
            return ask(Q.zero(expr.exp), assumptions)
        if ask(Q.irrational(expr.base),assumptions) and ask(Q.eq(expr.exp,-1)):
            return False
        return
    elif ask(Q.rational(expr.exp), assumptions):
        if ask(Q.prime(expr.base), assumptions) and is_exp_integer is False:
            return False
        if ask(Q.zero(expr.base)) and ask(Q.positive(expr.exp)):
            return True
        if ask(Q.eq(expr.base,1)):
            return True

@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