In [46]:
import numpy as np
from scipy.special import gamma
import matplotlib.pyplot as plt

Gamma function¶

$$ \Gamma(x) = \int_0^\infty t^{x-1} e^{-t} dt $$

for $x,t\in \mathbb R$ and $\Gamma: \mathbb R \to \mathbb R$. However, one can also extend the definition to complex numbers by analytic continuation and obtain the same definition but with $x, \Gamma(x) \in \mathbb C$. In Scipy, one uses the complex definition.

In [47]:
x = np.linspace(-2,6,1000)
G = gamma(x)
In [48]:
plt.plot(x,G)
plt.ylim(-100,100)
Out[48]:
(-100.0, 100.0)
No description has been provided for this image
In [49]:
# Natural logarithm of the Gamma function
x = np.linspace(-2,20)
plt.plot(x,np.log(gamma(x)))
/var/folders/2m/tgbjydr93_9_19gzzmp_v_3w0000gn/T/ipykernel_18975/2765431682.py:3: RuntimeWarning: invalid value encountered in log
  plt.plot(x,np.log(gamma(x)))
Out[49]:
[<matplotlib.lines.Line2D at 0x11f496d80>]
No description has been provided for this image
In [50]:
# Logarithm base 10 of the Gamma function
x = np.linspace(-2,20)
plt.plot(x,np.log10(gamma(x)))
# easy way to visualize n! of a very large number
/var/folders/2m/tgbjydr93_9_19gzzmp_v_3w0000gn/T/ipykernel_18975/3274935164.py:3: RuntimeWarning: invalid value encountered in log10
  plt.plot(x,np.log10(gamma(x)))
Out[50]:
[<matplotlib.lines.Line2D at 0x11f50aba0>]
No description has been provided for this image

Comparison with the factorial:¶

$ \Gamma(x) = (n-1)! $

In [51]:
def factorial(n):
    if n > 0:
        return n*factorial(n-1)
    if n == 0:
        return 1
    else:
        raise ValueError
In [52]:
print(factorial(4),4*3*2*1)
24 24
In [53]:
x = np.linspace(-2,6,1000)
G = gamma(x+1)

x_posinteger = np.linspace(0,6,6,dtype=int)
n = x_posinteger + 1
factorials = np.array([ factorial(n_i) for n_i in n ])
In [54]:
plt.plot(x,G,label="Gamma(x+1)")
plt.scatter(n,factorials,label="n!")
plt.legend()
plt.ylim(-100,200)
Out[54]:
(-100.0, 200.0)
No description has been provided for this image

Recursion of the Gamma function¶

In [55]:
x = np.linspace(-2,6,1000)
G = gamma(x+1)
G1 = x*gamma(x)
plt.plot(x,G,ls="-",label="Gamma(x+1)")
plt.plot(x,G1,ls="--",label="x*Gamma(x)")
plt.legend()
plt.ylim(-100,100)
Out[55]:
(-100.0, 100.0)
No description has been provided for this image

The gamma function and the Gaussian distribution¶

Consider the integral $I_0 = \int_{-\infty}^{\infty} e^{-a x^2} dx$. We can integrate by considering first the integral $I_0^2 = \int_{-\infty}^\infty e^{a(x^2 + y^2)} dx dy$ and changing to polar coordinates, $I_0^2 = \int_0^{\infty} \int_0^{2\pi} e^{-ar^2} rdrd\phi = \pi/a $ $\implies I_0 = \sqrt{\pi/a}$.

For $a = 1$, we have $I_0 = \sqrt{\pi}$. Now think of the integral

$$ \Gamma(1/2) = \int_0^{\infty} \frac{1}{\sqrt{t}}e^{-t} dt $$

With the change of variable $t = y^2$, we find $ \Gamma(1/2) = 2\int_0^\infty e^{-y^2} dy = \sqrt{\pi} $

In [56]:
# Verification
print(gamma(1/2),np.sqrt(np.pi))
1.7724538509055159 1.7724538509055159

By the recurrence relation, we can also find

In [57]:
print(gamma(3/2), (1/2)*gamma(1/2), (1/2)*np.sqrt(np.pi))
0.8862269254527579 0.8862269254527579 0.8862269254527579

Let's explore numerically

In [58]:
x = np.linspace(-10,10,100)
I0_integrand = np.exp(-x**2)
plt.plot(x,I0_integrand)
Out[58]:
[<matplotlib.lines.Line2D at 0x11f603ef0>]
No description has been provided for this image
In [59]:
dx = np.diff(x)[0]
np.sum(I0_integrand*dx), np.sqrt(np.pi)
Out[59]:
(np.float64(1.7724538509055194), np.float64(1.7724538509055159))

Beta function¶

In [68]:
from scipy.special import beta
In [69]:
beta(2,3)
Out[69]:
np.float64(0.08333333333333333)
In [70]:
gamma(2)*gamma(3)/gamma(2+3)
Out[70]:
np.float64(0.08333333333333333)
In [71]:
beta(3,2)
Out[71]:
np.float64(0.08333333333333333)
In [72]:
print(beta(1,5), 1/5)
0.2 0.2

Complex gamma function¶

In [65]:
x = np.linspace(-10,10,1000)
y = np.linspace(-10,10,1000)
x, y = np.meshgrid(x,y,indexing="ij")
z = x + 1j*y
gamma_eval = gamma(z)
In [66]:
plt.pcolormesh(np.real(z),np.imag(z),np.real(gamma_eval),vmin=-10,vmax=10,cmap="seismic_r")
plt.colorbar()
plt.grid()
No description has been provided for this image
In [67]:
plt.pcolormesh(np.real(z),np.imag(z),np.imag(gamma_eval),vmin=-10,vmax=10,cmap="seismic_r")
plt.colorbar()
plt.grid()
No description has been provided for this image
In [ ]: