【问题标题】:Random number generator that produces a power-law distribution?产生幂律分布的随机数生成器?
【发布时间】:2023-04-04 00:05:01
【问题描述】:

我正在为 C++ 命令行 Linux 应用程序编写一些测试。我想生成一堆具有幂律/长尾分布的整数。意思是,我经常得到一些数字,但其中大多数相对不常见。

理想情况下,我可以将一些魔术方程式与 rand() 或 stdlib 随机函数之一一起使用。如果没有,一个易于使用的 C/C++ 块会很棒。

谢谢!

【问题讨论】:

    标签: c++ math random power-law


    【解决方案1】:

    page at Wolfram MathWorld 讨论了如何从均匀分布(这是大多数随机数生成器提供的)中获得幂律分布。

    简短答案(以上链接的推导):

    x = [(x1^(n+1) - x0^(n+1))*y + x0^(n+1)]^(1/(n+1))
    

    其中y是统一变量,n是分布幂,x0x1定义范围的分布,x 是你的幂律分布变量。

    【讨论】:

    • 额外的小细节:y 是 [0,1] 范围内的统一变量。
    • dmckee 的回答提供了理解 Wolfram 文章中推导所必需的缺失上下文。
    【解决方案2】:

    如果您知道所需的分布(称为概率分布函数 (PDF))并对其进行了适当的归一化,则可以对其进行积分以获得累积分布函数 (CDF),然后反转 CDF(如果可能)以获得您需要从统一的[0,1] 分发到您想要的转换。

    所以你首先定义你想要的分布。

    P = F(x)
    

    (for x in [0,1]) 然后积分得到

    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...

    【讨论】:

      【解决方案3】:

      我只是想进行一个实际的模拟,作为对(正确)接受的答案的补充。尽管在 R 中,代码是如此简单,以至于是(伪)伪代码。

      接受答案中的Wolfram MathWorld formula 与其他可能更常见的方程之间的一个微小差异是 幂律指数 n(通常表示为 alpha)确实不带有明确的负号。所以选择的 alpha 值必须是负数,通常在 2 到 3 之间。

      x0x1 代表分布的下限和上限。

      原来是这样:

      set.seed(0)
      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(1e7)   # Number of samples
      x  = ((x1^(alpha+1) - x0^(alpha+1))*y + x0^(alpha+1))^(1/(alpha+1))
      plot(density(x), ylab="log density x", col=2)
      

      或以对数刻度绘制:

      plot(density(x), log="xy", ylab="log density x", col=2)
      

      以下是数据摘要:

      > summary(x)
         Min.   1st Qu.  Median    Mean   3rd Qu.    Max. 
        0.1000  0.1208  0.1584    0.2590  0.2511   4.9388 
      

      【讨论】:

      • 不知道为什么你说指数必须在 -2 和 -3 之间(我认为自然界中观察到的许多幂律分布的 alpha 介于 1 和 2 之间)但是谢谢你的行R 代码!
      • @SimonC。我是从page 4 left column of this paper 那里得到的。符号将始终为负(当公式带有减号时,alpha 表示为正值)。
      • 是的,对不起,我的错,我完全同意负号,我只是问为什么将 alpha 限制为 [-2,-3]。
      【解决方案4】:

      我无法评论生成幂律分布所需的数学(其他帖子有建议),但我建议您熟悉<random> 中的 TR1 C++ 标准库随机数工具。这些提供了比std::randstd::srand 更多的功能。新系统为生成器、引擎和发行版指定了一个模块化 API,并提供了一堆预设。

      包含的分发预设是:

      • uniform_int
      • bernoulli_distribution
      • geometric_distribution
      • poisson_distribution
      • binomial_distribution
      • uniform_real
      • exponential_distribution
      • normal_distribution
      • gamma_distribution

      当您定义幂律分布时,您应该能够将其插入现有的发电机和引擎。 Pete Becker 所著的The C++ Standard Library Extensions一书有一个关于<random> 的精彩章节。

      Here is an article 关于如何创建其他分布(包括 Cauchy、卡方、Student t 和 Snedecor F 的示例)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 1970-01-01
        • 2017-12-28
        • 2012-09-24
        • 1970-01-01
        • 2011-01-07
        • 2011-03-31
        相关资源
        最近更新 更多