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

Something specific for pFq([a,a],[a+1,a+1],-x) ? #50

Open
lrnv opened this issue Jan 19, 2023 · 2 comments
Open

Something specific for pFq([a,a],[a+1,a+1],-x) ? #50

lrnv opened this issue Jan 19, 2023 · 2 comments

Comments

@lrnv
Copy link

lrnv commented Jan 19, 2023

Hey,

I do not know deeply what are the algorithms implemente din this package, but I needed the derivative of gamma_inc for my gradient decent and implemented it there, using a call to

pFq([a,a],[a+1,a+1],-x)

where x would always be a positive real, and a could theoretically be any complex, but I only need positives reals too. The serie collapses to the simple :

$$2F_2(a,a,a+1,a+1,z) = \sum{n = 0}^{\infty} \left(\frac{a}{a+n}\right)^2 \frac{z^n}{n!},$$

or even :

$$2F_2(a,a,a+1,a+1,z) = a^2 \sum{n = 0}^{\infty} \left(\frac{1}{a+n}\right)^2 \frac{z^n}{n!},$$

and so i thought that it might be interesting to give it a specific implementation, surely the code for pFq is way too general for this one.

What do you think ? Could you point me in the right direction to implement something specific ?

@MikaelSlevinsky
Copy link
Collaborator

This may sound backwards, but I would probably implement the partial derivative of the incomplete gamma function $\gamma(a,z) = \frac{z^a}{a}M(a,a+1,-z)$ with respect to $a$ with $M$ already implemented here as the dual part of evaluating the mathematical definition at dual number a.

julia> using HypergeometricFunctions

julia> using HypergeometricFunctions.DualNumbers

julia> a = Dual(2.0, 1.0)
2.0 + 1.0ɛ

julia> z = 0.5
0.5

julia> inc_gam(a,z) = z^a/a*HypergeometricFunctions.M(a, a+1, -z)
inc_gam (generic function with 1 method)

julia> inc_gam(a,z)
0.09020401043104985 - 0.11289739433586389ɛ

julia> (inc_gam(2.0+sqrt(eps()), z) - inc_gam(2-sqrt(eps()), z))/2sqrt(eps()) # central difference
-0.11289739375934005

julia> imag(inc_gam(2.0+im*eps(), z)/eps()) # complex difference
-0.11289739433586389

@cadojo
Copy link

cadojo commented Jul 6, 2024

This may sound backwards, but I would probably implement the partial derivative of the incomplete gamma function γ(a,z)=zaaM(a,a+1,−z) with respect to a with M already implemented here...

For anyone interested, I just got this to work with the SciML ecosystem (ModelingToolkit and Symbolics, specifically) by registering HypergeometricFunctions.M, and SpecialFunctions.gamma as symbolic functions with floating point types. This let me take the gradient of the Power Law Cutoff Potential using ModelingToolkit.calculate_gradient!

using SpecialFunctions
using HypergeometricFunctions
using Symbolics

"""
Computes the lower incomplete gamma function.
"""
function lowergamma(a, x)
    p, q = SpecialFunctions.gamma_inc(a, x)
    return p * gamma(a)
end

@register_symbolic lowergamma(x::AbstractFloat, y::AbstractFloat)
@register_symbolic SpecialFunctions.gamma(x::AbstractFloat)
@register_symbolic HypergeometricFunctions.M(
    a::AbstractFloat, b::AbstractFloat, x::AbstractFloat)

function Symbolics.derivative(::typeof(lowergamma), args::NTuple{2, Any}, ::Val{1})
    a, x = args
    return (x^a / a) * HypergeometricFunctions.M(a, a + 1, -x) # https://github.com/JuliaMath/HypergeometricFunctions.jl/issues/50#issuecomment-1397363491
end

function Symbolics.derivative(::typeof(lowergamma), args::NTuple{2, Any}, ::Val{2})
    a, x = args
    return -x^(a - 1) * exp(-x) # https://en.wikipedia.org/wiki/Incomplete_gamma_function#Derivatives
end

using ModelingToolkit

model = begin
    @variables t
    u = @variables x(t) y(t) z(t)
    p = @parameters G m a α c

    G * α * m * lowergamma(3 // 2 - α // 2, (x^2 + y^2 + z^2) / c^2) /
    (2 * sqrt(x^2 + y^2 + z^2) * SpecialFunctions.gamma(5 // 2 - α // 2)) -
    3 * G * m * lowergamma(3 // 2 - α // 2, (x^2 + y^2 + z^2) / c^2) /
    (2 * sqrt(x^2 + y^2 + z^2) * SpecialFunctions.gamma(5 // 2 - α // 2)) +
    G * m * lowergamma(1 - α // 2, (x^2 + y^2 + z^2) / c^2) /
    (c * SpecialFunctions.gamma(3 // 2 - α // 2))
end

Symbolics.gradient(model, u)
3-element Vector{Num}:
 (-2((G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))*α) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))*x(t)*SpecialFunctions.gamma((5//2) - (1//2)*α)) / sqrt(x(t)^2 + y(t)^2 + z(t)^2) + (-2G*m*x(t)*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((-1//2)*α))) / ((c^3)*SpecialFunctions.gamma((3//2) - (1//2)*α)) + (3G*m*x(t)*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-G*m*x(t)*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*α) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-2x(t)*SpecialFunctions.gamma((5//2) - (1//2)*α)*((-3G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))) / sqrt(x(t)^2 + y(t)^2 + z(t)^2)
 (-2((G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))*α) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))*y(t)*SpecialFunctions.gamma((5//2) - (1//2)*α)) / sqrt(x(t)^2 + y(t)^2 + z(t)^2) + (3G*m*y(t)*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-G*m*y(t)*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*α) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-2y(t)*SpecialFunctions.gamma((5//2) - (1//2)*α)*((-3G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))) / sqrt(x(t)^2 + y(t)^2 + z(t)^2) + (-2G*m*y(t)*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((-1//2)*α))) / ((c^3)*SpecialFunctions.gamma((3//2) - (1//2)*α))
        (-2SpecialFunctions.gamma((5//2) - (1//2)*α)*((-3G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))*z(t)) / sqrt(x(t)^2 + y(t)^2 + z(t)^2) + (-2((G*m*lowergamma((3//2) - (1//2)*α, (x(t)^2 + y(t)^2 + z(t)^2) / (c^2))*α) / (4(SpecialFunctions.gamma((5//2) - (1//2)*α)^2)*(sqrt(x(t)^2 + y(t)^2 + z(t)^2)^2)))*SpecialFunctions.gamma((5//2) - (1//2)*α)*z(t)) / sqrt(x(t)^2 + y(t)^2 + z(t)^2) + (3G*m*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*z(t)*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-G*m*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((1//2) - (1//2)*α))*z(t)*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*α) / ((c^2)*SpecialFunctions.gamma((5//2) - (1//2)*α)*sqrt(x(t)^2 + y(t)^2 + z(t)^2)) + (-2G*m*z(t)*exp(-((x(t)^2 + y(t)^2 + z(t)^2) / (c^2)))*(((x(t)^2 + y(t)^2 + z(t)^2) / (c^2))^((-1//2)*α))) / ((c^3)*SpecialFunctions.gamma((3//2) - (1//2)*α))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants