Hypergeometric functions

您所在的位置:网站首页 f1=1f2=2f3=3f4=4 Hypergeometric functions

Hypergeometric functions

2023-03-26 13:56| 来源: 网络整理| 查看: 265

Evaluates the generalized hypergeometric function

\[\,_pF_q(a_1,\ldots,a_p; b_1,\ldots,b_q; z) = \sum_{n=0}^\infty \frac{(a_1)_n (a_2)_n \ldots (a_p)_n} {(b_1)_n(b_2)_n\ldots(b_q)_n} \frac{z^n}{n!}\]

where \((x)_n\) denotes the rising factorial (see rf()).

The parameters lists a_s and b_s may contain integers, real numbers, complex numbers, as well as exact fractions given in the form of tuples \((p, q)\). hyper() is optimized to handle integers and fractions more efficiently than arbitrary floating-point parameters (since rational parameters are by far the most common).

Examples

Verifying that hyper() gives the sum in the definition, by comparison with nsum():

>>> from mpmath import * >>> mp.dps = 25; mp.pretty = True >>> a,b,c,d = 2,3,4,5 >>> x = 0.25 >>> hyper([a,b],[c,d],x) 1.078903941164934876086237 >>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)*x**n/fac(n) >>> nsum(fn, [0, inf]) 1.078903941164934876086237

The parameters can be any combination of integers, fractions, floats and complex numbers:

>>> a, b, c, d, e = 1, (-1,2), pi, 3+4j, (2,3) >>> x = 0.2j >>> hyper([a,b],[c,d,e],x) (0.9923571616434024810831887 - 0.005753848733883879742993122j) >>> b, e = -0.5, mpf(2)/3 >>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)/rf(e,n)*x**n/fac(n) >>> nsum(fn, [0, inf]) (0.9923571616434024810831887 - 0.005753848733883879742993122j)

The \(\,_0F_0\) and \(\,_1F_0\) series are just elementary functions:

>>> a, z = sqrt(2), +pi >>> hyper([],[],z) 23.14069263277926900572909 >>> exp(z) 23.14069263277926900572909 >>> hyper([a],[],z) (-0.09069132879922920160334114 + 0.3283224323946162083579656j) >>> (1-z)**(-a) (-0.09069132879922920160334114 + 0.3283224323946162083579656j)

If any \(a_k\) coefficient is a nonpositive integer, the series terminates into a finite polynomial:

>>> hyper([1,1,1,-3],[2,5],1) 0.7904761904761904761904762 >>> identify(_) '(83/105)'

If any \(b_k\) is a nonpositive integer, the function is undefined (unless the series terminates before the division by zero occurs):

>>> hyper([1,1,1,-3],[-2,5],1) Traceback (most recent call last): ... ZeroDivisionError: pole in hypergeometric series >>> hyper([1,1,1,-1],[-2,5],1) 1.1

Except for polynomial cases, the radius of convergence \(R\) of the hypergeometric series is either \(R = \infty\) (if \(p \le q\)), \(R = 1\) (if \(p = q+1\)), or \(R = 0\) (if \(p > q+1\)).

The analytic continuations of the functions with \(p = q+1\), i.e. \(\,_2F_1\), \(\,_3F_2\), \(\,_4F_3\), etc, are all implemented and therefore these functions can be evaluated for \(|z| \ge 1\). The shortcuts hyp2f1(), hyp3f2() are available to handle the most common cases (see their documentation), but functions of higher degree are also supported via hyper():

>>> hyper([1,2,3,4], [5,6,7], 1) # 4F3 at finite-valued branch point 1.141783505526870731311423 >>> hyper([4,5,6,7], [1,2,3], 1) # 4F3 at pole +inf >>> hyper([1,2,3,4,5], [6,7,8,9], 10) # 5F4 (1.543998916527972259717257 - 0.5876309929580408028816365j) >>> hyper([1,2,3,4,5,6], [7,8,9,10,11], 1j) # 6F5 (0.9996565821853579063502466 + 0.0129721075905630604445669j)

Near \(z = 1\) with noninteger parameters:

>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','41/8'], 1) 2.219433352235586121250027 >>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], 1) +inf >>> eps1 = extradps(6)(lambda: 1 - mpf('1e-6'))() >>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], eps1) 2923978034.412973409330956

Please note that, as currently implemented, evaluation of \(\,_pF_{p-1}\) with \(p \ge 3\) may be slow or inaccurate when \(|z-1|\) is small, for some parameter values.

Evaluation may be aborted if convergence appears to be too slow. The optional maxterms (limiting the number of series terms) and maxprec (limiting the internal precision) keyword arguments can be used to control evaluation:

>>> hyper([1,2,3], [4,5,6], 10000) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([1,2,3], [4,5,6], 10000, maxterms=10**6) 7.622806053177969474396918e+4310

Additional options include force_series (which forces direct use of a hypergeometric series even if another evaluation method might work better) and asymp_tol which controls the target tolerance for using asymptotic series.

When \(p > q+1\), hyper computes the (iterated) Borel sum of the divergent series. For \(\,_2F_0\) the Borel sum has an analytic solution and can be computed efficiently (see hyp2f0()). For higher degrees, the functions is evaluated first by attempting to sum it directly as an asymptotic series (this only works for tiny \(|z|\)), and then by evaluating the Borel regularized sum using numerical integration. Except for special parameter combinations, this can be extremely slow.

>>> hyper([1,1], [], 0.5) # regularization of 2F0 (1.340965419580146562086448 + 0.8503366631752726568782447j) >>> hyper([1,1,1,1], [1], 0.5) # regularization of 4F1 (1.108287213689475145830699 + 0.5327107430640678181200491j)

With the following magnitude of argument, the asymptotic series for \(\,_3F_1\) gives only a few digits. Using Borel summation, hyper can produce a value with full accuracy:

>>> mp.dps = 15 >>> hyper([2,0.5,4], [5.25], '0.08', force_series=True) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([2,0.5,4], [5.25], '0.08', asymp_tol=1e-4) 1.0725535790737 >>> hyper([2,0.5,4], [5.25], '0.08') (1.07269542893559 + 5.54668863216891e-5j) >>> hyper([2,0.5,4], [5.25], '-0.08', asymp_tol=1e-4) 0.946344925484879 >>> hyper([2,0.5,4], [5.25], '-0.08') 0.946312503737771 >>> mp.dps = 25 >>> hyper([2,0.5,4], [5.25], '-0.08') 0.9463125037377662296700858

Note that with the positive \(z\) value, there is a complex part in the correct result, which falls below the tolerance of the asymptotic series.

By default, a parameter that appears in both a_s and b_s will be removed unless it is a nonpositive integer. This generally speeds up evaluation by producing a hypergeometric function of lower order. This optimization can be disabled by passing eliminate=False.

>>> hyper([1,2,3], [4,5,3], 10000) 1.268943190440206905892212e+4321 >>> hyper([1,2,3], [4,5,3], 10000, eliminate=False) Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. >>> hyper([1,2,3], [4,5,3], 10000, eliminate=False, maxterms=10**6) 1.268943190440206905892212e+4321

If a nonpositive integer \(-n\) appears in both a_s and b_s, this parameter cannot be unambiguously removed since it creates a term 0 / 0. In this case the hypergeometric series is understood to terminate before the division by zero occurs. This convention is consistent with Mathematica. An alternative convention of eliminating the parameters can be toggled with eliminate_all=True:

>>> hyper([2,-1], [-1], 3) 7.0 >>> hyper([2,-1], [-1], 3, eliminate_all=True) 0.25 >>> hyper([2], [], 3) 0.25


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3