def test_abs(): assert satask(Q.nonnegative(abs(x))) is True assert satask(Q.positive(abs(x)), ~Q.zero(x)) is True assert satask(Q.zero(x), ~Q.zero(abs(x))) is False assert satask(Q.zero(x), Q.zero(abs(x))) is True assert satask(Q.nonzero(x), ~Q.zero(abs(x))) is None # x could be complex assert satask(Q.zero(abs(x)), Q.zero(x)) is True
def _(expr): arg = expr.args[0] return [Q.nonnegative(expr), Equivalent(~Q.zero(arg), ~Q.zero(expr)), Q.even(arg) >> Q.even(expr), Q.odd(arg) >> Q.odd(expr), Q.integer(arg) >> Q.integer(expr), ]
def _(expr): base, exp = expr.base, expr.exp return [ (Q.real(base) & Q.even(exp) & Q.nonnegative(exp)) >> Q.nonnegative(expr), (Q.nonnegative(base) & Q.odd(exp) & Q.nonnegative(exp)) >> Q.nonnegative(expr), (Q.nonpositive(base) & Q.odd(exp) & Q.nonnegative(exp)) >> Q.nonpositive(expr), Equivalent(Q.zero(expr), Q.zero(base) & Q.positive(exp)) ]
def test_old_assump(): assert satask(Q.positive(1)) is True assert satask(Q.positive(-1)) is False assert satask(Q.positive(0)) is False assert satask(Q.positive(I)) is False assert satask(Q.positive(pi)) is True assert satask(Q.negative(1)) is False assert satask(Q.negative(-1)) is True assert satask(Q.negative(0)) is False assert satask(Q.negative(I)) is False assert satask(Q.negative(pi)) is False assert satask(Q.zero(1)) is False assert satask(Q.zero(-1)) is False assert satask(Q.zero(0)) is True assert satask(Q.zero(I)) is False assert satask(Q.zero(pi)) is False assert satask(Q.nonzero(1)) is True assert satask(Q.nonzero(-1)) is True assert satask(Q.nonzero(0)) is False assert satask(Q.nonzero(I)) is False assert satask(Q.nonzero(pi)) is True assert satask(Q.nonpositive(1)) is False assert satask(Q.nonpositive(-1)) is True assert satask(Q.nonpositive(0)) is True assert satask(Q.nonpositive(I)) is False assert satask(Q.nonpositive(pi)) is False assert satask(Q.nonnegative(1)) is True assert satask(Q.nonnegative(-1)) is False assert satask(Q.nonnegative(0)) is True assert satask(Q.nonnegative(I)) is False assert satask(Q.nonnegative(pi)) is True
def test_is_ge_le(): # test assumptions assert is_ge(x, S(0), Q.nonnegative(x)) is True assert is_ge(x, S(0), Q.negative(x)) is False # test registration class PowTest(Expr): def __new__(cls, base, exp): return Basic.__new__(cls, _sympify(base), _sympify(exp)) @dispatch(PowTest, PowTest) def _eval_is_ge(lhs, rhs): if type(lhs) == PowTest and type(rhs) == PowTest: return fuzzy_and([ is_ge(lhs.args[0], rhs.args[0]), is_ge(lhs.args[1], rhs.args[1]) ]) assert is_ge(PowTest(3, 9), PowTest(3, 2)) assert is_gt(PowTest(3, 9), PowTest(3, 2)) assert is_le(PowTest(3, 2), PowTest(3, 9)) assert is_lt(PowTest(3, 2), PowTest(3, 9))
def register_fact(klass, fact, registry=fact_registry): registry[klass] |= {fact} for klass, fact in [ (Mul, Equivalent(Q.zero, AnyArgs(Q.zero))), (MatMul, Implies(AllArgs(Q.square), Equivalent(Q.invertible, AllArgs(Q.invertible)))), (Add, Implies(AllArgs(Q.positive), Q.positive)), (Add, Implies(AllArgs(Q.negative), Q.negative)), (Mul, Implies(AllArgs(Q.positive), Q.positive)), (Mul, Implies(AllArgs(Q.commutative), Q.commutative)), (Mul, Implies(AllArgs(Q.real), Q.commutative)), (Pow, CustomLambda(lambda power: Implies(Q.real(power.base) & Q.even(power.exp) & Q.nonnegative(power.exp), Q.nonnegative(power)))), (Pow, CustomLambda(lambda power: Implies(Q.nonnegative(power.base) & Q.odd(power.exp) & Q.nonnegative(power.exp), Q.nonnegative(power)))), (Pow, CustomLambda(lambda power: Implies(Q.nonpositive(power.base) & Q.odd(power.exp) & Q.nonnegative(power.exp), Q.nonpositive(power)))), # This one can still be made easier to read. I think we need basic pattern # matching, so that we can just write Equivalent(Q.zero(x**y), Q.zero(x) & Q.positive(y)) (Pow, CustomLambda(lambda power: Equivalent(Q.zero(power), Q.zero(power.base) & Q.positive(power.exp)))), (Integer, CheckIsPrime(Q.prime)), # Implicitly assumes Mul has more than one arg # Would be AllArgs(Q.prime | Q.composite) except 1 is composite (Mul, Implies(AllArgs(Q.prime), ~Q.prime)), # More advanced prime assumptions will require inequalities, as 1 provides # a corner case. (Mul, Implies(AllArgs(Q.imaginary | Q.real), Implies(ExactlyOneArg(Q.imaginary), Q.imaginary))), (Mul, Implies(AllArgs(Q.real), Q.real)), (Add, Implies(AllArgs(Q.real), Q.real)),
registry[klass] |= {fact} for klass, fact in [ (Mul, Equivalent(Q.zero, AnyArgs(Q.zero))), (MatMul, Implies(AllArgs(Q.square), Equivalent(Q.invertible, AllArgs(Q.invertible)))), (Add, Implies(AllArgs(Q.positive), Q.positive)), (Add, Implies(AllArgs(Q.negative), Q.negative)), (Mul, Implies(AllArgs(Q.positive), Q.positive)), (Mul, Implies(AllArgs(Q.commutative), Q.commutative)), (Mul, Implies(AllArgs(Q.real), Q.commutative)), (Pow, CustomLambda(lambda power: Implies( Q.real(power.base) & Q.even(power.exp) & Q.nonnegative(power.exp), Q.nonnegative(power)))), (Pow, CustomLambda(lambda power: Implies( Q.nonnegative(power.base) & Q.odd(power.exp) & Q.nonnegative( power.exp), Q.nonnegative(power)))), (Pow, CustomLambda(lambda power: Implies( Q.nonpositive(power.base) & Q.odd(power.exp) & Q.nonnegative( power.exp), Q.nonpositive(power)))), # This one can still be made easier to read. I think we need basic pattern # matching, so that we can just write Equivalent(Q.zero(x**y), Q.zero(x) & Q.positive(y)) (Pow, CustomLambda( lambda power: Equivalent(Q.zero(power),
def test_pow_pos_neg(): assert satask(Q.nonnegative(x**2), Q.positive(x)) is True assert satask(Q.nonpositive(x**2), Q.positive(x)) is False assert satask(Q.positive(x**2), Q.positive(x)) is True assert satask(Q.negative(x**2), Q.positive(x)) is False assert satask(Q.real(x**2), Q.positive(x)) is True assert satask(Q.nonnegative(x**2), Q.negative(x)) is True assert satask(Q.nonpositive(x**2), Q.negative(x)) is False assert satask(Q.positive(x**2), Q.negative(x)) is True assert satask(Q.negative(x**2), Q.negative(x)) is False assert satask(Q.real(x**2), Q.negative(x)) is True assert satask(Q.nonnegative(x**2), Q.nonnegative(x)) is True assert satask(Q.nonpositive(x**2), Q.nonnegative(x)) is None assert satask(Q.positive(x**2), Q.nonnegative(x)) is None assert satask(Q.negative(x**2), Q.nonnegative(x)) is False assert satask(Q.real(x**2), Q.nonnegative(x)) is True assert satask(Q.nonnegative(x**2), Q.nonpositive(x)) is True assert satask(Q.nonpositive(x**2), Q.nonpositive(x)) is None assert satask(Q.positive(x**2), Q.nonpositive(x)) is None assert satask(Q.negative(x**2), Q.nonpositive(x)) is False assert satask(Q.real(x**2), Q.nonpositive(x)) is True assert satask(Q.nonnegative(x**3), Q.positive(x)) is True assert satask(Q.nonpositive(x**3), Q.positive(x)) is False assert satask(Q.positive(x**3), Q.positive(x)) is True assert satask(Q.negative(x**3), Q.positive(x)) is False assert satask(Q.real(x**3), Q.positive(x)) is True assert satask(Q.nonnegative(x**3), Q.negative(x)) is False assert satask(Q.nonpositive(x**3), Q.negative(x)) is True assert satask(Q.positive(x**3), Q.negative(x)) is False assert satask(Q.negative(x**3), Q.negative(x)) is True assert satask(Q.real(x**3), Q.negative(x)) is True assert satask(Q.nonnegative(x**3), Q.nonnegative(x)) is True assert satask(Q.nonpositive(x**3), Q.nonnegative(x)) is None assert satask(Q.positive(x**3), Q.nonnegative(x)) is None assert satask(Q.negative(x**3), Q.nonnegative(x)) is False assert satask(Q.real(x**3), Q.nonnegative(x)) is True assert satask(Q.nonnegative(x**3), Q.nonpositive(x)) is None assert satask(Q.nonpositive(x**3), Q.nonpositive(x)) is True assert satask(Q.positive(x**3), Q.nonpositive(x)) is False assert satask(Q.negative(x**3), Q.nonpositive(x)) is None assert satask(Q.real(x**3), Q.nonpositive(x)) is True # If x is zero, x**negative is not real. assert satask(Q.nonnegative(x**-2), Q.nonpositive(x)) is None assert satask(Q.nonpositive(x**-2), Q.nonpositive(x)) is None assert satask(Q.positive(x**-2), Q.nonpositive(x)) is None assert satask(Q.negative(x**-2), Q.nonpositive(x)) is None assert satask(Q.real(x**-2), Q.nonpositive(x)) is None