# Incomplete gamma functions. (2.01)
# (and chi-squared cumulative distribution)
# @see Numerical Recipes in Fortran 77 (Ch. 6.2 Special Functions).
from math import lgamma, exp, log
# Regularized lower incomplete gamma function.
# P(a, x) = γ(a, x) / Γ(a)
def gammaP(a, x):
return 1 - gammaQ(a, x)
# Regularized upper incomplete gamma function.
# Q(a, x) = Γ(a, x) / Γ(a)
def gammaQ(a, x):
if x < 0 or a <= 0:
raise ValueError('bad arguments')
if x < a+1:
return 1 - p_series(a, x)
else:
return q_continued_fraction(a, x)
def p_series(a, x, itmax=1000, eps=3.0E-7):
if x == 0: # !
return 0.0
ap=a
sum_=1/a
del_=sum_
for _ in range(1, 1+itmax):
ap=ap+1
del_=del_*x/ap
sum_=sum_+del_
if abs(del_) < abs(sum_)*eps:
return sum_*exp(-x+a*log(x)-lgamma(a))
raise ValueError('a too large, itmax too small')
def q_continued_fraction(a, x, itmax=1000, eps=3.0E-7, fpmin=1.0E-30):
b=x+1-a
c=1/fpmin
d=1/b
h=d
for i in range(1, 1+itmax):
an=-i*(i-a)
b=b+2
d=an*d+b
if abs(d) < fpmin: d=fpmin
c=b+an/c
if abs(c) < fpmin: c=fpmin
d=1/d
del_=d*c
h=h*del_
if abs(del_-1) < eps:
return h*exp(-x+a*log(x)-lgamma(a))
raise ValueError('a too large, itmax too small')
# Chi-squared cumulative distribution function.
def cdf(x, k):
return gammaP(k/2, x/2)
# Chi-squared p-value.
def pvalue(x, k):
return 1 - cdf(x, k)
# Expect PV: [0.99, 0.95, 0.5, 0.05, 0.01]
# @see Engineering Tables/Chi-squared Distribution - Wikibooks
ks=[1, 2, 4, 10, 100, 1000]
vs=[[1.57E-4, 0.00393, 0.455, 3.841, 6.635],
[ 0.0201, 0.103, 1.386, 5.991, 9.210],
[ 0.297, 0.711, 3.357, 9.488, 13.277],
[ 2.558, 3.940, 9.342, 18.307, 23.209],
[ 70.065, 77.929, 99.334, 124.342, 135.807],
[898.912, 927.594, 999.333, 1074.679, 1106.969]]
for k, v in zip(ks, vs):
print([round(pvalue(x, k), 2) for x in v])
IyBJbmNvbXBsZXRlIGdhbW1hIGZ1bmN0aW9ucy4gKDIuMDEpCiMgKGFuZCBjaGktc3F1YXJlZCBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbikKIyBAc2VlIE51bWVyaWNhbCBSZWNpcGVzIGluIEZvcnRyYW4gNzcgKENoLiA2LjIgU3BlY2lhbCBGdW5jdGlvbnMpLgoKZnJvbSBtYXRoIGltcG9ydCBsZ2FtbWEsIGV4cCwgbG9nCgojIFJlZ3VsYXJpemVkIGxvd2VyIGluY29tcGxldGUgZ2FtbWEgZnVuY3Rpb24uCiMgUChhLCB4KSA9IM6zKGEsIHgpIC8gzpMoYSkKZGVmIGdhbW1hUChhLCB4KToKICAgIHJldHVybiAxIC0gZ2FtbWFRKGEsIHgpCgojIFJlZ3VsYXJpemVkIHVwcGVyIGluY29tcGxldGUgZ2FtbWEgZnVuY3Rpb24uCiMgUShhLCB4KSA9IM6TKGEsIHgpIC8gzpMoYSkKZGVmIGdhbW1hUShhLCB4KToKICAgIGlmIHggPCAwIG9yIGEgPD0gMDoKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCdiYWQgYXJndW1lbnRzJykKICAgIGlmIHggPCBhKzE6CiAgICAgICAgcmV0dXJuIDEgLSBwX3NlcmllcyhhLCB4KQogICAgZWxzZToKICAgICAgICByZXR1cm4gcV9jb250aW51ZWRfZnJhY3Rpb24oYSwgeCkKCmRlZiBwX3NlcmllcyhhLCB4LCBpdG1heD0xMDAwLCBlcHM9My4wRS03KToKICAgIGlmIHggPT0gMDogIyAhCiAgICAgICAgcmV0dXJuIDAuMAogICAgYXA9YQogICAgc3VtXz0xL2EKICAgIGRlbF89c3VtXwogICAgZm9yIF8gaW4gcmFuZ2UoMSwgMStpdG1heCk6CiAgICAgICAgYXA9YXArMQogICAgICAgIGRlbF89ZGVsXyp4L2FwCiAgICAgICAgc3VtXz1zdW1fK2RlbF8KICAgICAgICBpZiBhYnMoZGVsXykgPCBhYnMoc3VtXykqZXBzOgogICAgICAgICAgICByZXR1cm4gc3VtXypleHAoLXgrYSpsb2coeCktbGdhbW1hKGEpKQogICAgcmFpc2UgVmFsdWVFcnJvcignYSB0b28gbGFyZ2UsIGl0bWF4IHRvbyBzbWFsbCcpCgpkZWYgcV9jb250aW51ZWRfZnJhY3Rpb24oYSwgeCwgaXRtYXg9MTAwMCwgZXBzPTMuMEUtNywgZnBtaW49MS4wRS0zMCk6CiAgICBiPXgrMS1hCiAgICBjPTEvZnBtaW4KICAgIGQ9MS9iCiAgICBoPWQKICAgIGZvciBpIGluIHJhbmdlKDEsIDEraXRtYXgpOgogICAgICAgIGFuPS1pKihpLWEpCiAgICAgICAgYj1iKzIKICAgICAgICBkPWFuKmQrYgogICAgICAgIGlmIGFicyhkKSA8IGZwbWluOiBkPWZwbWluCiAgICAgICAgYz1iK2FuL2MKICAgICAgICBpZiBhYnMoYykgPCBmcG1pbjogYz1mcG1pbgogICAgICAgIGQ9MS9kCiAgICAgICAgZGVsXz1kKmMKICAgICAgICBoPWgqZGVsXwogICAgICAgIGlmIGFicyhkZWxfLTEpIDwgZXBzOgogICAgICAgICAgICByZXR1cm4gaCpleHAoLXgrYSpsb2coeCktbGdhbW1hKGEpKQogICAgcmFpc2UgVmFsdWVFcnJvcignYSB0b28gbGFyZ2UsIGl0bWF4IHRvbyBzbWFsbCcpCgojIENoaS1zcXVhcmVkIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uLgpkZWYgY2RmKHgsIGspOgogICAgcmV0dXJuIGdhbW1hUChrLzIsIHgvMikKCiMgQ2hpLXNxdWFyZWQgcC12YWx1ZS4KZGVmIHB2YWx1ZSh4LCBrKToKICAgIHJldHVybiAxIC0gY2RmKHgsIGspCgojIEV4cGVjdCBQVjogWzAuOTksIDAuOTUsIDAuNSwgMC4wNSwgMC4wMV0KIyBAc2VlIEVuZ2luZWVyaW5nIFRhYmxlcy9DaGktc3F1YXJlZCBEaXN0cmlidXRpb24gLSBXaWtpYm9va3MKa3M9WzEsIDIsIDQsIDEwLCAxMDAsIDEwMDBdCnZzPVtbMS41N0UtNCwgMC4wMDM5MywgICAwLjQ1NSwgICAgMy44NDEsICAgIDYuNjM1XSwKICAgIFsgMC4wMjAxLCAgIDAuMTAzLCAgIDEuMzg2LCAgICA1Ljk5MSwgICAgOS4yMTBdLAogICAgWyAgMC4yOTcsICAgMC43MTEsICAgMy4zNTcsICAgIDkuNDg4LCAgIDEzLjI3N10sCiAgICBbICAyLjU1OCwgICAzLjk0MCwgICA5LjM0MiwgICAxOC4zMDcsICAgMjMuMjA5XSwKICAgIFsgNzAuMDY1LCAgNzcuOTI5LCAgOTkuMzM0LCAgMTI0LjM0MiwgIDEzNS44MDddLAogICAgWzg5OC45MTIsIDkyNy41OTQsIDk5OS4zMzMsIDEwNzQuNjc5LCAxMTA2Ljk2OV1dCgpmb3IgaywgdiBpbiB6aXAoa3MsIHZzKToKICAgIHByaW50KFtyb3VuZChwdmFsdWUoeCwgayksIDIpIGZvciB4IGluIHZdKQ==