def test_partial_simp(): # First test that hypergeometric function formulae work. a, b, c, d, e = (randcplx() for _ in range(5)) for func in [Hyper_Function([a, b, c], [d, e]), Hyper_Function([], [a, b, c, d, e])]: f = build_hypergeometric_formula(func) z = f.z assert f.closed_form == func(z) deriv1 = f.B.diff(z)*z deriv2 = f.M*f.B for func1, func2 in zip(deriv1, deriv2): assert tn(func1, func2, z) # Now test that formulae are partially simplified. from sympy.abc import a, b, z assert hyperexpand(hyper([3, a], [1, b], z)) == \ (-a*b/2 + a*z/2 + 2*a)*hyper([a + 1], [b], z) \ + (a*b/2 - 2*a + 1)*hyper([a], [b], z) assert tn( hyperexpand(hyper([3, d], [1, e], z)), hyper([3, d], [1, e], z), z) assert hyperexpand(hyper([3], [1, a, b], z)) == \ hyper((), (a, b), z) \ + z*hyper((), (a + 1, b), z)/(2*a) \ - z*(b - 4)*hyper((), (a + 1, b + 1), z)/(2*a*b) assert tn( hyperexpand(hyper([3], [1, d, e], z)), hyper([3], [1, d, e], z), z)
def test_plan_derivatives(): a1, a2, a3 = 1, 2, S('1/2') b1, b2 = 3, S('5/2') h = Hyper_Function((a1, a2, a3), (b1, b2)) h2 = Hyper_Function((a1 + 1, a2 + 1, a3 + 2), (b1 + 1, b2 + 1)) ops = devise_plan(h2, h, z) f = Formula(h, z, h(z), []) deriv = make_derivative_operator(f.M, z) assert tn((apply_operators(f.C, ops, deriv)*f.B)[0], h2(z), z) h2 = Hyper_Function((a1, a2 - 1, a3 - 2), (b1 - 1, b2 - 1)) ops = devise_plan(h2, h, z) assert tn((apply_operators(f.C, ops, deriv)*f.B)[0], h2(z), z)
def test_attrs(): a, b = symbols("a, b", cls=Dummy) f = Hyper_Function([2, a], [b]) assert f.ap == Tuple(2, a) assert f.bq == Tuple(b) assert f.args == (Tuple(2, a), Tuple(b)) assert f.sizes == (2, 1)
def test_gamma(): assert Hyper_Function([2, 3], [-1]).gamma == 0 assert Hyper_Function([-2, -3], [-1]).gamma == 2 n = Dummy(integer=True) assert Hyper_Function([-1, n, 1], []).gamma == 1 assert Hyper_Function([-1, -n, 1], []).gamma == 1 p = Dummy(integer=True, positive=True) assert Hyper_Function([-1, p, 1], []).gamma == 1 assert Hyper_Function([-1, -p, 1], []).gamma == 2
def test_suitable_origin(): assert Hyper_Function((S(1) / 2, ), (S(3) / 2, ))._is_suitable_origin() is True assert Hyper_Function((S(1) / 2, ), (S(1) / 2, ))._is_suitable_origin() is False assert Hyper_Function((S(1) / 2, ), (-S(1) / 2, ))._is_suitable_origin() is False assert Hyper_Function((S(1) / 2, ), (0, ))._is_suitable_origin() is False assert Hyper_Function((S(1) / 2, ), ( -1, 1, ))._is_suitable_origin() is False assert Hyper_Function((S(1) / 2, 0), (1, ))._is_suitable_origin() is False assert Hyper_Function((S(1) / 2, 1), (2, -S(2) / 3))._is_suitable_origin() is True assert Hyper_Function( (S(1) / 2, 1), (2, -S(2) / 3, S(3) / 2))._is_suitable_origin() is True
def test_suitable_origin(): assert Hyper_Function((S.Half, ), (Rational(3, 2), ))._is_suitable_origin() is True assert Hyper_Function((S.Half, ), (S.Half, ))._is_suitable_origin() is False assert Hyper_Function((S.Half, ), (Rational(-1, 2), ))._is_suitable_origin() is False assert Hyper_Function((S.Half, ), (0, ))._is_suitable_origin() is False assert Hyper_Function((S.Half, ), ( -1, 1, ))._is_suitable_origin() is False assert Hyper_Function((S.Half, 0), (1, ))._is_suitable_origin() is False assert (Hyper_Function((S.Half, 1), (2, Rational(-2, 3)))._is_suitable_origin() is True) assert (Hyper_Function( (S.Half, 1), (2, Rational(-2, 3), Rational(3, 2)))._is_suitable_origin() is True)
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_eq(): assert Hyper_Function([1], []) == Hyper_Function([1], []) assert (Hyper_Function([1], []) != Hyper_Function([1], [])) is False assert Hyper_Function([1], []) != Hyper_Function([2], []) assert Hyper_Function([1], []) != Hyper_Function([1, 2], []) assert Hyper_Function([1], []) != Hyper_Function([1], [2])
def test_has(): a, b, c = symbols("a, b, c", cls=Dummy) f = Hyper_Function([2, -a], [b]) assert f.has(a) assert f.has(Tuple(b)) assert not f.has(c)
def test_call(): a, b, x = symbols("a, b, x", cls=Dummy) f = Hyper_Function([2, a], [b]) assert f(x) == hyper([2, a], [b], x)
def test_plan(): assert devise_plan(Hyper_Function([0], ()), Hyper_Function([0], ()), z) == [] with raises(ValueError): devise_plan(Hyper_Function([1], ()), Hyper_Function((), ()), z) with raises(ValueError): devise_plan(Hyper_Function([2], [1]), Hyper_Function([2], [2]), z) with raises(ValueError): devise_plan(Hyper_Function([2], []), Hyper_Function([S("1/2")], []), z) # We cannot use pi/(10000 + n) because polys is insanely slow. a1, a2, b1 = (randcplx(n) for n in range(3)) b1 += 2*I h = hyper([a1, a2], [b1], z) h2 = hyper((a1 + 1, a2), [b1], z) assert tn(apply_operators(h, devise_plan(Hyper_Function((a1 + 1, a2), [b1]), Hyper_Function((a1, a2), [b1]), z), op), h2, z) h2 = hyper((a1 + 1, a2 - 1), [b1], z) assert tn(apply_operators(h, devise_plan(Hyper_Function((a1 + 1, a2 - 1), [b1]), Hyper_Function((a1, a2), [b1]), z), op), h2, z)