def test_Sum(): assert precedence(Sum(x, (x, y, y + 1))) == PRECEDENCE["Atom"]
def test_sympy__concrete__summations__Sum(): from sympy.concrete.summations import Sum assert _test_args(Sum(x, (x, 0, 10))) assert _test_args(Sum(x, (x, 0, y), (y, 0, 10)))
def _eval_rewrite_as_polynomial(self, n, m, x, **kwargs): from sympy.concrete.summations import Sum k = Dummy("k") kern = factorial(2*n - 2*k)/(2**n*factorial(n - k)*factorial( k)*factorial(n - 2*k - m))*S.NegativeOne**k*x**(n - m - 2*k) return (1 - x**2)**(m/2) * Sum(kern, (k, 0, floor((n - m)*S.Half)))
def check(pdf, set): x = Dummy('x') val = Sum(pdf(x), (x, set._inf, set._sup)).doit() _value_check(Eq(val, 1) != S.false, "The pdf is incorrect on the given set.")
def test_BernoulliProcess(): B = BernoulliProcess("B", p=0.6, success=1, failure=0) assert B.state_space == FiniteSet(0, 1) assert B.index_set == S.Naturals0 assert B.success == 1 assert B.failure == 0 X = BernoulliProcess("X", p=Rational(1, 3), success='H', failure='T') assert X.state_space == FiniteSet('H', 'T') H, T = symbols("H,T") assert E(X[1] + X[2] * X[3] ) == H**2 / 9 + 4 * H * T / 9 + H / 3 + 4 * T**2 / 9 + 2 * T / 3 t, x = symbols('t, x', positive=True, integer=True) assert isinstance(B[t], RandomIndexedSymbol) raises(ValueError, lambda: BernoulliProcess("X", p=1.1, success=1, failure=0)) raises(NotImplementedError, lambda: B(t)) raises(IndexError, lambda: B[-3]) assert B.joint_distribution(B[3], B[9]) == JointDistributionHandmade( Lambda( (B[3], B[9]), Piecewise((0.6, Eq(B[3], 1)), (0.4, Eq(B[3], 0)), (0, True)) * Piecewise((0.6, Eq(B[9], 1)), (0.4, Eq(B[9], 0)), (0, True)))) assert B.joint_distribution(2, B[4]) == JointDistributionHandmade( Lambda( (B[2], B[4]), Piecewise((0.6, Eq(B[2], 1)), (0.4, Eq(B[2], 0)), (0, True)) * Piecewise((0.6, Eq(B[4], 1)), (0.4, Eq(B[4], 0)), (0, True)))) # Test for the sum distribution of Bernoulli Process RVs Y = B[1] + B[2] + B[3] assert P(Eq(Y, 0)).round(2) == Float(0.06, 1) assert P(Eq(Y, 2)).round(2) == Float(0.43, 2) assert P(Eq(Y, 4)).round(2) == 0 assert P(Gt(Y, 1)).round(2) == Float(0.65, 2) # Test for independency of each Random Indexed variable assert P(Eq(B[1], 0) & Eq(B[2], 1) & Eq(B[3], 0) & Eq(B[4], 1)).round(2) == Float(0.06, 1) assert E(2 * B[1] + B[2]).round(2) == Float(1.80, 3) assert E(2 * B[1] + B[2] + 5).round(2) == Float(6.80, 3) assert E(B[2] * B[4] + B[10]).round(2) == Float(0.96, 2) assert E(B[2] > 0, Eq(B[1], 1) & Eq(B[2], 1)).round(2) == Float(0.60, 2) assert E(B[1]) == 0.6 assert P(B[1] > 0).round(2) == Float(0.60, 2) assert P(B[1] < 1).round(2) == Float(0.40, 2) assert P(B[1] > 0, B[2] <= 1).round(2) == Float(0.60, 2) assert P(B[12] * B[5] > 0).round(2) == Float(0.36, 2) assert P(B[12] * B[5] > 0, B[4] < 1).round(2) == Float(0.36, 2) assert P(Eq(B[2], 1), B[2] > 0) == 1 assert P(Eq(B[5], 3)) == 0 assert P(Eq(B[1], 1), B[1] < 0) == 0 assert P(B[2] > 0, Eq(B[2], 1)) == 1 assert P(B[2] < 0, Eq(B[2], 1)) == 0 assert P(B[2] > 0, B[2] == 7) == 0 assert P(B[5] > 0, B[5]) == BernoulliDistribution(0.6, 0, 1) raises(ValueError, lambda: P(3)) raises(ValueError, lambda: P(B[3] > 0, 3)) # test issue 19456 expr = Sum(B[t], (t, 0, 4)) expr2 = Sum(B[t], (t, 1, 3)) expr3 = Sum(B[t]**2, (t, 1, 3)) assert expr.doit() == B[0] + B[1] + B[2] + B[3] + B[4] assert expr2.doit() == Y assert expr3.doit() == B[1]**2 + B[2]**2 + B[3]**2 assert B[2 * t].free_symbols == {B[2 * t], t} assert B[4].free_symbols == {B[4]} assert B[x * t].free_symbols == {B[x * t], x, t} #test issue 20078 assert (2 * B[t] + 3 * B[t]).simplify() == 5 * B[t] assert (2 * B[t] - 3 * B[t]).simplify() == -B[t] assert (2 * (0.25 * B[t])).simplify() == 0.5 * B[t] assert (2 * B[t] * 0.25 * B[t]).simplify() == 0.5 * B[t]**2 assert (B[t]**2 + B[t]**3).simplify() == (B[t] + 1) * B[t]**2
def _eval_rewrite_as_polynomial(self, n, x, **kwargs): from sympy.concrete.summations import Sum k = Dummy("k") kern = S.NegativeOne**k*binomial(n, k)**2*((1 + x)/2)**(n - k)*((1 - x)/2)**k return Sum(kern, (k, 0, n))
def test_doit(): n = Symbol('n', integer=True) f = Sum(2 * n * x, (n, 1, 3)) d = Derivative(f, x) assert d.doit() == 12 assert d.doit(deep=False) == Sum(2*n, (n, 1, 3))
def _eval_rewrite_as_Sum(self, *args): from sympy.concrete.summations import Sum return exp(Sum(log(self.function), *self.limits))
def _eval_rewrite_as_Sum(self, expr, **kwargs): from sympy.concrete.summations import Sum i = uniquely_named_symbol('i', expr) s = Sum(self.arg[i, i], (i, 0, self.arg.rows - 1)) return s.doit()
def test_limit_seq_fail(): # improve Summation algorithm or add ad-hoc criteria e = (harmonic(n)**3 * Sum(1 / harmonic(k), (k, 1, n)) / (n * Sum(harmonic(k) / k, (k, 1, n)))) assert limit_seq(e, n) == 2 # No unique dominant term e = (Sum(2**k * binomial(2 * k, k) / k**2, (k, 1, n)) / (Sum(2**k / k * 2, (k, 1, n)) * Sum(binomial(2 * k, k), (k, 1, n)))) assert limit_seq(e, n) == S(3) / 7 # Simplifications of summations needs to be improved. e = n**3 * Sum(2**k / k**2, (k, 1, n))**2 / (2**n * Sum(2**k / k, (k, 1, n))) assert limit_seq(e, n) == 2 e = (harmonic(n) * Sum(2**k / k, (k, 1, n)) / (n * Sum(2**k * harmonic(k) / k**2, (k, 1, n)))) assert limit_seq(e, n) == 1 e = (Sum(2**k * factorial(k) / k**2, (k, 1, 2 * n)) / (Sum(4**k / k**2, (k, 1, n)) * Sum(factorial(k), (k, 1, 2 * n)))) assert limit_seq(e, n) == S(3) / 16
def apply(x): assert len(x.shape) == 1 return Equality(log(softmax(x)), x - MAX(x) - log(Sum(exp(x - MAX(x)))))
def _eval_product(self, term, limits): from sympy.concrete.delta import deltaproduct, _has_simple_delta from sympy.concrete.summations import summation from sympy.functions import KroneckerDelta, RisingFactorial (k, a, n) = limits if k not in term.free_symbols: if (term - 1).is_zero: return S.One return term**(n - a + 1) if a == n: return term.subs(k, a) if term.has(KroneckerDelta) and _has_simple_delta(term, limits[0]): return deltaproduct(term, limits) dif = n - a if dif.is_Integer: return Mul(*[term.subs(k, a + i) for i in range(dif + 1)]) elif term.is_polynomial(k): poly = term.as_poly(k) A = B = Q = S.One all_roots = roots(poly) M = 0 for r, m in all_roots.items(): M += m A *= RisingFactorial(a - r, n - a + 1)**m Q *= (n - r)**m if M < poly.degree(): arg = quo(poly, Q.as_poly(k)) B = self.func(arg, (k, a, n)).doit() return poly.LC()**(n - a + 1) * A * B elif term.is_Add: p, q = term.as_numer_denom() q = self._eval_product(q, (k, a, n)) if q.is_Number: # There is expression, which couldn't change by # as_numer_denom(). E.g. n**(2/3) + 1 --> (n**(2/3) + 1, 1). # We have to catch this case. from sympy.concrete.summations import Sum p = exp(Sum(log(p), (k, a, n))) else: p = self._eval_product(p, (k, a, n)) return p / q elif term.is_Mul: exclude, include = [], [] for t in term.args: p = self._eval_product(t, (k, a, n)) if p is not None: exclude.append(p) else: include.append(t) if not exclude: return None else: arg = term._new_rawargs(*include) A = Mul(*exclude) B = self.func(arg, (k, a, n)).doit() return A * B elif term.is_Pow: if not term.base.has(k): s = summation(term.exp, (k, a, n)) return term.base**s elif not term.exp.has(k): p = self._eval_product(term.base, (k, a, n)) if p is not None: return p**term.exp elif isinstance(term, Product): evaluated = term.doit() f = self._eval_product(evaluated, limits) if f is None: return self.func(evaluated, limits) else: return f
def test_match_bound(): V, W = map(Wild, "VW") x, y = symbols('x y') assert Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, W))) == {W: 2} assert Sum(x, (x, 1, 2)).match(Sum(V, (V, 1, W))) == {W: 2, V: x} assert Sum(x, (x, 1, 2)).match(Sum(V, (V, 1, 2))) == {V: x}
def deltasummation(f, limit, no_piecewise=False): """ Handle summations containing a KroneckerDelta. The idea for summation is the following: - If we are dealing with a KroneckerDelta expression, i.e. KroneckerDelta(g(x), j), we try to simplify it. If we could simplify it, then we sum the resulting expression. We already know we can sum a simplified expression, because only simple KroneckerDelta expressions are involved. If we couldn't simplify it, there are two cases: 1) The expression is a simple expression: we return the summation, taking care if we are dealing with a Derivative or with a proper KroneckerDelta. 2) The expression is not simple (i.e. KroneckerDelta(cos(x))): we can do nothing at all. - If the expr is a multiplication expr having a KroneckerDelta term: First we expand it. If the expansion did work, then we try to sum the expansion. If not, we try to extract a simple KroneckerDelta term, then we have two cases: 1) We have a simple KroneckerDelta term, so we return the summation. 2) We didn't have a simple term, but we do have an expression with simplified KroneckerDelta terms, so we sum this expression. Examples ======== >>> from sympy import oo, symbols >>> from sympy.abc import k >>> i, j = symbols('i, j', integer=True, finite=True) >>> from sympy.concrete.delta import deltasummation >>> from sympy import KroneckerDelta, Piecewise >>> deltasummation(KroneckerDelta(i, k), (k, -oo, oo)) 1 >>> deltasummation(KroneckerDelta(i, k), (k, 0, oo)) Piecewise((1, i >= 0), (0, True)) >>> deltasummation(KroneckerDelta(i, k), (k, 1, 3)) Piecewise((1, (i >= 1) & (i <= 3)), (0, True)) >>> deltasummation(k*KroneckerDelta(i, j)*KroneckerDelta(j, k), (k, -oo, oo)) j*KroneckerDelta(i, j) >>> deltasummation(j*KroneckerDelta(i, j), (j, -oo, oo)) i >>> deltasummation(i*KroneckerDelta(i, j), (i, -oo, oo)) j See Also ======== deltaproduct sympy.functions.special.tensor_functions.KroneckerDelta sympy.concrete.sums.summation """ from sympy.concrete.summations import summation from sympy.solvers import solve x, a, b = limit b -= 1 if ((b - a) < 0) == True: return S.Zero if not f.has(KroneckerDelta): return summation(f, limit) g = _expand_delta(f, x) if g.is_Add: return piecewise_fold( g.func(*[deltasummation(h, limit, no_piecewise) for h in g.args])) # try to extract a simple KroneckerDelta term delta, expr = _extract_delta(g, x) if not delta: return summation(f, limit) solns = solve(delta.args[0] - delta.args[1], x) if len(solns) == 0: return S.Zero elif len(solns) != 1: from sympy.concrete.summations import Sum return Sum(f, limit) value = solns[0] if no_piecewise: return expr.subs(x, value) return Piecewise( (expr.subs(x, value), Interval(a, b).as_relational(value)), (S.Zero, True))
def _eval_rewrite_as_polynomial(self, n, x, **kwargs): from sympy.concrete.summations import Sum k = Dummy("k") kern = binomial(n, 2*k) * (x**2 - 1)**k * x**(n - 2*k) return Sum(kern, (k, 0, floor(n/2)))
def is_convergent(self): r""" See docs of :obj:`.Sum.is_convergent()` for explanation of convergence in SymPy. Explanation =========== The infinite product: .. math:: \prod_{1 \leq i < \infty} f(i) is defined by the sequence of partial products: .. math:: \prod_{i=1}^{n} f(i) = f(1) f(2) \cdots f(n) as n increases without bound. The product converges to a non-zero value if and only if the sum: .. math:: \sum_{1 \leq i < \infty} \log{f(n)} converges. Examples ======== >>> from sympy import Product, Symbol, cos, pi, exp, oo >>> n = Symbol('n', integer=True) >>> Product(n/(n + 1), (n, 1, oo)).is_convergent() False >>> Product(1/n**2, (n, 1, oo)).is_convergent() False >>> Product(cos(pi/n), (n, 1, oo)).is_convergent() True >>> Product(exp(-n**2), (n, 1, oo)).is_convergent() False References ========== .. [1] https://en.wikipedia.org/wiki/Infinite_product """ from sympy.concrete.summations import Sum sequence_term = self.function log_sum = log(sequence_term) lim = self.limits try: is_conv = Sum(log_sum, *lim).is_convergent() except NotImplementedError: if Sum(sequence_term - 1, * lim).is_absolutely_convergent() is S.true: return S.true raise NotImplementedError( "The algorithm to find the product convergence of %s " "is not yet implemented" % (sequence_term)) return is_conv
def _eval_rewrite_as_polynomial(self, n, x, **kwargs): from sympy.concrete.summations import Sum k = Dummy("k") kern = S.NegativeOne**k * factorial( n - k) * (2*x)**(n - 2*k) / (factorial(k) * factorial(n - 2*k)) return Sum(kern, (k, 0, floor(n/2)))
def test_concrete(): x = Symbol("x") for c in (Product, Product(x, (x, 2, 4)), Sum, Sum(x, (x, 2, 4))): check(c)
def apply(expr, *limits): return LessThan(abs(UNION(expr, *limits)), Sum(abs(expr), *limits).simplify())