def asymmetric(in_arr): """ Creates the asymmetric form of input tensor. Input: Arraypy or TensorArray with equal axes (array shapes). Output: asymmetric array. Output type - Arraypy or TensorArray, depends of input Examples ======== >>> from sympy.tensor.arraypy import list2arraypy >>> from sympy.tensor.tensor_methods import asymmetric >>> a = list2arraypy(list(range(9)), (3,3)) >>> b = asymmetric(a) >>> print (b) 0 -1.00000000000000 -2.00000000000000 1.00000000000000 0 -1.00000000000000 2.00000000000000 1.00000000000000 0 """ if not isinstance(in_arr, Arraypy): raise TypeError('Input must be Arraypy or TensorArray type') flag = 0 for j in range(in_arr.rank): if (in_arr.shape[0] != in_arr.shape[j]): raise ValueError('Different size of arrays axes') # forming list of tuples for Arraypy constructor of type a = Arraypy( [(a, # b), (c, d), ... , (y, z)] ) arg = [(in_arr.start_index[i], in_arr.end_index[i]) for i in range(in_arr.rank)] # if in_arr TensorArray, then res_arr will be TensorArray, else it will be # Arraypy if isinstance(in_arr, TensorArray): res_arr = TensorArray(Arraypy(arg), in_arr.ind_char) else: res_arr = Arraypy(arg) signs = [0 for i in range(factorial(in_arr.rank))] temp_i = 0 for p in permutations(range(in_arr.rank)): signs[temp_i] = perm_parity(list(p)) temp_i += 1 index = [in_arr.start_index[i] for i in range(in_arr.rank)] for i in range(len(in_arr)): perm = list(permutations(index)) perm_number = 0 for temp_index in perm: res_arr[tuple(index)] += signs[perm_number] * \ in_arr[tuple(temp_index)] perm_number += 1 if isinstance(res_arr[tuple(index)], int): res_arr[tuple(index)] = float(res_arr[tuple(index)]) res_arr[tuple(index)] /= factorial(in_arr.rank) index = in_arr.next_index(index) return res_arr
def wedge(first_tensor, second_tensor): """ Finds outer product (wedge) of two tensor arguments. The algoritm is too find the asymmetric form of tensor product of two arguments. The resulted array is multiplied on coefficient which is coeff = factorial(p+s)/factorial(p)*factorial(s) Examples ======== from tensor_analysis.arraypy import Arraypy, Tensor from tensor_analysis.tensor_methods import wedge >>> a = Arraypy((3,), 'A').to_tensor((-1)) >>> b = Arraypy((3,), 'B').to_tensor((1,)) >>> c = wedge(a, b) >>> print(c) 0 10*A[0]*B[1] - 10*A[1]*B[0] 10*A[0]*B[2] - 10*A[2]*B[0] -10*A[0]*B[1] + 10*A[1]*B[0] 0 10*A[1]*B[2] - 10*A[2]*B[1] -10*A[0]*B[2] + 10*A[2]*B[0] -10*A[1]*B[2] + 10*A[2]*B[1] 0 """ if not isinstance(first_tensor, TensorArray): raise TypeError('Input must be of TensorArray type') if not isinstance(second_tensor, TensorArray): raise TypeError('Input must be of TensorArray type') p = len(first_tensor) s = len(second_tensor) coeff = factorial(p + s) / (factorial(p) * factorial(s)) return coeff * asymmetric(tensor_product(first_tensor, second_tensor))
def _eval_rewrite_as_polynomial(self, n, x): from sympy import Sum # TODO: Should make sure n is in N_0 k = Dummy("k") kern = RisingFactorial( -n, k) / (gamma(k + alpha + 1) * factorial(k)) * x**k return gamma(n + alpha + 1) / factorial(n) * Sum(kern, (k, 0, n))
def taylor_term(n, x, *previous_terms): if n < 0: return S.Zero else: x = sympify(x) if len(previous_terms) > 1: p = previous_terms[-1] return ( (3 ** (S(1) / 3) * x) ** (-n) * (3 ** (S(1) / 3) * x) ** (n + 1) * sin(pi * (2 * n / 3 + S(4) / 3)) * factorial(n) * gamma(n / 3 + S(2) / 3) / (sin(pi * (2 * n / 3 + S(2) / 3)) * factorial(n + 1) * gamma(n / 3 + S(1) / 3)) * p ) else: return ( S.One / (3 ** (S(2) / 3) * pi) * gamma((n + S.One) / S(3)) * sin(2 * pi * (n + S.One) / S(3)) / factorial(n) * (root(3, 3) * x) ** n )
def _eval_rewrite_as_polynomial(self, n, a, b, x): from sympy import Sum # TODO: Make sure n \in N k = Dummy("k") kern = (RisingFactorial(-n, k) * RisingFactorial(a + b + n + 1, k) * RisingFactorial(a + k + 1, n - k) / factorial(k) * ((1 - x)/2)**k) return 1 / factorial(n) * Sum(kern, (k, 0, n))
def calc2(n,m): if m >= 0: return assoc_legendre._calc2(n,m) else: factorial = C.Factorial m = -m return (-1)**m *factorial(n-m)/factorial(n+m) * assoc_legendre._calc2(n, m)
def as_real_imag(self, deep=True, **hints): # TODO: Handle deep and hints n, m, theta, phi = self.args re = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) * cos(m*phi) * assoc_legendre(n, m, cos(theta))) im = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) * sin(m*phi) * assoc_legendre(n, m, cos(theta))) return (re, im)
def _eval_rewrite_as_polynomial(self, n, x): from sympy import Sum # Make sure n \in N_0 if n.is_negative or n.is_integer is False: raise ValueError("Error: n should be a non-negative integer.") k = Dummy("k") kern = RisingFactorial( -n, k) / (gamma(k + alpha + 1) * factorial(k)) * x**k return gamma(n + alpha + 1) / factorial(n) * Sum(kern, (k, 0, n))
def _eval_rewrite_as_polynomial(self, n, a, b, x): from sympy import Sum # Make sure n \in N if n.is_negative or n.is_integer is False: raise ValueError("Error: n should be a non-negative integer.") k = Dummy("k") kern = (RisingFactorial(-n, k) * RisingFactorial(a + b + n + 1, k) * RisingFactorial(a + k + 1, n - k) / factorial(k) * ((1 - x)/2)**k) return 1 / factorial(n) * Sum(kern, (k, 0, n))
def taylor_term(n, x, *previous_terms): if n < 0: return S.Zero else: x = sympify(x) if len(previous_terms) > 1: p = previous_terms[-1] return (3**(S(1)/3)*x * Abs(sin(2*pi*(n + S.One)/S(3))) * factorial((n - S.One)/S(3)) / ((n + S.One) * Abs(cos(2*pi*(n + S.Half)/S(3))) * factorial((n - 2)/S(3))) * p) else: return (S.One/(root(3, 6)*pi) * gamma((n + S.One)/S(3)) * Abs(sin(2*pi*(n + S.One)/S(3))) / factorial(n) * (root(3, 3)*x)**n)
def interpolate(data, x): """ Construct an interpolating polynomial for the data points. Examples ======== >>> from sympy.polys.polyfuncs import interpolate >>> from sympy.abc import x A list is interpreted as though it were paired with a range starting from 1: >>> interpolate([1, 4, 9, 16], x) x**2 This can be made explicit by giving a list of coordinates: >>> interpolate([(1, 1), (2, 4), (3, 9)], x) x**2 The (x, y) coordinates can also be given as keys and values of a dictionary (and the points need not be equispaced): >>> interpolate([(-1, 2), (1, 2), (2, 5)], x) x**2 + 1 >>> interpolate({-1: 2, 1: 2, 2: 5}, x) x**2 + 1 """ n = len(data) poly = None if isinstance(data, dict): X, Y = list(zip(*data.items())) poly = interpolating_poly(n, x, X, Y) else: if isinstance(data[0], tuple): X, Y = list(zip(*data)) poly = interpolating_poly(n, x, X, Y) else: Y = list(data) numert = Mul(*[(x - i) for i in range(1, n + 1)]) denom = -factorial(n - 1) if n%2 == 0 else factorial(n - 1) coeffs = [] for i in range(1, n + 1): coeffs.append(numert/(x - i)/denom) denom = denom/(i - n)*i poly = Add(*[coeff*y for coeff, y in zip(coeffs, Y)]) return poly.expand()
def _nP(n, k=None, replacement=False): from sympy.functions.combinatorial.factorials import factorial from sympy.core.mul import prod if k == 0: return 1 if isinstance(n, SYMPY_INTS): # n different items # assert n >= 0 if k is None: return sum(_nP(n, i, replacement) for i in range(n + 1)) elif replacement: return n**k elif k > n: return 0 elif k == n: return factorial(k) elif k == 1: return n else: # assert k >= 0 return _product(n - k + 1, n) elif isinstance(n, _MultisetHistogram): if k is None: return sum(_nP(n, i, replacement) for i in range(n[_N] + 1)) elif replacement: return n[_ITEMS]**k elif k == n[_N]: return factorial(k)/prod([factorial(i) for i in n[_M] if i > 1]) elif k > n[_N]: return 0 elif k == 1: return n[_ITEMS] else: # assert k >= 0 tot = 0 n = list(n) for i in range(len(n[_M])): if not n[i]: continue n[_N] -= 1 if n[i] == 1: n[i] = 0 n[_ITEMS] -= 1 tot += _nP(_MultisetHistogram(n), k - 1) n[_ITEMS] += 1 n[i] = 1 else: n[i] -= 1 tot += _nP(_MultisetHistogram(n), k - 1) n[i] += 1 n[_N] += 1 return tot
def eval(cls, n, m, x): if m.could_extract_minus_sign(): # P^{-m}_n ---> F * P^m_n return S.NegativeOne**(-m) * (factorial(m + n)/factorial(n - m)) * assoc_legendre(n, -m, x) if m == 0: # P^0_n ---> L_n return legendre(n, x) if x == 0: return 2**m*sqrt(S.Pi) / (gamma((1 - m - n)/2)*gamma(1 - (m - n)/2)) if n.is_Number and m.is_Number and n.is_integer and m.is_integer: if n.is_negative: raise ValueError("%s : 1st index must be nonnegative integer (got %r)" % (cls, n)) if abs(m) > n: raise ValueError("%s : abs('2nd index') must be <= '1st index' (got %r, %r)" % (cls, n, m)) return cls._eval_at_order(int(n), abs(int(m))).subs(_x, x)
def jacobi_normalized(n, a, b, x): r""" Jacobi polynomial :math:`P_n^{\left(\alpha, \beta\right)}(x)` jacobi_normalized(n, alpha, beta, x) gives the nth Jacobi polynomial in x, :math:`P_n^{\left(\alpha, \beta\right)}(x)`. The Jacobi polynomials are orthogonal on :math:`[-1, 1]` with respect to the weight :math:`\left(1-x\right)^\alpha \left(1+x\right)^\beta`. This functions returns the polynomials normilzed: .. math:: \int_{-1}^{1} P_m^{\left(\alpha, \beta\right)}(x) P_n^{\left(\alpha, \beta\right)}(x) (1-x)^{\alpha} (1+x)^{\beta} \mathrm{d}x = \delta_{m,n} Examples ======== >>> from sympy import jacobi_normalized >>> from sympy.abc import n,a,b,x >>> jacobi_normalized(n, a, b, x) jacobi(n, a, b, x)/sqrt(2**(a + b + 1)*gamma(a + n + 1)*gamma(b + n + 1)/((a + b + 2*n + 1)*factorial(n)*gamma(a + b + n + 1))) See Also ======== gegenbauer, chebyshevt_root, chebyshevu, chebyshevu_root, legendre, assoc_legendre, hermite, laguerre, assoc_laguerre, sympy.polys.orthopolys.jacobi_poly, sympy.polys.orthopolys.gegenbauer_poly sympy.polys.orthopolys.chebyshevt_poly sympy.polys.orthopolys.chebyshevu_poly sympy.polys.orthopolys.hermite_poly sympy.polys.orthopolys.legendre_poly sympy.polys.orthopolys.laguerre_poly References ========== .. [1] http://en.wikipedia.org/wiki/Jacobi_polynomials .. [2] http://mathworld.wolfram.com/JacobiPolynomial.html .. [3] http://functions.wolfram.com/Polynomials/JacobiP/ """ nfactor = ( S(2) ** (a + b + 1) * (gamma(n + a + 1) * gamma(n + b + 1)) / (2 * n + a + b + 1) / (factorial(n) * gamma(n + a + b + 1)) ) return jacobi(n, a, b, x) / sqrt(nfactor)
def taylor_term(n, x, *previous_terms): from sympy.functions.combinatorial.numbers import euler if n < 0 or n % 2 == 1: return S.Zero else: x = sympify(x) return euler(n) / factorial(n) * x**(n)
def _compute_formula(f, x, P, Q, k, m, k_max): """Computes the formula for f.""" from sympy.polys import roots sol = [] for i in range(k_max + 1, k_max + m + 1): r = f.diff(x, i).limit(x, 0) / factorial(i) if r is S.Zero: continue kterm = m*k + i res = r p = P.subs(k, kterm) q = Q.subs(k, kterm) c1 = p.subs(k, 1/k).leadterm(k)[0] c2 = q.subs(k, 1/k).leadterm(k)[0] res *= (-c1 / c2)**k for r, mul in roots(p, k).items(): res *= rf(-r, k)**mul for r, mul in roots(q, k).items(): res /= rf(-r, k)**mul sol.append((res, kterm)) return sol
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg.is_Integer: if arg.is_positive: return factorial(arg - 1) else: return S.ComplexInfinity elif arg.is_Rational: if arg.q == 2: n = abs(arg.p) // arg.q if arg.is_positive: k, coeff = n, S.One else: n = k = n + 1 if n & 1 == 0: coeff = S.One else: coeff = S.NegativeOne for i in range(3, 2*k, 2): coeff *= i if arg.is_positive: return coeff*sqrt(S.Pi) / 2**n else: return 2**n*sqrt(S.Pi) / coeff if arg.is_integer and arg.is_nonpositive: return S.ComplexInfinity
def _eval_expand_func(self, **hints): n, z = self.args if n.is_Integer and n.is_nonnegative: if z.is_Add: coeff = z.args[0] if coeff.is_Integer: e = -(n + 1) if coeff > 0: tail = Add(*[Pow( z - i, e) for i in range(1, int(coeff) + 1)]) else: tail = -Add(*[Pow( z + i, e) for i in range(0, int(-coeff))]) return polygamma(n, z - coeff) + (-1)**n*factorial(n)*tail elif z.is_Mul: coeff, z = z.as_two_terms() if coeff.is_Integer and coeff.is_positive: tail = [ polygamma(n, z + Rational( i, coeff)) for i in range(0, int(coeff)) ] if n == 0: return Add(*tail)/coeff + log(coeff) else: return Add(*tail)/coeff**(n + 1) z *= coeff return polygamma(n, z)
def _eval_rewrite_as_polynomial(self, n, x, **kwargs): from sympy import Sum # Make sure n \in N_0 if n.is_negative or n.is_integer is False: raise ValueError("Error: n should be a non-negative integer.") k = Dummy("k") kern = RisingFactorial(-n, k) / factorial(k)**2 * x**k return Sum(kern, (k, 0, n))
def eval(cls, a, x): # For lack of a better place, we use this one to extract branching # information. The following can be # found in the literature (c/f references given above), albeit scattered: # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s # 2) For fixed positive integers s, lowergamma(s, x) is an entire # function of x. # 3) For fixed non-positive integers s, # lowergamma(s, exp(I*2*pi*n)*x) = # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x) # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)). # 4) For fixed non-integral s, # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x), # where lowergamma_unbranched(s, x) is an entire function (in fact # of both s and x), i.e. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x) from sympy import unpolarify, I if x == 0: return S.Zero nx, n = x.extract_branch_factor() if a.is_integer and a.is_positive: nx = unpolarify(x) if nx != x: return lowergamma(a, nx) elif a.is_integer and a.is_nonpositive: if n != 0: return 2*pi*I*n*(-1)**(-a)/factorial(-a) + lowergamma(a, nx) elif n != 0: return exp(2*pi*I*n*a)*lowergamma(a, nx) # Special values. if a.is_Number: if a is S.One: return S.One - exp(-x) elif a is S.Half: return sqrt(pi)*erf(sqrt(x)) elif a.is_Integer or (2*a).is_Integer: b = a - 1 if b.is_positive: if a.is_integer: return factorial(b) - exp(-x) * factorial(b) * Add(*[x ** k / factorial(k) for k in range(a)]) else: return gamma(a) * (lowergamma(S.Half, x)/sqrt(pi) - exp(-x) * Add(*[x**(k-S.Half) / gamma(S.Half+k) for k in range(1, a+S.Half)])) if not a.is_Integer: return (-1)**(S.Half - a) * pi*erf(sqrt(x)) / gamma(1-a) + exp(-x) * Add(*[x**(k+a-1)*gamma(a) / gamma(a+k) for k in range(1, S(3)/2-a)])
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 eval(cls, n, z): n, z = list(map(sympify, (n, z))) from sympy import unpolarify if n.is_integer: if n.is_nonnegative: nz = unpolarify(z) if z != nz: return polygamma(n, nz) if n == -1: return loggamma(z) else: if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: if n.is_Number: if n is S.Zero: return S.Infinity else: return S.Zero elif z.is_Integer: if z.is_nonpositive: return S.ComplexInfinity else: if n is S.Zero: return -S.EulerGamma + harmonic(z - 1, 1) elif n.is_odd: return (-1)**(n + 1)*factorial(n)*zeta(n + 1, z) if n == 0: if z is S.NaN: return S.NaN elif z.is_Rational: # TODO actually *any* n/m can be done, but that is messy lookup = {S(1)/2: -2*log(2) - S.EulerGamma, S(1)/3: -S.Pi/2/sqrt(3) - 3*log(3)/2 - S.EulerGamma, S(1)/4: -S.Pi/2 - 3*log(2) - S.EulerGamma, S(3)/4: -3*log(2) - S.EulerGamma + S.Pi/2, S(2)/3: -3*log(3)/2 + S.Pi/2/sqrt(3) - S.EulerGamma} if z > 0: n = floor(z) z0 = z - n if z0 in lookup: return lookup[z0] + Add(*[1/(z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n if z0 in lookup: return lookup[z0] - Add(*[1/(z0 - 1 - k) for k in range(n)]) elif z in (S.Infinity, S.NegativeInfinity): return S.Infinity else: t = z.extract_multiplicatively(S.ImaginaryUnit) if t in (S.Infinity, S.NegativeInfinity): return S.Infinity
def f(rv): if not rv.is_Mul: return rv rvd = rv.as_powers_dict() nd_fact_args = [[], []] # numerator, denominator for k in rvd: if isinstance(k, factorial) and rvd[k].is_Integer: if rvd[k].is_positive: nd_fact_args[0].extend([k.args[0]]*rvd[k]) else: nd_fact_args[1].extend([k.args[0]]*-rvd[k]) rvd[k] = 0 if not nd_fact_args[0] or not nd_fact_args[1]: return rv hit = False for m in range(2): i = 0 while i < len(nd_fact_args[m]): ai = nd_fact_args[m][i] for j in range(i + 1, len(nd_fact_args[m])): aj = nd_fact_args[m][j] sum = ai + aj if sum in nd_fact_args[1 - m]: hit = True nd_fact_args[1 - m].remove(sum) del nd_fact_args[m][j] del nd_fact_args[m][i] rvd[binomial(sum, ai if count_ops(ai) < count_ops(aj) else aj)] += ( -1 if m == 0 else 1) break else: i += 1 if hit: return Mul(*([k**rvd[k] for k in rvd] + [factorial(k) for k in nd_fact_args[0]]))/Mul(*[factorial(k) for k in nd_fact_args[1]]) return rv
def taylor_term(n, x, *previous_terms): if n < 0 or n % 2 == 1: return S.Zero else: x = sympify(x) if len(previous_terms) > 2: p = previous_terms[-2] return p * x**2 / (n*(n - 1)) else: return x**(n)/factorial(n)
def eval(cls, a, z): from sympy import unpolarify, I, expint if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: # TODO: Holds only for Re(a) > 0: return gamma(a) # We extract branching information here. C/f lowergamma. nx, n = z.extract_branch_factor() if a.is_integer and (a > 0) == True: nx = unpolarify(z) if z != nx: return uppergamma(a, nx) elif a.is_integer and (a <= 0) == True: if n != 0: return -2*pi*I*n*(-1)**(-a)/factorial(-a) + uppergamma(a, nx) elif n != 0: return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx) # Special values. if a.is_Number: if a is S.One: return exp(-z) elif a is S.Half: return sqrt(pi)*erfc(sqrt(z)) elif a.is_Integer or (2*a).is_Integer: b = a - 1 if b.is_positive: if a.is_integer: return exp(-z) * factorial(b) * Add(*[z**k / factorial(k) for k in range(a)]) else: return gamma(a) * erfc(sqrt(z)) + (-1)**(a - S(3)/2) * exp(-z) * sqrt(z) * Add(*[gamma(-S.Half - k) * (-z)**k / gamma(1-a) for k in range(a - S.Half)]) elif b.is_Integer: return expint(-b, z)*unpolarify(z)**(b + 1) if not a.is_Integer: return (-1)**(S.Half - a) * pi*erfc(sqrt(z))/gamma(1-a) - z**a * exp(-z) * Add(*[z**k * gamma(a) / gamma(a+k+1) for k in range(S.Half - a)])
def taylor_term(n, x, *previous_terms): if n == 0: return 1 / sympify(x) elif n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) B = C.bernoulli(n + 1) F = factorial(n + 1) return 2**(n + 1) * B/F * x**n
def wedge(first_tensor, second_tensor): """ Finds outer product (wedge) of two tensor arguments. The algoritm is too find the asymmetric form of tensor product of two arguments. The resulted array is multiplied on coefficient which is coeff = factorial(p+s)/factorial(p)*factorial(s) Examples ======== """ if not isinstance(first_tensor, TensorArray): raise TypeError('Input must be of TensorArray type') if not isinstance(second_tensor, TensorArray): raise TypeError('Input must be of TensorArray type') p = len(first_tensor) s = len(second_tensor) coeff = factorial(p + s) / factorial(p) * factorial(s) return coeff * asymmetric(tensor_product(first_tensor, second_tensor))
def taylor_term(n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) if len(previous_terms) >= 2 and n > 2: p = previous_terms[-2] return -p * (n - 2)**2/(n*(n - 1)) * x**2 else: k = (n - 1) // 2 R = RisingFactorial(S.Half, k) F = factorial(k) return (-1)**k * R / F * x**n / n
def taylor_term(n, x, *previous_terms): from sympy import bernoulli if n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) a = 2**(n + 1) B = bernoulli(n + 1) F = factorial(n + 1) return a*(a - 1) * B/F * x**n
def eval(cls, n, a, b, x): # Simplify to other polynomials # P^{a, a}_n(x) if a == b: if a == -S.Half: return RisingFactorial(S.Half, n) / factorial(n) * chebyshevt(n, x) elif a == S.Zero: return legendre(n, x) elif a == S.Half: return RisingFactorial(3*S.Half, n) / factorial(n + 1) * chebyshevu(n, x) else: return RisingFactorial(a + 1, n) / RisingFactorial(2*a + 1, n) * gegenbauer(n, a + S.Half, x) elif b == -a: # P^{a, -a}_n(x) return gamma(n + a + 1) / gamma(n + 1) * (1 + x)**(a/2) / (1 - x)**(a/2) * assoc_legendre(n, -a, x) elif a == -b: # P^{-b, b}_n(x) return gamma(n - b + 1) / gamma(n + 1) * (1 - x)**(b/2) / (1 + x)**(b/2) * assoc_legendre(n, b, x) if not n.is_Number: # Symbolic result P^{a,b}_n(x) # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) if x.could_extract_minus_sign(): return S.NegativeOne**n * jacobi(n, b, a, -x) # We can evaluate for some special values of x if x == S.Zero: return (2**(-n) * gamma(a + n + 1) / (gamma(a + 1) * factorial(n)) * hyper([-b - n, -n], [a + 1], -1)) if x == S.One: return RisingFactorial(a + 1, n) / factorial(n) elif x == S.Infinity: if n.is_positive: # Make sure a+b+2*n \notin Z if (a + b + 2*n).is_integer: raise ValueError("Error. a + b + 2*n should not be an integer.") return RisingFactorial(a + b + n + 1, n) * S.Infinity else: # n is a given fixed integer, evaluate into polynomial return jacobi_poly(n, a, b, x)
def taylor_term(n, x, *previous_terms): """ Returns the next term in the Taylor series expansion """ from sympy import bernoulli if n == 0: return 1 / sympify(x) elif n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) B = bernoulli(n + 1) F = factorial(n + 1) return 2 * (1 - 2**n) * B / F * x**n
def test_bell_perm(): assert [len(set(generate_bell(i))) for i in range(1, 7)] == [factorial(i) for i in range(1, 7)] assert list(generate_bell(3)) == [(0, 1, 2), (0, 2, 1), (2, 0, 1), (2, 1, 0), (1, 2, 0), (1, 0, 2)] # generate_bell and trotterjohnson are advertised to return the same # permutations; this is not technically necessary so this test could # be removed for n in range(1, 5): p = Permutation(range(n)) b = generate_bell(n) for bi in b: assert bi == tuple(p.array_form) p = p.next_trotterjohnson() raises(ValueError, lambda: list(generate_bell(0)) ) # XXX is this consistent with other permutation algorithms?
def _solve_simple(f, x, DE, g, k): """Converts DE into RE and solves using :func:`rsolve`.""" from sympy.solvers import rsolve RE = hyper_re(DE, g, k) init = {} for i in range(len(Add.make_args(RE))): if i: f = f.diff(x) init[g(k).subs(k, i)] = f.limit(x, 0) / factorial(i) sol = rsolve(RE, g(k), init) if sol: return (sol, S.Zero, S.Zero)
def _eval_nseries(self, x, n, logx): if len(self.args) == 1: from sympy import Order, ceiling, expand_multinomial arg = self.args[0].nseries(x, n=n, logx=logx) lt = arg.compute_leading_term(x, logx=logx) lte = 1 if lt.is_Pow: lte = lt.exp if ceiling(n/lte) >= 1: s = Add(*[(-S.One)**(k - 1)*Integer(k)**(k - 2)/ factorial(k - 1)*arg**k for k in range(1, ceiling(n/lte))]) s = expand_multinomial(s) else: s = S.Zero return s + Order(x**n, x) return super(LambertW, self)._eval_nseries(x, n, logx)
def test_gosper_sum_AeqB_part2(): f2a = n**2 * a**n f2b = (n - r / 2) * binomial(r, n) f2c = factorial(n - 1)**2 / (factorial(n - x) * factorial(n + x)) g2a = -a * (a + 1) / (a - 1)**3 + a**(m + 1) * ( a**2 * m**2 - 2 * a * m**2 + m**2 - 2 * a * m + 2 * m + a + 1) / (a - 1)**3 g2b = (m - r) * binomial(r, m) / 2 ff = factorial(1 - x) * factorial(1 + x) g2c = 1 / ff * (1 - 1 / x**2) + factorial(m)**2 / ( x**2 * factorial(m - x) * factorial(m + x)) g = gosper_sum(f2a, (n, 0, m)) assert g is not None and simplify(g - g2a) == 0 g = gosper_sum(f2b, (n, 0, m)) assert g is not None and simplify(g - g2b) == 0 g = gosper_sum(f2c, (n, 1, m)) assert g is not None and simplify(g - g2c) == 0
def _eval_expand_func(self, **hints): n, z = self.args if n.is_Integer and n.is_nonnegative: if z.is_Add: coeff = z.args[0] if coeff.is_Integer: e = -(n + 1) if coeff > 0: tail = Add(*[Pow( z - i, e) for i in range(1, int(coeff) + 1)]) else: tail = -Add(*[Pow( z + i, e) for i in range(0, int(-coeff))]) return polygamma(n, z - coeff) + (-1)**n*factorial(n)*tail elif z.is_Mul: coeff, z = z.as_two_terms() if coeff.is_Integer and coeff.is_positive: tail = [ polygamma(n, z + Rational( i, coeff)) for i in range(0, int(coeff)) ] if n == 0: return Add(*tail)/coeff + log(coeff) else: return Add(*tail)/coeff**(n + 1) z *= coeff if n == 0 and z.is_Rational: p, q = z.as_numer_denom() # Reference: # Values of the polygamma functions at rational arguments, J. Choi, 2007 part_1 = -S.EulerGamma - pi * cot(p * pi / q) / 2 - log(q) + Add( *[cos(2 * k * pi * p / q) * log(2 * sin(k * pi / q)) for k in range(1, q)]) if z > 0: n = floor(z) z0 = z - n return part_1 + Add(*[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n return part_1 - Add(*[1 / (z0 - 1 - k) for k in range(n)]) return polygamma(n, z)
def eval(cls, a, x): # For lack of a better place, we use this one to extract branching # information. The following can be # found in the literature (c/f references given above), albeit scattered: # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s # 2) For fixed positive integers s, lowergamma(s, x) is an entire # function of x. # 3) For fixed non-positive integers s, # lowergamma(s, exp(I*2*pi*n)*x) = # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x) # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)). # 4) For fixed non-integral s, # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x), # where lowergamma_unbranched(s, x) is an entire function (in fact # of both s and x), i.e. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x) from sympy import unpolarify, I if x == 0: return S.Zero nx, n = x.extract_branch_factor() if a.is_integer and a.is_positive: nx = unpolarify(x) if nx != x: return lowergamma(a, nx) elif a.is_integer and a.is_nonpositive: if n != 0: return 2 * pi * I * n * (-1)**( -a) / factorial(-a) + lowergamma(a, nx) elif n != 0: return exp(2 * pi * I * n * a) * lowergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return S.One - exp(-x) elif a is S.Half: return sqrt(pi) * erf(sqrt(x)) elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, x) - x**b * exp(-x) if not a.is_Integer: return (cls(a + 1, x) + x**a * exp(-x)) / a
def _eval_nseries(self, x, n, logx, cdir=0): if len(self.args) == 1: from sympy.functions.elementary.integers import ceiling from sympy.series.order import Order arg = self.args[0].nseries(x, n=n, logx=logx) lt = arg.compute_leading_term(x, logx=logx) lte = 1 if lt.is_Pow: lte = lt.exp if ceiling(n/lte) >= 1: s = Add(*[(-S.One)**(k - 1)*Integer(k)**(k - 2)/ factorial(k - 1)*arg**k for k in range(1, ceiling(n/lte))]) s = expand_multinomial(s) else: s = S.Zero return s + Order(x**n, x) return super()._eval_nseries(x, n, logx)
def apply(given): assert len(given) == 2 assert given[0].is_ForAll and len(given[0].limits) == 2 j, a, n_munis_1 = given[0].limits[0] assert a == 1 x, S = given[0].limits[1] contains = given[0].function assert contains.is_Contains ref, _S = contains.args assert S == _S and ref.is_LAMBDA and S.is_set dtype = S.element_type assert len(ref.limits) == 1 i, a, _n_munis_1 = ref.limits[0] assert _n_munis_1 == n_munis_1 and a == 0 piecewise = ref.function assert piecewise.is_Piecewise and len(piecewise.args) == 3 x0, condition0 = piecewise.args[0] assert condition0.is_Equality and {*condition0.args} == {i, j} xj, conditionj = piecewise.args[1] assert conditionj.is_Equality and {*conditionj.args} == {i, 0} xi, conditioni = piecewise.args[2] assert conditioni n = n_munis_1 + 1 assert x[j] == xj and x[i] == xi and x[0] == x0 and dtype == x.dtype assert given[1].is_ForAll and len(given[1].limits) == 1 _x, _S = given[1].limits[0] assert x == _x and S == _S equality = given[1].function assert equality.is_Equality and {*equality.args } == {abs(x.set_comprehension()), n} return Equality(abs(S), factorial(n) * abs(UNION[x:S]({x.set_comprehension()})), given=given)
def test_guess_generating_function(): x = Symbol('x') assert guess_generating_function( [fibonacci(k) for k in range(5, 15)])['ogf'] == ((3 * x + 5) / (-x**2 - x + 1)) assert guess_generating_function( [1, 2, 5, 14, 41, 124, 383, 1200, 3799, 12122, 38919])['ogf'] == ((1 / (x**4 + 2 * x**2 - 4 * x + 1))**S.Half) assert guess_generating_function( sympify( "[3/2, 11/2, 0, -121/2, -363/2, 121, 4719/2, 11495/2, -8712, -178717/2]" ))['ogf'] == (x + Rational(3, 2)) / (11 * x**2 - 3 * x + 1) assert guess_generating_function([factorial(k) for k in range(12)], types=['egf'])['egf'] == 1 / (-x + 1) assert guess_generating_function([k + 1 for k in range(12)], types=['egf']) == { 'egf': (x + 1) * exp(x), 'lgdegf': (x + 2) / (x + 1) }
def test_rsolve_hyper(): assert rsolve_hyper([-1, -1, 1], 0, n) in [ C0 * (S.Half - S.Half * sqrt(5))**n + C1 * (S.Half + S.Half * sqrt(5))**n, C1 * (S.Half - S.Half * sqrt(5))**n + C0 * (S.Half + S.Half * sqrt(5))**n, ] assert rsolve_hyper([n**2 - 2, -2 * n - 1, 1], 0, n) in [ C0 * rf(sqrt(2), n) + C1 * rf(-sqrt(2), n), C1 * rf(sqrt(2), n) + C0 * rf(-sqrt(2), n), ] assert rsolve_hyper([n**2 - k, -2 * n - 1, 1], 0, n) in [ C0 * rf(sqrt(k), n) + C1 * rf(-sqrt(k), n), C1 * rf(sqrt(k), n) + C0 * rf(-sqrt(k), n), ] assert rsolve_hyper([2 * n * (n + 1), -n**2 - 3 * n + 2, n - 1], 0, n) == C1 * factorial(n) + C0 * 2**n assert rsolve_hyper( [n + 2, -(2 * n + 3) * (17 * n**2 + 51 * n + 39), n + 1], 0, n) == None assert rsolve_hyper([-n - 1, -1, 1], 0, n) == None assert rsolve_hyper([-1, 1], n, n).expand() == C0 + n**2 / 2 - n / 2 assert rsolve_hyper([-1, 1], 1 + n, n).expand() == C0 + n**2 / 2 + n / 2 assert rsolve_hyper([-1, 1], 3 * (n + n**2), n).expand() == C0 + n**3 - n assert rsolve_hyper([-a, 1], 0, n).expand() == C0 * a**n assert rsolve_hyper( [-a, 0, 1], 0, n).expand() == (-1)**n * C1 * a**(n / 2) + C0 * a**(n / 2) assert rsolve_hyper([1, 1, 1], 0, n).expand() == \ C0*(Rational(-1, 2) - sqrt(3)*I/2)**n + C1*(Rational(-1, 2) + sqrt(3)*I/2)**n assert rsolve_hyper([1, -2 * n / a - 2 / a, 1], 0, n) is None
def test_diff_nth_derivative(): f = Function("f") n = Symbol("n", integer=True) expr = diff(sin(x), (x, n)) expr2 = diff(f(x), (x, 2)) expr3 = diff(f(x), (x, n)) assert expr.subs(sin(x), cos(-x)) == Derivative(cos(-x), (x, n)) assert expr.subs(n, 1).doit() == cos(x) assert expr.subs(n, 2).doit() == -sin(x) assert expr2.subs(Derivative(f(x), x), y) == Derivative(y, x) # Currently not supported (cannot determine if `n > 1`): # assert expr3.subs(Derivative(f(x), x), y) == Derivative(y, (x, n-1)) assert expr3 == Derivative(f(x), (x, n)) assert diff(x, (x, n)) == Piecewise((x, Eq(n, 0)), (1, Eq(n, 1)), (0, True)) assert diff(2 * x, (x, n)).dummy_eq( Sum( Piecewise( ( 2 * x * factorial(n) / (factorial(y) * factorial(-y + n)), Eq(y, 0) & Eq(Max(0, -y + n), 0), ), ( 2 * factorial(n) / (factorial(y) * factorial(-y + n)), Eq(y, 0) & Eq(Max(0, -y + n), 1), ), (0, True), ), (y, 0, n), )) # TODO: assert diff(x**2, (x, n)) == x**(2-n)*ff(2, n) exprm = x * sin(x) mul_diff = diff(exprm, (x, n)) assert isinstance(mul_diff, Sum) for i in range(5): assert mul_diff.subs(n, i).doit() == exprm.diff((x, i)).expand() exprm2 = 2 * y * x * sin(x) * cos(x) * log(x) * exp(x) dex = exprm2.diff((x, n)) assert isinstance(dex, Sum) for i in range(7): assert dex.subs(n, i).doit().expand() == exprm2.diff((x, i)).expand() assert (cos(x) * sin(y)).diff([[x, y, z]]) == NDimArray( [-sin(x) * sin(y), cos(x) * cos(y), 0])
def eval(cls, a, z): from sympy import unpolarify, I, expint if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: # TODO: Holds only for Re(a) > 0: return gamma(a) # We extract branching information here. C/f lowergamma. nx, n = z.extract_branch_factor() if a.is_integer and (a > 0) == True: nx = unpolarify(z) if z != nx: return uppergamma(a, nx) elif a.is_integer and (a <= 0) == True: if n != 0: return -2 * pi * I * n * (-1)**( -a) / factorial(-a) + uppergamma(a, nx) elif n != 0: return gamma(a) * (1 - exp(2 * pi * I * n * a)) + exp( 2 * pi * I * n * a) * uppergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return exp(-z) elif a is S.Half: return sqrt(pi) * (1 - erf(sqrt(z))) # TODO could use erfc... elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, z) + z**b * exp(-z) elif b.is_Integer: return expint(-b, z) * unpolarify(z)**(b + 1) if not a.is_Integer: return (cls(a + 1, z) - z**a * exp(-z)) / a
def _solve_explike_DE(f, x, DE, g, k): """Solves DE with constant coefficients.""" from sympy.solvers import rsolve for t in Add.make_args(DE): coeff, d = t.as_independent(g) if coeff.free_symbols: return RE = exp_re(DE, g, k) init = {} for i in range(len(Add.make_args(RE))): if i: f = f.diff(x) init[g(k).subs(k, i)] = f.limit(x, 0) sol = rsolve(RE, g(k), init) if sol: return (sol / factorial(k), S.Zero, S.Zero)
def _stirling1(n, k): if n == k == 0: return S.One if 0 in (n, k): return S.Zero n1 = n - 1 # some special values if n == k: return S.One elif k == 1: return factorial(n1) elif k == n1: return C.binomial(n, 2) elif k == n - 2: return (3 * n - 1) * C.binomial(n, 3) / 4 elif k == n - 3: return C.binomial(n, 2) * C.binomial(n, 4) # general recurrence return n1 * _stirling1(n1, k) + _stirling1(n1, k - 1)
def apply(*given): forall_x, forall_p, equality = given assert forall_x.is_ForAll and forall_p.is_ForAll assert len(forall_x.limits) == 1 x, S = forall_x.limits[0] assert forall_x.function.is_Equality x_set_comprehension, e = forall_x.function.args assert x_set_comprehension == x.set_comprehension() assert len(forall_p.limits) == 2 (_x, _S), (p, P) = forall_p.limits assert x == _x and S == _S assert forall_p.function.is_Contains lamda, _S = forall_p.function.args assert S == _S assert lamda.is_LAMBDA n = x.shape[0] k = lamda.variable assert lamda == LAMBDA[k:n](x[p[k]]) if P.is_set: P = P.condition_set().condition assert p.shape[0] == n lhs, rhs = P.args assert rhs == Interval(0, n - 1, integer=True) assert lhs == p.set_comprehension() assert equality.is_Equality assert equality.rhs == n assert equality.lhs.is_Abs assert equality.lhs.arg == e return Equality(abs(S), factorial(n), given=given)
def test_maxima_functions(): assert parse_maxima('expand( (x+1)^2)') == x**2 + 2 * x + 1 assert parse_maxima('factor( x**2 + 2*x + 1)') == (x + 1)**2 assert parse_maxima('2*cos(x)^2 + sin(x)^2') == 2 * cos(x)**2 + sin(x)**2 assert parse_maxima('trigexpand(sin(2*x)+cos(2*x))') == \ -1 + 2*cos(x)**2 + 2*cos(x)*sin(x) assert parse_maxima('solve(x^2-4,x)') == [-2, 2] assert parse_maxima('limit((1+1/x)^x,x,inf)') == E assert parse_maxima('limit(sqrt(-x)/x,x,0,minus)') is -oo assert parse_maxima('diff(x^x, x)') == x**x * (1 + log(x)) assert parse_maxima('sum(k, k, 1, n)', name_dict=dict( n=Symbol('n', integer=True), k=Symbol('k', integer=True))) == (n**2 + n) / 2 assert parse_maxima('product(k, k, 1, n)', name_dict=dict(n=Symbol('n', integer=True), k=Symbol('k', integer=True))) == factorial(n) assert parse_maxima('ratsimp((x^2-1)/(x+1))') == x - 1 assert Abs( parse_maxima('float(sec(%pi/3) + csc(%pi/3))') - 3.154700538379252) < 10**(-5)
def test_sympify_factorial(): assert sympify('x!') == factorial(x) assert sympify('(x+1)!') == factorial(x + 1) assert sympify('(1 + y*(x + 1))!') == factorial(1 + y * (x + 1)) assert sympify('(1 + y*(x + 1)!)^2') == (1 + y * factorial(x + 1))**2 assert sympify('y*x!') == y * factorial(x) assert sympify('x!!') == factorial2(x) assert sympify('(x+1)!!') == factorial2(x + 1) assert sympify('(1 + y*(x + 1))!!') == factorial2(1 + y * (x + 1)) assert sympify('(1 + y*(x + 1)!!)^2') == (1 + y * factorial2(x + 1))**2 assert sympify('y*x!!') == y * factorial2(x) assert sympify('factorial2(x)!') == factorial(factorial2(x)) raises(SympifyError, lambda: sympify("+!!")) raises(SympifyError, lambda: sympify(")!!")) raises(SympifyError, lambda: sympify("!")) raises(SympifyError, lambda: sympify("(!)")) raises(SympifyError, lambda: sympify("x!!!"))
def _rsolve_hypergeometric(f, x, P, Q, k, m): """Recursive wrapper to rsolve_hypergeometric. Returns a Tuple of (formula, series independent terms, maximum power of x in independent terms) if successful otherwise ``None``. See :func:`rsolve_hypergeometric` for details. """ from sympy.polys import lcm, roots from sympy.integrals import integrate # transformation - c proots, qroots = roots(P, k), roots(Q, k) all_roots = dict(proots) all_roots.update(qroots) scale = lcm( [r.as_numer_denom()[1] for r, t in all_roots.items() if r.is_rational]) f, P, Q, m = _transformation_c(f, x, P, Q, k, m, scale) # transformation - a qroots = roots(Q, k) if qroots: k_min = Min(*qroots.keys()) else: k_min = S.Zero shift = k_min + m f, P, Q, m = _transformation_a(f, x, P, Q, k, m, shift) l = (x * f).limit(x, 0) if not isinstance(l, Limit) and l != 0: # Ideally should only be l != 0 return None qroots = roots(Q, k) if qroots: k_max = Max(*qroots.keys()) else: k_max = S.Zero ind, mp = S.Zero, -oo for i in range(k_max + m + 1): r = f.diff(x, i).limit(x, 0) / factorial(i) if r.is_finite is False: old_f = f f, P, Q, m = _transformation_a(f, x, P, Q, k, m, i) f, P, Q, m = _transformation_e(f, x, P, Q, k, m) sol, ind, mp = _rsolve_hypergeometric(f, x, P, Q, k, m) sol = _apply_integrate(sol, x, k) sol = _apply_shift(sol, i) ind = integrate(ind, x) ind += (old_f - ind).limit(x, 0) # constant of integration mp += 1 return sol, ind, mp elif r: ind += r * x**(i + shift) pow_x = Rational((i + shift), scale) if pow_x > mp: mp = pow_x # maximum power of x ind = ind.subs(x, x**(1 / scale)) sol = _compute_formula(f, x, P, Q, k, m, k_max) sol = _apply_shift(sol, shift) sol = _apply_scale(sol, scale) return sol, ind, mp
def _eval_rewrite_as_polynomial(self, n, x): from sympy 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 _eval_rewrite_as_polynomial(self, n, a, x): from sympy import Sum k = Dummy("k") kern = ((-1)**k * RisingFactorial(a, n - k) * (2 * x)**(n - 2 * k) / (factorial(k) * factorial(n - 2 * k))) return Sum(kern, (k, 0, floor(n / 2)))
def _eval_rewrite_as_polynomial(self, n, x): from sympy import Sum k = Dummy("k") kern = (-1)**k / (factorial(k) * factorial(n - 2 * k)) * (2 * x)**(n - 2 * k) return factorial(n) * Sum(kern, (k, 0, floor(n / 2)))
def _eval_rewrite_as_zeta(self, n, z, **kwargs): if n.is_integer: if (n - S.One).is_nonnegative: return (-1)**(n + 1) * factorial(n) * zeta(n + 1, z)
def _eval_rewrite_as_factorial(self, z, **kwargs): return factorial(z - 1)
def to_sequence(self): """ Finds the recurrence relation in power series expansion of the function. Examples ======== >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators >>> from sympy.polys.domains import ZZ, QQ >>> from sympy import symbols >>> x = symbols('x') >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx') >>> HolonomicFunction(Dx - 1, x, 0, [1]).to_sequence() HolonomicSequence((-1) + (n + 1)Sn, n), u(0) = 1 See Also ======== HolonomicFunction.series References ========== hal.inria.fr/inria-00070025/document """ dict1 = {} n = symbols('n', integer=True) dom = self.annihilator.parent.base.dom R, _ = RecurrenceOperators(dom.old_poly_ring(n), 'Sn') for i, j in enumerate(self.annihilator.listofpoly): listofdmp = j.all_coeffs() degree = len(listofdmp) - 1 for k in range(degree + 1): coeff = listofdmp[degree - k] if coeff == 0: continue if i - k in dict1: dict1[i - k] += (coeff * rf(n - k + 1, i)) else: dict1[i - k] = (coeff * rf(n - k + 1, i)) sol = [] lower = min(dict1.keys()) upper = max(dict1.keys()) for j in range(lower, upper + 1): if j in dict1.keys(): sol.append(dict1[j].subs(n, n - lower)) else: sol.append(S(0)) # recurrence relation sol = RecurrenceOperator(sol, R) if not self._have_init_cond: return HolonomicSequence(sol) if self.x0 != 0: return HolonomicSequence(sol) # computing the initial conditions for recurrence order = sol.order all_roots = roots(sol.listofpoly[-1].rep, filter='Z') all_roots = all_roots.keys() if all_roots: max_root = max(all_roots) if max_root >= 0: order += max_root + 1 y0 = _extend_y0(self, order) u0 = [] # u(n) = y^n(0)/factorial(n) for i, j in enumerate(y0): u0.append(j / factorial(i)) return HolonomicSequence(sol, u0)
def test_PoissonProcess(): X = PoissonProcess("X", 3) assert X.state_space == S.Naturals0 assert X.index_set == Interval(0, oo) assert X.lamda == 3 t, d, x, y = symbols('t d x y', positive=True) assert isinstance(X(t), RandomIndexedSymbol) assert X.distribution(t) == PoissonDistribution(3 * t) raises(ValueError, lambda: PoissonProcess("X", -1)) raises(NotImplementedError, lambda: X[t]) raises(IndexError, lambda: X(-5)) assert X.joint_distribution(X(2), X(3)) == JointDistributionHandmade( Lambda((X(2), X(3)), 6**X(2) * 9**X(3) * exp(-15) / (factorial(X(2)) * factorial(X(3))))) assert X.joint_distribution(4, 6) == JointDistributionHandmade( Lambda((X(4), X(6)), 12**X(4) * 18**X(6) * exp(-30) / (factorial(X(4)) * factorial(X(6))))) assert P(X(t) < 1) == exp(-3 * t) assert P(Eq(X(t), 0), Contains(t, Interval.Lopen(3, 5))) == exp(-6) # exp(-2*lamda) res = P(Eq(X(t), 1), Contains(t, Interval.Lopen(3, 4))) assert res == 3 * exp(-3) # Equivalent to P(Eq(X(t), 1))**4 because of non-overlapping intervals assert P( Eq(X(t), 1) & Eq(X(d), 1) & Eq(X(x), 1) & Eq(X(y), 1), Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Lopen(1, 2)) & Contains(x, Interval.Lopen(2, 3)) & Contains(y, Interval.Lopen(3, 4))) == res**4 # Return Probability because of overlapping intervals assert P(Eq(X(t), 2) & Eq(X(d), 3), Contains(t, Interval.Lopen(0, 2)) & Contains(d, Interval.Ropen(2, 4))) == \ Probability(Eq(X(d), 3) & Eq(X(t), 2), Contains(t, Interval.Lopen(0, 2)) & Contains(d, Interval.Ropen(2, 4))) raises(ValueError, lambda: P( Eq(X(t), 2) & Eq(X(d), 3), Contains(t, Interval.Lopen(0, 4)) & Contains(d, Interval.Lopen(3, oo))) ) # no bound on d assert P(Eq(X(3), 2)) == 81 * exp(-9) / 2 assert P(Eq(X(t), 2), Contains(t, Interval.Lopen(0, 5))) == 225 * exp(-15) / 2 # Check that probability works correctly by adding it to 1 res1 = P(X(t) <= 3, Contains(t, Interval.Lopen(0, 5))) res2 = P(X(t) > 3, Contains(t, Interval.Lopen(0, 5))) assert res1 == 691 * exp(-15) assert (res1 + res2).simplify() == 1 # Check Not and Or assert P(Not(Eq(X(t), 2) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) & \ Contains(d, Interval.Lopen(7, 8))).simplify() == -18*exp(-6) + 234*exp(-9) + 1 assert P(Eq(X(t), 2) | Ne(X(t), 4), Contains(t, Interval.Ropen(2, 4))) == 1 - 36 * exp(-6) raises(ValueError, lambda: P(X(t) > 2, X(t) + X(d))) assert E( X(t)) == 3 * t # property of the distribution at a given timestamp assert E( X(t)**2 + X(d) * 2 + X(y)**3, Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Lopen(1, 2)) & Contains(y, Interval.Ropen(3, 4))) == 75 assert E(X(t)**2, Contains(t, Interval.Lopen(0, 1))) == 12 assert E(x*(X(t) + X(d))*(X(t)**2+X(d)**2), Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Ropen(1, 2))) == \ Expectation(x*(X(d) + X(t))*(X(d)**2 + X(t)**2), Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Ropen(1, 2))) # Value Error because of infinite time bound raises(ValueError, lambda: E(X(t)**3, Contains(t, Interval.Lopen(1, oo)))) # Equivalent to E(X(t)**2) - E(X(d)**2) == E(X(1)**2) - E(X(1)**2) == 0 assert E((X(t) + X(d)) * (X(t) - X(d)), Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Lopen(1, 2))) == 0 assert E(X(2) + x * E(X(5))) == 15 * x + 6 assert E(x * X(1) + y) == 3 * x + y assert P(Eq(X(1), 2) & Eq(X(t), 3), Contains(t, Interval.Lopen(1, 2))) == 81 * exp(-6) / 4 Y = PoissonProcess("Y", 6) Z = X + Y assert Z.lamda == X.lamda + Y.lamda == 9 raises(ValueError, lambda: X + 5) # should be added be only PoissonProcess instance N, M = Z.split(4, 5) assert N.lamda == 4 assert M.lamda == 5 raises(ValueError, lambda: Z.split(3, 2)) # 2+3 != 9 raises( ValueError, lambda: P(Eq(X(t), 0), Contains(t, Interval.Lopen(1, 3)) & Eq(X(1), 0))) # check if it handles queries with two random variables in one args res1 = P(Eq(N(3), N(5))) assert res1 == P(Eq(N(t), 0), Contains(t, Interval(3, 5))) res2 = P(N(3) > N(1)) assert res2 == P((N(t) > 0), Contains(t, Interval(1, 3))) assert P(N(3) < N(1)) == 0 # condition is not possible res3 = P(N(3) <= N(1)) # holds only for Eq(N(3), N(1)) assert res3 == P(Eq(N(t), 0), Contains(t, Interval(1, 3))) # tests from https://www.probabilitycourse.com/chapter11/11_1_2_basic_concepts_of_the_poisson_process.php X = PoissonProcess('X', 10) # 11.1 assert P(Eq(X(S(1) / 3), 3) & Eq(X(1), 10)) == exp(-10) * Rational(8000000000, 11160261) assert P(Eq(X(1), 1), Eq(X(S(1) / 3), 3)) == 0 assert P(Eq(X(1), 10), Eq(X(S(1) / 3), 3)) == P(Eq(X(S(2) / 3), 7)) X = PoissonProcess('X', 2) # 11.2 assert P(X(S(1) / 2) < 1) == exp(-1) assert P(X(3) < 1, Eq(X(1), 0)) == exp(-4) assert P(Eq(X(4), 3), Eq(X(2), 3)) == exp(-4) X = PoissonProcess('X', 3) assert P(Eq(X(2), 5) & Eq(X(1), 2)) == Rational(81, 4) * exp(-6) # check few properties assert P( X(2) <= 3, X(1) >= 1) == 3 * P(Eq(X(1), 0)) + 2 * P(Eq(X(1), 1)) + P(Eq(X(1), 2)) assert P(X(2) <= 3, X(1) > 1) == 2 * P(Eq(X(1), 0)) + 1 * P(Eq(X(1), 1)) assert P(Eq(X(2), 5) & Eq(X(1), 2)) == P(Eq(X(1), 3)) * P(Eq(X(1), 2)) assert P(Eq(X(3), 4), Eq(X(1), 3)) == P(Eq(X(2), 1)) #test issue 20078 assert (2 * X(t) + 3 * X(t)).simplify() == 5 * X(t) assert (2 * X(t) - 3 * X(t)).simplify() == -X(t) assert (2 * (0.25 * X(t))).simplify() == 0.5 * X(t) assert (2 * X(t) * 0.25 * X(t)).simplify() == 0.5 * X(t)**2 assert (X(t)**2 + X(t)**3).simplify() == (X(t) + 1) * X(t)**2
def _eval_rewrite_as_polynomial(self, n, m, x, **kwargs): from sympy import Sum k = Dummy("k") kern = factorial(2*n - 2*k)/(2**n*factorial(n - k)*factorial( k)*factorial(n - 2*k - m))*(-1)**k*x**(n - m - 2*k) return (1 - x**2)**(m/2) * Sum(kern, (k, 0, floor((n - m)*S.Half)))
def test_factorial_series(): n = Symbol('n', integer=True) assert factorial(n).series(n, 0, 3) == \ 1 - n*EulerGamma + n**2*(EulerGamma**2/2 + pi**2/12) + O(n**3)
def test_factorial_Mod(): pr = Symbol('pr', prime=True) p, q = 10**9 + 9, 10**9 + 33 # prime modulo r, s = 10**7 + 5, 33333333 # composite modulo assert Mod(factorial(pr - 1), pr) == pr - 1 assert Mod(factorial(pr - 1), -pr) == -1 assert Mod(factorial(r - 1, evaluate=False), r) == 0 assert Mod(factorial(s - 1, evaluate=False), s) == 0 assert Mod(factorial(p - 1, evaluate=False), p) == p - 1 assert Mod(factorial(q - 1, evaluate=False), q) == q - 1 assert Mod(factorial(p - 50, evaluate=False), p) == 854928834 assert Mod(factorial(q - 1800, evaluate=False), q) == 905504050 assert Mod(factorial(153, evaluate=False), r) == Mod(factorial(153), r) assert Mod(factorial(255, evaluate=False), s) == Mod(factorial(255), s) assert Mod(factorial(4, evaluate=False), 3) == S.Zero assert Mod(factorial(5, evaluate=False), 6) == S.Zero
def test_rf_eval_apply(): x, y = symbols('x,y') n, k = symbols('n k', integer=True) m = Symbol('m', integer=True, nonnegative=True) assert rf(nan, y) is nan assert rf(x, nan) is nan assert unchanged(rf, x, y) assert rf(oo, 0) == 1 assert rf(-oo, 0) == 1 assert rf(oo, 6) is oo assert rf(-oo, 7) is -oo assert rf(-oo, 6) is oo assert rf(oo, -6) is oo assert rf(-oo, -7) is oo assert rf(-1, pi) == 0 assert rf(-5, 1 + I) == 0 assert unchanged(rf, -3, k) assert unchanged(rf, x, Symbol('k', integer=False)) assert rf(-3, Symbol('k', integer=False)) == 0 assert rf(Symbol('x', negative=True, integer=True), Symbol('k', integer=False)) == 0 assert rf(x, 0) == 1 assert rf(x, 1) == x assert rf(x, 2) == x * (x + 1) assert rf(x, 3) == x * (x + 1) * (x + 2) assert rf(x, 5) == x * (x + 1) * (x + 2) * (x + 3) * (x + 4) assert rf(x, -1) == 1 / (x - 1) assert rf(x, -2) == 1 / ((x - 1) * (x - 2)) assert rf(x, -3) == 1 / ((x - 1) * (x - 2) * (x - 3)) assert rf(1, 100) == factorial(100) assert rf(x**2 + 3 * x, 2) == (x**2 + 3 * x) * (x**2 + 3 * x + 1) assert isinstance(rf(x**2 + 3 * x, 2), Mul) assert rf(x**3 + x, -2) == 1 / ((x**3 + x - 1) * (x**3 + x - 2)) assert rf(Poly(x**2 + 3 * x, x), 2) == Poly(x**4 + 8 * x**3 + 19 * x**2 + 12 * x, x) assert isinstance(rf(Poly(x**2 + 3 * x, x), 2), Poly) raises(ValueError, lambda: rf(Poly(x**2 + 3 * x, x, y), 2)) assert rf(Poly(x**3 + x, x), -2) == 1 / (x**6 - 9 * x**5 + 35 * x**4 - 75 * x**3 + 94 * x**2 - 66 * x + 20) raises(ValueError, lambda: rf(Poly(x**3 + x, x, y), -2)) assert rf(x, m).is_integer is None assert rf(n, k).is_integer is None assert rf(n, m).is_integer is True assert rf(n, k + pi).is_integer is False assert rf(n, m + pi).is_integer is False assert rf(pi, m).is_integer is False def check(x, k, o, n): a, b = Dummy(), Dummy() r = lambda x, k: o(a, b).rewrite(n).subs({a: x, b: k}) for i in range(-5, 5): for j in range(-5, 5): assert o(i, j) == r(i, j), (o, n, i, j) check(x, k, rf, ff) check(x, k, rf, binomial) check(n, k, rf, factorial) check(x, y, rf, factorial) check(x, y, rf, binomial) assert rf(x, k).rewrite(ff) == ff(x + k - 1, k) assert rf(x, k).rewrite(gamma) == Piecewise( (gamma(k + x) / gamma(x), x > 0), ((-1)**k * gamma(1 - x) / gamma(-k - x + 1), True)) assert rf(5, k).rewrite(gamma) == gamma(k + 5) / 24 assert rf(x, k).rewrite(binomial) == factorial(k) * binomial(x + k - 1, k) assert rf(n, k).rewrite(factorial) == Piecewise( (factorial(k + n - 1) / factorial(n - 1), n > 0), ((-1)**k * factorial(-n) / factorial(-k - n), True)) assert rf(5, k).rewrite(factorial) == factorial(k + 4) / 24 assert rf(x, y).rewrite(factorial) == rf(x, y) assert rf(x, y).rewrite(binomial) == rf(x, y) import random from mpmath import rf as mpmath_rf for i in range(100): x = -500 + 500 * random.random() k = -500 + 500 * random.random() assert (abs(mpmath_rf(x, k) - rf(x, k)) < 10**(-15))