python - 线性同余发生器 - 弱测试结果

标签 python numpy random lcg

我正在尝试执行Dieharder Suite在我的线性同余发生器上进行测试。

我不确定测试是否是在我的发电机上进行的,或者只是结果太弱。

我使用生成器生成 2,5 mio 行,并将它们保存到带有以下 header 的文件 testrands.txt 中:

#==================================================================
# generator lcg  seed = 1
#==================================================================
type: d
count: 100000
numbit: 32
1015568748
1586005467
2165703038
3027450565
217083232
1587069247
......

我关注了this说明(如示例中所示)

然后我用了 Dieharder suite按以下方式进行测试:

dieharder -g 202 -f testrands.txt -a

现在结果出奇的弱(也许我生成的数字太少了?)

1

2

我按照指南中的方式进行操作,但似乎仍然不符合预期 - LCG 通过了生日间隔(我认为不应该),并且其余结果出奇地弱

我的LCG:

import numpy as np

class LCG(object):

    UZERO: np.uint32 = np.uint32(0)
    UONE : np.uint32 = np.uint32(1)

    def __init__(self, seed: np.uint32, a: np.uint32, c: np.uint32) -> None:
        self._seed: np.uint32 = np.uint32(seed)
        self._a   : np.uint32 = np.uint32(a)
        self._c   : np.uint32 = np.uint32(c)

    def next(self) -> np.uint32:
        self._seed = self._a * self._seed + self._c
        return self._seed

    def seed(self) -> np.uint32:
        return self._seed

    def set_seed(self, seed: np.uint32) -> np.uint32:
        self._seed = seed

    def skip(self, ns: np.int32) -> None:
        """
        Signed argument - skip forward as well as backward

        The algorithm here to determine the parameters used to skip ahead is
        described in the paper F. Brown, "Random Number Generation with Arbitrary Stride,"
        Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
        O(log2(N)) operations instead of O(N). It computes parameters
        A and C which can then be used to find x_N = A*x_0 + C mod 2^M.
        """

        nskip: np.uint32 = np.uint32(ns)

        a: np.uint32 = self._a
        c: np.uint32 = self._c

        a_next: np.uint32 = LCG.UONE
        c_next: np.uint32 = LCG.UZERO

        while nskip > LCG.UZERO:
            if (nskip & LCG.UONE) != LCG.UZERO:
                a_next = a_next * a
                c_next = c_next * a + c

            c = (a + LCG.UONE) * c
            a = a * a

            nskip = nskip >> LCG.UONE

        self._seed = a_next * self._seed + c_next


#%%
np.seterr(over='ignore')

a = np.uint32(1664525)
c = np.uint32(1013904223)
seed = np.uint32(1)

rng = LCG(seed, a, c)
q = [rng.next() for _ in range(0, 2500000)]

最佳答案

恭喜,您已经证明您的 LCG 实现与更现代的生成器相比没有竞争力。

请注意birthday spacings testbirthday test 不同。 。 LCG 有可能通过前者,但任何报告其完整 k 位状态的全周期 k 位生成器在任何样本大小的 α ≤ 0.01 水平上总是无法通过后者。 n ≥ 3*2k/2。 (对于您的 32 位实现,样本大小为 3*216 = 196608。)如果它是全周期生成器,则不会有任何重复值,并且 "birthday paradox"告诉我们,如果值流确实是随机的,则应该至少有一个 p ≥ 0.99。

关于python - 线性同余发生器 - 弱测试结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57126612/

相关文章:

python - 如何在 SQLAlchemy 中的文本数组列上创建 GIN 索引(使用 PostgreSQL 和 python)

python - 如何在同一个 numpy 数组上使用 matplotlib 的 imshow 和等高线图?

python - IRR 库仅适用于支付期和复利期以年为单位的情况(工程经济)

python - 计算图像中两个像素之间的距离

Python 2.7。使用正则表达式从字符串的某些部分提取数据

python - 当worker抛出异常时pool.map和pool.imap_unordered之间的区别

Android:为文件名创建唯一的字符串

java - bluej 中的纸牌游戏

arrays - 如何从数组中打乱文本而不重复单词并遍历整个数组? ( swift )

Python 读取文件并识别 UnicodeDecodeError 的来源