【问题标题】:Linear congruential generator - weak tests results线性同余生成器 - 弱测试结果
【发布时间】:2019-11-29 06:48:49
【问题描述】:

我正在尝试对我的线性同余生成器进行Dieharder Suite 测试。

我不确定是在我的生成器上进行了测试,还是只是结果太弱了。

我使用生成器生成 2,5 条 mio 行,并将它们保存到文件 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

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

我按照指南中的方式做,但似乎仍然不是应该的 - 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)]

【问题讨论】:

  • 我同意@pjs,这看起来很适合LCG,我自己很久以前就在LCG上死忠了。它快速、方便、便宜,但不是高质量的 RNG。

标签: python numpy random lcg


【解决方案1】:

恭喜,您已经证明您的 LCG 实施无法与更现代的发电机竞争。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    • 2015-08-22
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2016-07-03
    相关资源
    最近更新 更多