我正在为C ++命令行Linux应用程序编写一些测试。我想生成一堆具有幂律/长尾分布的整数。意思是,我经常得到一些数字,但大多数都是相对不频繁的。
理想情况下,我可以使用rand()或其中一个stdlib随机函数。如果没有,一个易于使用的C / C ++块就会很棒。
谢谢!
答案 0 :(得分:34)
本page at Wolfram MathWorld讨论了如何从均匀分布中获得幂律分布(这是大多数随机数生成器提供的分布)。
简短回答(从以上链接推导出来):
x = [(x1^(n+1) - x0^(n+1))*y + x0^(n+1)]^(1/(n+1))
其中 y 是统一变量, n 是分配能力, x0 和 x1 定义范围分布, x 是你的幂律分布变量。
答案 1 :(得分:18)
如果您知道所需的分布(称为概率分布函数(PDF))并将其正确归一化,则可以将其集成以获得累积分布函数(CDF),然后反转CDF(如果可能)以获取您需要从统一[0,1]
分发到您想要的转换。
所以你首先要定义你想要的发行版。
P = F(x)
(对于[0,1]中的x)然后积分给出
C(y) = \int_0^y F(x) dx
如果可以倒置,你可以
y = F^{-1}(C)
请调用rand()
并将结果插入最后一行的C
并使用y。
这个结果被称为采样的基本定理。由于归一化要求和分析反转函数的需要,这是一个麻烦。
或者,您可以使用拒绝技术:将数字均匀地投射到所需范围内,然后抛出另一个数字并与第一次投掷所在位置的PDF进行比较。如果第二次投掷超过PDF则拒绝。对于具有大量低概率区域的PDF来说效率低下,比如那些长尾巴的那些......
中间方法涉及通过暴力反转CDF:将CDF存储为查找表,并进行反向查找以获得结果。
这里真正的问题是简单的x^-n
分布在范围[0,1]
上是不可规范化的,所以你不能使用抽样定理。尝试(x + 1)^ - n而不是......
答案 2 :(得分:3)
我无法评论产生幂律分布所需的数学(其他帖子有建议),但我建议您熟悉<random>
中的TR1 C ++标准库随机数设施。这些提供的功能比std::rand
和std::srand
更多。新系统为发生器,引擎和发行版指定了模块化API,并提供了大量预设。
包含的分发预设为:
uniform_int
bernoulli_distribution
geometric_distribution
poisson_distribution
binomial_distribution
uniform_real
exponential_distribution
normal_distribution
gamma_distribution
定义幂律分布时,您应该能够将其插入现有的发电机和引擎中。 Pete Becker撰写的 C ++标准库扩展一书对<random>
有一个很好的章节。
Here is an article关于如何创建其他发行版(包含Cauchy,Chi-squared,Student t和Snedecor F的示例)
答案 3 :(得分:3)
我只想进行实际模拟,作为(正确)接受的答案的补充。虽然在R中,代码很简单,但是(伪)-pseudo-code。
接受的答案中的Wolfram MathWorld formula与其他可能更常见的方程之间的微小差异是幂律指数 n
(通常表示为因为alpha)没有明确的负号。因此,所选的alpha值必须为负值,通常在2到3之间。
x0
和x1
代表分发的下限和上限。
所以这是:
x1 = 5 # Maximum value
x0 = 0.1 # It can't be zero; otherwise X^0^(neg) is 1/0.
alpha = -2.5 # It has to be negative.
y = runif(1e5) # Number of samples
x = ((x1^(alpha+1) - x0^(alpha+1))*y + x0^(alpha+1))^(1/(alpha+1))
hist(x, prob = T, breaks=40, ylim=c(0,10), xlim=c(0,1.2), border=F,
col="yellowgreen", main="Power law density")
lines(density(x), col="chocolate", lwd=1)
lines(density(x, adjust=2), lty="dotted", col="darkblue", lwd=2)
或以对数标度绘制:
h = hist(x, prob=T, breaks=40, plot=F)
plot(h$count, log="xy", type='l', lwd=1, lend=2,
xlab="", ylab="", main="Density in logarithmic scale")
以下是数据摘要:
> summary(x)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.1000 0.1208 0.1584 0.2590 0.2511 4.9388