【问题标题】:mersenne twister - is there a way to jump to a particular state?mersenne twister - 有没有办法跳转到特定状态?
【发布时间】:2011-05-10 05:27:26
【问题描述】:

我有点不确定这个问题的正确论坛。它介于理论补偿之间。科学/数学和编程。

我使用 Mersenne-Twister 生成伪随机数。现在,从给定的种子开始,我想跳到序列中的第 n 个数字。

我看过这个:http://www-personal.umich.edu/~wagnerr/MersenneTwister.html,一个方案可能如下:

假设,我只需要来自特定种子 s 的完整随机序列中的前 N 个数字。
我将序列拆分为 p 个子序列,遍历所有 N 个数字,并将随机数生成器的状态向量保存在每个子序列的开头。
现在要达到第 n 个数字,我会看到 n 落在第 k 个子序列中,我将加载状态向量对于这个子序列并生成 m 个连续的随机数,其中第 k 个子序列中的第 m 个数字与完整序列中的第 n 个数字相同 ( n = m + (k-1) * N /p)。

但是状态向量是 624 x 4 字节长!我想知道实际上是否可以跳转到 mersenne-twister 生成的序列中的任意元素。

【问题讨论】:

    标签: algorithm random mersenne-twister


    【解决方案1】:

    我认为您所要求的将违反加密安全随机数生成器的定义,所以很遗憾,我认为这是不可能的。

    【讨论】:

    • 它不会违反加密安全生成器的定义(我认为),而且 Mersenne Twister 不是加密安全随机数生成器(我知道)。
    • ... 例如,考虑序列SHA256("secret seed" + n) for n = 1, 2,... 和+ 是字符串连接。这不是使用安全哈希函数创建 PRNG 的常用方法,因此我不确定它的安全属性,但我无法立即看出它为什么不安全。它将具有均匀分布(就像 MT 一样),并且是随机访问的。
    • 这将违背一个好的随机数生成器的定义——对于“好”的合适定义,MT 似乎符合大多数(所有?)定义。或者简单地说——如果很容易到达序列中的给定点,那么算法首先就不会有那么多内部状态。
    • @phkahler:你是说在 CTR 模式下使用的安全分组密码不是一个好的随机数生成器吗?好的随机数生成器定义的哪一部分失败了?不过,我喜欢您的第二点:与一些假设的随机访问计算相比,所有这些内部状态可能不仅仅是只是关于加速它。 MT 失败的 secure PRNG 定义的主要部分是,如果您观察到 624 个输出,您可以永远预测序列的其余部分。不过,短子序列内的分布很好。
    • -1 Mersenne Twister 不是加密安全的,因为它是线性的。
    【解决方案2】:

    Mersenne Twister 可以表示为 F2(包含两个元素 0 和 1 的字段)上的(相当大的)矩阵。到下一个状态的转换是乘以这个矩阵。

    要跳转到流中的某个任意位置,您可以通过重复平方计算此矩阵的相应幂,并将其与您的初始状态相乘。

    【讨论】:

    • 实用吗? This paper链接自jHackTheRipper's answer似乎表明矩阵方法需要太多内存,多项式乘法方法更可行。
    【解决方案3】:

    是的,这是可能的!它被称为向前跳跃

    您可以在 MT 作者的主页上找到使用 Mersenne Twister 执行此操作的所有详细信息。提供代码以及解释算法的科学出版物:

    http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/JUMP/index.html

    【讨论】:

    • 内存和 CPU 要求有多高?如果不是太多,也许 Python 可以将 reinstatejumpahead() 函数用于其 random 模块。
    • 没什么大不了的。这只是关于乘以矩阵。原始论文 (math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/…) 指出,在旧的 Intel Core 2 Duo 上,MT19937(最常见的磁偏角,所以可能是你在 Python 中的磁偏角)将需要 6.692 秒。使用当今的架构,您可以在一秒钟内完成。
    【解决方案4】:

    今天,有一种方法可以使用 discard。复杂性与等效进步​​的数量成线性关系。

    一个工作示例:

      std::mt19937 engine(0);
      std::uniform_int_distribution<int> dis(0, 9);
      auto generator = std::bind(std::ref(dis), std::ref(engine));
    
      qDebug() << "First sequence: ";
      for (int i = 0; i < 20; i++) {
        qDebug() << "Random value: " << generator();
      }
    
      engine.seed(0); // reset
      engine.discard(15); // discard the first 15 numbers from the first sequence
      qDebug() << "Last five numbers from first sequence: ";
      for (int i = 0; i < 5; i++) {
        qDebug() << "Random value: " << generator();
      }
    

    【讨论】:

      猜你喜欢
      • 2014-02-22
      • 2020-03-20
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      相关资源
      最近更新 更多