def test_reduction_operators(): a1, a2, b1 = (randcplx(n) for n in range(3)) h = hyper([a1], [b1], z) assert ReduceOrder(2, 0) is None assert ReduceOrder(2, -1) is None assert ReduceOrder(1, S('1/2')) is None h2 = hyper((a1, a2), (b1, a2), z) assert tn(ReduceOrder(a2, a2).apply(h, op), h2, z) h2 = hyper((a1, a2 + 1), (b1, a2), z) assert tn(ReduceOrder(a2 + 1, a2).apply(h, op), h2, z) h2 = hyper((a2 + 4, a1), (b1, a2), z) assert tn(ReduceOrder(a2 + 4, a2).apply(h, op), h2, z) # test several step order reduction ap = (a2 + 4, a1, b1 + 1) bq = (a2, b1, b1) func, ops = reduce_order(Hyper_Function(ap, bq)) assert func.ap == (a1, ) assert func.bq == (b1, ) assert tn(apply_operators(h, ops, op), hyper(ap, bq, z), z)
def test_meijerg_formulae(): from sympy.simplify.hyperexpand import MeijerFormulaCollection formulae = MeijerFormulaCollection().formulae for sig in formulae: for formula in formulae[sig]: g = meijerg(formula.func.an, formula.func.ap, formula.func.bm, formula.func.bq, formula.z) rep = {} for sym in formula.symbols: rep[sym] = randcplx() # first test if the closed-form is actually correct g = g.subs(rep) closed_form = formula.closed_form.subs(rep) z = formula.z assert tn(g, closed_form, z) # now test the computed matrix cl = (formula.C * formula.B)[0].subs(rep) assert tn(closed_form, cl, z) deriv1 = z * formula.B.diff(z) deriv2 = formula.M * formula.B for d1, d2 in zip(deriv1, deriv2): assert tn(d1.subs(rep), d2.subs(rep), z)
def can_do_meijer(a1, a2, b1, b2, numeric=True): """ This helper function tries to hyperexpand() the meijer g-function corresponding to the parameters a1, a2, b1, b2. It returns False if this expansion still contains g-functions. If numeric is True, it also tests the so-obtained formula numerically (at random values) and returns False if the test fails. Else it returns True. """ from sympy import unpolarify, expand r = hyperexpand(meijerg(a1, a2, b1, b2, z)) if r.has(meijerg): return False # NOTE hyperexpand() returns a truly branched function, whereas numerical # evaluation only works on the main branch. Since we are evaluating on # the main branch, this should not be a problem, but expressions like # exp_polar(I*pi/2*x)**a are evaluated incorrectly. We thus have to get # rid of them. The expand heuristically does this... r = unpolarify( expand( r, force=True, power_base=True, power_exp=False, mul=False, log=False, multinomial=False, basic=False, )) if not numeric: return True repl = {} for n, ai in enumerate(meijerg(a1, a2, b1, b2, z).free_symbols - {z}): repl[ai] = randcplx(n) return tn(meijerg(a1, a2, b1, b2, z).subs(repl), r.subs(repl), z)
def can_do(ap, bq, numerical=True, div=1, lowerplane=False): r = hyperexpand(hyper(ap, bq, z)) if r.has(hyper): return False if not numerical: return True repl = {} randsyms = r.free_symbols - {z} while randsyms: # Only randomly generated parameters are checked. for n, ai in enumerate(randsyms): repl[ai] = randcplx(n) / div if not any(b.is_Integer and b <= 0 for b in Tuple(*bq).subs(repl)): break [a, b, c, d] = [2, -1, 3, 1] if lowerplane: [a, b, c, d] = [2, -2, 3, -1] return tn(hyper(ap, bq, z).subs(repl), r.replace(exp_polar, exp).subs(repl), z, a=a, b=b, c=c, d=d)
def valid(a, b): from sympy.testing.randtest import verify_numerically as tn if not (tn(a, b) and a == b): return False return True
def check(eq, ans): return tn(eq, ans) and eq == ans
def test_rewrite(): from sympy import polar_lift, exp, I assert besselj(n, z).rewrite(jn) == sqrt(2 * z / pi) * jn(n - S.Half, z) assert bessely(n, z).rewrite(yn) == sqrt(2 * z / pi) * yn(n - S.Half, z) assert besseli(n, z).rewrite(besselj) == exp(-I * n * pi / 2) * besselj( n, polar_lift(I) * z) assert besselj(n, z).rewrite(besseli) == exp(I * n * pi / 2) * besseli( n, polar_lift(-I) * z) nu = randcplx() assert tn(besselj(nu, z), besselj(nu, z).rewrite(besseli), z) assert tn(besselj(nu, z), besselj(nu, z).rewrite(bessely), z) assert tn(besseli(nu, z), besseli(nu, z).rewrite(besselj), z) assert tn(besseli(nu, z), besseli(nu, z).rewrite(bessely), z) assert tn(bessely(nu, z), bessely(nu, z).rewrite(besselj), z) assert tn(bessely(nu, z), bessely(nu, z).rewrite(besseli), z) assert tn(besselk(nu, z), besselk(nu, z).rewrite(besselj), z) assert tn(besselk(nu, z), besselk(nu, z).rewrite(besseli), z) assert tn(besselk(nu, z), besselk(nu, z).rewrite(bessely), z) # check that a rewrite was triggered, when the order is set to a generic # symbol 'nu' assert yn(nu, z) != yn(nu, z).rewrite(jn) assert hn1(nu, z) != hn1(nu, z).rewrite(jn) assert hn2(nu, z) != hn2(nu, z).rewrite(jn) assert jn(nu, z) != jn(nu, z).rewrite(yn) assert hn1(nu, z) != hn1(nu, z).rewrite(yn) assert hn2(nu, z) != hn2(nu, z).rewrite(yn) # rewriting spherical bessel functions (SBFs) w.r.t. besselj, bessely is # not allowed if a generic symbol 'nu' is used as the order of the SBFs # to avoid inconsistencies (the order of bessel[jy] is allowed to be # complex-valued, whereas SBFs are defined only for integer orders) order = nu for f in (besselj, bessely): assert hn1(order, z) == hn1(order, z).rewrite(f) assert hn2(order, z) == hn2(order, z).rewrite(f) assert (jn(order, z).rewrite(besselj) == sqrt(2) * sqrt(pi) * sqrt(1 / z) * besselj(order + S.Half, z) / 2) assert (jn(order, z).rewrite(bessely) == (-1)**nu * sqrt(2) * sqrt(pi) * sqrt(1 / z) * bessely(-order - S.Half, z) / 2) # for integral orders rewriting SBFs w.r.t bessel[jy] is allowed N = Symbol("n", integer=True) ri = randint(-11, 10) for order in (ri, N): for f in (besselj, bessely): assert yn(order, z) != yn(order, z).rewrite(f) assert jn(order, z) != jn(order, z).rewrite(f) assert hn1(order, z) != hn1(order, z).rewrite(f) assert hn2(order, z) != hn2(order, z).rewrite(f) for func, refunc in product((yn, jn, hn1, hn2), (jn, yn, besselj, bessely)): assert tn(func(ri, z), func(ri, z).rewrite(refunc), z)
def test_expand(): from sympy import besselsimp, Symbol, exp, exp_polar, I assert expand_func(besselj( S.Half, z).rewrite(jn)) == sqrt(2) * sin(z) / (sqrt(pi) * sqrt(z)) assert expand_func(bessely( S.Half, z).rewrite(yn)) == -sqrt(2) * cos(z) / (sqrt(pi) * sqrt(z)) # XXX: teach sin/cos to work around arguments like # x*exp_polar(I*pi*n/2). Then change besselsimp -> expand_func assert besselsimp(besselj(S.Half, z)) == sqrt(2) * sin(z) / (sqrt(pi) * sqrt(z)) assert besselsimp(besselj(Rational(-1, 2), z)) == sqrt(2) * cos(z) / (sqrt(pi) * sqrt(z)) assert besselsimp(besselj(Rational( 5, 2), z)) == -sqrt(2) * (z**2 * sin(z) + 3 * z * cos(z) - 3 * sin(z)) / (sqrt(pi) * z**Rational(5, 2)) assert besselsimp(besselj(Rational( -5, 2), z)) == -sqrt(2) * (z**2 * cos(z) - 3 * z * sin(z) - 3 * cos(z)) / (sqrt(pi) * z**Rational(5, 2)) assert besselsimp(bessely(S.Half, z)) == -(sqrt(2) * cos(z)) / (sqrt(pi) * sqrt(z)) assert besselsimp(bessely(Rational(-1, 2), z)) == sqrt(2) * sin(z) / (sqrt(pi) * sqrt(z)) assert besselsimp(bessely(Rational( 5, 2), z)) == sqrt(2) * (z**2 * cos(z) - 3 * z * sin(z) - 3 * cos(z)) / (sqrt(pi) * z**Rational(5, 2)) assert besselsimp(bessely(Rational( -5, 2), z)) == -sqrt(2) * (z**2 * sin(z) + 3 * z * cos(z) - 3 * sin(z)) / (sqrt(pi) * z**Rational(5, 2)) assert besselsimp(besseli(S.Half, z)) == sqrt(2) * sinh(z) / (sqrt(pi) * sqrt(z)) assert besselsimp(besseli(Rational(-1, 2), z)) == sqrt(2) * cosh(z) / (sqrt(pi) * sqrt(z)) assert besselsimp(besseli(Rational( 5, 2), z)) == sqrt(2) * (z**2 * sinh(z) - 3 * z * cosh(z) + 3 * sinh(z)) / (sqrt(pi) * z**Rational(5, 2)) assert besselsimp(besseli(Rational( -5, 2), z)) == sqrt(2) * (z**2 * cosh(z) - 3 * z * sinh(z) + 3 * cosh(z)) / (sqrt(pi) * z**Rational(5, 2)) assert (besselsimp(besselk(S.Half, z)) == besselsimp( besselk(Rational(-1, 2), z)) == sqrt(pi) * exp(-z) / (sqrt(2) * sqrt(z))) assert (besselsimp(besselk(Rational(5, 2), z)) == besselsimp( besselk(Rational(-5, 2), z)) == sqrt(2) * sqrt(pi) * (z**2 + 3 * z + 3) * exp(-z) / (2 * z**Rational(5, 2))) def check(eq, ans): return tn(eq, ans) and eq == ans rn = randcplx(a=1, b=0, d=0, c=2) for besselx in [besselj, bessely, besseli, besselk]: ri = S(2 * randint(-11, 10) + 1) / 2 # half integer in [-21/2, 21/2] assert tn(besselsimp(besselx(ri, z)), besselx(ri, z)) assert check( expand_func(besseli(rn, x)), besseli(rn - 2, x) - 2 * (rn - 1) * besseli(rn - 1, x) / x, ) assert check( expand_func(besseli(-rn, x)), besseli(-rn + 2, x) + 2 * (-rn + 1) * besseli(-rn + 1, x) / x, ) assert check( expand_func(besselj(rn, x)), -besselj(rn - 2, x) + 2 * (rn - 1) * besselj(rn - 1, x) / x, ) assert check( expand_func(besselj(-rn, x)), -besselj(-rn + 2, x) + 2 * (-rn + 1) * besselj(-rn + 1, x) / x, ) assert check( expand_func(besselk(rn, x)), besselk(rn - 2, x) + 2 * (rn - 1) * besselk(rn - 1, x) / x, ) assert check( expand_func(besselk(-rn, x)), besselk(-rn + 2, x) - 2 * (-rn + 1) * besselk(-rn + 1, x) / x, ) assert check( expand_func(bessely(rn, x)), -bessely(rn - 2, x) + 2 * (rn - 1) * bessely(rn - 1, x) / x, ) assert check( expand_func(bessely(-rn, x)), -bessely(-rn + 2, x) + 2 * (-rn + 1) * bessely(-rn + 1, x) / x, ) n = Symbol("n", integer=True, positive=True) assert (expand_func(besseli(n + 2, z)) == besseli(n, z) + (-2 * n - 2) * (-2 * n * besseli(n, z) / z + besseli(n - 1, z)) / z) assert (expand_func(besselj(n + 2, z)) == -besselj(n, z) + (2 * n + 2) * (2 * n * besselj(n, z) / z - besselj(n - 1, z)) / z) assert (expand_func(besselk(n + 2, z)) == besselk(n, z) + (2 * n + 2) * (2 * n * besselk(n, z) / z + besselk(n - 1, z)) / z) assert (expand_func(bessely(n + 2, z)) == -bessely(n, z) + (2 * n + 2) * (2 * n * bessely(n, z) / z - bessely(n - 1, z)) / z) assert expand_func(besseli( n + S.Half, z).rewrite(jn)) == (sqrt(2) * sqrt(z) * exp(-I * pi * (n + S.Half) / 2) * exp_polar(I * pi / 4) * jn(n, z * exp_polar(I * pi / 2)) / sqrt(pi)) assert expand_func(besselj( n + S.Half, z).rewrite(jn)) == sqrt(2) * sqrt(z) * jn(n, z) / sqrt(pi) r = Symbol("r", real=True) p = Symbol("p", positive=True) i = Symbol("i", integer=True) for besselx in [besselj, bessely, besseli, besselk]: assert besselx(i, p).is_extended_real is True assert besselx(i, x).is_extended_real is None assert besselx(x, z).is_extended_real is None for besselx in [besselj, besseli]: assert besselx(i, r).is_extended_real is True for besselx in [bessely, besselk]: assert besselx(i, r).is_extended_real is None
def test_meijer(): raises(TypeError, lambda: meijerg(1, z)) raises(TypeError, lambda: meijerg(((1, ), (2, )), (3, ), (4, ), z)) assert meijerg(((1, 2), (3,)), ((4,), (5,)), z) == \ meijerg(Tuple(1, 2), Tuple(3), Tuple(4), Tuple(5), z) g = meijerg((1, 2), (3, 4, 5), (6, 7, 8, 9), (10, 11, 12, 13, 14), z) assert g.an == Tuple(1, 2) assert g.ap == Tuple(1, 2, 3, 4, 5) assert g.aother == Tuple(3, 4, 5) assert g.bm == Tuple(6, 7, 8, 9) assert g.bq == Tuple(6, 7, 8, 9, 10, 11, 12, 13, 14) assert g.bother == Tuple(10, 11, 12, 13, 14) assert g.argument == z assert g.nu == 75 assert g.delta == -1 assert g.is_commutative is True assert g.is_number is False #issue 13071 assert meijerg([[], []], [[S.Half], [0]], 1).is_number is True assert meijerg([1, 2], [3], [4], [5], z).delta == S.Half # just a few checks to make sure that all arguments go where they should assert tn(meijerg(Tuple(), Tuple(), Tuple(0), Tuple(), -z), exp(z), z) assert tn( sqrt(pi) * meijerg(Tuple(), Tuple(), Tuple(0), Tuple(S.Half), z**2 / 4), cos(z), z) assert tn(meijerg(Tuple(1, 1), Tuple(), Tuple(1), Tuple(0), z), log(1 + z), z) # test exceptions raises(ValueError, lambda: meijerg(((3, 1), (2, )), ((oo, ), (2, 0)), x)) raises(ValueError, lambda: meijerg(((3, 1), (2, )), ((1, ), (2, 0)), x)) # differentiation g = meijerg((randcplx(), ), (randcplx() + 2 * I, ), Tuple(), (randcplx(), randcplx()), z) assert td(g, z) g = meijerg(Tuple(), (randcplx(), ), Tuple(), (randcplx(), randcplx()), z) assert td(g, z) g = meijerg(Tuple(), Tuple(), Tuple(randcplx()), Tuple(randcplx(), randcplx()), z) assert td(g, z) a1, a2, b1, b2, c1, c2, d1, d2 = symbols('a1:3, b1:3, c1:3, d1:3') assert meijerg((a1, a2), (b1, b2), (c1, c2), (d1, d2), z).diff(z) == \ (meijerg((a1 - 1, a2), (b1, b2), (c1, c2), (d1, d2), z) + (a1 - 1)*meijerg((a1, a2), (b1, b2), (c1, c2), (d1, d2), z))/z assert meijerg([z, z], [], [], [], z).diff(z) == \ Derivative(meijerg([z, z], [], [], [], z), z) # meijerg is unbranched wrt parameters from sympy import polar_lift as pl assert meijerg([pl(a1)], [pl(a2)], [pl(b1)], [pl(b2)], pl(z)) == \ meijerg([a1], [a2], [b1], [b2], pl(z)) # integrand from sympy.abc import a, b, c, d, s assert meijerg([a], [b], [c], [d], z).integrand(s) == \ z**s*gamma(c - s)*gamma(-a + s + 1)/(gamma(b - s)*gamma(-d + s + 1))
def u(an, ap, bm, bq): m = meijerg(an, ap, bm, bq, z) m2 = hyperexpand(m, allow_hyper=True) if m2.has(meijerg) and not (m2.is_Piecewise and len(m2.args) == 3): return False return tn(m, m2, z)
def test_lowergamma(): from sympy import meijerg, expint assert lowergamma(x, 0) == 0 assert lowergamma(x, y).diff(y) == y**(x - 1) * exp(-y) assert td(lowergamma(randcplx(), y), y) assert td(lowergamma(x, randcplx()), x) assert lowergamma(x, y).diff(x) == \ gamma(x)*digamma(x) - uppergamma(x, y)*log(y) \ - meijerg([], [1, 1], [0, 0, x], [], y) assert lowergamma(S.Half, x) == sqrt(pi) * erf(sqrt(x)) assert not lowergamma(S.Half - 3, x).has(lowergamma) assert not lowergamma(S.Half + 3, x).has(lowergamma) assert lowergamma(S.Half, x, evaluate=False).has(lowergamma) assert tn(lowergamma(S.Half + 3, x, evaluate=False), lowergamma(S.Half + 3, x), x) assert tn(lowergamma(S.Half - 3, x, evaluate=False), lowergamma(S.Half - 3, x), x) assert tn_branch(-3, lowergamma) assert tn_branch(-4, lowergamma) assert tn_branch(Rational(1, 3), lowergamma) assert tn_branch(pi, lowergamma) assert lowergamma(3, exp_polar(4 * pi * I) * x) == lowergamma(3, x) assert lowergamma(y, exp_polar(5*pi*I)*x) == \ exp(4*I*pi*y)*lowergamma(y, x*exp_polar(pi*I)) assert lowergamma(-2, exp_polar(5*pi*I)*x) == \ lowergamma(-2, x*exp_polar(I*pi)) + 2*pi*I assert conjugate(lowergamma(x, y)) == lowergamma(conjugate(x), conjugate(y)) assert conjugate(lowergamma(x, 0)) == 0 assert unchanged(conjugate, lowergamma(x, -oo)) assert lowergamma(0, x)._eval_is_meromorphic(x, 0) == False assert lowergamma(S(1) / 3, x)._eval_is_meromorphic(x, 0) == False assert lowergamma(1, x, evaluate=False)._eval_is_meromorphic(x, 0) == True assert lowergamma(x, x)._eval_is_meromorphic(x, 0) == False assert lowergamma(x + 1, x)._eval_is_meromorphic(x, 0) == False assert lowergamma(1 / x, x)._eval_is_meromorphic(x, 0) == False assert lowergamma(0, x + 1)._eval_is_meromorphic(x, 0) == False assert lowergamma(S(1) / 3, x + 1)._eval_is_meromorphic(x, 0) == True assert lowergamma(1, x + 1, evaluate=False)._eval_is_meromorphic(x, 0) == True assert lowergamma(x, x + 1)._eval_is_meromorphic(x, 0) == True assert lowergamma(x + 1, x + 1)._eval_is_meromorphic(x, 0) == True assert lowergamma(1 / x, x + 1)._eval_is_meromorphic(x, 0) == False assert lowergamma(0, 1 / x)._eval_is_meromorphic(x, 0) == False assert lowergamma(S(1) / 3, 1 / x)._eval_is_meromorphic(x, 0) == False assert lowergamma(1, 1 / x, evaluate=False)._eval_is_meromorphic(x, 0) == False assert lowergamma(x, 1 / x)._eval_is_meromorphic(x, 0) == False assert lowergamma(x + 1, 1 / x)._eval_is_meromorphic(x, 0) == False assert lowergamma(1 / x, 1 / x)._eval_is_meromorphic(x, 0) == False assert lowergamma(x, 2).series(x, oo, 3) == \ 2**x*(1 + 2/(x + 1))*exp(-2)/x + O(exp(x*log(2))/x**3, (x, oo)) assert lowergamma( x, y).rewrite(expint) == -y**x * expint(-x + 1, y) + gamma(x) k = Symbol('k', integer=True) assert lowergamma( k, y).rewrite(expint) == -y**k * expint(-k + 1, y) + gamma(k) k = Symbol('k', integer=True, positive=False) assert lowergamma(k, y).rewrite(expint) == lowergamma(k, y) assert lowergamma(x, y).rewrite(uppergamma) == gamma(x) - uppergamma(x, y) assert lowergamma(70, 6) == factorial( 69 ) - 69035724522603011058660187038367026272747334489677105069435923032634389419656200387949342530805432320 * exp( -6) assert (lowergamma(S(77) / 2, 6) - lowergamma(S(77) / 2, 6, evaluate=False)).evalf() < 1e-16 assert (lowergamma(-S(77) / 2, 6) - lowergamma(-S(77) / 2, 6, evaluate=False)).evalf() < 1e-16