def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if all(ask(Q.invertible(arg), assumptions) for arg in mmul.args): return True if any(ask(Q.invertible(arg), assumptions) is False for arg in mmul.args): return False
def Mul(expr, assumptions): """ Integer*Integer -> Integer Integer*Irrational -> !Integer Odd/Even -> !Integer Integer*Rational -> ? """ if expr.is_number: return AskIntegerHandler._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 else: return _output
def MatPow(expr, assumptions): # only for integer powers base, exp = expr.args int_exp = ask(Q.integer(exp), assumptions) if int_exp: return ask(Q.unitary(base), assumptions) return None
def refine_atan2(expr, assumptions): """ Handler for the atan2 function Examples ======== >>> from sympy import Symbol, Q, refine, atan2 >>> from sympy.assumptions.refine import refine_atan2 >>> from sympy.abc import x, y >>> refine_atan2(atan2(y,x), Q.real(y) & Q.positive(x)) atan(y/x) >>> refine_atan2(atan2(y,x), Q.negative(y) & Q.negative(x)) atan(y/x) - pi >>> refine_atan2(atan2(y,x), Q.positive(y) & Q.negative(x)) atan(y/x) + pi """ from sympy.functions.elementary.complexes import atan from sympy.core import S y, x = expr.args if ask(Q.real(y) & Q.positive(x), assumptions): return atan(y / x) elif ask(Q.negative(y) & Q.negative(x), assumptions): return atan(y / x) - S.Pi elif ask(Q.positive(y) & Q.negative(x), assumptions): return atan(y / x) + S.Pi else: return expr
def refine_abs(expr, assumptions): """ Handler for the absolute value. Examples ======== >>> from sympy import Symbol, Q, refine, Abs >>> from sympy.assumptions.refine import refine_abs >>> from sympy.abc import x >>> refine_abs(Abs(x), Q.real(x)) >>> refine_abs(Abs(x), Q.positive(x)) x >>> refine_abs(Abs(x), Q.negative(x)) -x """ from sympy.core.logic import fuzzy_not arg = expr.args[0] if ask(Q.real(arg), assumptions) and fuzzy_not(ask(Q.negative(arg), assumptions)): # if it's nonnegative return arg if ask(Q.negative(arg), assumptions): return -arg
def Basic(expr, assumptions): _real = ask(expr, Q.real, assumptions) if _real: _rational = ask(expr, Q.rational, assumptions) if _rational is None: return None return not _rational else: return _real
def Mul(expr, assumptions): """ Return True if expr is bounded, False if not and None if unknown. TRUTH TABLE B U ? s /s +---+---+---+---+ B | B | U | ? | legend: +---+---+---+---+ B = Bounded U | U | U | ? | U = Unbounded +---+---+---+ ? = unknown boundedness ? | ? | s = signed (hence nonzero) +---+---+ /s = not signed """ result = True for arg in expr.args: _bounded = ask(Q.bounded(arg), assumptions) if _bounded: continue elif _bounded is None: if result is None: return None if ask(Q.nonzero(arg), assumptions) is None: return None if result is not False: result = None else: result = False return result
def test_functions_in_assumptions(): from sympy.logic.boolalg import Equivalent, Xor x = symbols("x") assert ask(x, Q.negative, Q.real(x) >> Q.positive(x)) is False assert ask(x, Q.negative, Equivalent(Q.real(x), Q.positive(x))) is False assert ask(x, Q.negative, Xor(Q.real(x), Q.negative(x))) is False
def refine_exp(expr, assumptions): """ Handler for exponential function. >>> from sympy import Symbol, Q, exp, I, pi >>> from sympy.assumptions.refine import refine_exp >>> from sympy.abc import x >>> refine_exp(exp(pi*I*2*x), Q.real(x)) >>> refine_exp(exp(pi*I*2*x), Q.integer(x)) 1 """ arg = expr.args[0] if arg.is_Mul: coeff = arg.as_coefficient(S.Pi*S.ImaginaryUnit) if coeff: if ask(Q.integer(2*coeff), assumptions): if ask(Q.even(coeff), assumptions): return S.One elif ask(Q.odd(coeff), assumptions): return S.NegativeOne elif ask(Q.even(coeff + S.Half), assumptions): return -S.ImaginaryUnit elif ask(Q.odd(coeff + S.Half), assumptions): return S.ImaginaryUnit
def test_extended_real(): x = symbols('x') assert ask(x, Q.extended_real, Assume(x, Q.positive)) == True assert ask(-x, Q.extended_real, Assume(x, Q.positive)) == True assert ask(-x, Q.extended_real, Assume(x, Q.negative)) == True assert ask(x+S.Infinity, Q.extended_real, Assume(x, Q.real)) == True
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
def refine_Pow(expr, assumptions): """ Handler for instances of Pow. >>> from sympy import Symbol, Assume, Q >>> from sympy.assumptions.refine import refine_Pow >>> from sympy.abc import x >>> refine_Pow((-1)**x, Assume(x, Q.real)) >>> refine_Pow((-1)**x, Assume(x, Q.even)) 1 >>> refine_Pow((-1)**x, Assume(x, Q.odd)) -1 """ from sympy.core import Pow, Rational from sympy.functions import sign if ask(expr.base, Q.real, assumptions): if expr.base.is_number: if ask(expr.exp, Q.even, assumptions): return abs(expr.base) ** expr.exp if ask(expr.exp, Q.odd, assumptions): return sign(expr.base) * abs(expr.base) ** expr.exp if isinstance(expr.exp, Rational): if type(expr.base) is Pow: return abs(expr.base.base) ** (expr.base.exp * expr.exp)
def MatPow(expr, assumptions): # only for integer powers base, exp = expr.args int_exp = ask(Q.integer(exp), assumptions) if int_exp and ask(~Q.negative(exp), assumptions): return ask(Q.fullrank(base), assumptions) return None
def Mul(expr, assumptions): """ Even * Integer -> Even Even * Odd -> Even Integer * Odd -> ? Odd * Odd -> Odd """ if expr.is_number: return AskEvenHandler._number(expr, assumptions) even, odd, irrational = False, 0, False 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 ask(Q.irrational(arg), assumptions): # one irrational makes the result False # two makes it undefined if irrational: break irrational = True else: break else: if irrational: return False if even: return True if odd == len(expr.args): return False
def test_extended_real(): x = symbols('x') assert ask(Q.extended_real(x), Q.positive(x)) == True assert ask(Q.extended_real(-x), Q.positive(x)) == True assert ask(Q.extended_real(-x), Q.negative(x)) == True assert ask(Q.extended_real(x+S.Infinity), Q.real(x)) == True
def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if (all(ask(Q.orthogonal(arg), assumptions) for arg in mmul.args) and factor == 1): return True if any(ask(Q.invertible(arg), assumptions) == False for arg in mmul.args): return False
def test_remove_safe(): global_assumptions.add(Q.integer(x)) with assuming(): assert ask(Q.integer(x)) global_assumptions.remove(Q.integer(x)) assert not ask(Q.integer(x)) assert ask(Q.integer(x)) global_assumptions.clear() # for the benefit of other tests
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
def test_custom_context(): """Test ask with custom assumptions context""" x = symbols('x') assert ask(x, Q.integer) == None local_context = AssumptionsContext() local_context.add(Assume(x, Q.integer)) assert ask(x, Q.integer, context = local_context) == True assert ask(x, Q.integer) == None
def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if (all(ask(Q.positive_definite(arg), assumptions) for arg in mmul.args) and factor > 0): return True if len(mmul.args) >= 2 and mmul.args[0] == mmul.args[-1].T: return ask(Q.positive_definite( MatMul(*mmul.args[1:-1])), assumptions)
def test_global(): """Test ask with global assumptions""" x = symbols('x') assert ask(x, Q.integer) == None global_assumptions.add(Assume(x, Q.integer)) assert ask(x, Q.integer) == True global_assumptions.clear() assert ask(x, Q.integer) == None
def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if all(ask(Q.symmetric(arg), assumptions) for arg in mmul.args): return True if len(mmul.args) >= 2 and mmul.args[0] == mmul.args[-1].T: if len(mmul.args) == 2: return True return ask(Q.symmetric(MatMul(*mmul.args[1:-1])), assumptions)
def log(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 Pow(expr, assumptions): """ Hermitian**Integer -> Hermitian """ if expr.is_number: return AskRealHandler._number(expr, assumptions) if ask(Q.hermitian(expr.base), assumptions): if ask(Q.integer(expr.exp), assumptions): return True
def MatPow(expr, assumptions): # only for integer powers base, exp = expr.args int_exp = ask(Q.integer(exp), assumptions) if not int_exp: return None if exp.is_negative == False: return ask(Q.integer_elements(base), assumptions) return None
def Equivalent(expr, assumptions): p, q = expr.args pt = ask(p, assumptions=assumptions) if pt is None: return None qt = ask(q, assumptions=assumptions) if qt is None: return None return pt == qt
def MatrixSlice(expr, assumptions): # TODO: implement sathandlers system for the matrices. # Now it duplicates the general fact: Implies(Q.diagonal, Q.symmetric). if ask(Q.diagonal(expr), assumptions): return True if not expr.on_diag: return None else: return ask(Q.symmetric(expr.parent), assumptions)
def Pow(expr, assumptions): if expr.is_number: return expr.evalf() > 0 if ask(expr.base, Q.positive, assumptions): return True if ask(expr.base, Q.negative, assumptions): if ask(expr.exp, Q.even, assumptions): return True if ask(expr.exp, Q.even, assumptions): return False
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
def Mul(expr, assumptions): if expr.is_number: return AskPositiveHandler._number(expr, assumptions) result = True for arg in expr.args: if ask(arg, Q.positive, assumptions): continue elif ask(arg, Q.negative, assumptions): result = result ^ True else: return return result
def _(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.invertible(expr.parent), assumptions)
def _(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.positive_definite(expr.parent), assumptions)
def MatAdd(expr, assumptions): return all(ask(Q.symmetric(arg), assumptions) for arg in expr.args)
def MS_elements(predicate, expr, assumptions): """ Matrix Slice elements """ return ask(predicate(expr.parent), assumptions)
def sin(expr, assumptions): if ask(expr.args[0], Q.real, assumptions): return True
def Abs(expr, assumptions): return ask(expr.args[0], Q.integer, assumptions)
def _(expr, assumptions): factor, matrices = expr.as_coeff_matrices() if all(ask(Q.upper_triangular(m), assumptions) for m in matrices): return True
def _(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.unitary(expr.parent), assumptions)
def _(expr, assumptions): if all(ask(Q.fullrank(arg), assumptions) for arg in expr.args): return True
def _(expr, assumptions): return ask(Q.fullrank(expr.arg), assumptions)
def _(expr, assumptions): if ask(Q.orthogonal(expr.parent), assumptions): return True
def _(expr, assumptions): # a power of a positive definite matrix is positive definite if ask(Q.positive_definite(expr.args[0]), assumptions): return True
def _(expr, assumptions): if all(ask(Q.positive_definite(arg), assumptions) for arg in expr.args): return True
def _(expr, assumptions): return ask(Q.invertible(expr.arg), assumptions)
def _(expr, assumptions): if all(ask(Q.upper_triangular(arg), assumptions) for arg in expr.args): return True
def _(expr, assumptions): return ask(Q.unitary(expr.arg), assumptions)
def _(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if all(ask(Q.invertible(arg), assumptions) for arg in mmul.args): return True if any(ask(Q.invertible(arg), assumptions) is False for arg in mmul.args): return False
def _(expr, assumptions): return ask(Q.upper_triangular(expr.arg), assumptions)
def Pow(expr, assumptions): return expr.exp.is_Rational and ask(expr.base, 'algebraic', assumptions)
def Transpose(expr, assumptions): return ask(Q.symmetric(expr.arg), assumptions)
def _(expr, assumptions): if (not expr.is_square or ask(Q.invertible(expr), assumptions) is False): return False if Q.unitary(expr) in conjuncts(assumptions): return True
def _(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.upper_triangular(expr.parent), assumptions)
def _(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.orthogonal(expr.parent), assumptions)
def _(expr, assumptions): return ask(Q.orthogonal(expr.arg), assumptions)
def _is_coeff(factor): return ask(Q.algebraic(factor))
def _(expr, assumptions): if (len(expr.args) == 1 and ask(Q.orthogonal(expr.args[0]), assumptions)): return True
def ZeroMatrix(expr, assumptions): return ask(Q.square(expr), assumptions)
def _(expr, assumptions): if expr.rowblocksizes != expr.colblocksizes: return None return fuzzy_and([ask(Q.invertible(a), assumptions) for a in expr.diag])
def BM_elements(predicate, expr, assumptions): """ Block Matrix elements """ return all(ask(predicate(b), assumptions) for b in expr.blocks)
def _(expr, assumptions): return ask(Q.positive_definite(expr.arg), assumptions)