4 votos

Evaluar numéricamente la función hipergeométrica de Gauss ${}_{2}F_{1}(a,b;c;x) $ para grandes $|a|$ o $|b|$ y $x\ll 0$ o $ x \approx 1$ ?

Necesito calcular la función hipergeométrica de Gauss $${}_{2}F_{1}(a,b;c;x)$$ para el caso en que uno de $|a|$ o $|b|$ es grande y $x\ll 0$ o $ x \approx 1$ . Al emplear algunos transformaciones lineales Puedo elegir si quiero $x\ll 0$ o $ x \approx 1$ pero los parámetros superiores siguen siendo grandes en valor absoluto.

Por ejemplo, considere $a=1000, b=0.006, c=0.01, x = -9000$ . Utilizando las transformaciones o no, estos valores de los parámetros dan lugar a errores con hypergeom en MATLAB, hyperg_2F1 de la gsl en R y hypergeo de la hypergeo en R. Funciona cuando $a$ es de alrededor de 100. Sin embargo, necesito calcular ${}_{2}F_{1}$ con $a$ a partir de $10^6$ .

¿Hay algún truco conocido para este problema?

0 votos

Wolfram Mathematica no tiene problemas con esa entrada, aunque para $a = 10^6$ el tiempo de cálculo es de unos segundos.

0 votos

@uranix Eso es interesante - entonces al menos puedo estar seguro de que hay maneras de hacer esto. ¿Cuánto tiempo de computación para $a=10^6$ ?

0 votos

2 segundos. Encontré una interesante recurrencia aquí en la página 31 people.maths.ox.ac.uk/porterm/research/pearson_final.pdf . Estoy desarrollando una respuesta ahora

2voto

uranix Puntos 3824

De Abramowitz y Stegun, 15.2.10 $$ (c-a){}_2F_1(a-1, b; c; z) + (2a-c+(b-a)z){}_2F_1(a, b; c; z) +a(z-1){}_2F_1(a+1, b; c; z) = 0 $$ Dejemos que $G(a) = {}_2F_1(a, b; c; z)$ . Entonces podemos utilizar $$ G(a+1) = \frac{2a-c+(b-a)z}{a(1-z)}G(a)+\frac{c-a}{a(1-z)}G(a-1) $$ recurrencia para calcular $G(a)$ para grandes valores de $a$ partiendo de un par $G(a - \lfloor a \rfloor + 1), G(a - \lfloor a \rfloor + 2)$ .

Aquí está el código MATLAB que implementa esta idea (se basa en hypergeom para los pequeños $a$ )

function g = Hyp2F1(a, b, c, z)
    steps = max(floor(a) - 2, 0);
    t = a - steps;
    g = hypergeom([t, b], c, z);
    gprev = hypergeom([t-1, b], c, z);

    for j = 1:steps
        gsave = g;
        alpha = (2 * t - c + (b - t) * z) / t / (1 - z);
        beta = (c - t) / t / (1 - z);
        g = alpha * g + beta * gprev;
        t = t + 1;
        gprev = gsave;
    end
end

0 votos

Una solución muy limpia que parece ser rápida y fiable - es un poco extraño que tales técnicas no hayan sido implementadas en las funciones 2F1 disponibles para MATLAB y R. De todos modos, muchas gracias.

1 votos

@vgnils Gracias, estoy pensando en alguna optimización que debería mejorar la precisión. Creo que este caso es bastante raro y hay demasiados casos posibles para los parámetros, por lo que cubrir todos los casos es imposible. Además, echa un vistazo a esta pregunta, math.stackexchange.com/questions/478052/ . Hay un enlace al código de MATLAB que utiliza esta idea entre otras.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X