Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /sympy /series /limits.py
| from sympy.calculus.accumulationbounds import AccumBounds | |
| from sympy.core import S, Symbol, Add, sympify, Expr, PoleError, Mul | |
| from sympy.core.exprtools import factor_terms | |
| from sympy.core.numbers import Float, _illegal | |
| from sympy.core.function import AppliedUndef | |
| from sympy.core.symbol import Dummy | |
| from sympy.functions.combinatorial.factorials import factorial | |
| from sympy.functions.elementary.complexes import (Abs, sign, arg, re) | |
| from sympy.functions.elementary.exponential import (exp, log) | |
| from sympy.functions.special.gamma_functions import gamma | |
| from sympy.polys import PolynomialError, factor | |
| from sympy.series.order import Order | |
| from .gruntz import gruntz | |
| def limit(e, z, z0, dir="+"): | |
| """Computes the limit of ``e(z)`` at the point ``z0``. | |
| Parameters | |
| ========== | |
| e : expression, the limit of which is to be taken | |
| z : symbol representing the variable in the limit. | |
| Other symbols are treated as constants. Multivariate limits | |
| are not supported. | |
| z0 : the value toward which ``z`` tends. Can be any expression, | |
| including ``oo`` and ``-oo``. | |
| dir : string, optional (default: "+") | |
| The limit is bi-directional if ``dir="+-"``, from the right | |
| (z->z0+) if ``dir="+"``, and from the left (z->z0-) if | |
| ``dir="-"``. For infinite ``z0`` (``oo`` or ``-oo``), the ``dir`` | |
| argument is determined from the direction of the infinity | |
| (i.e., ``dir="-"`` for ``oo``). | |
| Examples | |
| ======== | |
| >>> from sympy import limit, sin, oo | |
| >>> from sympy.abc import x | |
| >>> limit(sin(x)/x, x, 0) | |
| 1 | |
| >>> limit(1/x, x, 0) # default dir='+' | |
| oo | |
| >>> limit(1/x, x, 0, dir="-") | |
| -oo | |
| >>> limit(1/x, x, 0, dir='+-') | |
| zoo | |
| >>> limit(1/x, x, oo) | |
| 0 | |
| Notes | |
| ===== | |
| First we try some heuristics for easy and frequent cases like "x", "1/x", | |
| "x**2" and similar, so that it's fast. For all other cases, we use the | |
| Gruntz algorithm (see the gruntz() function). | |
| See Also | |
| ======== | |
| limit_seq : returns the limit of a sequence. | |
| """ | |
| return Limit(e, z, z0, dir).doit(deep=False) | |
| def heuristics(e, z, z0, dir): | |
| """Computes the limit of an expression term-wise. | |
| Parameters are the same as for the ``limit`` function. | |
| Works with the arguments of expression ``e`` one by one, computing | |
| the limit of each and then combining the results. This approach | |
| works only for simple limits, but it is fast. | |
| """ | |
| rv = None | |
| if z0 is S.Infinity: | |
| rv = limit(e.subs(z, 1/z), z, S.Zero, "+") | |
| if isinstance(rv, Limit): | |
| return | |
| elif (e.is_Mul or e.is_Add or e.is_Pow or (e.is_Function and not isinstance(e, AppliedUndef))): | |
| r = [] | |
| from sympy.simplify.simplify import together | |
| for a in e.args: | |
| l = limit(a, z, z0, dir) | |
| if l.has(S.Infinity) and l.is_finite is None: | |
| if isinstance(e, Add): | |
| m = factor_terms(e) | |
| if not isinstance(m, Mul): # try together | |
| m = together(m) | |
| if not isinstance(m, Mul): # try factor if the previous methods failed | |
| m = factor(e) | |
| if isinstance(m, Mul): | |
| return heuristics(m, z, z0, dir) | |
| return | |
| return | |
| elif isinstance(l, Limit): | |
| return | |
| elif l is S.NaN: | |
| return | |
| else: | |
| r.append(l) | |
| if r: | |
| rv = e.func(*r) | |
| if rv is S.NaN and e.is_Mul and any(isinstance(rr, AccumBounds) for rr in r): | |
| r2 = [] | |
| e2 = [] | |
| for ii, rval in enumerate(r): | |
| if isinstance(rval, AccumBounds): | |
| r2.append(rval) | |
| else: | |
| e2.append(e.args[ii]) | |
| if len(e2) > 0: | |
| e3 = Mul(*e2).simplify() | |
| l = limit(e3, z, z0, dir) | |
| rv = l * Mul(*r2) | |
| if rv is S.NaN: | |
| try: | |
| from sympy.simplify.ratsimp import ratsimp | |
| rat_e = ratsimp(e) | |
| except PolynomialError: | |
| return | |
| if rat_e is S.NaN or rat_e == e: | |
| return | |
| return limit(rat_e, z, z0, dir) | |
| return rv | |
| class Limit(Expr): | |
| """Represents an unevaluated limit. | |
| Examples | |
| ======== | |
| >>> from sympy import Limit, sin | |
| >>> from sympy.abc import x | |
| >>> Limit(sin(x)/x, x, 0) | |
| Limit(sin(x)/x, x, 0, dir='+') | |
| >>> Limit(1/x, x, 0, dir="-") | |
| Limit(1/x, x, 0, dir='-') | |
| """ | |
| def __new__(cls, e, z, z0, dir="+"): | |
| e = sympify(e) | |
| z = sympify(z) | |
| z0 = sympify(z0) | |
| if z0 in (S.Infinity, S.ImaginaryUnit*S.Infinity): | |
| dir = "-" | |
| elif z0 in (S.NegativeInfinity, S.ImaginaryUnit*S.NegativeInfinity): | |
| dir = "+" | |
| if(z0.has(z)): | |
| raise NotImplementedError("Limits approaching a variable point are" | |
| " not supported (%s -> %s)" % (z, z0)) | |
| if isinstance(dir, str): | |
| dir = Symbol(dir) | |
| elif not isinstance(dir, Symbol): | |
| raise TypeError("direction must be of type basestring or " | |
| "Symbol, not %s" % type(dir)) | |
| if str(dir) not in ('+', '-', '+-'): | |
| raise ValueError("direction must be one of '+', '-' " | |
| "or '+-', not %s" % dir) | |
| obj = Expr.__new__(cls) | |
| obj._args = (e, z, z0, dir) | |
| return obj | |
| def free_symbols(self): | |
| e = self.args[0] | |
| isyms = e.free_symbols | |
| isyms.difference_update(self.args[1].free_symbols) | |
| isyms.update(self.args[2].free_symbols) | |
| return isyms | |
| def pow_heuristics(self, e): | |
| _, z, z0, _ = self.args | |
| b1, e1 = e.base, e.exp | |
| if not b1.has(z): | |
| res = limit(e1*log(b1), 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) | |
| if base_lim is S.NegativeInfinity and ex_lim is S.Infinity: | |
| return S.ComplexInfinity | |
| 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 str(dir) == '+-': | |
| r = limit(e, z, z0, dir='+') | |
| l = limit(e, z, z0, dir='-') | |
| if isinstance(r, Limit) and isinstance(l, Limit): | |
| if r.args[0] == l.args[0]: | |
| return self | |
| if r == l: | |
| return l | |
| if r.is_infinite and l.is_infinite: | |
| return S.ComplexInfinity | |
| raise ValueError("The limit does not exist since " | |
| "left hand limit = %s and right hand limit = %s" | |
| % (l, r)) | |
| if z0 is S.ComplexInfinity: | |
| raise NotImplementedError("Limits at complex " | |
| "infinity are not implemented") | |
| if z0.is_infinite: | |
| cdir = sign(z0) | |
| cdir = cdir/abs(cdir) | |
| e = e.subs(z, cdir*z) | |
| dir = "-" | |
| z0 = S.Infinity | |
| 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 = S.Zero | |
| if str(dir) == "+": | |
| cdir = S.One | |
| elif str(dir) == "-": | |
| cdir = S.NegativeOne | |
| 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) | |
| arg_flag = isinstance(expr, arg) | |
| sign_flag = isinstance(expr, sign) | |
| if abs_flag or sign_flag or arg_flag: | |
| try: | |
| sig = limit(expr.args[0], z, z0, dir) | |
| if sig.is_zero: | |
| sig = limit(1/expr.args[0], z, z0, dir) | |
| except NotImplementedError: | |
| return expr | |
| else: | |
| if sig.is_extended_real: | |
| if (sig < 0) == True: | |
| return (-expr.args[0] if abs_flag else | |
| S.NegativeOne if sign_flag else S.Pi) | |
| elif (sig > 0) == True: | |
| return (expr.args[0] if abs_flag else | |
| S.One if sign_flag else S.Zero) | |
| 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 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 z0 is S.Infinity: | |
| if e.is_Mul: | |
| e = factor_terms(e) | |
| dummy = Dummy('z', positive=z.is_positive, negative=z.is_negative, real=z.is_real) | |
| newe = e.subs(z, 1/dummy) | |
| # cdir changes sign as oo- should become 0+ | |
| cdir = -cdir | |
| newz = dummy | |
| else: | |
| newe = e.subs(z, z + z0) | |
| newz = z | |
| try: | |
| coeff, ex = newe.leadterm(newz, 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 | |
| try: | |
| coeff = newe.as_leading_term(newz, cdir=cdir) | |
| if coeff != newe and (coeff.has(exp) or coeff.has(S.Exp1)): | |
| return gruntz(coeff, newz, 0, "-" if re(cdir).is_negative else "+") | |
| except (ValueError, NotImplementedError, PoleError): | |
| pass | |
| else: | |
| if isinstance(coeff, AccumBounds) and ex == S.Zero: | |
| return coeff | |
| if coeff.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity, S.NaN): | |
| return self | |
| if not coeff.has(newz): | |
| if ex.is_positive: | |
| return S.Zero | |
| elif ex == 0: | |
| return coeff | |
| elif ex.is_negative: | |
| if cdir == 1: | |
| return S.Infinity*sign(coeff) | |
| elif cdir == -1: | |
| return S.NegativeInfinity*sign(coeff)*S.NegativeOne**(S.One + ex) | |
| else: | |
| return S.ComplexInfinity | |
| else: | |
| raise NotImplementedError("Not sure of sign of %s" % ex) | |
| # 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 non-negative z0. | |
| if z0.is_extended_nonnegative: | |
| e = e.rewrite(factorial, gamma) | |
| l = None | |
| try: | |
| 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 | |
Xet Storage Details
- Size:
- 13.3 kB
- Xet hash:
- febdf10c03735c51938ffded161cad5ffd59d79ee3d56f62c6c9ba51fd806096
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.