def _eval_rewrite_as_Sum(self, arg): if arg.is_even: k = C.Dummy("k", integer=True) j = C.Dummy("j", integer=True) n = self.args[0] / 2 Em = (S.ImaginaryUnit * C.Sum( C.Sum( C.binomial(k, j) * ((-1)**j * (k - 2*j)**(2*n + 1)) / (2**k*S.ImaginaryUnit**k * k), (j, 0, k)), (k, 1, 2*n + 1))) return Em
def __contains__(self, o): if isinstance(o, Point): x = C.Dummy('x', real=True) y = C.Dummy('y', real=True) res = self.equation(x, y).subs({x: o[0], y: o[1]}) return trigsimp(simplify(res)) is S.Zero elif isinstance(o, Ellipse): return self == o return False
def fdiff(self, argindex=1): if argindex == 1: return 1 / self.args[0] s = C.Dummy('x') return Lambda(s**(-1), s) else: raise ArgumentIndexError(self, argindex)
def __new__(cls): from sympy.sets.sets import FiniteSet x = C.Dummy('x') #construct "by hand" to avoid infinite loop obj = Expr.__new__(cls, Tuple(x), x) obj.nargs = FiniteSet(1) return obj
def _eval_rewrite_as_Sum(self, ap, bq, z): from sympy.functions import factorial, RisingFactorial, Piecewise n = C.Dummy("n", integer=True) rfap = Tuple(*[RisingFactorial(a, n) for a in ap]) rfbq = Tuple(*[RisingFactorial(b, n) for b in bq]) coeff = Mul(*rfap) / Mul(*rfbq) return Piecewise((C.Sum(coeff * z**n / factorial(n), (n, 0, oo)), self.convergence_statement), (self, True))
def _eval_rewrite_as_Sum(self, n, k_sym=None, symbols=None): if (k_sym is not None) or (symbols is not None): return self # Dobinski's formula if not n.is_nonnegative: return self k = C.Dummy('k', integer=True, nonnegative=True) return 1 / E * C.Sum(k**n / factorial(k), (k, 0, S.Infinity))
def doit(self, **hints): """Evaluates limit""" 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, gamma) if e.is_Mul: if abs(z0) is S.Infinity: # XXX todo: this should probably be stated in the # negative -- i.e. to exclude expressions that should # not be handled this way but I'm not sure what that # condition is; when ok is True it means that the leading # term approach is going to succeed (hopefully) 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 = C.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 C.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 return r
def fdiff(self, argindex=1): """ Returns the first derivative of the function. """ if argindex == 1: return 1/self.args[0] s = C.Dummy('x') return Lambda(s**(-1), s) else: raise ArgumentIndexError(self, argindex)
def circumference(self): """The circumference of the ellipse. Examples -------- >>> from sympy import Point, Ellipse >>> p1 = Point(0, 0) >>> e1 = Ellipse(p1, 3, 1) >>> e1.circumference 12*Integral(sqrt((-8*_x**2/9 + 1)/(-_x**2 + 1)), (_x, 0, 1)) """ if self.eccentricity == 1: return 2*pi*self.hradius else: x = C.Dummy('x', real=True) return 4*self.major*\ C.Integral(sqrt((1 - (self.eccentricity*x)**2)/(1 - x**2)), (x, 0, 1))
def _eval_subs(self, old, new): if self == old: return new arg = self.args[0] o = old if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) old = exp(old.exp*log(old.base)) if old.func is exp: # exp(a*expr) .subs( exp(b*expr), y ) -> y ** (a/b) a, expr_terms = self.args[0].as_coeff_mul() b, expr_terms_= old.args[0].as_coeff_mul() if expr_terms == expr_terms_: return new**(a/b) if arg.is_Add: # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = old.args[0] new_l = [] old_al = [] coeff2, terms2 = oarg.as_coeff_mul() for a in arg.args: a = a._eval_subs(old, new) coeff1, terms1 = a.as_coeff_mul() if terms1 == terms2: new_l.append(new**(coeff1/coeff2)) else: old_al.append(a._eval_subs(old, new)) if new_l: new_l.append(self.func(Add(*old_al))) r = Mul(*new_l) return r if old is S.Exp1: # treat this however Pow is being treated u = C.Dummy('u') return (u**self.args[0]).subs(u, new) old = o return Function._eval_subs(self, old, new)
def _eval_subs(self, old, new): arg = self.args[0] o = old if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) o = exp(o.exp*log(o.base)) if o.func is exp: # exp(a*expr) .subs( exp(b*expr), y ) -> y ** (a/b) a, expr_terms = self.args[0].as_independent( C.Symbol, as_Add=False) b, expr_terms_ = o.args[0].as_independent( C.Symbol, as_Add=False) if expr_terms == expr_terms_: return new**(a/b) if arg.is_Add: # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = o.args[0] new_l = [] o_al = [] coeff2, terms2 = oarg.as_coeff_mul() for a in arg.args: a = a._subs(o, new) coeff1, terms1 = a.as_coeff_mul() if terms1 == terms2: new_l.append(new**(coeff1/coeff2)) else: o_al.append(a._subs(o, new)) if new_l: new_l.append(self.func(Add(*o_al))) r = Mul(*new_l) return r if o is S.Exp1: # treat this however Pow is being treated u = C.Dummy('u', positive=True) return (u**self.args[0]).xreplace({u: new}) return Function._eval_subs(self, o, new)
def limit(e, z, z0, dir="+"): """ Compute the limit of e(z) at the point z0. z0 can be any expression, including oo and -oo. For dir="+" (default) it calculates the limit from the right (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0 (oo or -oo), the dir argument doesn't matter. Examples ======== >>> from sympy import limit, sin, Symbol, oo >>> from sympy.abc import x >>> limit(sin(x)/x, x, 0) 1 >>> limit(1/x, x, 0, dir="+") oo >>> limit(1/x, x, 0, dir="-") -oo >>> 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). """ from sympy import Wild, log e = sympify(e) z = sympify(z) z0 = sympify(z0) if e == z: return z0 if e.is_Rational: return e 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, gamma) if e.func is tan: # discontinuity at odd multiples of pi/2; 0 at even disc = S.Pi / 2 sign = 1 if dir == '-': sign *= -1 i = limit(sign * e.args[0], z, z0) / disc if i.is_integer: if i.is_even: return S.Zero elif i.is_odd: if dir == '+': return S.NegativeInfinity else: return S.Infinity if e.func is cot: # discontinuity at multiples of pi; 0 at odd pi/2 multiples disc = S.Pi sign = 1 if dir == '-': sign *= -1 i = limit(sign * e.args[0], z, z0) / disc if i.is_integer: if dir == '-': return S.NegativeInfinity else: return S.Infinity elif (2 * i).is_integer: return S.Zero if e.is_Pow: b, ex = e.args c = None # records sign of b if b is +/-z or has a bounded value if b.is_Mul: c, b = b.as_two_terms() if c is S.NegativeOne and b == z: c = '-' elif b == z: c = '+' if ex.is_number: if c is None: base = b.subs(z, z0) if base.is_finite and (ex.is_bounded or base is not S.One): return base**ex else: if z0 == 0 and ex < 0: if dir != c: # integer if ex.is_even: return S.Infinity elif ex.is_odd: return S.NegativeInfinity # rational elif ex.is_Rational: return (S.NegativeOne**ex) * S.Infinity else: return S.ComplexInfinity return S.Infinity return z0**ex if e.is_Mul or not z0 and e.is_Pow and b.func is log: if e.is_Mul: if abs(z0) is S.Infinity: n, d = e.as_numer_denom() # XXX todo: this should probably be stated in the # negative -- i.e. to exclude expressions that should # not be handled this way but I'm not sure what that # condition is; when ok is True it means that the leading # term approach is going to succeed (hopefully) 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 (n, d)): u = C.Dummy(positive=(z0 is S.Infinity)) inve = (n / d).subs(z, 1 / u) return limit(inve.as_leading_term(u), u, S.Zero, "+" if z0 is S.Infinity else "-") # weed out the z-independent terms i, d = e.as_independent(z) if i is not S.One and i.is_bounded: return i * limit(d, z, z0, dir) else: i, d = S.One, e if not z0: # look for log(z)**q or z**p*log(z)**q p, q = Wild("p"), Wild("q") r = d.match(z**p * log(z)**q) if r: p, q = [r.get(w, w) for w in [p, q]] if q and q.is_number and p.is_number: if q > 0: if p > 0: return S.Zero else: return -oo * i else: if p >= 0: return S.Zero else: return -oo * i if e.is_Add: if e.is_polynomial() and not z0.is_unbounded: return Add(*[limit(term, z, z0, dir) for term in e.args]) # this is a case like limit(x*y+x*z, z, 2) == x*y+2*x # but we need to make sure, that the general gruntz() algorithm is # executed for a case like "limit(sqrt(x+1)-sqrt(x),x,oo)==0" unbounded = [] unbounded_result = [] unbounded_const = [] unknown = [] unknown_result = [] finite = [] zero = [] def _sift(term): if z not in term.free_symbols: if term.is_unbounded: unbounded_const.append(term) else: finite.append(term) else: result = term.subs(z, z0) bounded = result.is_bounded if bounded is False or result is S.NaN: unbounded.append(term) if result != S.NaN: # take result from direction given result = limit(term, z, z0, dir) unbounded_result.append(result) elif bounded: if result: finite.append(result) else: zero.append(term) else: unknown.append(term) unknown_result.append(result) for term in e.args: _sift(term) bad = bool(unknown and unbounded) if bad or len(unknown) > 1 or len(unbounded) > 1 and not zero: uu = unknown + unbounded # we won't be able to resolve this with unbounded # terms, e.g. Sum(1/k, (k, 1, n)) - log(n) as n -> oo: # since the Sum is unevaluated it's boundedness is # unknown and the log(n) is oo so you get Sum - oo # which is unsatisfactory. BUT...if there are both # unknown and unbounded terms (condition 'bad') or # there are multiple terms that are unknown, or # there are multiple symbolic unbounded terms they may # respond better if they are made into a rational # function, so give them a chance to do so before # reporting failure. u = Add(*uu) f = u.normal() if f != u: unknown = [] unbounded = [] unbounded_result = [] unknown_result = [] _sift(limit(f, z, z0, dir)) # We came in with a) unknown and unbounded terms or b) had multiple # unknown terms # At this point we've done one of 3 things. # (1) We did nothing with f so we now report the error # showing the troublesome terms which are now in uu. OR # (2) We did something with f but the result came back as unknown. # Normally this wouldn't be a problem, # but we had either multiple terms that were troublesome (unk and # unbounded or multiple unknown terms) so if we # weren't able to resolve the boundedness by now, that indicates a # problem so we report the error showing the troublesome terms which are # now in uu. if unknown: if bad: msg = 'unknown and unbounded terms present in %s' elif unknown: msg = 'multiple terms with unknown boundedness in %s' raise NotImplementedError(msg % uu) # OR # (3) the troublesome terms have been identified as finite or unbounded # and we proceed with the non-error code since the lists have been updated. u = Add(*unknown_result) if unbounded_result or unbounded_const: unbounded.extend(zero) inf_limit = Add(*(unbounded_result + unbounded_const)) if inf_limit is not S.NaN: return inf_limit + u if finite: return Add(*finite) + limit(Add(*unbounded), z, z0, dir) + u else: return Add(*finite) + u if e.is_Order: args = e.args return C.Order(limit(args[0], z, z0), *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) return r
def limit(e, z, z0, dir="+"): """ Compute the limit of e(z) at the point z0. z0 can be any expression, including oo and -oo. For dir="+" (default) it calculates the limit from the right (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0 (oo or -oo), the dir argument doesn't matter. Examples ======== >>> from sympy import limit, sin, Symbol, oo >>> from sympy.abc import x >>> limit(sin(x)/x, x, 0) 1 >>> limit(1/x, x, 0, dir="+") oo >>> limit(1/x, x, 0, dir="-") -oo >>> 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). """ e = sympify(e) z = sympify(z) z0 = sympify(z0) 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, gamma) if e.is_Mul: if abs(z0) is S.Infinity: # XXX todo: this should probably be stated in the # negative -- i.e. to exclude expressions that should # not be handled this way but I'm not sure what that # condition is; when ok is True it means that the leading # term approach is going to succeed (hopefully) 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 = C.Dummy(positive=(z0 is S.Infinity)) inve = e.subs(z, 1 / u) return limit(inve.as_leading_term(u), u, S.Zero, "+" if z0 is S.Infinity else "-") if e.is_Order: return C.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) return r
def __new__(cls): x = C.Dummy('x') #construct "by hand" to avoid infinite loop return Expr.__new__(cls, Tuple(x), x)
def test_print_Dummy(): d = C.Dummy('d') p = setup_test_printer() assert p._print_Dummy(d) == "d_%i" % d.dummy_index
def subexp(e, sub): """Is "sub" a subexpression of "e"? """ #we substitute some symbol for the "sub", and if the #expression changes, the substitution was successful, thus the answer #is yes. return e.subs(sub, C.Dummy('u')) != e
def limit(e, z, z0, dir="+"): """ Compute the limit of e(z) at the point z0. z0 can be any expression, including oo and -oo. For dir="+" (default) it calculates the limit from the right (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0 (oo or -oo), the dir argument doesn't matter. Examples ======== >>> from sympy import limit, sin, Symbol, oo >>> from sympy.abc import x >>> limit(sin(x)/x, x, 0) 1 >>> limit(1/x, x, 0, dir="+") oo >>> limit(1/x, x, 0, dir="-") -oo >>> 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). """ from sympy import Wild, log e = sympify(e) z = sympify(z) z0 = sympify(z0) if e == z: return z0 if e.is_Rational: return e 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, gamma) if e.func is tan: # discontinuity at odd multiples of pi/2; 0 at even disc = S.Pi/2 sign = 1 if dir == '-': sign *= -1 i = limit(sign*e.args[0], z, z0)/disc if i.is_integer: if i.is_even: return S.Zero elif i.is_odd: if dir == '+': return S.NegativeInfinity else: return S.Infinity if e.func is cot: # discontinuity at multiples of pi; 0 at odd pi/2 multiples disc = S.Pi sign = 1 if dir == '-': sign *= -1 i = limit(sign*e.args[0], z, z0)/disc if i.is_integer: if dir == '-': return S.NegativeInfinity else: return S.Infinity elif (2*i).is_integer: return S.Zero if e.is_Pow: b, ex = e.args c = None # records sign of b if b is +/-z or has a bounded value if b.is_Mul: c, b = b.as_two_terms() if c is S.NegativeOne and b == z: c = '-' elif b == z: c = '+' if ex.is_number: if c is None: base = b.subs(z, z0) if base != 0 and (ex.is_bounded or base is not S.One): return base**ex else: if z0 == 0 and ex < 0: if dir != c: # integer if ex.is_even: return S.Infinity elif ex.is_odd: return S.NegativeInfinity # rational elif ex.is_Rational: return (S.NegativeOne**ex)*S.Infinity else: return S.ComplexInfinity return S.Infinity return z0**ex if e.is_Mul or not z0 and e.is_Pow and b.func is log: if e.is_Mul: if abs(z0) is S.Infinity: n, d = e.as_numer_denom() # XXX todo: this should probably be stated in the # negative -- i.e. to exclude expressions that should # not be handled this way but I'm not sure what that # condition is; when ok is True it means that the leading # term approach is going to succeed (hopefully) 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 (n, d)): u = C.Dummy(positive=(z0 is S.Infinity)) inve = (n/d).subs(z, 1/u) return limit(inve.as_leading_term(u), u, S.Zero, "+" if z0 is S.Infinity else "-") # weed out the z-independent terms i, d = e.as_independent(z) if i is not S.One and i.is_bounded: return i*limit(d, z, z0, dir) else: i, d = S.One, e if not z0: # look for log(z)**q or z**p*log(z)**q p, q = Wild("p"), Wild("q") r = d.match(z**p * log(z)**q) if r: p, q = [r.get(w, w) for w in [p, q]] if q and q.is_number and p.is_number: if q > 0: if p > 0: return S.Zero else: return -oo*i else: if p >= 0: return S.Zero else: return -oo*i if e.is_Add: if e.is_polynomial(): if not z0.is_unbounded: return Add(*[limit(term, z, z0, dir) for term in e.args]) elif e.is_rational_function(z): rval = Add(*[limit(term, z, z0, dir) for term in e.args]) if rval != S.NaN: return rval if not any([a.is_unbounded for a in e.args]): e = e.normal() # workaround for issue 3744 if e.is_Order: args = e.args return C.Order(limit(args[0], z, z0), *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) return r
def _eval_rewrite_as_Sum(self, n, m=None): k = C.Dummy("k", integer=True) if m is None: m = S.One return C.Sum(k**(-m), (k, 1, n))
""" This module mainly implements special orthogonal polynomials. See also functions.combinatorial.numbers which contains some combinatorial polynomials. """ from sympy.core import S, C, Rational, Function from sympy.utilities.memoization import recurrence_memo, assoc_recurrence_memo from sympy.functions.combinatorial.factorials import factorial _x = C.Dummy('x') class PolynomialSequence(Function): """Polynomial sequence with 1 index n >= 0 """ nargs = 2 @classmethod def eval(cls, n, x): if n.is_integer and n >= 0: return cls.calc(int(n)).subs(_x, x) if n.is_negative: raise ValueError("%s index must be nonnegative integer (got %r)" % (cls, n))