def E(expr): res1 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1), (x, 0, oo), (y, -oo, oo), meijerg=True) res2 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1), (y, -oo, oo), (x, 0, oo), meijerg=True) assert expand_mul(res1) == expand_mul(res2) return res1
def test_issue841(): from sympy import expand_mul from sympy.abc import k assert expand_mul(integrate(exp(-x ** 2) * exp(I * k * x), (x, -oo, oo))) == sqrt(pi) * exp(-k ** 2 / 4) a, d = symbols("a d", positive=True) assert expand_mul(integrate(exp(-a * x ** 2 + 2 * d * x), (x, -oo, oo))) == sqrt(pi) * exp(d ** 2 / a) / sqrt(a)
def eval(cls, arg): from sympy.simplify.simplify import signsimp if hasattr(arg, '_eval_Abs'): obj = arg._eval_Abs() if obj is not None: return obj # handle what we can arg = signsimp(arg, evaluate=False) if arg.is_Mul: known = [] unk = [] for t in arg.args: tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known*unk if arg is S.NaN: return S.NaN if arg.is_Pow: base, exponent = arg.as_base_exp() if base.is_real: if exponent.is_integer: if exponent.is_even: return arg if base is S.NegativeOne: return S.One if base.func is cls and exponent is S.NegativeOne: return arg return Abs(base)**exponent if base.is_positive == True: return base**re(exponent) return (-base)**re(exponent)*C.exp(-S.Pi*im(exponent)) if isinstance(arg, C.exp): return C.exp(re(arg.args[0])) if arg.is_zero: # it may be an Expr that is zero return S.Zero if arg.is_nonnegative: return arg if arg.is_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_nonnegative: return arg2 if arg.is_Add: if arg.has(S.Infinity, S.NegativeInfinity): if any(a.is_infinite for a in arg.as_real_imag()): return S.Infinity if arg.is_real is None and arg.is_imaginary is None: if all(a.is_real or a.is_imaginary or (S.ImaginaryUnit*a).is_real for a in arg.args): from sympy import expand_mul return sqrt(expand_mul(arg*arg.conjugate())) if arg.is_real is False and arg.is_imaginary is False: from sympy import expand_mul return sqrt(expand_mul(arg*arg.conjugate()))
def test_acsch(): x = Symbol('x') assert acsch(-x) == acsch(-x) assert acsch(x) == -acsch(-x) # values at fixed points assert acsch(1) == log(1 + sqrt(2)) assert acsch(-1) == - log(1 + sqrt(2)) assert acsch(0) == zoo assert acsch(2) == log((1+sqrt(5))/2) assert acsch(-2) == - log((1+sqrt(5))/2) assert acsch(I) == - I*pi/2 assert acsch(-I) == I*pi/2 assert acsch(-I*(sqrt(6) + sqrt(2))) == I*pi / 12 assert acsch(I*(sqrt(2) + sqrt(6))) == -I*pi / 12 assert acsch(-I*(1 + sqrt(5))) == I*pi / 10 assert acsch(I*(1 + sqrt(5))) == -I*pi / 10 assert acsch(-I*2 / sqrt(2 - sqrt(2))) == I*pi / 8 assert acsch(I*2 / sqrt(2 - sqrt(2))) == -I*pi / 8 assert acsch(-I*2) == I*pi / 6 assert acsch(I*2) == -I*pi / 6 assert acsch(-I*sqrt(2 + 2/sqrt(5))) == I*pi / 5 assert acsch(I*sqrt(2 + 2/sqrt(5))) == -I*pi / 5 assert acsch(-I*sqrt(2)) == I*pi / 4 assert acsch(I*sqrt(2)) == -I*pi / 4 assert acsch(-I*(sqrt(5)-1)) == 3*I*pi / 10 assert acsch(I*(sqrt(5)-1)) == -3*I*pi / 10 assert acsch(-I*2 / sqrt(3)) == I*pi / 3 assert acsch(I*2 / sqrt(3)) == -I*pi / 3 assert acsch(-I*2 / sqrt(2 + sqrt(2))) == 3*I*pi / 8 assert acsch(I*2 / sqrt(2 + sqrt(2))) == -3*I*pi / 8 assert acsch(-I*sqrt(2 - 2/sqrt(5))) == 2*I*pi / 5 assert acsch(I*sqrt(2 - 2/sqrt(5))) == -2*I*pi / 5 assert acsch(-I*(sqrt(6) - sqrt(2))) == 5*I*pi / 12 assert acsch(I*(sqrt(6) - sqrt(2))) == -5*I*pi / 12 # properties # acsch(x) == asinh(1/x) assert acsch(-I*sqrt(2)) == asinh(I/sqrt(2)) assert acsch(-I*2 / sqrt(3)) == asinh(I*sqrt(3) / 2) # acsch(x) == -I*asin(I/x) assert acsch(-I*sqrt(2)) == -I*asin(-1/sqrt(2)) assert acsch(-I*2 / sqrt(3)) == -I*asin(-sqrt(3)/2) # csch(acsch(x)) / x == 1 assert expand_mul(csch(acsch(-I*(sqrt(6) + sqrt(2)))) / (-I*(sqrt(6) + sqrt(2)))) == 1 assert expand_mul(csch(acsch(I*(1 + sqrt(5)))) / ((I*(1 + sqrt(5))))) == 1 assert (csch(acsch(I*sqrt(2 - 2/sqrt(5)))) / (I*sqrt(2 - 2/sqrt(5)))).simplify() == 1 assert (csch(acsch(-I*sqrt(2 - 2/sqrt(5)))) / (-I*sqrt(2 - 2/sqrt(5)))).simplify() == 1 # numerical evaluation assert str(acsch(5*I+1).n(6)) == '0.0391819 - 0.193363*I' assert str(acsch(-5*I+1).n(6)) == '0.0391819 + 0.193363*I'
def test_asech(): x = Symbol('x') assert asech(-x) == asech(-x) # values at fixed points assert asech(1) == 0 assert asech(-1) == pi*I assert asech(0) == oo assert asech(2) == I*pi/3 assert asech(-2) == 2*I*pi / 3 # at infinites assert asech(oo) == I*pi/2 assert asech(-oo) == I*pi/2 assert asech(zoo) == nan assert asech(I) == log(1 + sqrt(2)) - I*pi/2 assert asech(-I) == log(1 + sqrt(2)) + I*pi/2 assert asech(sqrt(2) - sqrt(6)) == 11*I*pi / 12 assert asech(sqrt(2 - 2/sqrt(5))) == I*pi / 10 assert asech(-sqrt(2 - 2/sqrt(5))) == 9*I*pi / 10 assert asech(2 / sqrt(2 + sqrt(2))) == I*pi / 8 assert asech(-2 / sqrt(2 + sqrt(2))) == 7*I*pi / 8 assert asech(sqrt(5) - 1) == I*pi / 5 assert asech(1 - sqrt(5)) == 4*I*pi / 5 assert asech(-sqrt(2*(2 + sqrt(2)))) == 5*I*pi / 8 # properties # asech(x) == acosh(1/x) assert asech(sqrt(2)) == acosh(1/sqrt(2)) assert asech(2/sqrt(3)) == acosh(sqrt(3)/2) assert asech(2/sqrt(2 + sqrt(2))) == acosh(sqrt(2 + sqrt(2))/2) assert asech(S(2)) == acosh(1/S(2)) # asech(x) == I*acos(1/x) # (Note: the exact formula is asech(x) == +/- I*acos(1/x)) assert asech(-sqrt(2)) == I*acos(-1/sqrt(2)) assert asech(-2/sqrt(3)) == I*acos(-sqrt(3)/2) assert asech(-S(2)) == I*acos(-S.Half) assert asech(-2/sqrt(2)) == I*acos(-sqrt(2)/2) # sech(asech(x)) / x == 1 assert expand_mul(sech(asech(sqrt(6) - sqrt(2))) / (sqrt(6) - sqrt(2))) == 1 assert expand_mul(sech(asech(sqrt(6) + sqrt(2))) / (sqrt(6) + sqrt(2))) == 1 assert (sech(asech(sqrt(2 + 2/sqrt(5)))) / (sqrt(2 + 2/sqrt(5)))).simplify() == 1 assert (sech(asech(-sqrt(2 + 2/sqrt(5)))) / (-sqrt(2 + 2/sqrt(5)))).simplify() == 1 assert (sech(asech(sqrt(2*(2 + sqrt(2))))) / (sqrt(2*(2 + sqrt(2))))).simplify() == 1 assert expand_mul(sech(asech((1 + sqrt(5)))) / ((1 + sqrt(5)))) == 1 assert expand_mul(sech(asech((-1 - sqrt(5)))) / ((-1 - sqrt(5)))) == 1 assert expand_mul(sech(asech((-sqrt(6) - sqrt(2)))) / ((-sqrt(6) - sqrt(2)))) == 1 # numerical evaluation assert str(asech(5*I).n(6)) == '0.19869 - 1.5708*I' assert str(asech(-5*I).n(6)) == '0.19869 + 1.5708*I'
def test_issue_3940(): a, b, c, d = symbols('a:d', positive=True, finite=True) assert integrate(exp(-x**2 + I*c*x), x) == \ -sqrt(pi)*exp(-c**2/4)*erf(I*c/2 - x)/2 assert integrate(exp(a*x**2 + b*x + c), x) == \ sqrt(pi)*exp(c)*exp(-b**2/(4*a))*erfi(sqrt(a)*x + b/(2*sqrt(a)))/(2*sqrt(a)) from sympy import expand_mul from sympy.abc import k assert expand_mul(integrate(exp(-x**2)*exp(I*k*x), (x, -oo, oo))) == \ sqrt(pi)*exp(-k**2/4) a, d = symbols('a d', positive=True) assert expand_mul(integrate(exp(-a*x**2 + 2*d*x), (x, -oo, oo))) == \ sqrt(pi)*exp(d**2/a)/sqrt(a)
def eval(cls, arg): from sympy.simplify.simplify import signsimp if hasattr(arg, "_eval_Abs"): obj = arg._eval_Abs() if obj is not None: return obj # handle what we can arg = signsimp(arg, evaluate=False) if arg.is_Mul: known = [] unk = [] for t in arg.args: tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known * unk if arg is S.NaN: return S.NaN if arg.is_zero: # it may be an Expr that is zero return S.Zero if arg.is_nonnegative: return arg if arg.is_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_nonnegative: return arg2 if arg.is_real is False and arg.is_imaginary is False: from sympy import expand_mul return sqrt(expand_mul(arg * arg.conjugate())) if arg.is_real is None and arg.is_imaginary is None and arg.is_Add: if all(a.is_real or a.is_imaginary or (S.ImaginaryUnit * a).is_real for a in arg.args): from sympy import expand_mul return sqrt(expand_mul(arg * arg.conjugate())) if arg.is_Pow: base, exponent = arg.as_base_exp() if exponent.is_even and base.is_real: return arg if exponent.is_integer and base is S.NegativeOne: return S.One
def _eval_expand_trig(self, **hints): from sympy import expand_mul arg = self.args[0] x = None if arg.is_Add: # TODO, implement more if deep stuff here # TODO: Do this more efficiently for more than two terms x, y = arg.as_two_terms() sx = sin(x, evaluate=False)._eval_expand_trig() sy = sin(y, evaluate=False)._eval_expand_trig() cx = cos(x, evaluate=False)._eval_expand_trig() cy = cos(y, evaluate=False)._eval_expand_trig() return sx*cy + sy*cx else: n, x = arg.as_coeff_Mul(rational=True) if n.is_Integer: # n will be positive because of .eval # canonicalization # See http://mathworld.wolfram.com/Multiple-AngleFormulas.html if n.is_odd: return (-1)**((n - 1)/2)*C.chebyshevt(n, sin(x)) else: return expand_mul((-1)**(n/2 - 1)*cos(x)*C.chebyshevu(n - 1, sin(x)), deep=False) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_Rational: return self.rewrite(sqrt) return sin(arg)
def _eval_as_leading_term(self, x): from sympy import expand_mul, factor_terms old = self self = expand_mul(self) if not self.is_Add: return self.as_leading_term(x) unbounded = [t for t in self.args if t.is_unbounded] self = self.func(*[t.as_leading_term(x) for t in self.args]).removeO() if not self: # simple leading term analysis gave us 0 but we have to send # back a term, so compute the leading term (via series) return old.compute_leading_term(x) elif self is S.NaN: return old.func._from_args(unbounded) elif not self.is_Add: return self else: plain = self.func(*[s for s, _ in self.extract_leading_order(x)]) rv = factor_terms(plain, fraction=False) rv_simplify = rv.simplify() # if it simplifies to an x-free expression, return that; # tests don't fail if we don't but it seems nicer to do this if x not in rv_simplify.free_symbols: if rv_simplify.is_zero and plain.is_zero is not True: return (self - plain)._eval_as_leading_term(x) return rv_simplify return rv
def _bell_poly(n, prev): s = 1 a = 1 for k in xrange(2, n+1): a = a * (n-k+1) // (k-1) s += a * prev[k-1] return expand_mul(_sym * s)
def test_sqrtdenest(): d = {sqrt(5 + 2 * sqrt(6)): sqrt(2) + sqrt(3), sqrt(sqrt(2)): sqrt(sqrt(2)), sqrt(5+sqrt(7)): sqrt(5+sqrt(7)), sqrt(3+sqrt(5+2*sqrt(7))): sqrt(6+3*sqrt(7))/(sqrt(2)*(5+2*sqrt(7))**Rational(1,4)) + 3*(5+2*sqrt(7))**Rational(1,4)/(sqrt(2)*sqrt(6+3*sqrt(7))), sqrt(3+2*sqrt(3)): 3**Rational(1,4)/sqrt(2)+3/(sqrt(2)*3**Rational(1,4))} for i in d: assert sqrtdenest(i) == d[i] or denester([i])[0] == d[i] # this test caused a pattern recognition failure in sqrtdenest # nest = sqrt(2) + sqrt(5) - sqrt(7) nest = symbols('nest') x0, x1, x2, x3, x4, x5, x6 = symbols('x:7') l = sqrt(2) + sqrt(5) r = sqrt(7) + nest s = (l**2 - r**2).expand() + nest**2 # == nest**2 ok = solve(nest**4 - s**2, nest)[1] # this will change if results order changes assert abs((l - r).subs(nest, ok).n()) < 1e-12 x0 = sqrt(3) x2 = root(45*I*x0 - 28, 3) x3 = 19/x2 x4 = x2 + x3 x5 = -x4 - 14 x6 = sqrt(-x5) ans = -x0*x6/3 + x0*sqrt(-x4 + 28 - 6*sqrt(210)*x6/x5)/3 assert expand_mul(radsimp(ok) - ans) == 0 # issue 2554 eq = sqrt(sqrt(sqrt(2) + 2) + 2) assert sqrtdenest(eq) == eq
def _bell_incomplete_poly(n, k, symbols): r""" The second kind of Bell polynomials (incomplete Bell polynomials). Calculated by recurrence formula: .. math:: B_{n,k}(x_1, x_2, \dotsc, x_{n-k+1}) = \sum_{m=1}^{n-k+1} \x_m \binom{n-1}{m-1} B_{n-m,k-1}(x_1, x_2, \dotsc, x_{n-m-k}) where B_{0,0} = 1; B_{n,0} = 0; for n>=1 B_{0,k} = 0; for k>=1 """ if (n==0) and (k==0): return S.One elif (n==0) or (k==0): return S.Zero s = S.Zero a = S.One for m in xrange(1, n-k+2): s += a*bell._bell_incomplete_poly(n-m, k-1, symbols)*symbols[m-1] a = a*(n-m)/m return expand_mul(s)
def _eval_as_leading_term(self, x): from sympy import expand_mul, factor_terms old = self self = expand_mul(self) if not self.is_Add: return self.as_leading_term(x) unbounded = [t for t in self.args if t.is_unbounded] if unbounded: return Add._from_args(unbounded) self = Add(*[t.as_leading_term(x) for t in self.args]).removeO() if not self: # simple leading term analysis gave us 0 but we have to send # back a term, so compute the leading term (via series) return old.compute_leading_term(x) elif not self.is_Add: return self else: plain = Add(*[s for s, _ in self.extract_leading_order(x)]) rv = factor_terms(plain, fraction=False) rv_fraction = factor_terms(rv, fraction=True) # if it simplifies to an x-free expression, return that; # tests don't fail if we don't but it seems nicer to do this if x not in rv_fraction.free_symbols: return rv_fraction return rv
def eval(cls, arg): if arg.is_Mul: known = [] unk = [] for t in arg.args: tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known*unk if arg is S.NaN: return S.NaN if arg.is_zero: return arg if arg.is_positive: return arg if arg.is_negative: return -arg if arg.is_real is False: from sympy import expand_mul return sqrt( expand_mul(arg * arg.conjugate()) ) if arg.is_Pow: base, exponent = arg.as_base_exp() if exponent.is_even and base.is_real: return arg
def eval(cls, arg): if hasattr(arg, "_eval_Abs"): obj = arg._eval_Abs() if obj is not None: return obj if arg.is_Mul: known = [] unk = [] for t in arg.args: tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known * unk if arg is S.NaN: return S.NaN if arg.is_nonnegative: return arg if arg.is_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_nonnegative: return arg2 if arg.is_real is False and arg.is_imaginary is False: from sympy import expand_mul return sqrt(expand_mul(arg * arg.conjugate())) if arg.is_Pow: base, exponent = arg.as_base_exp() if exponent.is_even and base.is_real: return arg
def _combine_inverse(lhs, rhs): """ Returns lhs - rhs, but treats arguments like symbols, so things like oo - oo return 0, instead of a nan. """ from sympy import oo, I, expand_mul if lhs == oo and rhs == oo or lhs == oo*I and rhs == oo*I: return S.Zero return expand_mul(lhs - rhs)
def _eval_expand_func(self, **hints): from sympy import log, expand_mul, Dummy, exp_polar, I s, z = self.args if s == 1: return -log(1 + exp_polar(-I*pi)*z) if s.is_Integer and s <= 0: u = Dummy('u') start = u/(1 - u) for _ in range(-s): start = u*start.diff(u) return expand_mul(start).subs(u, z) return polylog(s, z)
def _inverse_mellin_transform(F, s, x_, strip, as_meijerg=False): """ A helper for the real inverse_mellin_transform function, this one here assumes x to be real and positive. """ from sympy import (expand, expand_mul, hyperexpand, meijerg, And, Or, arg, pi, re, factor, Heaviside, gamma, Add) x = _dummy('t', 'inverse-mellin-transform', F, positive=True) # Actually, we won't try integration at all. Instead we use the definition # of the Meijer G function as a fairly general inverse mellin transform. F = F.rewrite(gamma) for g in [factor(F), expand_mul(F), expand(F)]: if g.is_Add: # do all terms separately ress = [_inverse_mellin_transform(G, s, x, strip, as_meijerg, noconds=False) \ for G in g.args] conds = [p[1] for p in ress] ress = [p[0] for p in ress] res = Add(*ress) if not as_meijerg: res = factor(res, gens=res.atoms(Heaviside)) return res.subs(x, x_), And(*conds) try: a, b, C, e, fac = _rewrite_gamma(g, s, strip[0], strip[1]) except IntegralTransformError: continue G = meijerg(a, b, C/x**e) if as_meijerg: h = G else: h = hyperexpand(G) if h.is_Piecewise and len(h.args) == 3: # XXX we break modularity here! h = Heaviside(x - abs(C))*h.args[0].args[0] \ + Heaviside(abs(C) - x)*h.args[1].args[0] # We must ensure that the intgral along the line we want converges, # and return that value. # See [L], 5.2 cond = [abs(arg(G.argument)) < G.delta*pi] # Note: we allow ">=" here, this corresponds to convergence if we let # limits go to oo symetrically. ">" corresponds to absolute convergence. cond += [And(Or(len(G.ap) != len(G.bq), 0 >= re(G.nu) + 1), abs(arg(G.argument)) == G.delta*pi)] cond = Or(*cond) if cond is False: raise IntegralTransformError('Inverse Mellin', F, 'does not converge') return (h*fac).subs(x, x_), cond raise IntegralTransformError('Inverse Mellin', F, '')
def solution(pars): (a2,a1,a0),(t1,t2),(k1,k2),(y0,yd0)=pars a2,a1,a0 = map(int,[a2,a1,a0]) den = a2*s**2+a1*s+a0 V1 = apart(1/s/den).as_ordered_terms() # const. V2 = apart(1/s**2/den).as_ordered_terms() # lin. Iv1,Iv2 = ilt_pfe(V1),ilt_pfe(V2) LIC = (a2*(s*y0+yd0) + a1*y0)/den y1 = ILT(LIC, s,t) y2 = k1*Iv2 # k1, t y3 = (k2-k1)*Iv2.subs(t,t-t1)*H(t-t1) # k2-k1,(t-t1)*H(t-t1) y4 = (t1*(k2-k1)-k2*t2)*Iv1.subs(t,t-t1)*H(t-t1) # t1*(k2-k1)-k2*t2,H(t-t1), nulove pre spojite y5 = -k2*Iv2.subs(t,t-t2)*H(t-t2) # -k2, (t-t2)*H(t-t2) y = expand_mul(simplify(y1+y2+y3+y4+y5)) return y
def _eval_expand_func(self, **hints): from sympy import log, expand_mul, Dummy, exp_polar, I if hints.get('deep', False): s, z = map(lambda x: x._eval_expand_func(**hints), self.args) else: s, z = self.args if s == 1: return -log(1 + exp_polar(-I*pi)*z) if s.is_Integer and s <= 0: u = Dummy('u') start = u/(1 - u) for _ in range(-s): start = u*start.diff(u) return expand_mul(start).subs(u, z) return polylog(s, z)
def eval(cls, arg): if arg is S.NaN: return S.NaN if arg.is_zero: return arg if arg.is_positive: return arg if arg.is_negative: return -arg coeff, terms = arg.as_coeff_mul() if coeff is not S.One: return cls(coeff) * cls(Mul(*terms)) if arg.is_real is False: from sympy import expand_mul return sqrt( expand_mul(arg * arg.conjugate()) ) if arg.is_Pow: base, exponent = arg.as_base_exp() if exponent.is_even and base.is_real: return arg return
def eval(cls, nu, z): from sympy import unpolarify, expand_mul, uppergamma, exp, gamma, factorial nu2 = unpolarify(nu) if nu != nu2: return expint(nu2, z) if nu.is_Integer and nu <= 0 or (not nu.is_Integer and (2 * nu).is_Integer): return unpolarify(expand_mul(z ** (nu - 1) * uppergamma(1 - nu, z))) # Extract branching information. This can be deduced from what is # explained in lowergamma.eval(). z, n = z.extract_branch_factor() if n == 0: return if nu.is_integer: if (nu > 0) is not True: return return expint(nu, z) - 2 * pi * I * n * (-1) ** (nu - 1) / factorial(nu - 1) * unpolarify(z) ** (nu - 1) else: return (exp(2 * I * pi * nu * n) - 1) * z ** (nu - 1) * gamma(1 - nu) + expint(nu, z)
def _eval_expand_mul(self, **hints): from sympy import fraction, expand_mul # Handle things like 1/(x*(x + 1)), which are automatically converted # to 1/x*1/(x + 1) expr = self n, d = fraction(expr) if d.is_Mul: expr = n/d._eval_expand_mul(**hints) if not expr.is_Mul: return expand_mul(expr, deep=False) plain, sums, rewrite = [], [], False for factor in expr.args: if factor.is_Add: sums.append(factor) rewrite = True else: if factor.is_commutative: plain.append(factor) else: sums.append(Basic(factor)) # Wrapper if not rewrite: return expr else: plain = Mul(*plain) if sums: terms = Mul._expandsums(sums) args = [] for term in terms: t = Mul(plain, term) if t.is_Mul and any(a.is_Add for a in t.args): t = t._eval_expand_mul() args.append(t) return Add(*args) else: return plain
def doit(self, **hints): """ Try to evaluate the transform in closed form. This general function handles linearity, but apart from that leaves pretty much everything to _compute_transform. Standard hints are the following: - ``simplify``: whether or not to simplify the result - ``noconds``: if True, don't return convergence conditions - ``needeval``: if True, raise IntegralTransformError instead of returning IntegralTransform objects The default values of these hints depend on the concrete transform, usually the default is ``(simplify, noconds, needeval) = (True, False, False)``. """ from sympy import Add, expand_mul, Mul from sympy.core.function import AppliedUndef needeval = hints.pop('needeval', False) try_directly = not any(func.has(self.function_variable) \ for func in self.function.atoms(AppliedUndef)) if try_directly: try: return self._compute_transform(self.function, self.function_variable, self.transform_variable, **hints) except IntegralTransformError: pass fn = self.function if not fn.is_Add: fn = expand_mul(fn) if fn.is_Add: hints['needeval'] = needeval res = [self.__class__(*([x] + list(self.args[1:]))).doit(**hints) for x in fn.args] extra = [] ress = [] for x in res: if not isinstance(x, tuple): x = [x] ress.append(x[0]) if len(x) > 1: extra += [x[1:]] res = Add(*ress) if not extra: return res try: extra = self._collapse_extra(extra) return tuple([res]) + tuple(extra) except IntegralTransformError: pass if needeval: raise IntegralTransformError(self.__class__._name, self.function, 'needeval') # TODO handle derivatives etc # pull out constant coefficients coeff, rest = fn.as_coeff_mul(self.function_variable) return coeff*self.__class__(*([Mul(*rest)] + list(self.args[1:])))
>>> _rewrite_sin((2*pi, 0), s, 0, S(1)/2) (gamma(2*s), gamma(-2*s + 1), pi) >>> _rewrite_sin((2*pi, 0), s, S(1)/2, 1) (gamma(2*s - 1), gamma(-2*s + 2), -pi) """ # (This is a separate function because it is moderately complicated, # and I want to doctest it.) # We want to use pi/sin(pi*x) = gamma(x)*gamma(1-x). # But there is one comlication: the gamma functions determine the # inegration contour in the definition of the G-function. Usually # it would not matter if this is slightly shifted, unless this way # we create an undefined function! # So we try to write this in such a way that the gammas are # eminently on the right side of the strip. from sympy import expand_mul, pi, ceiling, gamma, re m = expand_mul(m/pi) n = expand_mul(n/pi) r = ceiling(-m*a - n.as_real_imag()[0]) # Don't use re(n), does not expand return gamma(m*s + n + r), gamma(1 - n - r - m*s), (-1)**r*pi class MellinTransformStripError(ValueError): """ Exception raised by _rewrite_gamma. Mainly for internal use. """ pass def _rewrite_gamma(f, s, a, b): """ Try to rewrite the product f(s) as a product of gamma functions, so that the inverse mellin transform of f can be expressed as a meijer G function.
def test_pinjoint_arbitrary_axis(): theta, omega = dynamicsymbols('theta_J, omega_J') # When the bodies are attached though masscenters but axess are opposite. N, A, P, C = _generate_body() PinJoint('J', P, C, child_axis=-A.x) assert (-A.x).angle_between(N.x) == 0 assert -A.x.express(N) == N.x assert A.dcm(N) == Matrix([[-1, 0, 0], [0, -cos(theta), -sin(theta)], [0, -sin(theta), cos(theta)]]) assert A.ang_vel_in(N) == omega*N.x assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) assert C.masscenter.pos_from(P.masscenter) == 0 assert C.masscenter.pos_from(P.masscenter).express(N).simplify() == 0 assert C.masscenter.vel(N) == 0 # When axes are different and parent joint is at masscenter but child joint # is at a unit vector from child masscenter. N, A, P, C = _generate_body() PinJoint('J', P, C, child_axis=A.y, child_joint_pos=A.x) assert A.y.angle_between(N.x) == 0 # Axis are aligned assert A.y.express(N) == N.x assert A.dcm(N) == Matrix([[0, -cos(theta), -sin(theta)], [1, 0, 0], [0, -sin(theta), cos(theta)]]) assert A.ang_vel_in(N) == omega*N.x assert A.ang_vel_in(N).express(A) == omega * A.y assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) angle = A.ang_vel_in(N).angle_between(A.y) assert angle.xreplace({omega: 1}) == 0 assert C.masscenter.vel(N) == omega*A.z assert C.masscenter.pos_from(P.masscenter) == -A.x assert (C.masscenter.pos_from(P.masscenter).express(N).simplify() == cos(theta)*N.y + sin(theta)*N.z) assert C.masscenter.vel(N).angle_between(A.x) == pi/2 # Similar to previous case but wrt parent body N, A, P, C = _generate_body() PinJoint('J', P, C, parent_axis=N.y, parent_joint_pos=N.x) assert N.y.angle_between(A.x) == 0 # Axis are aligned assert N.y.express(A) == A.x assert A.dcm(N) == Matrix([[0, 1, 0], [-cos(theta), 0, sin(theta)], [sin(theta), 0, cos(theta)]]) assert A.ang_vel_in(N) == omega*N.y assert A.ang_vel_in(N).express(A) == omega*A.x assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) angle = A.ang_vel_in(N).angle_between(A.x) assert angle.xreplace({omega: 1}) == 0 assert C.masscenter.vel(N).simplify() == - omega*N.z assert C.masscenter.pos_from(P.masscenter) == N.x # Both joint pos id defined but different axes N, A, P, C = _generate_body() PinJoint('J', P, C, parent_joint_pos=N.x, child_joint_pos=A.x, child_axis=A.x+A.y) assert expand_mul(N.x.angle_between(A.x + A.y)) == 0 # Axis are aligned assert (A.x + A.y).express(N).simplify() == sqrt(2)*N.x assert _simplify_matrix(A.dcm(N)) == Matrix([ [sqrt(2)/2, -sqrt(2)*cos(theta)/2, -sqrt(2)*sin(theta)/2], [sqrt(2)/2, sqrt(2)*cos(theta)/2, sqrt(2)*sin(theta)/2], [0, -sin(theta), cos(theta)]]) assert A.ang_vel_in(N) == omega*N.x assert (A.ang_vel_in(N).express(A).simplify() == (omega*A.x + omega*A.y)/sqrt(2)) assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) angle = A.ang_vel_in(N).angle_between(A.x + A.y) assert angle.xreplace({omega: 1}) == 0 assert C.masscenter.vel(N).simplify() == (omega * A.z)/sqrt(2) assert C.masscenter.pos_from(P.masscenter) == N.x - A.x assert (C.masscenter.pos_from(P.masscenter).express(N).simplify() == (1 - sqrt(2)/2)*N.x + sqrt(2)*cos(theta)/2*N.y + sqrt(2)*sin(theta)/2*N.z) assert (C.masscenter.vel(N).express(N).simplify() == -sqrt(2)*omega*sin(theta)/2*N.y + sqrt(2)*omega*cos(theta)/2*N.z) assert C.masscenter.vel(N).angle_between(A.x) == pi/2 N, A, P, C = _generate_body() PinJoint('J', P, C, parent_joint_pos=N.x, child_joint_pos=A.x, child_axis=A.x+A.y-A.z) assert expand_mul(N.x.angle_between(A.x + A.y - A.z)) == 0 # Axis aligned assert (A.x + A.y - A.z).express(N).simplify() == sqrt(3)*N.x assert _simplify_matrix(A.dcm(N)) == Matrix([ [sqrt(3)/3, -sqrt(6)*sin(theta + pi/4)/3, sqrt(6)*cos(theta + pi/4)/3], [sqrt(3)/3, sqrt(6)*cos(theta + pi/12)/3, sqrt(6)*sin(theta + pi/12)/3], [-sqrt(3)/3, sqrt(6)*cos(theta + 5*pi/12)/3, sqrt(6)*sin(theta + 5*pi/12)/3]]) assert A.ang_vel_in(N) == omega*N.x assert A.ang_vel_in(N).express(A).simplify() == (omega*A.x + omega*A.y - omega*A.z)/sqrt(3) assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) angle = A.ang_vel_in(N).angle_between(A.x + A.y-A.z) assert angle.xreplace({omega: 1}) == 0 assert C.masscenter.vel(N).simplify() == (omega*A.y + omega*A.z)/sqrt(3) assert C.masscenter.pos_from(P.masscenter) == N.x - A.x assert (C.masscenter.pos_from(P.masscenter).express(N).simplify() == (1 - sqrt(3)/3)*N.x + sqrt(6)*sin(theta + pi/4)/3*N.y - sqrt(6)*cos(theta + pi/4)/3*N.z) assert (C.masscenter.vel(N).express(N).simplify() == sqrt(6)*omega*cos(theta + pi/4)/3*N.y + sqrt(6)*omega*sin(theta + pi/4)/3*N.z) assert C.masscenter.vel(N).angle_between(A.x) == pi/2 N, A, P, C = _generate_body() m, n = symbols('m n') PinJoint('J', P, C, parent_joint_pos=m*N.x, child_joint_pos=n*A.x, child_axis=A.x+A.y-A.z, parent_axis=N.x-N.y+N.z) angle = (N.x-N.y+N.z).angle_between(A.x+A.y-A.z) assert expand_mul(angle) == 0 # Axis are aligned assert ((A.x-A.y+A.z).express(N).simplify() == (-4*cos(theta)/3 - S(1)/3)*N.x + (S(1)/3 - 4*sin(theta + pi/6)/3)*N.y + (4*cos(theta + pi/3)/3 - S(1)/3)*N.z) assert _simplify_matrix(A.dcm(N)) == Matrix([ [S(1)/3 - 2*cos(theta)/3, -2*sin(theta + pi/6)/3 - S(1)/3, 2*cos(theta + pi/3)/3 + S(1)/3], [2*cos(theta + pi/3)/3 + S(1)/3, 2*cos(theta)/3 - S(1)/3, 2*sin(theta + pi/6)/3 + S(1)/3], [-2*sin(theta + pi/6)/3 - S(1)/3, 2*cos(theta + pi/3)/3 + S(1)/3, 2*cos(theta)/3 - S(1)/3]]) assert A.ang_vel_in(N) == (omega*N.x - omega*N.y + omega*N.z)/sqrt(3) assert A.ang_vel_in(N).express(A).simplify() == (omega*A.x + omega*A.y - omega*A.z)/sqrt(3) assert A.ang_vel_in(N).magnitude() == sqrt(omega**2) angle = A.ang_vel_in(N).angle_between(A.x+A.y-A.z) assert angle.xreplace({omega: 1}) == 0 assert (C.masscenter.vel(N).simplify() == (m*omega*N.y + m*omega*N.z + n*omega*A.y + n*omega*A.z)/sqrt(3)) assert C.masscenter.pos_from(P.masscenter) == m*N.x - n*A.x assert (C.masscenter.pos_from(P.masscenter).express(N).simplify() == (m + n*(2*cos(theta) - 1)/3)*N.x + n*(2*sin(theta + pi/6) + 1)/3*N.y - n*(2*cos(theta + pi/3) + 1)/3*N.z) assert (C.masscenter.vel(N).express(N).simplify() == -2*n*omega*sin(theta)/3*N.x + (sqrt(3)*m + 2*n*cos(theta + pi/6))*omega/3*N.y + (sqrt(3)*m + 2*n*sin(theta + pi/3))*omega/3*N.z) assert expand_mul(C.masscenter.vel(N).angle_between(m*N.x - n*A.x)) == pi/2
def test_acsch(): x = Symbol('x') assert unchanged(acsch, x) assert acsch(-x) == -acsch(x) # values at fixed points assert acsch(1) == log(1 + sqrt(2)) assert acsch(-1) == -log(1 + sqrt(2)) assert acsch(0) is zoo assert acsch(2) == log((1 + sqrt(5)) / 2) assert acsch(-2) == -log((1 + sqrt(5)) / 2) assert acsch(I) == -I * pi / 2 assert acsch(-I) == I * pi / 2 assert acsch(-I * (sqrt(6) + sqrt(2))) == I * pi / 12 assert acsch(I * (sqrt(2) + sqrt(6))) == -I * pi / 12 assert acsch(-I * (1 + sqrt(5))) == I * pi / 10 assert acsch(I * (1 + sqrt(5))) == -I * pi / 10 assert acsch(-I * 2 / sqrt(2 - sqrt(2))) == I * pi / 8 assert acsch(I * 2 / sqrt(2 - sqrt(2))) == -I * pi / 8 assert acsch(-I * 2) == I * pi / 6 assert acsch(I * 2) == -I * pi / 6 assert acsch(-I * sqrt(2 + 2 / sqrt(5))) == I * pi / 5 assert acsch(I * sqrt(2 + 2 / sqrt(5))) == -I * pi / 5 assert acsch(-I * sqrt(2)) == I * pi / 4 assert acsch(I * sqrt(2)) == -I * pi / 4 assert acsch(-I * (sqrt(5) - 1)) == 3 * I * pi / 10 assert acsch(I * (sqrt(5) - 1)) == -3 * I * pi / 10 assert acsch(-I * 2 / sqrt(3)) == I * pi / 3 assert acsch(I * 2 / sqrt(3)) == -I * pi / 3 assert acsch(-I * 2 / sqrt(2 + sqrt(2))) == 3 * I * pi / 8 assert acsch(I * 2 / sqrt(2 + sqrt(2))) == -3 * I * pi / 8 assert acsch(-I * sqrt(2 - 2 / sqrt(5))) == 2 * I * pi / 5 assert acsch(I * sqrt(2 - 2 / sqrt(5))) == -2 * I * pi / 5 assert acsch(-I * (sqrt(6) - sqrt(2))) == 5 * I * pi / 12 assert acsch(I * (sqrt(6) - sqrt(2))) == -5 * I * pi / 12 assert acsch(nan) is nan # properties # acsch(x) == asinh(1/x) assert acsch(-I * sqrt(2)) == asinh(I / sqrt(2)) assert acsch(-I * 2 / sqrt(3)) == asinh(I * sqrt(3) / 2) # acsch(x) == -I*asin(I/x) assert acsch(-I * sqrt(2)) == -I * asin(-1 / sqrt(2)) assert acsch(-I * 2 / sqrt(3)) == -I * asin(-sqrt(3) / 2) # csch(acsch(x)) / x == 1 assert expand_mul( csch(acsch(-I * (sqrt(6) + sqrt(2)))) / (-I * (sqrt(6) + sqrt(2)))) == 1 assert expand_mul(csch(acsch(I * (1 + sqrt(5)))) / (I * (1 + sqrt(5)))) == 1 assert (csch(acsch(I * sqrt(2 - 2 / sqrt(5)))) / (I * sqrt(2 - 2 / sqrt(5)))).simplify() == 1 assert (csch(acsch(-I * sqrt(2 - 2 / sqrt(5)))) / (-I * sqrt(2 - 2 / sqrt(5)))).simplify() == 1 # numerical evaluation assert str(acsch(5 * I + 1).n(6)) == '0.0391819 - 0.193363*I' assert str(acsch(-5 * I + 1).n(6)) == '0.0391819 + 0.193363*I'
def test_probability(): # various integrals from probability theory from sympy.abc import x, y from sympy import symbols, Symbol, Abs, expand_mul, combsimp, powsimp, sin mu1, mu2 = symbols("mu1 mu2", real=True, nonzero=True, finite=True) sigma1, sigma2 = symbols("sigma1 sigma2", real=True, nonzero=True, finite=True, positive=True) rate = Symbol("lambda", real=True, positive=True, finite=True) def normal(x, mu, sigma): return 1 / sqrt(2 * pi * sigma ** 2) * exp(-(x - mu) ** 2 / 2 / sigma ** 2) def exponential(x, rate): return rate * exp(-rate * x) assert integrate(normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == 1 assert integrate(x * normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == mu1 assert integrate(x ** 2 * normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == mu1 ** 2 + sigma1 ** 2 assert integrate(x ** 3 * normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == mu1 ** 3 + 3 * mu1 * sigma1 ** 2 assert integrate(normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 assert ( integrate(x * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1 ) assert ( integrate(y * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu2 ) assert ( integrate(x * y * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1 * mu2 ) assert ( integrate( (x + y + 1) * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True ) == 1 + mu1 + mu2 ) assert ( integrate( (x + y - 1) * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True ) == -1 + mu1 + mu2 ) i = integrate(x ** 2 * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) assert not i.has(Abs) assert simplify(i) == mu1 ** 2 + sigma1 ** 2 assert ( integrate(y ** 2 * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == sigma2 ** 2 + mu2 ** 2 ) assert integrate(exponential(x, rate), (x, 0, oo), meijerg=True) == 1 assert integrate(x * exponential(x, rate), (x, 0, oo), meijerg=True) == 1 / rate assert integrate(x ** 2 * exponential(x, rate), (x, 0, oo), meijerg=True) == 2 / rate ** 2 def E(expr): res1 = integrate(expr * exponential(x, rate) * normal(y, mu1, sigma1), (x, 0, oo), (y, -oo, oo), meijerg=True) res2 = integrate(expr * exponential(x, rate) * normal(y, mu1, sigma1), (y, -oo, oo), (x, 0, oo), meijerg=True) assert expand_mul(res1) == expand_mul(res2) return res1 assert E(1) == 1 assert E(x * y) == mu1 / rate assert E(x * y ** 2) == mu1 ** 2 / rate + sigma1 ** 2 / rate ans = sigma1 ** 2 + 1 / rate ** 2 assert simplify(E((x + y + 1) ** 2) - E(x + y + 1) ** 2) == ans assert simplify(E((x + y - 1) ** 2) - E(x + y - 1) ** 2) == ans assert simplify(E((x + y) ** 2) - E(x + y) ** 2) == ans # Beta' distribution alpha, beta = symbols("alpha beta", positive=True) betadist = x ** (alpha - 1) * (1 + x) ** (-alpha - beta) * gamma(alpha + beta) / gamma(alpha) / gamma(beta) assert integrate(betadist, (x, 0, oo), meijerg=True) == 1 i = integrate(x * betadist, (x, 0, oo), meijerg=True, conds="separate") assert (combsimp(i[0]), i[1]) == (alpha / (beta - 1), 1 < beta) j = integrate(x ** 2 * betadist, (x, 0, oo), meijerg=True, conds="separate") assert j[1] == (1 < beta - 1) assert combsimp(j[0] - i[0] ** 2) == (alpha + beta - 1) * alpha / (beta - 2) / (beta - 1) ** 2 # Beta distribution # NOTE: this is evaluated using antiderivatives. It also tests that # meijerint_indefinite returns the simplest possible answer. a, b = symbols("a b", positive=True) betadist = x ** (a - 1) * (-x + 1) ** (b - 1) * gamma(a + b) / (gamma(a) * gamma(b)) assert simplify(integrate(betadist, (x, 0, 1), meijerg=True)) == 1 assert simplify(integrate(x * betadist, (x, 0, 1), meijerg=True)) == a / (a + b) assert simplify(integrate(x ** 2 * betadist, (x, 0, 1), meijerg=True)) == a * (a + 1) / (a + b) / (a + b + 1) assert simplify(integrate(x ** y * betadist, (x, 0, 1), meijerg=True)) == gamma(a + b) * gamma(a + y) / gamma( a ) / gamma(a + b + y) # Chi distribution k = Symbol("k", integer=True, positive=True) chi = 2 ** (1 - k / 2) * x ** (k - 1) * exp(-x ** 2 / 2) / gamma(k / 2) assert powsimp(integrate(chi, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x * chi, (x, 0, oo), meijerg=True)) == sqrt(2) * gamma((k + 1) / 2) / gamma(k / 2) assert simplify(integrate(x ** 2 * chi, (x, 0, oo), meijerg=True)) == k # Chi^2 distribution chisquared = 2 ** (-k / 2) / gamma(k / 2) * x ** (k / 2 - 1) * exp(-x / 2) assert powsimp(integrate(chisquared, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x * chisquared, (x, 0, oo), meijerg=True)) == k assert simplify(integrate(x ** 2 * chisquared, (x, 0, oo), meijerg=True)) == k * (k + 2) assert combsimp(integrate(((x - k) / sqrt(2 * k)) ** 3 * chisquared, (x, 0, oo), meijerg=True)) == 2 * sqrt( 2 ) / sqrt(k) # Dagum distribution a, b, p = symbols("a b p", positive=True) # XXX (x/b)**a does not work dagum = a * p / x * (x / b) ** (a * p) / (1 + x ** a / b ** a) ** (p + 1) assert simplify(integrate(dagum, (x, 0, oo), meijerg=True)) == 1 # XXX conditions are a mess arg = x * dagum assert simplify(integrate(arg, (x, 0, oo), meijerg=True, conds="none")) == a * b * gamma(1 - 1 / a) * gamma( p + 1 + 1 / a ) / ((a * p + 1) * gamma(p)) assert simplify(integrate(x * arg, (x, 0, oo), meijerg=True, conds="none")) == a * b ** 2 * gamma( 1 - 2 / a ) * gamma(p + 1 + 2 / a) / ((a * p + 2) * gamma(p)) # F-distribution d1, d2 = symbols("d1 d2", positive=True) f = ( sqrt(((d1 * x) ** d1 * d2 ** d2) / (d1 * x + d2) ** (d1 + d2)) / x / gamma(d1 / 2) / gamma(d2 / 2) * gamma((d1 + d2) / 2) ) assert simplify(integrate(f, (x, 0, oo), meijerg=True)) == 1 # TODO conditions are a mess assert simplify(integrate(x * f, (x, 0, oo), meijerg=True, conds="none")) == d2 / (d2 - 2) assert simplify(integrate(x ** 2 * f, (x, 0, oo), meijerg=True, conds="none")) == d2 ** 2 * (d1 + 2) / d1 / ( d2 - 4 ) / (d2 - 2) # TODO gamma, rayleigh # inverse gaussian lamda, mu = symbols("lamda mu", positive=True) dist = sqrt(lamda / 2 / pi) * x ** (-S(3) / 2) * exp(-lamda * (x - mu) ** 2 / x / 2 / mu ** 2) mysimp = lambda expr: simplify(expr.rewrite(exp)) assert mysimp(integrate(dist, (x, 0, oo))) == 1 assert mysimp(integrate(x * dist, (x, 0, oo))) == mu assert mysimp(integrate((x - mu) ** 2 * dist, (x, 0, oo))) == mu ** 3 / lamda assert mysimp(integrate((x - mu) ** 3 * dist, (x, 0, oo))) == 3 * mu ** 5 / lamda ** 2 # Levi c = Symbol("c", positive=True) assert integrate(sqrt(c / 2 / pi) * exp(-c / 2 / (x - mu)) / (x - mu) ** S("3/2"), (x, mu, oo)) == 1 # higher moments oo # log-logistic distn = (beta / alpha) * x ** (beta - 1) / alpha ** (beta - 1) / (1 + x ** beta / alpha ** beta) ** 2 assert simplify(integrate(distn, (x, 0, oo))) == 1 # NOTE the conditions are a mess, but correctly state beta > 1 assert simplify(integrate(x * distn, (x, 0, oo), conds="none")) == pi * alpha / beta / sin(pi / beta) # (similar comment for conditions applies) assert simplify(integrate(x ** y * distn, (x, 0, oo), conds="none")) == pi * alpha ** y * y / beta / sin( pi * y / beta ) # weibull k = Symbol("k", positive=True) n = Symbol("n", positive=True) distn = k / lamda * (x / lamda) ** (k - 1) * exp(-(x / lamda) ** k) assert simplify(integrate(distn, (x, 0, oo))) == 1 assert simplify(integrate(x ** n * distn, (x, 0, oo))) == lamda ** n * gamma(1 + n / k) # rice distribution from sympy import besseli nu, sigma = symbols("nu sigma", positive=True) rice = x / sigma ** 2 * exp(-(x ** 2 + nu ** 2) / 2 / sigma ** 2) * besseli(0, x * nu / sigma ** 2) assert integrate(rice, (x, 0, oo), meijerg=True) == 1 # can someone verify higher moments? # Laplace distribution mu = Symbol("mu", real=True) b = Symbol("b", positive=True) laplace = exp(-abs(x - mu) / b) / 2 / b assert integrate(laplace, (x, -oo, oo), meijerg=True) == 1 assert integrate(x * laplace, (x, -oo, oo), meijerg=True) == mu assert integrate(x ** 2 * laplace, (x, -oo, oo), meijerg=True) == 2 * b ** 2 + mu ** 2 # TODO are there other distributions supported on (-oo, oo) that we can do? # misc tests k = Symbol("k", positive=True) assert combsimp(expand_mul(integrate(log(x) * x ** (k - 1) * exp(-x) / gamma(k), (x, 0, oo)))) == polygamma(0, k)
def simp_pows(expr): return expand_mul(simplify(powsimp(expr, force=True)), deep=True).replace(exp_polar, exp) # XXX ? # Now test the inverses of all direct transforms tested above # Section 8.4.2 assert IMT(-1/(nu + s), s, x, (-oo, None)) == x**nu*Heaviside(x - 1)
def _eval_Abs(self): from sympy import expand_mul return sqrt( expand_mul(self * self.conjugate()) )
def simp_hyp(expr): return factor_terms(expand_mul(expr)).rewrite(sin)
def solve_linear(lhs, rhs=0, x=[], exclude=[]): """ Return a tuple containing derived from f = lhs - rhs that is either: (numerator, denominator) of f; if this comes back as (0, 1) it means that f was actually zero even though it may have had symbols: e.g. y*cos(x)**2 + y*sin(x)**2 - y = y*(0) = 0 If the numerator is not zero then the function is guaranteed not to be zero. or (symbol, solution) where symbol appears linearly in the numerator of f, is in x (if given) and is not in exclude (if given). No simplification is done to f other than and mul=True expansion, so the solution will correspond strictly to a unique solution. Examples: >>> from sympy.solvers.solvers import solve_linear >>> from sympy.abc import x, y, z These are linear in x and 1/x: >>> solve_linear(x + y**2) (x, -y**2) >>> solve_linear(1/x - y**2) (x, y**(-2)) When not linear in x or y then the numerator and denominator are returned. >>> solve_linear(x**2/y**2 - 3) (x**2 - 3*y**2, y**2) If x is allowed to cancel, then this appears linear, but this sort of cancellation is not done so the solultion will always satisfy the original expression without causing a division by zero error. >>> solve_linear(x**2*(1/x - z**2/x)) (x**2*(x - x*z**2), x**2) You can give a list of what you prefer for x candidates: >>> solve_linear(x + y + z, x=[y]) (y, -x - z) You can also indicate what variables you don't want to consider: >>> solve_linear(x + y + z, exclude=[x, z]) (y, -x - z) If only x was excluded then a solution for y or z might be obtained. """ from sympy import expand_mul, Equality if isinstance(lhs, Equality): rhs += lhs.rhs lhs = lhs.lhs n, d = (lhs - rhs).as_numer_denom() ex = expand_mul(n) if not ex: return ex, d exclude = set(exclude) syms = ex.free_symbols if not x: x = syms else: x = syms.intersection(x) x = x.difference(exclude) for xi in x: dn = n.diff(xi) # if not dn then this is a pseudo-function of xi if dn and not dn.has(xi): return xi, -(n.subs(xi, 0)) / dn return n, d
def _minpoly_groebner(ex, x, cls): """ Computes the minimal polynomial of an algebraic number using Groebner bases Examples ======== >>> from sympy import minimal_polynomial, sqrt, Rational >>> from sympy.abc import x >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False) x**2 - 2*x - 1 """ from sympy.polys.polytools import degree from sympy.core.function import expand_multinomial generator = numbered_symbols('a', cls=Dummy) mapping, symbols, replace = {}, {}, [] def update_mapping(ex, exp, base=None): a = next(generator) symbols[ex] = a if base is not None: mapping[ex] = a**exp + base else: mapping[ex] = exp.as_expr(a) return a def bottom_up_scan(ex): if ex.is_Atom: if ex is S.ImaginaryUnit: if ex not in mapping: return update_mapping(ex, 2, 1) else: return symbols[ex] elif ex.is_Rational: return ex elif ex.is_Add: return Add(*[bottom_up_scan(g) for g in ex.args]) elif ex.is_Mul: return Mul(*[bottom_up_scan(g) for g in ex.args]) elif ex.is_Pow: if ex.exp.is_Rational: if ex.exp < 0 and ex.base.is_Add: coeff, terms = ex.base.as_coeff_add() elt, _ = primitive_element(terms, polys=True) alg = ex.base - coeff # XXX: turn this into eval() inverse = invert(elt.gen + coeff, elt).as_expr() base = inverse.subs(elt.gen, alg).expand() if ex.exp == -1: return bottom_up_scan(base) else: ex = base**(-ex.exp) if not ex.exp.is_Integer: base, exp = (ex.base**ex.exp.p).expand(), Rational( 1, ex.exp.q) else: base, exp = ex.base, ex.exp base = bottom_up_scan(base) expr = base**exp if expr not in mapping: return update_mapping(expr, 1 / exp, -base) else: return symbols[expr] elif ex.is_AlgebraicNumber: if ex.root not in mapping: return update_mapping(ex.root, ex.minpoly) else: return symbols[ex.root] raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex) def simpler_inverse(ex): """ Returns True if it is more likely that the minimal polynomial algorithm works better with the inverse """ if ex.is_Pow: if (1 / ex.exp).is_integer and ex.exp < 0: if ex.base.is_Add: return True if ex.is_Mul: hit = True a = [] for p in ex.args: if p.is_Add: return False if p.is_Pow: if p.base.is_Add and p.exp > 0: return False if hit: return True return False inverted = False ex = expand_multinomial(ex) if ex.is_AlgebraicNumber: return ex.minpoly.as_expr(x) elif ex.is_Rational: result = ex.q * x - ex.p else: inverted = simpler_inverse(ex) if inverted: ex = ex**-1 res = None if ex.is_Pow and (1 / ex.exp).is_Integer: n = 1 / ex.exp res = _minimal_polynomial_sq(ex.base, n, x) elif _is_sum_surds(ex): res = _minimal_polynomial_sq(ex, S.One, x) if res is not None: result = res if res is None: bus = bottom_up_scan(ex) F = [x - bus] + list(mapping.values()) G = groebner(F, list(symbols.values()) + [x], order='lex') _, factors = factor_list(G[-1]) # by construction G[-1] has root `ex` result = _choose_factor(factors, x, ex) if inverted: result = _invertx(result, x) if result.coeff(x**degree(result, x)) < 0: result = expand_mul(-result) return result
def doit(self, **hints): """ Try to evaluate the transform in closed form. This general function handles linearity, but apart from that leaves pretty much everything to _compute_transform. Standard hints are the following: - ``simplify``: whether or not to simplify the result - ``noconds``: if True, don't return convergence conditions - ``needeval``: if True, raise IntegralTransformError instead of returning IntegralTransform objects The default values of these hints depend on the concrete transform, usually the default is ``(simplify, noconds, needeval) = (True, False, False)``. """ from sympy import Add, expand_mul, Mul from sympy.core.function import AppliedUndef needeval = hints.pop('needeval', False) try_directly = not any(func.has(self.function_variable) \ for func in self.function.atoms(AppliedUndef)) if try_directly: try: return self._compute_transform(self.function, self.function_variable, self.transform_variable, **hints) except IntegralTransformError: pass fn = self.function if not fn.is_Add: fn = expand_mul(fn) if fn.is_Add: hints['needeval'] = needeval res = [ self.__class__(*([x] + list(self.args[1:]))).doit(**hints) for x in fn.args ] extra = [] ress = [] for x in res: if not isinstance(x, tuple): x = [x] ress.append(x[0]) if len(x) > 1: extra += [x[1:]] res = Add(*ress) if not extra: return res try: extra = self._collapse_extra(extra) return tuple([res]) + tuple(extra) except IntegralTransformError: pass if needeval: raise IntegralTransformError(self.__class__._name, self.function, 'needeval') # TODO handle derivatives etc # pull out constant coefficients coeff, rest = fn.as_coeff_mul(self.function_variable) return coeff * self.__class__(*([Mul(*rest)] + list(self.args[1:])))
def simp_pows(expr): return simplify(powsimp(expand_mul(expr, deep=False), force=True)).replace(exp_polar, exp)
def test_probability(): # various integrals from probability theory from sympy.abc import x, y from sympy import symbols, Symbol, Abs, expand_mul, combsimp, powsimp, sin mu1, mu2 = symbols('mu1 mu2', real=True, nonzero=True, finite=True) sigma1, sigma2 = symbols('sigma1 sigma2', real=True, nonzero=True, finite=True, positive=True) rate = Symbol('lambda', real=True, positive=True, finite=True) def normal(x, mu, sigma): return 1 / sqrt(2 * pi * sigma**2) * exp(-(x - mu)**2 / 2 / sigma**2) def exponential(x, rate): return rate * exp(-rate * x) assert integrate(normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == 1 assert integrate(x*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == \ mu1 assert integrate(x**2*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \ == mu1**2 + sigma1**2 assert integrate(x**3*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \ == mu1**3 + 3*mu1*sigma1**2 assert integrate(normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 assert integrate(x * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1 assert integrate(y * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu2 assert integrate(x * y * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1 * mu2 assert integrate( (x + y + 1) * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 + mu1 + mu2 assert integrate((x + y - 1)*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == \ -1 + mu1 + mu2 i = integrate(x**2 * normal(x, mu1, sigma1) * normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) assert not i.has(Abs) assert simplify(i) == mu1**2 + sigma1**2 assert integrate(y**2*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == \ sigma2**2 + mu2**2 assert integrate(exponential(x, rate), (x, 0, oo), meijerg=True) == 1 assert integrate(x*exponential(x, rate), (x, 0, oo), meijerg=True) == \ 1/rate assert integrate(x**2*exponential(x, rate), (x, 0, oo), meijerg=True) == \ 2/rate**2 def E(expr): res1 = integrate(expr * exponential(x, rate) * normal(y, mu1, sigma1), (x, 0, oo), (y, -oo, oo), meijerg=True) res2 = integrate(expr * exponential(x, rate) * normal(y, mu1, sigma1), (y, -oo, oo), (x, 0, oo), meijerg=True) assert expand_mul(res1) == expand_mul(res2) return res1 assert E(1) == 1 assert E(x * y) == mu1 / rate assert E(x * y**2) == mu1**2 / rate + sigma1**2 / rate ans = sigma1**2 + 1 / rate**2 assert simplify(E((x + y + 1)**2) - E(x + y + 1)**2) == ans assert simplify(E((x + y - 1)**2) - E(x + y - 1)**2) == ans assert simplify(E((x + y)**2) - E(x + y)**2) == ans # Beta' distribution alpha, beta = symbols('alpha beta', positive=True) betadist = x**(alpha - 1)*(1 + x)**(-alpha - beta)*gamma(alpha + beta) \ /gamma(alpha)/gamma(beta) assert integrate(betadist, (x, 0, oo), meijerg=True) == 1 i = integrate(x * betadist, (x, 0, oo), meijerg=True, conds='separate') assert (combsimp(i[0]), i[1]) == (alpha / (beta - 1), 1 < beta) j = integrate(x**2 * betadist, (x, 0, oo), meijerg=True, conds='separate') assert j[1] == (1 < beta - 1) assert combsimp(j[0] - i[0]**2) == (alpha + beta - 1)*alpha \ /(beta - 2)/(beta - 1)**2 # Beta distribution # NOTE: this is evaluated using antiderivatives. It also tests that # meijerint_indefinite returns the simplest possible answer. a, b = symbols('a b', positive=True) betadist = x**(a - 1) * (-x + 1)**(b - 1) * gamma(a + b) / (gamma(a) * gamma(b)) assert simplify(integrate(betadist, (x, 0, 1), meijerg=True)) == 1 assert simplify(integrate(x*betadist, (x, 0, 1), meijerg=True)) == \ a/(a + b) assert simplify(integrate(x**2*betadist, (x, 0, 1), meijerg=True)) == \ a*(a + 1)/(a + b)/(a + b + 1) assert simplify(integrate(x**y*betadist, (x, 0, 1), meijerg=True)) == \ gamma(a + b)*gamma(a + y)/gamma(a)/gamma(a + b + y) # Chi distribution k = Symbol('k', integer=True, positive=True) chi = 2**(1 - k / 2) * x**(k - 1) * exp(-x**2 / 2) / gamma(k / 2) assert powsimp(integrate(chi, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x*chi, (x, 0, oo), meijerg=True)) == \ sqrt(2)*gamma((k + 1)/2)/gamma(k/2) assert simplify(integrate(x**2 * chi, (x, 0, oo), meijerg=True)) == k # Chi^2 distribution chisquared = 2**(-k / 2) / gamma(k / 2) * x**(k / 2 - 1) * exp(-x / 2) assert powsimp(integrate(chisquared, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x * chisquared, (x, 0, oo), meijerg=True)) == k assert simplify(integrate(x**2*chisquared, (x, 0, oo), meijerg=True)) == \ k*(k + 2) assert combsimp( integrate(((x - k) / sqrt(2 * k))**3 * chisquared, (x, 0, oo), meijerg=True)) == 2 * sqrt(2) / sqrt(k) # Dagum distribution a, b, p = symbols('a b p', positive=True) # XXX (x/b)**a does not work dagum = a * p / x * (x / b)**(a * p) / (1 + x**a / b**a)**(p + 1) assert simplify(integrate(dagum, (x, 0, oo), meijerg=True)) == 1 # XXX conditions are a mess arg = x * dagum assert simplify(integrate( arg, (x, 0, oo), meijerg=True, conds='none')) == a * b * gamma(1 - 1 / a) * gamma(p + 1 + 1 / a) / ( (a * p + 1) * gamma(p)) assert simplify(integrate( x * arg, (x, 0, oo), meijerg=True, conds='none')) == a * b**2 * gamma(1 - 2 / a) * gamma(p + 1 + 2 / a) / ( (a * p + 2) * gamma(p)) # F-distribution d1, d2 = symbols('d1 d2', positive=True) f = sqrt(((d1*x)**d1 * d2**d2)/(d1*x + d2)**(d1 + d2))/x \ /gamma(d1/2)/gamma(d2/2)*gamma((d1 + d2)/2) assert simplify(integrate(f, (x, 0, oo), meijerg=True)) == 1 # TODO conditions are a mess assert simplify(integrate(x * f, (x, 0, oo), meijerg=True, conds='none')) == d2 / (d2 - 2) assert simplify( integrate(x**2 * f, (x, 0, oo), meijerg=True, conds='none')) == d2**2 * (d1 + 2) / d1 / (d2 - 4) / (d2 - 2) # TODO gamma, rayleigh # inverse gaussian lamda, mu = symbols('lamda mu', positive=True) dist = sqrt(lamda / 2 / pi) * x**(-S(3) / 2) * exp( -lamda * (x - mu)**2 / x / 2 / mu**2) mysimp = lambda expr: simplify(expr.rewrite(exp)) assert mysimp(integrate(dist, (x, 0, oo))) == 1 assert mysimp(integrate(x * dist, (x, 0, oo))) == mu assert mysimp(integrate((x - mu)**2 * dist, (x, 0, oo))) == mu**3 / lamda assert mysimp(integrate((x - mu)**3 * dist, (x, 0, oo))) == 3 * mu**5 / lamda**2 # Levi c = Symbol('c', positive=True) assert integrate( sqrt(c / 2 / pi) * exp(-c / 2 / (x - mu)) / (x - mu)**S('3/2'), (x, mu, oo)) == 1 # higher moments oo # log-logistic distn = (beta/alpha)*x**(beta - 1)/alpha**(beta - 1)/ \ (1 + x**beta/alpha**beta)**2 assert simplify(integrate(distn, (x, 0, oo))) == 1 # NOTE the conditions are a mess, but correctly state beta > 1 assert simplify(integrate(x*distn, (x, 0, oo), conds='none')) == \ pi*alpha/beta/sin(pi/beta) # (similar comment for conditions applies) assert simplify(integrate(x**y*distn, (x, 0, oo), conds='none')) == \ pi*alpha**y*y/beta/sin(pi*y/beta) # weibull k = Symbol('k', positive=True) n = Symbol('n', positive=True) distn = k / lamda * (x / lamda)**(k - 1) * exp(-(x / lamda)**k) assert simplify(integrate(distn, (x, 0, oo))) == 1 assert simplify(integrate(x**n*distn, (x, 0, oo))) == \ lamda**n*gamma(1 + n/k) # rice distribution from sympy import besseli nu, sigma = symbols('nu sigma', positive=True) rice = x / sigma**2 * exp(-(x**2 + nu**2) / 2 / sigma**2) * besseli( 0, x * nu / sigma**2) assert integrate(rice, (x, 0, oo), meijerg=True) == 1 # can someone verify higher moments? # Laplace distribution mu = Symbol('mu', real=True) b = Symbol('b', positive=True) laplace = exp(-abs(x - mu) / b) / 2 / b assert integrate(laplace, (x, -oo, oo), meijerg=True) == 1 assert integrate(x * laplace, (x, -oo, oo), meijerg=True) == mu assert integrate(x**2*laplace, (x, -oo, oo), meijerg=True) == \ 2*b**2 + mu**2 # TODO are there other distributions supported on (-oo, oo) that we can do? # misc tests k = Symbol('k', positive=True) assert combsimp( expand_mul( integrate(log(x) * x**(k - 1) * exp(-x) / gamma(k), (x, 0, oo)))) == polygamma(0, k)
def simp_pows(expr): return expand_mul(simplify(powsimp(expr, force=True)), deep=True).replace(exp_polar, exp) # XXX ?
def eval(cls, arg): from sympy.simplify.simplify import signsimp from sympy import Atom if hasattr(arg, '_eval_Abs'): obj = arg._eval_Abs() if obj is not None: return obj if not isinstance(arg, Expr): raise TypeError("Bad argument type for Abs(): %s" % type(arg)) # handle what we can arg = signsimp(arg, evaluate=False) if arg.is_Mul: known = [] unk = [] for t in Mul.make_args(arg): tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known * unk if arg is S.NaN: return S.NaN if arg.is_Pow: base, exponent = arg.as_base_exp() if base.is_real: if exponent.is_integer: if exponent.is_even: return arg if base is S.NegativeOne: return S.One if base.func is cls and exponent is S.NegativeOne: return arg return Abs(base)**exponent if base.is_positive == True: return base**re(exponent) return (-base)**re(exponent) * exp(-S.Pi * im(exponent)) if isinstance(arg, exp): return exp(re(arg.args[0])) if arg.is_number or isinstance(arg, (cls, Atom)): if arg.is_zero: return S.Zero if arg.is_nonnegative: return arg if arg.is_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_nonnegative: return arg2 if arg.is_Add: if arg.has(S.Infinity, S.NegativeInfinity): if any(a.is_infinite for a in arg.as_real_imag()): return S.Infinity if arg.is_real is None and arg.is_imaginary is None: if all(a.is_real or a.is_imaginary or (S.ImaginaryUnit * a).is_real for a in arg.args): from sympy import expand_mul return sqrt(expand_mul(arg * arg.conjugate())) if arg.is_real is False and arg.is_imaginary is False: from sympy import expand_mul return sqrt(expand_mul(arg * arg.conjugate()))
def minimal_polynomial(ex, x=None, **args): """ Computes the minimal polynomial of an algebraic element. Parameters ========== ex : algebraic element expression x : independent variable of the minimal polynomial Options ======= compose : if ``True`` ``_minpoly_compose`` is used, if ``False`` the ``groebner`` algorithm polys : if ``True`` returns a ``Poly`` object domain : ground domain Notes ===== By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex`` are computed, then the arithmetic operations on them are performed using the resultant and factorization. If ``compose=False``, a bottom-up algorithm is used with ``groebner``. The default algorithm stalls less frequently. If no ground domain is given, it will be generated automatically from the expression. Examples ======== >>> from sympy import minimal_polynomial, sqrt, solve, QQ >>> from sympy.abc import x, y >>> minimal_polynomial(sqrt(2), x) x**2 - 2 >>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2))) x - sqrt(2) >>> minimal_polynomial(sqrt(2) + sqrt(3), x) x**4 - 10*x**2 + 1 >>> minimal_polynomial(solve(x**3 + x + 3)[0], x) x**3 + x + 3 >>> minimal_polynomial(sqrt(y), x) x**2 - y """ from sympy.polys.polytools import degree from sympy.polys.domains import FractionField from sympy.core.basic import preorder_traversal compose = args.get('compose', True) polys = args.get('polys', False) dom = args.get('domain', None) ex = sympify(ex) for expr in preorder_traversal(ex): if expr.is_AlgebraicNumber: compose = False break if x is not None: x, cls = sympify(x), Poly else: x, cls = Dummy('x'), PurePoly if not dom: dom = FractionField(QQ, list( ex.free_symbols)) if ex.free_symbols else QQ if hasattr(dom, 'symbols') and x in dom.symbols: raise GeneratorsError( "the variable %s is an element of the ground domain %s" % (x, dom)) if compose: result = _minpoly_compose(ex, x, dom) result = result.primitive()[1] c = result.coeff(x**degree(result, x)) if c.is_negative: result = expand_mul(-result) return cls(result, x, field=True) if polys else result.collect(x) if not dom.is_QQ: raise NotImplementedError("groebner method only works for QQ") result = _minpoly_groebner(ex, x, cls) return cls(result, x, field=True) if polys else result.collect(x)
>>> _rewrite_sin((2*pi, 0), s, 0, S(1)/2) (gamma(2*s), gamma(-2*s + 1), pi) >>> _rewrite_sin((2*pi, 0), s, S(1)/2, 1) (gamma(2*s - 1), gamma(-2*s + 2), -pi) """ # (This is a separate function because it is moderately complicated, # and I want to doctest it.) # We want to use pi/sin(pi*x) = gamma(x)*gamma(1-x). # But there is one comlication: the gamma functions determine the # inegration contour in the definition of the G-function. Usually # it would not matter if this is slightly shifted, unless this way # we create an undefined function! # So we try to write this in such a way that the gammas are # eminently on the right side of the strip. from sympy import expand_mul, pi, ceiling, gamma, re m = expand_mul(m / pi) n = expand_mul(n / pi) r = ceiling(-m * a - n.as_real_imag()[0]) # Don't use re(n), does not expand return gamma(m * s + n + r), gamma(1 - n - r - m * s), (-1)**r * pi class MellinTransformStripError(ValueError): """ Exception raised by _rewrite_gamma. Mainly for internal use. """ pass def _rewrite_gamma(f, s, a, b): """
def minimal_polynomial(ex, x=None, **args): """ Computes the minimal polynomial of an algebraic number. Parameters ========== ex : algebraic number expression x : indipendent variable of the minimal polynomial Options ======= compose : if ``True`` _minpoly1`` is used, else the ``groebner`` algorithm polys : if ``True`` returns a ``Poly`` object Notes ===== By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex`` are computed, then the arithmetic operations on them are performed using the resultant and factorization. If ``compose=False``, a bottom-up algorithm is used with ``groebner``. The default algorithm stalls less frequently. Examples ======== >>> from sympy import minimal_polynomial, sqrt, solve >>> from sympy.abc import x >>> minimal_polynomial(sqrt(2), x) x**2 - 2 >>> minimal_polynomial(sqrt(2) + sqrt(3), x) x**4 - 10*x**2 + 1 >>> minimal_polynomial(solve(x**3 + x + 3)[0], x) x**3 + x + 3 """ from sympy.polys.polytools import degree from sympy.core.function import expand_multinomial from sympy.core.basic import preorder_traversal compose = args.get('compose', True) polys = args.get('polys', False) ex = sympify(ex) for expr in preorder_traversal(ex): if expr.is_AlgebraicNumber: compose = False break if ex.is_AlgebraicNumber: compose = False if x is not None: x, cls = sympify(x), Poly else: x, cls = Dummy('x'), PurePoly if compose: result = _minpoly1(ex, x) result = result.primitive()[1] c = result.coeff(x**degree(result, x)) if c < 0: result = expand_mul(-result) c = -c return cls(result, x, field=True) if polys else result generator = numbered_symbols('a', cls=Dummy) mapping, symbols, replace = {}, {}, [] def update_mapping(ex, exp, base=None): a = generator.next() symbols[ex] = a if base is not None: mapping[ex] = a**exp + base else: mapping[ex] = exp.as_expr(a) return a def bottom_up_scan(ex): if ex.is_Atom: if ex is S.ImaginaryUnit: if ex not in mapping: return update_mapping(ex, 2, 1) else: return symbols[ex] elif ex.is_Rational: return ex elif ex.is_Add: return Add(*[bottom_up_scan(g) for g in ex.args]) elif ex.is_Mul: return Mul(*[bottom_up_scan(g) for g in ex.args]) elif ex.is_Pow: if ex.exp.is_Rational: if ex.exp < 0 and ex.base.is_Add: coeff, terms = ex.base.as_coeff_add() elt, _ = primitive_element(terms, polys=True) alg = ex.base - coeff # XXX: turn this into eval() inverse = invert(elt.gen + coeff, elt).as_expr() base = inverse.subs(elt.gen, alg).expand() if ex.exp == -1: return bottom_up_scan(base) else: ex = base**(-ex.exp) if not ex.exp.is_Integer: base, exp = (ex.base**ex.exp.p).expand(), Rational( 1, ex.exp.q) else: base, exp = ex.base, ex.exp base = bottom_up_scan(base) expr = base**exp if expr not in mapping: return update_mapping(expr, 1 / exp, -base) else: return symbols[expr] elif ex.is_AlgebraicNumber: if ex.root not in mapping: return update_mapping(ex.root, ex.minpoly) else: return symbols[ex.root] raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex) def simpler_inverse(ex): """ Returns True if it is more likely that the minimal polynomial algorithm works better with the inverse """ if ex.is_Pow: if (1 / ex.exp).is_integer and ex.exp < 0: if ex.base.is_Add: return True if ex.is_Mul: hit = True a = [] for p in ex.args: if p.is_Add: return False if p.is_Pow: if p.base.is_Add and p.exp > 0: return False if hit: return True return False inverted = False ex = expand_multinomial(ex) if ex.is_AlgebraicNumber: if not polys: return ex.minpoly.as_expr(x) else: return ex.minpoly.replace(x) elif ex.is_Rational: result = ex.q * x - ex.p else: inverted = simpler_inverse(ex) if inverted: ex = ex**-1 res = None if ex.is_Pow and (1 / ex.exp).is_Integer: n = 1 / ex.exp res = _minimal_polynomial_sq(ex.base, n, x) elif _is_sum_surds(ex): res = _minimal_polynomial_sq(ex, S.One, x) if res is not None: result = res if res is None: bus = bottom_up_scan(ex) F = [x - bus] + mapping.values() G = groebner(F, symbols.values() + [x], order='lex') _, factors = factor_list(G[-1]) # by construction G[-1] has root `ex` result = _choose_factor(factors, x, ex) if inverted: result = _invertx(result, x) if result.coeff(x**degree(result, x)) < 0: result = expand_mul(-result) if polys: return cls(result, x, field=True) else: return result
def solve_linear(lhs, rhs=0, x=[], exclude=[]): """ Return a tuple containing derived from f = lhs - rhs that is either: (numerator, denominator) of f; if this comes back as (0, 1) it means that f was actually zero even though it may have had symbols: e.g. y*cos(x)**2 + y*sin(x)**2 - y = y*(0) = 0 If the numerator is not zero then the function is guaranteed not to be zero. or (symbol, solution) where symbol appears linearly in the numerator of f, is in x (if given) and is not in exclude (if given). No simplification is done to f other than and mul=True expansion, so the solution will correspond strictly to a unique solution. Examples: >>> from sympy.solvers.solvers import solve_linear >>> from sympy.abc import x, y, z These are linear in x and 1/x: >>> solve_linear(x + y**2) (x, -y**2) >>> solve_linear(1/x - y**2) (x, y**(-2)) When not linear in x or y then the numerator and denominator are returned. >>> solve_linear(x**2/y**2 - 3) (x**2 - 3*y**2, y**2) If x is allowed to cancel, then this appears linear, but this sort of cancellation is not done so the solultion will always satisfy the original expression without causing a division by zero error. >>> solve_linear(x**2*(1/x - z**2/x)) (x**2*(x - x*z**2), x**2) You can give a list of what you prefer for x candidates: >>> solve_linear(x + y + z, x=[y]) (y, -x - z) You can also indicate what variables you don't want to consider: >>> solve_linear(x + y + z, exclude=[x, z]) (y, -x - z) If only x was excluded then a solution for y or z might be obtained. """ from sympy import expand_mul, Equality if isinstance(lhs, Equality): rhs += lhs.rhs lhs = lhs.lhs n, d = (lhs - rhs).as_numer_denom() ex = expand_mul(n) if not ex: return ex, d exclude = set(exclude) syms = ex.free_symbols if not x: x = syms else: x = syms.intersection(x) x = x.difference(exclude) for xi in x: dn = n.diff(xi) # if not dn then this is a pseudo-function of xi if dn and not dn.has(xi): return xi, -(n.subs(xi, 0))/dn return n, d
def _eval_as_leading_term(self, x, logx=None, cdir=0): from sympy import expand_mul, Order, Piecewise, piecewise_fold, log old = self if old.has(Piecewise): old = piecewise_fold(old) # This expansion is the last part of expand_log. expand_log also calls # expand_mul with factor=True, which would be more expensive if any(isinstance(a, log) for a in self.args): logflags = dict(deep=True, log=True, mul=False, power_exp=False, power_base=False, multinomial=False, basic=False, force=False, factor=False) old = old.expand(**logflags) expr = expand_mul(old) if not expr.is_Add: return expr.as_leading_term(x, logx=logx, cdir=cdir) infinite = [t for t in expr.args if t.is_infinite] leading_terms = [ t.as_leading_term(x, logx=logx, cdir=cdir) for t in expr.args ] min, new_expr = Order(0), 0 try: for term in leading_terms: order = Order(term, x) if not min or order not in min: min = order new_expr = term elif min in order: new_expr += term except TypeError: return expr is_zero = new_expr.is_zero if is_zero is None: new_expr = new_expr.trigsimp().cancel() is_zero = new_expr.is_zero if is_zero is True: # simple leading term analysis gave us cancelled terms but we have to send # back a term, so compute the leading term (via series) n0 = min.getn() res = Order(1) incr = S.One while res.is_Order: res = old._eval_nseries( x, n=n0 + incr, logx=None, cdir=cdir).cancel().powsimp().trigsimp() incr *= 2 return res.as_leading_term(x, logx=logx, cdir=cdir) elif new_expr is S.NaN: return old.func._from_args(infinite) else: return new_expr
def test_probability(): # various integrals from probability theory from sympy.abc import x, y, z from sympy import symbols, Symbol, Abs, expand_mul, combsimp, powsimp mu1, mu2 = symbols('mu1 mu2', real=True, finite=True, bounded=True) sigma1, sigma2 = symbols('sigma1 sigma2', real=True, finite=True, bounded=True, positive=True) rate = Symbol('lambda', real=True, positive=True, bounded=True) def normal(x, mu, sigma): return 1/sqrt(2*pi*sigma**2)*exp(-(x-mu)**2/2/sigma**2) def exponential(x, rate): return rate*exp(-rate*x) assert integrate(normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == 1 assert integrate(x*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == mu1 assert integrate(x**2*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \ == mu1**2 + sigma1**2 assert integrate(x**3*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \ == mu1**3 + 3*mu1*sigma1**2 assert integrate(normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 assert integrate(x*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1 assert integrate(y*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu2 assert integrate(x*y*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1*mu2 assert integrate((x+y+1)*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 + mu1 + mu2 assert integrate((x+y-1)*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == -1 + mu1 + mu2 i = integrate(x**2*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) assert not i.has(Abs) assert simplify(i) == mu1**2 + sigma1**2 assert integrate(y**2*normal(x, mu1, sigma1)*normal(y, mu2, sigma2), (x, -oo, oo), (y, -oo, oo), meijerg=True) == \ sigma2**2 + mu2**2 assert integrate(exponential(x, rate), (x, 0, oo), meijerg=True) == 1 assert integrate(x*exponential(x, rate), (x, 0, oo), meijerg=True) == 1/rate assert integrate(x**2*exponential(x, rate), (x, 0, oo), meijerg=True) \ == 2/rate**2 def E(expr): res1 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1), (x, 0, oo), (y, -oo, oo), meijerg=True) res2 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1), (y, -oo, oo), (x, 0, oo), meijerg=True) assert expand_mul(res1) == expand_mul(res2) return res1 assert E(1) == 1 assert E(x*y) == mu1/rate assert E(x*y**2) == mu1**2/rate + sigma1**2/rate assert simplify(E((x+y+1)**2) - E(x+y+1)**2) == (rate**2*sigma1**2 + 1)/rate**2 assert simplify(E((x+y-1)**2) - E(x+y-1)**2) == (rate**2*sigma1**2 + 1)/rate**2 assert simplify(E((x+y)**2) - E(x+y)**2) == (rate**2*sigma1**2 + 1)/rate**2 # Beta' distribution alpha, beta = symbols('alpha beta', positive=True) betadist = x**(alpha-1)*(1+x)**(-alpha - beta)*gamma(alpha+beta) \ /gamma(alpha)/gamma(beta) assert integrate(betadist, (x, 0, oo), meijerg=True) == 1 i = integrate(x*betadist, (x, 0, oo), meijerg=True, conds='separate') assert (combsimp(i[0]), i[1]) == (alpha/(beta - 1), 1 < beta) j = integrate(x**2*betadist, (x, 0, oo), meijerg=True, conds='separate') assert j[1] == (1 < beta - 1) assert combsimp(j[0] - i[0]**2) == (alpha + beta - 1)*alpha \ /(beta - 2)/(beta - 1)**2 # Chi distribution k = Symbol('k', integer=True, positive=True) chi = 2**(1-k/2)*x**(k-1)*exp(-x**2/2)/gamma(k/2) assert powsimp(integrate(chi, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x*chi, (x, 0, oo), meijerg=True)) == \ sqrt(2)*gamma((k + 1)/2)/gamma(k/2) assert simplify(integrate(x**2*chi, (x, 0, oo), meijerg=True)) == k # Chi^2 distribution chisquared = 2**(-k/2)/gamma(k/2)*x**(k/2-1)*exp(-x/2) assert powsimp(integrate(chisquared, (x, 0, oo), meijerg=True)) == 1 assert simplify(integrate(x*chisquared, (x, 0, oo), meijerg=True)) == k assert simplify(integrate(x**2*chisquared, (x, 0, oo), meijerg=True)) == \ k*(k + 2) assert combsimp(integrate(((x-k)/sqrt(2*k))**3*chisquared, (x, 0, oo), meijerg=True)) == 2*sqrt(2)/sqrt(k) # Dagum distribution a, b, p = symbols('a b p', positive=True) # XXX (x/b)**a does not work dagum = a*p/x*(x/b)**(a*p)/(1 + x**a/b**a)**(p+1) assert simplify(integrate(dagum, (x, 0, oo), meijerg=True)) == 1 # XXX conditions are a mess assert simplify(integrate(x*dagum, (x, 0, oo), meijerg=True, conds='none')) \ == b*gamma(1 - 1/a)*gamma(p + 1/a)/gamma(p) assert simplify(integrate(x**2*dagum, (x, 0, oo), meijerg=True, conds='none')) \ == b**2*gamma(1 - 2/a)*gamma(p + 2/a)/gamma(p) # F-distribution d1, d2 = symbols('d1 d2', positive=True) f = sqrt(((d1*x)**d1 * d2**d2)/(d1*x + d2)**(d1+d2))/x \ /gamma(d1/2)/gamma(d2/2)*gamma((d1 + d2)/2) assert simplify(integrate(f, (x, 0, oo), meijerg=True)) == 1 # TODO conditions are a mess assert simplify(integrate(x*f, (x, 0, oo), meijerg=True, conds='none')) == \ d2/(d2 - 2) assert simplify(integrate(x**2*f, (x, 0, oo), meijerg=True, conds='none')) == \ d2**2*(d1 + 2)/d1/(d2 - 4)/(d2 - 2) # TODO gamma, inverse gaussian, Levi, log-logistic, rayleigh, weibull # rice distribution from sympy import besseli nu, sigma = symbols('nu sigma', positive=True) rice = x/sigma**2*exp(-(x**2+ nu**2)/2/sigma**2)*besseli(0, x*nu/sigma**2) assert integrate(rice, (x, 0, oo), meijerg=True) == 1 # can someone verify higher moments? # Laplace distribution mu = Symbol('mu', real=True) b = Symbol('b', positive=True) laplace = exp(-abs(x-mu)/b)/2/b assert integrate(laplace, (x, -oo, oo), meijerg=True) == 1 assert integrate(x*laplace, (x, -oo, oo), meijerg=True) == mu assert integrate(x**2*laplace, (x, -oo, oo), meijerg=True) == 2*b**2 + mu**2 # TODO are there other distributions supported on (-oo, oo) that we can do? # misc tests k = Symbol('k', positive=True) assert combsimp(expand_mul(integrate(log(x) * x**(k-1) * exp(-x) / gamma(k), (x, 0, oo)))) == polygamma(0, k)
def minimal_polynomial(ex, x=None, compose=True, polys=False, domain=None): """ Computes the minimal polynomial of an algebraic element. Parameters ========== ex : Expr Element or expression whose minimal polynomial is to be calculated. x : Symbol, optional Independent variable of the minimal polynomial compose : boolean, optional (default=True) Method to use for computing minimal polynomial. If ``compose=True`` (default) then ``_minpoly_compose`` is used, if ``compose=False`` then groebner bases are used. polys : boolean, optional (default=False) If ``True`` returns a ``Poly`` object else an ``Expr`` object. domain : Domain, optional Ground domain Notes ===== By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex`` are computed, then the arithmetic operations on them are performed using the resultant and factorization. If ``compose=False``, a bottom-up algorithm is used with ``groebner``. The default algorithm stalls less frequently. If no ground domain is given, it will be generated automatically from the expression. Examples ======== >>> from sympy import minimal_polynomial, sqrt, solve, QQ >>> from sympy.abc import x, y >>> minimal_polynomial(sqrt(2), x) x**2 - 2 >>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2))) x - sqrt(2) >>> minimal_polynomial(sqrt(2) + sqrt(3), x) x**4 - 10*x**2 + 1 >>> minimal_polynomial(solve(x**3 + x + 3)[0], x) x**3 + x + 3 >>> minimal_polynomial(sqrt(y), x) x**2 - y """ from sympy.polys.polytools import degree from sympy.polys.domains import FractionField from sympy.core.basic import preorder_traversal ex = sympify(ex) if ex.is_number: # not sure if it's always needed but try it for numbers (issue 8354) ex = _mexpand(ex, recursive=True) for expr in preorder_traversal(ex): if expr.is_AlgebraicNumber: compose = False break if x is not None: x, cls = sympify(x), Poly else: x, cls = Dummy('x'), PurePoly if not domain: if ex.free_symbols: domain = FractionField(QQ, list(ex.free_symbols)) else: domain = QQ if hasattr(domain, 'symbols') and x in domain.symbols: raise GeneratorsError("the variable %s is an element of the ground " "domain %s" % (x, domain)) if compose: result = _minpoly_compose(ex, x, domain) result = result.primitive()[1] c = result.coeff(x**degree(result, x)) if c.is_negative: result = expand_mul(-result) return cls(result, x, field=True) if polys else result.collect(x) if not domain.is_QQ: raise NotImplementedError("groebner method only works for QQ") result = _minpoly_groebner(ex, x, cls) return cls(result, x, field=True) if polys else result.collect(x)
def test_asech(): x = Symbol('x') assert unchanged(asech, -x) # values at fixed points assert asech(1) == 0 assert asech(-1) == pi * I assert asech(0) is oo assert asech(2) == I * pi / 3 assert asech(-2) == 2 * I * pi / 3 assert asech(nan) is nan # at infinites assert asech(oo) == I * pi / 2 assert asech(-oo) == I * pi / 2 assert asech(zoo) == I * AccumBounds(-pi / 2, pi / 2) assert asech(I) == log(1 + sqrt(2)) - I * pi / 2 assert asech(-I) == log(1 + sqrt(2)) + I * pi / 2 assert asech(sqrt(2) - sqrt(6)) == 11 * I * pi / 12 assert asech(sqrt(2 - 2 / sqrt(5))) == I * pi / 10 assert asech(-sqrt(2 - 2 / sqrt(5))) == 9 * I * pi / 10 assert asech(2 / sqrt(2 + sqrt(2))) == I * pi / 8 assert asech(-2 / sqrt(2 + sqrt(2))) == 7 * I * pi / 8 assert asech(sqrt(5) - 1) == I * pi / 5 assert asech(1 - sqrt(5)) == 4 * I * pi / 5 assert asech(-sqrt(2 * (2 + sqrt(2)))) == 5 * I * pi / 8 # properties # asech(x) == acosh(1/x) assert asech(sqrt(2)) == acosh(1 / sqrt(2)) assert asech(2 / sqrt(3)) == acosh(sqrt(3) / 2) assert asech(2 / sqrt(2 + sqrt(2))) == acosh(sqrt(2 + sqrt(2)) / 2) assert asech(2) == acosh(S.Half) # asech(x) == I*acos(1/x) # (Note: the exact formula is asech(x) == +/- I*acos(1/x)) assert asech(-sqrt(2)) == I * acos(-1 / sqrt(2)) assert asech(-2 / sqrt(3)) == I * acos(-sqrt(3) / 2) assert asech(-S(2)) == I * acos(Rational(-1, 2)) assert asech(-2 / sqrt(2)) == I * acos(-sqrt(2) / 2) # sech(asech(x)) / x == 1 assert expand_mul(sech(asech(sqrt(6) - sqrt(2))) / (sqrt(6) - sqrt(2))) == 1 assert expand_mul(sech(asech(sqrt(6) + sqrt(2))) / (sqrt(6) + sqrt(2))) == 1 assert (sech(asech(sqrt(2 + 2 / sqrt(5)))) / (sqrt(2 + 2 / sqrt(5)))).simplify() == 1 assert (sech(asech(-sqrt(2 + 2 / sqrt(5)))) / (-sqrt(2 + 2 / sqrt(5)))).simplify() == 1 assert (sech(asech(sqrt(2 * (2 + sqrt(2))))) / (sqrt(2 * (2 + sqrt(2))))).simplify() == 1 assert expand_mul(sech(asech(1 + sqrt(5))) / (1 + sqrt(5))) == 1 assert expand_mul(sech(asech(-1 - sqrt(5))) / (-1 - sqrt(5))) == 1 assert expand_mul(sech(asech(-sqrt(6) - sqrt(2))) / (-sqrt(6) - sqrt(2))) == 1 # numerical evaluation assert str(asech(5 * I).n(6)) == '0.19869 - 1.5708*I' assert str(asech(-5 * I).n(6)) == '0.19869 + 1.5708*I'