Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of appellf1 #14882

Merged
merged 9 commits into from Jul 9, 2018
Copy path View file
@@ -1972,6 +1972,10 @@ def test_sympy__functions__special__hyper__HyperRep_sinasin():
from sympy.functions.special.hyper import HyperRep_sinasin
assert _test_args(HyperRep_sinasin(x, y))

def test_sympy__functions__special__hyper__appellf1():
from sympy.functions.special.hyper import appellf1
a, b1, b2, c, x, y = symbols('a b1 b2 c x y')
assert _test_args(appellf1(a, b1, b2, c, x, y))

@SKIP("abstract class")
def test_sympy__functions__special__polynomials__OrthogonalPolynomial():
Copy path View file
@@ -36,7 +36,7 @@
from sympy.functions.special.bsplines import bspline_basis, bspline_basis_set, interpolating_spline
from sympy.functions.special.bessel import (besselj, bessely, besseli, besselk,
hankel1, hankel2, jn, yn, jn_zeros, hn1, hn2, airyai, airybi, airyaiprime, airybiprime)
from sympy.functions.special.hyper import hyper, meijerg
from sympy.functions.special.hyper import hyper, meijerg, appellf1
from sympy.functions.special.polynomials import (legendre, assoc_legendre,
hermite, chebyshevt, chebyshevu, chebyshevu_root, chebyshevt_root,
laguerre, assoc_laguerre, gegenbauer, jacobi, jacobi_normalized)
@@ -11,6 +11,7 @@

from sympy.functions import (sqrt, exp, log, sin, cos, asin, atan,
sinh, cosh, asinh, acosh, atanh, acoth, Abs)
from sympy.utilities.iterables import default_sort_key

class TupleArg(Tuple):
def limit(self, x, xlim, dir='+'):
@@ -1043,3 +1044,47 @@ def _expr_big(cls, a, z, n):
@classmethod
def _expr_big_minus(cls, a, z, n):
return -1/sqrt(1 + 1/z)*sinh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n)

class appellf1(Function):
r"""
This is the Appell hypergeometric function of two variables as:
.. math ::
F_1(a,b_1,b_2,c,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty}
\frac{(a)_{m+n} (b_1)_m (b_2)_n}{(c)_{m+n}}
\frac{x^m y^n}{m! n!}.
References
==========
.. [1] https://en.wikipedia.org/wiki/Appell_series
.. [2] http://functions.wolfram.com/HypergeometricFunctions/AppellF1/
"""

@classmethod
def eval(cls, a, b1, b2, c, x, y):
if default_sort_key(b1) > default_sort_key(b2):
b1, b2 = b2, b1
x, y = y, x
return cls(a, b1, b2, c, x, y)
elif b1 == b2 and default_sort_key(x) > default_sort_key(y):
x, y = y, x
return cls(a, b1, b2, c, x, y)

def _eval_rewrite_as_factorial(self, *args):
from sympy import symbols, Sum, RisingFactorial, factorial
m, n = symbols('m n', integer = True)
a, b1, b2, c, x, y = self.args
return Sum(x**m*y**n*RisingFactorial(a, m + n)*RisingFactorial(b1, m)*\
RisingFactorial(b2, n)/(factorial(m)*factorial(n)*RisingFactorial(c, m + n)), (m, 0, oo), (n, 0, oo)).rewrite(factorial)

def fdiff(self, argindex=5):
a, b1, b2, c, x, y = self.args
if argindex == 5:
return (a*b1/c)*appellf1(a + 1, b1 + 1, b2, c + 1, x, y)
elif argindex == 6:
return (a*b2/c)*appellf1(a + 1, b1, b2 + 1, c + 1, x, y)
elif argindex in (1, 2, 3, 4):
raise NotImplementedError("Unable to find derivative wrt to {}".format(self.args[argindex-1]))

This comment has been minimized.

Copy link
@Upabjojr

Upabjojr Jul 9, 2018

Contributor

maybe this should return the unevaluated derivative:

return Derivative(self, self.args[argindex-1])
else:
raise ArgumentIndexError(self, argindex)
@@ -1,5 +1,5 @@
from sympy import (hyper, meijerg, S, Tuple, pi, I, exp, log,
cos, sqrt, symbols, oo, Derivative, gamma, O)
cos, sqrt, symbols, oo, Derivative, gamma, O, appellf1)
from sympy.series.limits import limit
from sympy.abc import x, z, k
from sympy.utilities.pytest import raises, slow
@@ -343,3 +343,27 @@ def test_limits():
O(k**6) # issue 6350
assert limit(meijerg((), (), (1,), (0,), -x), x, 0) == \
meijerg(((), ()), ((1,), (0,)), 0) # issue 6052

def test_appellf1():
a, b1, b2, c, x, y = symbols('a b1 b2 c x y')
assert appellf1(a, b2, b1, c, y, x) == appellf1(a, b1, b2, c, x, y)
assert appellf1(a, b1, b1, c, y, x) == appellf1(a, b1, b1, c, x, y)

def test_derivative_appellf1():
from sympy import diff
a, b1, b2, c, x, y, z = symbols('a b1 b2 c x y z')
assert diff(appellf1(a, b1, b2, c, x, y), x) == a*b1*appellf1(a + 1, b2, b1 + 1, c + 1, y, x)/c
assert diff(appellf1(a, b1, b2, c, x, y), y) == a*b2*appellf1(a + 1, b1, b2 + 1, c + 1, x, y)/c
assert diff(appellf1(a, b1, b2, c, x, y), z) == 0

def test_appellf1_rewrite_factorial():
from sympy import factorial, Sum, oo
x, y = symbols('x y')
m, n = symbols('m n', integer=True)
assert appellf1(1 ,2 ,2, 1, 0.5, 0.6).rewrite(factorial) == \
Sum(0.5**m*0.6**n*factorial(m + 1)*factorial(n + 1)/(factorial(m)*\
factorial(n)), (m, 0, oo), (n, 0, oo))

This comment has been minimized.

Copy link
@Upabjojr

Upabjojr Jul 9, 2018

Contributor

I was unable to get these expressions in Mathematica. Did you use Mathematica to verify these results?

This comment has been minimized.

Copy link
@ashishkg0022

ashishkg0022 Jul 9, 2018

Author Contributor

RisingFactorial.rewrite(factorial) gives wrong result in sympy. I think we don't need this. Once this issue (#14871) is fixed, it can be added later.


assert appellf1(1 ,2 ,4, 2, x, y).rewrite(factorial) == \
Sum(x**m*y**n*factorial(m + 1)*factorial(m + n)*factorial(n + 3)/(6*factorial(m)*\
factorial(n)*factorial(m + n + 1)), (m, 0, oo), (n, 0, oo))
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.