Python的random
模块中包含以下方法:
def gammavariate(self, alpha, beta):
"""Gamma distribution. Not the gamma function!
Conditions on the parameters are alpha > 0 and beta > 0.
The probability distribution function is:
x ** (alpha - 1) * math.exp(-x / beta)
pdf(x) = --------------------------------------
math.gamma(alpha) * beta ** alpha
"""
# alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
# Warning: a few older sources define the gamma distribution in terms
# of alpha > -1.0
if alpha <= 0.0 or beta <= 0.0:
raise ValueError('gammavariate: alpha and beta must be > 0.0')
random = self.random
if alpha > 1.0:
# Uses R.C.H. Cheng, "The generation of Gamma
# variables with non-integral shape parameters",
# Applied Statistics, (1977), 26, No. 1, p71-74
ainv = _sqrt(2.0 * alpha - 1.0)
bbb = alpha - LOG4
ccc = alpha + ainv
while 1:
u1 = random()
if not 1e-7 < u1 < .9999999:
continue
u2 = 1.0 - random()
v = _log(u1/(1.0-u1))/ainv
x = alpha*_exp(v)
z = u1*u1*u2
r = bbb+ccc*v-x
if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
return x * beta
elif alpha == 1.0:
# expovariate(1)
u = random()
while u <= 1e-7:
u = random()
return -_log(u) * beta
else: # alpha is between 0 and 1 (exclusive)
# Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
while 1:
u = random()
b = (_e + alpha)/_e
p = b*u
if p <= 1.0:
x = p ** (1.0/alpha)
else:
x = -_log((b-p)/alpha)
u1 = random()
if p > 1.0:
if u1 <= x ** (alpha - 1.0):
break
elif u1 <= _exp(-x):
break
return x * beta
在将代码移植到Java上以供使用时,我的IDE一直在抱怨ainv
变量名称存在拼写错误(拼写错误)。这个名字来自哪里,背后的理由是什么?如果有人能找到 Applied Statistics,(1977),26,No.1,p71-74 的参考资料,那么能够阅读这些页面可能会有所帮助。
附录
这可能对任何人都有用,也可能没有用,但这里是移植过的类的部分实现。代码似乎是完整的,但JetBrains Intellij IDEA如果没有添加到IDE的字典中则会抱怨ainv
的拼写。这导致了一些关于是否应该被认为是正确拼写的犹豫不决。这是该计划抱怨的唯一错字。
import java.util.Random;
class XRandom extends Random {
static final double LOG4 = Math.log(4);
static final double SG_MAGIC_CONST = 1 + Math.log(4.5);
double gammaVariate(double alpha, double beta) {
if (alpha <= 0 || beta <= 0)
throw new RuntimeException("gammaVariate: alpha and beta must be > 0");
if (alpha > 1) {
double ainv, bbb, ccc, u1, v, x, z, r;
ainv = Math.sqrt(2 * alpha - 1);
bbb = alpha - LOG4;
ccc = alpha + ainv;
while (true) {
u1 = this.nextDouble();
if (u1 <= 1e-7 || u1 >= .9999999)
continue;
v = Math.log(u1 / (1 - u1)) / ainv;
x = alpha * Math.exp(v);
z = u1 * u1 * (1 - this.nextDouble());
r = bbb + ccc * v - x;
if (r + SG_MAGIC_CONST - 4.5 * z >= 0 || r >= Math.log(z))
return x * beta;
}
}
if (alpha < 1) {
double b, p, x, u1;
while (true) {
b = (Math.E + alpha) / Math.E;
p = b * this.nextDouble();
x = p <= 1 ? Math.pow(p, 1 / alpha) : -Math.log((b - p) / alpha);
u1 = this.nextDouble();
if (p > 1) {
if (u1 <= Math.pow(x, alpha - 1))
break;
} else if (u1 <= Math.exp(-x))
break;
}
return x * beta;
}
double u;
do {
u = this.nextDouble();
} while (u <= 1e-7);
return -Math.log(u) * beta;
}
}
答案 0 :(得分:0)
不确定为什么IDE认为这是一个错字,但是你不需要声明ainv
变量吗?
double ainv = Math.sqrt(2.0 * alpha - 1.0) ;
至于它的目的,它看起来只是在其他两个地方使用的中间计算。
答案 1 :(得分:0)
我找到了第71页here,但是第72-75页似乎需要一个帐户才能以全分辨率查看它们。