def test_contains_4(): assert Order(sin(1 / x**2)).contains(Order(cos(1 / x**2))) is True assert Order(cos(1 / x**2)).contains(Order(sin(1 / x**2))) is True
def test_Order(): assert precedence(Order(x)) == PRECEDENCE["Atom"]
def test_contains_3(): assert Order(x * y**2).contains(Order(x**2 * y)) is None assert Order(x**2 * y).contains(Order(x * y**2)) is None
def test_free_symbols(): assert Order(1).free_symbols == set() assert Order(x).free_symbols == {x} assert Order(1, x).free_symbols == {x} assert Order(x * y).free_symbols == {x, y} assert Order(x, x, y).free_symbols == {x, y}
def test_simple_1(): o = Rational(0) assert Order(2 * x) == Order(x) assert Order(x) * 3 == Order(x) assert -28 * Order(x) == Order(x) assert Order(Order(x)) == Order(x) assert Order(Order(x), y) == Order(Order(x), x, y) assert Order(-23) == Order(1) assert Order(exp(x)) == Order(1, x) assert Order(exp(1 / x)).expr == exp(1 / x) assert Order(x * exp(1 / x)).expr == x * exp(1 / x) assert Order(x**(o / 3)).expr == x**(o / 3) assert Order(x**(o * Rational(5, 3))).expr == x**(o * Rational(5, 3)) assert Order(x**2 + x + y, x) == O(1, x) assert Order(x**2 + x + y, y) == O(1, y) raises(ValueError, lambda: Order(exp(x), x, x)) raises(TypeError, lambda: Order(x, 2 - x))
def test_multivar_0a(): assert Order(exp(1 / x) * exp(1 / y)).expr == exp(1 / x) * exp(1 / y)
def test_multivar_mul_1(): assert Order(x + y) * x == Order(x**2 + y * x, x, y)
def doit(self, **hints): """Evaluates the limit. Parameters ========== deep : bool, optional (default: True) Invoke the ``doit`` method of the expressions involved before taking the limit. hints : optional keyword arguments To be passed to ``doit`` methods; only used if deep is True. """ from sympy.functions import RisingFactorial e, z, z0, dir = self.args if z0 is S.ComplexInfinity: raise NotImplementedError("Limits at complex " "infinity are not implemented") if hints.get('deep', True): e = e.doit(**hints) z = z.doit(**hints) z0 = z0.doit(**hints) if e == z: return z0 if not e.has(z): return e # gruntz fails on factorials but works with the gamma function # If no factorial term is present, e should remain unchanged. # factorial is defined to be zero for negative inputs (which # differs from gamma) so only rewrite for positive z0. if z0.is_extended_positive: e = e.rewrite([factorial, RisingFactorial], gamma) if e.is_Mul: if abs(z0) is S.Infinity: e = factor_terms(e) e = e.rewrite(fibonacci, GoldenRatio) ok = lambda w: (z in w.free_symbols and any( a.is_polynomial(z) or any( z in m.free_symbols and m.is_polynomial(z) for m in Mul.make_args(a)) for a in Add.make_args(w))) if all(ok(w) for w in e.as_numer_denom()): u = Dummy(positive=True) if z0 is S.NegativeInfinity: inve = e.subs(z, -1 / u) else: inve = e.subs(z, 1 / u) try: r = limit(inve.as_leading_term(u), u, S.Zero, "+") if isinstance(r, Limit): return self else: return r except ValueError: pass if e.is_Order: return Order(limit(e.expr, z, z0), *e.args[1:]) l = None try: if str(dir) == '+-': r = gruntz(e, z, z0, '+') l = gruntz(e, z, z0, '-') if l != r: raise ValueError( "The limit does not exist since " "left hand limit = %s and right hand limit = %s" % (l, r)) else: r = gruntz(e, z, z0, dir) if r is S.NaN or l is S.NaN: raise PoleError() except (PoleError, ValueError): if l is not None: raise r = heuristics(e, z, z0, dir) if r is None: return self return r
def truncate(self, n=6): ffps = self.ffps pt_xk = ffps.xk.coeff(n) x, x0 = ffps.x, ffps.x0 return self.polynomial(n) + Order(pt_xk, (x, x0))
def doit(self, **hints): """Evaluates limit""" from sympy.series.limitseq import limit_seq from sympy.functions import RisingFactorial e, z, z0, dir = self.args if hints.get('deep', True): e = e.doit(**hints) z = z.doit(**hints) z0 = z0.doit(**hints) if e == z: return z0 if not e.has(z): return e # gruntz fails on factorials but works with the gamma function # If no factorial term is present, e should remain unchanged. # factorial is defined to be zero for negative inputs (which # differs from gamma) so only rewrite for positive z0. if z0.is_positive: e = e.rewrite([factorial, RisingFactorial], gamma) if e.is_Mul: if abs(z0) is S.Infinity: e = factor_terms(e) ok = lambda w: (z in w.free_symbols and any( a.is_polynomial(z) or any( z in m.free_symbols and m.is_polynomial(z) for m in Mul.make_args(a)) for a in Add.make_args(w))) if all(ok(w) for w in e.as_numer_denom()): u = Dummy(positive=(z0 is S.Infinity)) inve = e.subs(z, 1 / u) r = limit(inve.as_leading_term(u), u, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(r, Limit): return self else: return r if e.is_Order: return Order(limit(e.expr, z, z0), *e.args[1:]) try: r = gruntz(e, z, z0, dir) if r is S.NaN: raise PoleError() except (PoleError, ValueError): r = heuristics(e, z, z0, dir) if r is None: return self except NotImplementedError: # Trying finding limits of sequences if hints.get('sequence', True) and z0 is S.Infinity: trials = hints.get('trials', 5) r = limit_seq(e, z, trials) if r is None: raise NotImplementedError() else: raise NotImplementedError() return r
def test_series(): e = Symbol("e") x = Symbol("x") for c in (Limit, Limit(e, x, 1), Order, Order(e)): check(c)
def doit(self, **hints): """Evaluates the limit. Parameters ========== deep : bool, optional (default: True) Invoke the ``doit`` method of the expressions involved before taking the limit. hints : optional keyword arguments To be passed to ``doit`` methods; only used if deep is True. """ e, z, z0, dir = self.args if z0 is S.ComplexInfinity: raise NotImplementedError("Limits at complex " "infinity are not implemented") if hints.get('deep', True): e = e.doit(**hints) z = z.doit(**hints) z0 = z0.doit(**hints) if e == z: return z0 if not e.has(z): return e if z0 is S.NaN: return S.NaN if e.has(*_illegal): return self if e.is_Order: return Order(limit(e.expr, z, z0), *e.args[1:]) cdir = 0 if str(dir) == "+": cdir = 1 elif str(dir) == "-": cdir = -1 def set_signs(expr): if not expr.args: return expr newargs = tuple(set_signs(arg) for arg in expr.args) if newargs != expr.args: expr = expr.func(*newargs) abs_flag = isinstance(expr, Abs) sign_flag = isinstance(expr, sign) if abs_flag or sign_flag: sig = limit(expr.args[0], z, z0, dir) if sig.is_zero: sig = limit(1/expr.args[0], z, z0, dir) if sig.is_extended_real: if (sig < 0) == True: return -expr.args[0] if abs_flag else S.NegativeOne elif (sig > 0) == True: return expr.args[0] if abs_flag else S.One return expr if e.has(Float): # Convert floats like 0.5 to exact SymPy numbers like S.Half, to # prevent rounding errors which can lead to unexpected execution # of conditional blocks that work on comparisons # Also see comments in https://github.com/sympy/sympy/issues/19453 from sympy.simplify.simplify import nsimplify e = nsimplify(e) e = set_signs(e) if e.is_meromorphic(z, z0): if abs(z0) is S.Infinity: newe = e.subs(z, 1/z) # cdir changes sign as oo- should become 0+ cdir = -cdir else: newe = e.subs(z, z + z0) try: coeff, ex = newe.leadterm(z, cdir=cdir) except ValueError: pass else: if ex > 0: return S.Zero elif ex == 0: return coeff if cdir == 1 or not(int(ex) & 1): return S.Infinity*sign(coeff) elif cdir == -1: return S.NegativeInfinity*sign(coeff) else: return S.ComplexInfinity if abs(z0) is S.Infinity: if e.is_Mul: e = factor_terms(e) newe = e.subs(z, 1/z) # cdir changes sign as oo- should become 0+ cdir = -cdir else: newe = e.subs(z, z + z0) try: coeff, ex = newe.leadterm(z, cdir=cdir) except (ValueError, NotImplementedError, PoleError): # The NotImplementedError catching is for custom functions from sympy.simplify.powsimp import powsimp e = powsimp(e) if e.is_Pow: r = self.pow_heuristics(e) if r is not None: return r else: if coeff.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity): return self if not coeff.has(z): if ex.is_positive: return S.Zero elif ex == 0: return coeff elif ex.is_negative: if ex.is_integer: if cdir == 1 or ex.is_even: return S.Infinity*sign(coeff) elif cdir == -1: return S.NegativeInfinity*sign(coeff) else: return S.ComplexInfinity else: if cdir == 1: return S.Infinity*sign(coeff) elif cdir == -1: return S.Infinity*sign(coeff)*S.NegativeOne**ex else: return S.ComplexInfinity # gruntz fails on factorials but works with the gamma function # If no factorial term is present, e should remain unchanged. # factorial is defined to be zero for negative inputs (which # differs from gamma) so only rewrite for positive z0. if z0.is_extended_positive: e = e.rewrite(factorial, gamma) l = None try: if str(dir) == '+-': r = gruntz(e, z, z0, '+') l = gruntz(e, z, z0, '-') if l != r: raise ValueError("The limit does not exist since " "left hand limit = %s and right hand limit = %s" % (l, r)) else: r = gruntz(e, z, z0, dir) if r is S.NaN or l is S.NaN: raise PoleError() except (PoleError, ValueError): if l is not None: raise r = heuristics(e, z, z0, dir) if r is None: return self return r
def test_basic1(): assert limit(x, x, oo) is oo assert limit(x, x, -oo) is -oo assert limit(-x, x, oo) is -oo assert limit(x**2, x, -oo) is oo assert limit(-x**2, x, oo) is -oo assert limit(x * log(x), x, 0, dir="+") == 0 assert limit(1 / x, x, oo) == 0 assert limit(exp(x), x, oo) is oo assert limit(-exp(x), x, oo) is -oo assert limit(exp(x) / x, x, oo) is oo assert limit(1 / x - exp(-x), x, oo) == 0 assert limit(x + 1 / x, x, oo) is oo assert limit(x - x**2, x, oo) is -oo assert limit((1 + x)**(1 + sqrt(2)), x, 0) == 1 assert limit((1 + x)**oo, x, 0) == Limit((x + 1)**oo, x, 0) assert limit((1 + x)**oo, x, 0, dir='-') == Limit((x + 1)**oo, x, 0, dir='-') assert limit((1 + x + y)**oo, x, 0, dir='-') == Limit((x + y + 1)**oo, x, 0, dir='-') assert limit(y / x / log(x), x, 0) == -oo * sign(y) assert limit(cos(x + y) / x, x, 0) == sign(cos(y)) * oo assert limit(gamma(1 / x + 3), x, oo) == 2 assert limit(S.NaN, x, -oo) is S.NaN assert limit(Order(2) * x, x, S.NaN) is S.NaN assert limit(1 / (x - 1), x, 1, dir="+") is oo assert limit(1 / (x - 1), x, 1, dir="-") is -oo assert limit(1 / (5 - x)**3, x, 5, dir="+") is -oo assert limit(1 / (5 - x)**3, x, 5, dir="-") is oo assert limit(1 / sin(x), x, pi, dir="+") is -oo assert limit(1 / sin(x), x, pi, dir="-") is oo assert limit(1 / cos(x), x, pi / 2, dir="+") is -oo assert limit(1 / cos(x), x, pi / 2, dir="-") is oo assert limit(1 / tan(x**3), x, (2 * pi)**Rational(1, 3), dir="+") is oo assert limit(1 / tan(x**3), x, (2 * pi)**Rational(1, 3), dir="-") is -oo assert limit(1 / cot(x)**3, x, (pi * Rational(3, 2)), dir="+") is -oo assert limit(1 / cot(x)**3, x, (pi * Rational(3, 2)), dir="-") is oo # test bi-directional limits assert limit(sin(x) / x, x, 0, dir="+-") == 1 assert limit(x**2, x, 0, dir="+-") == 0 assert limit(1 / x**2, x, 0, dir="+-") is oo # test failing bi-directional limits assert limit(1 / x, x, 0, dir="+-") is zoo # approaching 0 # from dir="+" assert limit(1 + 1 / x, x, 0) is oo # from dir='-' # Add assert limit(1 + 1 / x, x, 0, dir='-') is -oo # Pow assert limit(x**(-2), x, 0, dir='-') is oo assert limit(x**(-3), x, 0, dir='-') is -oo assert limit(1 / sqrt(x), x, 0, dir='-') == (-oo) * I assert limit(x**2, x, 0, dir='-') == 0 assert limit(sqrt(x), x, 0, dir='-') == 0 assert limit(x**-pi, x, 0, dir='-') == oo * sign((-1)**(-pi)) assert limit((1 + cos(x))**oo, x, 0) == Limit((cos(x) + 1)**oo, x, 0)
def doit(self, **hints): """Evaluates the limit. Parameters ========== deep : bool, optional (default: True) Invoke the ``doit`` method of the expressions involved before taking the limit. hints : optional keyword arguments To be passed to ``doit`` methods; only used if deep is True. """ from sympy import sign from sympy.functions import RisingFactorial e, z, z0, dir = self.args if z0 is S.ComplexInfinity: raise NotImplementedError("Limits at complex " "infinity are not implemented") if hints.get('deep', True): e = e.doit(**hints) z = z.doit(**hints) z0 = z0.doit(**hints) if e == z: return z0 if not e.has(z): return e if e.is_meromorphic(z, z0): if abs(z0) is S.Infinity: newe = e.subs(z, -1/z) else: newe = e.subs(z, z + z0) try: coeff, exp = newe.leadterm(z) if coeff is not S.ComplexInfinity: if exp > 0: return S.Zero elif exp == 0: return coeff if str(dir) == "+" or not(int(exp) & 1): return S.Infinity*sign(coeff) elif str(dir) == "-": return S.NegativeInfinity*sign(coeff) else: return S.ComplexInfinity except ValueError: pass # gruntz fails on factorials but works with the gamma function # If no factorial term is present, e should remain unchanged. # factorial is defined to be zero for negative inputs (which # differs from gamma) so only rewrite for positive z0. if z0.is_extended_positive: e = e.rewrite([factorial, RisingFactorial], gamma) if e.is_Mul and abs(z0) is S.Infinity: e = factor_terms(e) u = Dummy('u', positive=True) if z0 is S.NegativeInfinity: inve = e.subs(z, -1/u) else: inve = e.subs(z, 1/u) try: f = inve.as_leading_term(u) if f.is_meromorphic(u, S.Zero): r = limit(f, u, S.Zero, "+") if isinstance(r, Limit): return self else: return r except (ValueError, NotImplementedError, PoleError): pass if e.is_Order: return Order(limit(e.expr, z, z0), *e.args[1:]) l = None try: if str(dir) == '+-': r = gruntz(e, z, z0, '+') l = gruntz(e, z, z0, '-') if l != r: raise ValueError("The limit does not exist since " "left hand limit = %s and right hand limit = %s" % (l, r)) else: r = gruntz(e, z, z0, dir) if r is S.NaN or l is S.NaN: raise PoleError() except (PoleError, ValueError): if l is not None: raise r = heuristics(e, z, z0, dir) if r is None: return self return r
def test_contains(): assert Order(1, x) not in Order(1) assert Order(1) in Order(1, x) raises(TypeError, lambda: Order(x * y**2) in Order(x**2 * y))
def test_order_oo(): x = Symbol('x', positive=True) assert Order(x)*oo != Order(1, x) assert limit(oo/(x**2 - 4), x, oo) is oo
def test_add_1(): assert Order(x + x) == Order(x) assert Order(3 * x - 2 * x**2) == Order(x) assert Order(1 + x) == Order(1, x) assert Order(1 + 1 / x) == Order(1 / x) assert Order(log(x) + 1 / log(x)) == Order(log(x)) assert Order(exp(1 / x) + x) == Order(exp(1 / x)) assert Order(exp(1 / x) + 1 / x**20) == Order(exp(1 / x))
def test_as_expr_variables(): assert Order(x).as_expr_variables(None) == (x, ((x, 0), )) assert Order(x).as_expr_variables(((x, 0), )) == (x, ((x, 0), )) assert Order(y).as_expr_variables(((x, 0), )) == (y, ((x, 0), (y, 0))) assert Order(y).as_expr_variables( ((x, 0), (y, 0))) == (y, ((x, 0), (y, 0)))
def test_multivar_2(): assert Order(x**2 * y + y**2 * x, x, y).expr == x**2 * y + y**2 * x
def test_contains_0(): assert Order(1, x).contains(Order(1, x)) assert Order(1, x).contains(Order(1)) assert Order(1).contains(Order(1, x)) is False
def test_multivar_3(): assert (Order(x) + Order(y)).args in [(Order(x), Order(y)), (Order(y), Order(x))] assert Order(x) + Order(y) + Order(x + y) == Order(x + y) assert (Order(x**2 * y) + Order(y**2 * x)).args in [ (Order(x * y**2), Order(y * x**2)), (Order(y * x**2), Order(x * y**2)) ] assert (Order(x**2 * y) + Order(y * x)) == Order(x * y)
def test_contains_1(): assert Order(x).contains(Order(x)) assert Order(x).contains(Order(x**2)) assert not Order(x**2).contains(Order(x)) assert not Order(x).contains(Order(1 / x)) assert not Order(1 / x).contains(Order(exp(1 / x))) assert not Order(x).contains(Order(exp(1 / x))) assert Order(1 / x).contains(Order(x)) assert Order(exp(1 / x)).contains(Order(x)) assert Order(exp(1 / x)).contains(Order(1 / x)) assert Order(exp(1 / x)).contains(Order(exp(1 / x))) assert Order(exp(2 / x)).contains(Order(exp(1 / x))) assert not Order(exp(1 / x)).contains(Order(exp(2 / x)))
def test_eval(): assert Order(x).subs(Order(x), 1) == 1 assert Order(x).subs(x, y) == Order(y) assert Order(x).subs(y, x) == Order(x) assert Order(x).subs(x, x + y) == Order(x + y, (x, -y)) assert (O(1)**x).is_Pow
def test_contains_2(): assert Order(x).contains(Order(y)) is None assert Order(x).contains(Order(y * x)) assert Order(y * x).contains(Order(x)) assert Order(y).contains(Order(x * y)) assert Order(x).contains(Order(y**2 * x))
def test_order_conjugate_transpose(): x = Symbol('x', real=True) y = Symbol('y', imaginary=True) assert conjugate(Order(x)) == Order(conjugate(x)) assert conjugate(Order(y)) == Order(conjugate(y)) assert conjugate(Order(x**2)) == Order(conjugate(x)**2) assert conjugate(Order(y**2)) == Order(conjugate(y)**2) assert transpose(Order(x)) == Order(transpose(x)) assert transpose(Order(y)) == Order(transpose(y)) assert transpose(Order(x**2)) == Order(transpose(x)**2) assert transpose(Order(y**2)) == Order(transpose(y)**2)
def doit(self, **hints): """Evaluates the limit. Parameters ========== deep : bool, optional (default: True) Invoke the ``doit`` method of the expressions involved before taking the limit. hints : optional keyword arguments To be passed to ``doit`` methods; only used if deep is True. """ from sympy import Abs, exp, log, sign from sympy.calculus.util import AccumBounds from sympy.functions import RisingFactorial e, z, z0, dir = self.args if z0 is S.ComplexInfinity: raise NotImplementedError("Limits at complex " "infinity are not implemented") if hints.get('deep', True): e = e.doit(**hints) z = z.doit(**hints) z0 = z0.doit(**hints) if e == z: return z0 if not e.has(z): return e cdir = 0 if str(dir) == "+": cdir = 1 elif str(dir) == "-": cdir = -1 def remove_abs(expr): if not expr.args: return expr newargs = tuple(remove_abs(arg) for arg in expr.args) if newargs != expr.args: expr = expr.func(*newargs) if isinstance(expr, Abs): sig = limit(expr.args[0], z, z0, dir) if sig.is_zero: sig = limit(1/expr.args[0], z, z0, dir) if sig.is_extended_real: if (sig < 0) == True: return -expr.args[0] elif (sig > 0) == True: return expr.args[0] return expr e = remove_abs(e) if e.is_meromorphic(z, z0): if abs(z0) is S.Infinity: newe = e.subs(z, -1/z) else: newe = e.subs(z, z + z0) try: coeff, ex = newe.leadterm(z, cdir) except ValueError: pass else: if ex > 0: return S.Zero elif ex == 0: return coeff if str(dir) == "+" or not(int(ex) & 1): return S.Infinity*sign(coeff) elif str(dir) == "-": return S.NegativeInfinity*sign(coeff) else: return S.ComplexInfinity # gruntz fails on factorials but works with the gamma function # If no factorial term is present, e should remain unchanged. # factorial is defined to be zero for negative inputs (which # differs from gamma) so only rewrite for positive z0. if z0.is_extended_positive: e = e.rewrite([factorial, RisingFactorial], gamma) if e.is_Mul and abs(z0) is S.Infinity: e = factor_terms(e) u = Dummy('u', positive=True) if z0 is S.NegativeInfinity: inve = e.subs(z, -1/u) else: inve = e.subs(z, 1/u) try: f = inve.as_leading_term(u).gammasimp() if f.is_meromorphic(u, S.Zero): r = limit(f, u, S.Zero, "+") if isinstance(r, Limit): return self else: return r except (ValueError, NotImplementedError, PoleError): pass if e.is_Order: return Order(limit(e.expr, z, z0), *e.args[1:]) if e.is_Pow: if e.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity, S.NaN): return self b1, e1 = e.base, e.exp f1 = e1*log(b1) if f1.is_meromorphic(z, z0): res = limit(f1, z, z0) return exp(res) ex_lim = limit(e1, z, z0) base_lim = limit(b1, z, z0) if base_lim is S.One: if ex_lim in (S.Infinity, S.NegativeInfinity): res = limit(e1*(b1 - 1), z, z0) return exp(res) elif ex_lim.is_real: return S.One if base_lim in (S.Zero, S.Infinity, S.NegativeInfinity) and ex_lim is S.Zero: res = limit(f1, z, z0) return exp(res) if base_lim is S.NegativeInfinity: if ex_lim is S.NegativeInfinity: return S.Zero if ex_lim is S.Infinity: return S.ComplexInfinity if not isinstance(base_lim, AccumBounds) and not isinstance(ex_lim, AccumBounds): res = base_lim**ex_lim if res is not S.ComplexInfinity and not res.is_Pow: return res l = None try: if str(dir) == '+-': r = gruntz(e, z, z0, '+') l = gruntz(e, z, z0, '-') if l != r: raise ValueError("The limit does not exist since " "left hand limit = %s and right hand limit = %s" % (l, r)) else: r = gruntz(e, z, z0, dir) if r is S.NaN or l is S.NaN: raise PoleError() except (PoleError, ValueError): if l is not None: raise r = heuristics(e, z, z0, dir) if r is None: return self return r