线性同余生成器的随机数质量


14

我正在针对各种外力对Langevin方程进行一些模拟。有人告诉我C的rand()使用stdlib.h可能会导致我的结果出现偏差,因此我使用的是梅森·扭曲器。

但是,我想确切地知道(并看到)线性同余生成器可以在模拟中引入什么样的误差。这些是我尝试过的事情:

  • 生成随机数的3D元组以尝试查看超平面。我什么也看不到。
  • 对大随机数向量进行FFT。对于Mersenne Twister和,这几乎是相同的rand()
  • 检查布朗运动中粒子的均分原理。两个积分器同意的预期值具有相同的有效位数。KE=12kBT
  • 看看他们在不属于幂二的数个箱中的储物效果如何。两者给出相同的定性结果,没有人比这更好。
  • 综观布朗路径看不清楚分歧。再次,没有运气。x=0
  • 圆上的点分布。填充,仅在外围。它们之间以及最近的邻居之间(Shor的回答,在评论中下方)。在该要点中可用,安装所需的库后,只需在Julia 0.5.0中运行即可(请参阅要点以获取说明)。

我想强调的是,我正在物理模拟的背景下寻找引入的偏差。例如,我已经看到rand()在不使用Mersenne Twister的情况下,顽固测试失败了,但是对于我来说,这并不意味着太多。

您是否有任何物理,具体的示例来说明不良的随机数发生器如何破坏蒙特卡洛模拟?

注意:我已经看到PRNG的效果如何RANDU。我对一些不明显的示例感兴趣,这些示例看起来很无辜,但最终会产生偏见。


1
没有您所要求的示例,但是在我自己的C程序中一直使用drand48()/ srand48()而不是rand()/ srand()。他们各自的手册页记录了所使用的不同prng算法(有关rand算法的信息,请参阅man random),我相信drand48通常是可取的,尽管我的详细了解很少。当我想要保证跨平台的便携式重现性时,我从C,第二版,WHPress等人的数字食谱,Cambridge UP 1992,ISBN 0-521-43108-5,第280页上对ran1()进行了编码。我可以说,但是还没有进行定量测试。

使用random()或drand48()/ lrand48()(我总是将后者用于分子动力学和蒙特卡洛模拟,这非常好)。另外,请尝试使用随机种子。对于单粒子Langevin方程的模拟,这应该绰绰有余。
valerio

我们使用的是周长,而不是圆形。

@PeterShor感谢您的纠正。我已经更新了答案,恐怕还是没有运气。
RedPointyJackson

1
@DanielShapero random和urandom应该是加密安全的RNG,旨在用于加密目的,例如生成密钥。它的硬件方面是,在Linux上,它们使用环境熵,这与硬件加速不同。实际上,它们根本不适合像蒙特卡洛模拟之类的东西。
基里尔

Answers:


3

描述由于RNG不足(尽管他们未使用LCG)而导致物理系统的蒙特卡罗模拟失败的一个有趣参考资料是:

A. Ferrenberg和DP Landau。蒙特卡洛模拟:“良好”随机数生成器的隐藏错误。物理评论快报63(23):3382-3384,1992。

Ferrenberg和Landua研究的Ising模型是RNG的良好测试,因为您可以与精确的解决方案进行比较(针对二维问题),并找出数字中的错误出路。这些模型应该在没有太大困难的情况下以老式的32位算术PMMLCG显示故障。

另一个有趣的参考是:

H.鲍克和斯蒂芬·梅滕斯。伪随机硬币的尾巴比尾巴还多。arXiv:cond-mat / 0307138 [cond-mat.stat-mech]

Bauke和Mertens强烈反对二进制线性反馈移位寄存器样式的随机数生成器。鲍克和默滕斯还有其他与此有关的论文。

在3D散点图中很难找到Marsaglia平面。您可以尝试旋转图以获得更好的视图,有时它们会突然出现在您面前。您还可以进行统计均匀性的3D测试-对于较早的32位LCG,这些测试将在相当数量的仓中失败。例如,使用3个维度的20x20x20的栅格网格进行均匀性测试,足以检测出m = 2 ^ 31-1,a = 7 ^ 5的PMMLCG缺乏均匀性。


1

可以使用TestU01 PRNG测试套件来找出其中哪些测试rand失败。(有关测试套件的概述,请参见TestU01:用于随机数生成器的经验测试的AC库。)比提出自己的蒙特卡洛模拟要容易得多。从某种意义上讲,这也是软件可组合性(和软件正确性)的问题:给定PRNG在小型,简单的测试中似乎可以正常工作,您如何知道它的病理行为不会被更大的程序触发?

这是代码:

#include "TestU01.h"

int main() {
  // Same as rand() on my machine
  unif01_Gen* gen = ulcg_CreateLCG(2147483647, 16807, 0, 12345);

  bbattery_SmallCrush(gen);
  bbattery_Crush(gen);

  return 0;
}

对于SmallCrush套件,有15个测试中有3个失败(有关详细说明和所有参考,请参见 TestU01中的guidelongtestu01.pdf;这是来自10个测试的15个统计信息)。

  • n tdtdtI1,{Ij+1Ij}

  • n t[0,1)tdt

  • nt[0,1)XnP(X<x)=xtn=2×106t=6χ2<10300

假设所有这些都是“典型”的蒙特卡洛模拟(尽管它们可能不像您所想到的问题),那么结论是它们的 rand某些未知子集失败了。但是,我不知道为什么专门指定该子集,所以我无法说出它是否可以解决您自己的问题。

考虑到描述的简单性,MaxOft似乎特别令人怀疑。

Crush套件中的测试中,rand有140项中有51项失败(96个测试中有140项统计信息)。一些失败的测试(例如Fourier3)是在位字符串上完成的,因此也许它们与您无关。另一个失败的奇怪测试是GCD,它测试两个随机整数的GCD分布。(再次,我不知道为什么这个特定的测试失败或您的模拟是否会因此而遭受损失。)

PS:还要注意的另一件事是,rand()实际上比成功通过所有SmallCrushCrushBigCrush测试(例如MRG32k3a)的某些PRNG慢(请参见上面的L'Ecuyer&Simard论文)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.