337 lines
11 KiB
Python
337 lines
11 KiB
Python
from sympy.core.numbers import (E, Rational, oo, pi, zoo)
|
|
from sympy.core.singleton import S
|
|
from sympy.core.symbol import Symbol
|
|
from sympy.functions.elementary.exponential import (exp, log)
|
|
from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt)
|
|
from sympy.functions.elementary.trigonometric import (cos, sin, tan)
|
|
from sympy.calculus.accumulationbounds import AccumBounds
|
|
from sympy.core import Add, Mul, Pow
|
|
from sympy.core.expr import unchanged
|
|
from sympy.testing.pytest import raises, XFAIL
|
|
from sympy.abc import x
|
|
|
|
a = Symbol('a', real=True)
|
|
B = AccumBounds
|
|
|
|
|
|
def test_AccumBounds():
|
|
assert B(1, 2).args == (1, 2)
|
|
assert B(1, 2).delta is S.One
|
|
assert B(1, 2).mid == Rational(3, 2)
|
|
assert B(1, 3).is_real == True
|
|
|
|
assert B(1, 1) is S.One
|
|
|
|
assert B(1, 2) + 1 == B(2, 3)
|
|
assert 1 + B(1, 2) == B(2, 3)
|
|
assert B(1, 2) + B(2, 3) == B(3, 5)
|
|
|
|
assert -B(1, 2) == B(-2, -1)
|
|
|
|
assert B(1, 2) - 1 == B(0, 1)
|
|
assert 1 - B(1, 2) == B(-1, 0)
|
|
assert B(2, 3) - B(1, 2) == B(0, 2)
|
|
|
|
assert x + B(1, 2) == Add(B(1, 2), x)
|
|
assert a + B(1, 2) == B(1 + a, 2 + a)
|
|
assert B(1, 2) - x == Add(B(1, 2), -x)
|
|
|
|
assert B(-oo, 1) + oo == B(-oo, oo)
|
|
assert B(1, oo) + oo is oo
|
|
assert B(1, oo) - oo == B(-oo, oo)
|
|
assert (-oo - B(-1, oo)) is -oo
|
|
assert B(-oo, 1) - oo is -oo
|
|
|
|
assert B(1, oo) - oo == B(-oo, oo)
|
|
assert B(-oo, 1) - (-oo) == B(-oo, oo)
|
|
assert (oo - B(1, oo)) == B(-oo, oo)
|
|
assert (-oo - B(1, oo)) is -oo
|
|
|
|
assert B(1, 2)/2 == B(S.Half, 1)
|
|
assert 2/B(2, 3) == B(Rational(2, 3), 1)
|
|
assert 1/B(-1, 1) == B(-oo, oo)
|
|
|
|
assert abs(B(1, 2)) == B(1, 2)
|
|
assert abs(B(-2, -1)) == B(1, 2)
|
|
assert abs(B(-2, 1)) == B(0, 2)
|
|
assert abs(B(-1, 2)) == B(0, 2)
|
|
c = Symbol('c')
|
|
raises(ValueError, lambda: B(0, c))
|
|
raises(ValueError, lambda: B(1, -1))
|
|
r = Symbol('r', real=True)
|
|
raises(ValueError, lambda: B(r, r - 1))
|
|
|
|
|
|
def test_AccumBounds_mul():
|
|
assert B(1, 2)*2 == B(2, 4)
|
|
assert 2*B(1, 2) == B(2, 4)
|
|
assert B(1, 2)*B(2, 3) == B(2, 6)
|
|
assert B(0, 2)*B(2, oo) == B(0, oo)
|
|
l, r = B(-oo, oo), B(-a, a)
|
|
assert l*r == B(-oo, oo)
|
|
assert r*l == B(-oo, oo)
|
|
l, r = B(1, oo), B(-3, -2)
|
|
assert l*r == B(-oo, -2)
|
|
assert r*l == B(-oo, -2)
|
|
assert B(1, 2)*0 == 0
|
|
assert B(1, oo)*0 == B(0, oo)
|
|
assert B(-oo, 1)*0 == B(-oo, 0)
|
|
assert B(-oo, oo)*0 == B(-oo, oo)
|
|
|
|
assert B(1, 2)*x == Mul(B(1, 2), x, evaluate=False)
|
|
|
|
assert B(0, 2)*oo == B(0, oo)
|
|
assert B(-2, 0)*oo == B(-oo, 0)
|
|
assert B(0, 2)*(-oo) == B(-oo, 0)
|
|
assert B(-2, 0)*(-oo) == B(0, oo)
|
|
assert B(-1, 1)*oo == B(-oo, oo)
|
|
assert B(-1, 1)*(-oo) == B(-oo, oo)
|
|
assert B(-oo, oo)*oo == B(-oo, oo)
|
|
|
|
|
|
def test_AccumBounds_div():
|
|
assert B(-1, 3)/B(3, 4) == B(Rational(-1, 3), 1)
|
|
assert B(-2, 4)/B(-3, 4) == B(-oo, oo)
|
|
assert B(-3, -2)/B(-4, 0) == B(S.Half, oo)
|
|
|
|
# these two tests can have a better answer
|
|
# after Union of B is improved
|
|
assert B(-3, -2)/B(-2, 1) == B(-oo, oo)
|
|
assert B(2, 3)/B(-2, 2) == B(-oo, oo)
|
|
|
|
assert B(-3, -2)/B(0, 4) == B(-oo, Rational(-1, 2))
|
|
assert B(2, 4)/B(-3, 0) == B(-oo, Rational(-2, 3))
|
|
assert B(2, 4)/B(0, 3) == B(Rational(2, 3), oo)
|
|
|
|
assert B(0, 1)/B(0, 1) == B(0, oo)
|
|
assert B(-1, 0)/B(0, 1) == B(-oo, 0)
|
|
assert B(-1, 2)/B(-2, 2) == B(-oo, oo)
|
|
|
|
assert 1/B(-1, 2) == B(-oo, oo)
|
|
assert 1/B(0, 2) == B(S.Half, oo)
|
|
assert (-1)/B(0, 2) == B(-oo, Rational(-1, 2))
|
|
assert 1/B(-oo, 0) == B(-oo, 0)
|
|
assert 1/B(-1, 0) == B(-oo, -1)
|
|
assert (-2)/B(-oo, 0) == B(0, oo)
|
|
assert 1/B(-oo, -1) == B(-1, 0)
|
|
|
|
assert B(1, 2)/a == Mul(B(1, 2), 1/a, evaluate=False)
|
|
|
|
assert B(1, 2)/0 == B(1, 2)*zoo
|
|
assert B(1, oo)/oo == B(0, oo)
|
|
assert B(1, oo)/(-oo) == B(-oo, 0)
|
|
assert B(-oo, -1)/oo == B(-oo, 0)
|
|
assert B(-oo, -1)/(-oo) == B(0, oo)
|
|
assert B(-oo, oo)/oo == B(-oo, oo)
|
|
assert B(-oo, oo)/(-oo) == B(-oo, oo)
|
|
assert B(-1, oo)/oo == B(0, oo)
|
|
assert B(-1, oo)/(-oo) == B(-oo, 0)
|
|
assert B(-oo, 1)/oo == B(-oo, 0)
|
|
assert B(-oo, 1)/(-oo) == B(0, oo)
|
|
|
|
|
|
def test_issue_18795():
|
|
r = Symbol('r', real=True)
|
|
a = B(-1,1)
|
|
c = B(7, oo)
|
|
b = B(-oo, oo)
|
|
assert c - tan(r) == B(7-tan(r), oo)
|
|
assert b + tan(r) == B(-oo, oo)
|
|
assert (a + r)/a == B(-oo, oo)*B(r - 1, r + 1)
|
|
assert (b + a)/a == B(-oo, oo)
|
|
|
|
|
|
def test_AccumBounds_func():
|
|
assert (x**2 + 2*x + 1).subs(x, B(-1, 1)) == B(-1, 4)
|
|
assert exp(B(0, 1)) == B(1, E)
|
|
assert exp(B(-oo, oo)) == B(0, oo)
|
|
assert log(B(3, 6)) == B(log(3), log(6))
|
|
|
|
|
|
@XFAIL
|
|
def test_AccumBounds_powf():
|
|
nn = Symbol('nn', nonnegative=True)
|
|
assert B(1 + nn, 2 + nn)**B(1, 2) == B(1 + nn, (2 + nn)**2)
|
|
i = Symbol('i', integer=True, negative=True)
|
|
assert B(1, 2)**i == B(2**i, 1)
|
|
|
|
|
|
def test_AccumBounds_pow():
|
|
assert B(0, 2)**2 == B(0, 4)
|
|
assert B(-1, 1)**2 == B(0, 1)
|
|
assert B(1, 2)**2 == B(1, 4)
|
|
assert B(-1, 2)**3 == B(-1, 8)
|
|
assert B(-1, 1)**0 == 1
|
|
|
|
assert B(1, 2)**Rational(5, 2) == B(1, 4*sqrt(2))
|
|
assert B(0, 2)**S.Half == B(0, sqrt(2))
|
|
|
|
neg = Symbol('neg', negative=True)
|
|
assert unchanged(Pow, B(neg, 1), S.Half)
|
|
nn = Symbol('nn', nonnegative=True)
|
|
assert B(nn, nn + 1)**S.Half == B(sqrt(nn), sqrt(nn + 1))
|
|
assert B(nn, nn + 1)**nn == B(nn**nn, (nn + 1)**nn)
|
|
assert unchanged(Pow, B(nn, nn + 1), x)
|
|
i = Symbol('i', integer=True)
|
|
assert B(1, 2)**i == B(Min(1, 2**i), Max(1, 2**i))
|
|
i = Symbol('i', integer=True, nonnegative=True)
|
|
assert B(1, 2)**i == B(1, 2**i)
|
|
assert B(0, 1)**i == B(0**i, 1)
|
|
|
|
assert B(1, 5)**(-2) == B(Rational(1, 25), 1)
|
|
assert B(-1, 3)**(-2) == B(0, oo)
|
|
assert B(0, 2)**(-3) == B(Rational(1, 8), oo)
|
|
assert B(-2, 0)**(-3) == B(-oo, -Rational(1, 8))
|
|
assert B(0, 2)**(-2) == B(Rational(1, 4), oo)
|
|
assert B(-1, 2)**(-3) == B(-oo, oo)
|
|
assert B(-3, -2)**(-3) == B(Rational(-1, 8), Rational(-1, 27))
|
|
assert B(-3, -2)**(-2) == B(Rational(1, 9), Rational(1, 4))
|
|
assert B(0, oo)**S.Half == B(0, oo)
|
|
assert B(-oo, 0)**(-2) == B(0, oo)
|
|
assert B(-2, 0)**(-2) == B(Rational(1, 4), oo)
|
|
|
|
assert B(Rational(1, 3), S.Half)**oo is S.Zero
|
|
assert B(0, S.Half)**oo is S.Zero
|
|
assert B(S.Half, 1)**oo == B(0, oo)
|
|
assert B(0, 1)**oo == B(0, oo)
|
|
assert B(2, 3)**oo is oo
|
|
assert B(1, 2)**oo == B(0, oo)
|
|
assert B(S.Half, 3)**oo == B(0, oo)
|
|
assert B(Rational(-1, 3), Rational(-1, 4))**oo is S.Zero
|
|
assert B(-1, Rational(-1, 2))**oo is S.NaN
|
|
assert B(-3, -2)**oo is zoo
|
|
assert B(-2, -1)**oo is S.NaN
|
|
assert B(-2, Rational(-1, 2))**oo is S.NaN
|
|
assert B(Rational(-1, 2), S.Half)**oo is S.Zero
|
|
assert B(Rational(-1, 2), 1)**oo == B(0, oo)
|
|
assert B(Rational(-2, 3), 2)**oo == B(0, oo)
|
|
assert B(-1, 1)**oo == B(-oo, oo)
|
|
assert B(-1, S.Half)**oo == B(-oo, oo)
|
|
assert B(-1, 2)**oo == B(-oo, oo)
|
|
assert B(-2, S.Half)**oo == B(-oo, oo)
|
|
|
|
assert B(1, 2)**x == Pow(B(1, 2), x, evaluate=False)
|
|
|
|
assert B(2, 3)**(-oo) is S.Zero
|
|
assert B(0, 2)**(-oo) == B(0, oo)
|
|
assert B(-1, 2)**(-oo) == B(-oo, oo)
|
|
|
|
assert (tan(x)**sin(2*x)).subs(x, B(0, pi/2)) == \
|
|
Pow(B(-oo, oo), B(0, 1))
|
|
|
|
|
|
def test_AccumBounds_exponent():
|
|
# base is 0
|
|
z = 0**B(a, a + S.Half)
|
|
assert z.subs(a, 0) == B(0, 1)
|
|
assert z.subs(a, 1) == 0
|
|
p = z.subs(a, -1)
|
|
assert p.is_Pow and p.args == (0, B(-1, -S.Half))
|
|
# base > 0
|
|
# when base is 1 the type of bounds does not matter
|
|
assert 1**B(a, a + 1) == 1
|
|
# otherwise we need to know if 0 is in the bounds
|
|
assert S.Half**B(-2, 2) == B(S(1)/4, 4)
|
|
assert 2**B(-2, 2) == B(S(1)/4, 4)
|
|
|
|
# +eps may introduce +oo
|
|
# if there is a negative integer exponent
|
|
assert B(0, 1)**B(S(1)/2, 1) == B(0, 1)
|
|
assert B(0, 1)**B(0, 1) == B(0, 1)
|
|
|
|
# positive bases have positive bounds
|
|
assert B(2, 3)**B(-3, -2) == B(S(1)/27, S(1)/4)
|
|
assert B(2, 3)**B(-3, 2) == B(S(1)/27, 9)
|
|
|
|
# bounds generating imaginary parts unevaluated
|
|
assert unchanged(Pow, B(-1, 1), B(1, 2))
|
|
assert B(0, S(1)/2)**B(1, oo) == B(0, S(1)/2)
|
|
assert B(0, 1)**B(1, oo) == B(0, oo)
|
|
assert B(0, 2)**B(1, oo) == B(0, oo)
|
|
assert B(0, oo)**B(1, oo) == B(0, oo)
|
|
assert B(S(1)/2, 1)**B(1, oo) == B(0, oo)
|
|
assert B(S(1)/2, 1)**B(-oo, -1) == B(0, oo)
|
|
assert B(S(1)/2, 1)**B(-oo, oo) == B(0, oo)
|
|
assert B(S(1)/2, 2)**B(1, oo) == B(0, oo)
|
|
assert B(S(1)/2, 2)**B(-oo, -1) == B(0, oo)
|
|
assert B(S(1)/2, 2)**B(-oo, oo) == B(0, oo)
|
|
assert B(S(1)/2, oo)**B(1, oo) == B(0, oo)
|
|
assert B(S(1)/2, oo)**B(-oo, -1) == B(0, oo)
|
|
assert B(S(1)/2, oo)**B(-oo, oo) == B(0, oo)
|
|
assert B(1, 2)**B(1, oo) == B(0, oo)
|
|
assert B(1, 2)**B(-oo, -1) == B(0, oo)
|
|
assert B(1, 2)**B(-oo, oo) == B(0, oo)
|
|
assert B(1, oo)**B(1, oo) == B(0, oo)
|
|
assert B(1, oo)**B(-oo, -1) == B(0, oo)
|
|
assert B(1, oo)**B(-oo, oo) == B(0, oo)
|
|
assert B(2, oo)**B(1, oo) == B(2, oo)
|
|
assert B(2, oo)**B(-oo, -1) == B(0, S(1)/2)
|
|
assert B(2, oo)**B(-oo, oo) == B(0, oo)
|
|
|
|
|
|
def test_comparison_AccumBounds():
|
|
assert (B(1, 3) < 4) == S.true
|
|
assert (B(1, 3) < -1) == S.false
|
|
assert (B(1, 3) < 2).rel_op == '<'
|
|
assert (B(1, 3) <= 2).rel_op == '<='
|
|
|
|
assert (B(1, 3) > 4) == S.false
|
|
assert (B(1, 3) > -1) == S.true
|
|
assert (B(1, 3) > 2).rel_op == '>'
|
|
assert (B(1, 3) >= 2).rel_op == '>='
|
|
|
|
assert (B(1, 3) < B(4, 6)) == S.true
|
|
assert (B(1, 3) < B(2, 4)).rel_op == '<'
|
|
assert (B(1, 3) < B(-2, 0)) == S.false
|
|
|
|
assert (B(1, 3) <= B(4, 6)) == S.true
|
|
assert (B(1, 3) <= B(-2, 0)) == S.false
|
|
|
|
assert (B(1, 3) > B(4, 6)) == S.false
|
|
assert (B(1, 3) > B(-2, 0)) == S.true
|
|
|
|
assert (B(1, 3) >= B(4, 6)) == S.false
|
|
assert (B(1, 3) >= B(-2, 0)) == S.true
|
|
|
|
# issue 13499
|
|
assert (cos(x) > 0).subs(x, oo) == (B(-1, 1) > 0)
|
|
|
|
c = Symbol('c')
|
|
raises(TypeError, lambda: (B(0, 1) < c))
|
|
raises(TypeError, lambda: (B(0, 1) <= c))
|
|
raises(TypeError, lambda: (B(0, 1) > c))
|
|
raises(TypeError, lambda: (B(0, 1) >= c))
|
|
|
|
|
|
def test_contains_AccumBounds():
|
|
assert (1 in B(1, 2)) == S.true
|
|
raises(TypeError, lambda: a in B(1, 2))
|
|
assert 0 in B(-1, 0)
|
|
raises(TypeError, lambda:
|
|
(cos(1)**2 + sin(1)**2 - 1) in B(-1, 0))
|
|
assert (-oo in B(1, oo)) == S.true
|
|
assert (oo in B(-oo, 0)) == S.true
|
|
|
|
# issue 13159
|
|
assert Mul(0, B(-1, 1)) == Mul(B(-1, 1), 0) == 0
|
|
import itertools
|
|
for perm in itertools.permutations([0, B(-1, 1), x]):
|
|
assert Mul(*perm) == 0
|
|
|
|
|
|
def test_intersection_AccumBounds():
|
|
assert B(0, 3).intersection(B(1, 2)) == B(1, 2)
|
|
assert B(0, 3).intersection(B(1, 4)) == B(1, 3)
|
|
assert B(0, 3).intersection(B(-1, 2)) == B(0, 2)
|
|
assert B(0, 3).intersection(B(-1, 4)) == B(0, 3)
|
|
assert B(0, 1).intersection(B(2, 3)) == S.EmptySet
|
|
raises(TypeError, lambda: B(0, 3).intersection(1))
|
|
|
|
|
|
def test_union_AccumBounds():
|
|
assert B(0, 3).union(B(1, 2)) == B(0, 3)
|
|
assert B(0, 3).union(B(1, 4)) == B(0, 4)
|
|
assert B(0, 3).union(B(-1, 2)) == B(-1, 3)
|
|
assert B(0, 3).union(B(-1, 4)) == B(-1, 4)
|
|
raises(TypeError, lambda: B(0, 3).union(1))
|