def deltaproduct(f, limit): """ Handle products containing a KroneckerDelta. See Also ======== deltasummation sympy.functions.special.tensor_functions.KroneckerDelta sympy.concrete.products.product """ from sympy.concrete.products import product if ((limit[2] - limit[1]) < 0) is True: return S.One if not f.has(KroneckerDelta): return product(f, limit) if f.is_Add: # Identify the term in the Add that has a simple KroneckerDelta delta = None terms = [] for arg in sorted(f.args, key=default_sort_key): if delta is None and _has_simple_delta(arg, limit[0]): delta = arg else: terms.append(arg) newexpr = f.func(*terms) k = Dummy("kprime", integer=True) if isinstance(limit[1], int) and isinstance(limit[2], int): result = deltaproduct(newexpr, limit) + sum([ deltaproduct(newexpr, (limit[0], limit[1], ik - 1)) * delta.subs(limit[0], ik) * deltaproduct(newexpr, (limit[0], ik + 1, limit[2])) for ik in range(int(limit[1]), int(limit[2] + 1))] ) else: result = deltaproduct(newexpr, limit) + deltasummation( deltaproduct(newexpr, (limit[0], limit[1], k - 1)) * delta.subs(limit[0], k) * deltaproduct(newexpr, (limit[0], k + 1, limit[2])), (k, limit[1], limit[2]), no_piecewise=True ) return _remove_multiple_delta(result) delta, _ = _extract_delta(f, limit[0]) if not delta: g = _expand_delta(f, limit[0]) if f != g: from sympy import factor try: return factor(deltaproduct(g, limit)) except AssertionError: return deltaproduct(g, limit) return product(f, limit) from sympy import Eq c = Eq(limit[2], limit[1] - 1) return _remove_multiple_delta(f.subs(limit[0], limit[1])*KroneckerDelta(limit[2], limit[1])) + \ S.One*_simplify_delta(KroneckerDelta(limit[2], limit[1] - 1))
def deltaproduct(f, limit): """ Handle products containing a KroneckerDelta. See Also ======== deltasummation sympy.functions.special.tensor_functions.KroneckerDelta sympy.concrete.products.product """ from sympy.concrete.products import product if ((limit[2] - limit[1]) < 0) == True: return S.One if not f.has(KroneckerDelta): return product(f, limit) if f.is_Add: # Identify the term in the Add that has a simple KroneckerDelta delta = None terms = [] for arg in sorted(f.args, key=default_sort_key): if delta is None and _has_simple_delta(arg, limit[0]): delta = arg else: terms.append(arg) newexpr = f.func(*terms) k = Dummy("kprime", integer=True) if isinstance(limit[1], int) and isinstance(limit[2], int): result = deltaproduct(newexpr, limit) + sum([ deltaproduct(newexpr, (limit[0], limit[1], ik - 1)) * delta.subs(limit[0], ik) * deltaproduct(newexpr, (limit[0], ik + 1, limit[2])) for ik in range(int(limit[1]), int(limit[2] + 1)) ]) else: result = deltaproduct(newexpr, limit) + deltasummation( deltaproduct(newexpr, (limit[0], limit[1], k - 1)) * delta.subs(limit[0], k) * deltaproduct(newexpr, (limit[0], k + 1, limit[2])), (k, limit[1], limit[2]), no_piecewise=_has_simple_delta(newexpr, limit[0])) return _remove_multiple_delta(result) delta, _ = _extract_delta(f, limit[0]) if not delta: g = _expand_delta(f, limit[0]) if f != g: from sympy import factor try: return factor(deltaproduct(g, limit)) except AssertionError: return deltaproduct(g, limit) return product(f, limit) return _remove_multiple_delta(f.subs(limit[0], limit[1])*KroneckerDelta(limit[2], limit[1])) + \ S.One*_simplify_delta(KroneckerDelta(limit[2], limit[1] - 1))
def test_special_products(): # Wallis product assert product((4*k)**2 / (4*k**2 - 1), (k, 1, n)) == \ 4**n*factorial(n)**2/rf(S.Half, n)/rf(Rational(3, 2), n) # Euler's product formula for sin assert product(1 + a/k**2, (k, 1, n)) == \ rf(1 - sqrt(-a), n)*rf(1 + sqrt(-a), n)/factorial(n)**2
def test__eval_product(): from sympy.abc import i, n # issue 4809 a = Function('a') assert product(2*a(i), (i, 1, n)) == 2**n * Product(a(i), (i, 1, n)) # issue 4810 assert product(2**i, (i, 1, n)) == 2**(n*(n + 1)/2) k, m = symbols('k m', integer=True) assert product(2**i, (i, k, m)) == 2**(-k**2/2 + k/2 + m**2/2 + m/2) n = Symbol('n', negative=True, integer=True) p = Symbol('p', positive=True, integer=True) assert product(2**i, (i, n, p)) == 2**(-n**2/2 + n/2 + p**2/2 + p/2) assert product(2**i, (i, p, n)) == 2**(n**2/2 + n/2 - p**2/2 + p/2)
def test_multiple_products(): assert product(x, (n, 1, k), (k, 1, m)) == x**(m**2/2 + m/2) assert product(f(n), ( n, 1, m), (m, 1, k)) == Product(f(n), (n, 1, m), (m, 1, k)).doit() assert Product(f(n), (m, 1, k), (n, 1, k)).doit() == \ Product(Product(f(n), (m, 1, k)), (n, 1, k)).doit() == \ product(f(n), (m, 1, k), (n, 1, k)) == \ product(product(f(n), (m, 1, k)), (n, 1, k)) == \ Product(f(n)**k, (n, 1, k)) assert Product( x, (x, 1, k), (k, 1, n)).doit() == Product(factorial(k), (k, 1, n)) assert Product(x**k, (n, 1, k), (k, 1, m)).variables == [n, k]
def maxima_product(a1, a2, a3, a4): return product(a1, (a2, a3, a4))
def test_evalf_mul(): # SymPy should not try to expand this; it should be handled term-wise # in evalf through mpmath assert NS(product(1 + sqrt(n) * I, (n, 1, 500)), 1) == '5.e+567 + 2.e+568*I'
def test_issue_14036(): a, n = symbols('a n') assert product(1 - a**2 / (n*pi)**2, [n, 1, oo]) != 0
def test_issue_9983(): n = Symbol('n', integer=True, positive=True) p = Product(1 + 1/n**Rational(2, 3), (n, 1, oo)) assert p.is_convergent() is S.false assert product(1 + 1/n**Rational(2, 3), (n, 1, oo)) == p.doit()
def test_product_pow(): # issue 4817 assert product(2**f(k), (k, 1, n)) == 2**Sum(f(k), (k, 1, n)) assert product(2**(2*f(k)), (k, 1, n)) == 2**Sum(2*f(k), (k, 1, n))
def test_rational_products(): assert product(1 + 1/k, (k, 1, n)) == rf(2, n)/factorial(n)
def test_simple_products(): assert product(2, (k, a, n)) == 2**(n - a + 1) assert product(k, (k, 1, n)) == factorial(n) assert product(k**3, (k, 1, n)) == factorial(n)**3 assert product(k + 1, (k, 0, n - 1)) == factorial(n) assert product(k + 1, (k, a, n - 1)) == rf(1 + a, n - a) assert product(cos(k), (k, 0, 5)) == cos(1)*cos(2)*cos(3)*cos(4)*cos(5) assert product(cos(k), (k, 3, 5)) == cos(3)*cos(4)*cos(5) assert product(cos(k), (k, 1, Rational(5, 2))) != cos(1)*cos(2) assert isinstance(product(k**k, (k, 1, n)), Product) assert Product(x**k, (k, 1, n)).variables == [k] raises(ValueError, lambda: Product(n)) raises(ValueError, lambda: Product(n, k)) raises(ValueError, lambda: Product(n, k, 1)) raises(ValueError, lambda: Product(n, k, 1, 10)) raises(ValueError, lambda: Product(n, (k, 1))) assert product(1, (n, 1, oo)) == 1 # issue 8301 assert product(2, (n, 1, oo)) is oo assert product(-1, (n, 1, oo)).func is Product