1. 程式人生 > >偽隨機數生成演算法-梅森旋轉(Mersenne Twister/MT)

偽隨機數生成演算法-梅森旋轉(Mersenne Twister/MT)

今天主要是來研究梅森旋轉演算法,它是用來產生偽隨機數的,實際上產生偽隨機數的方法有很多種,比如線性同餘法,

平方取中法等等。但是這些方法產生的隨機數質量往往不是很高,而今天介紹的梅森旋轉演算法可以產生高質量的偽隨

機數,並且效率高效,彌補了傳統偽隨機數生成器的不足。梅森旋轉演算法的最長週期取自一個梅森素數,

由此命名為梅森旋轉演算法。常見的兩種為基於32位的MT19937-32和基於64位的MT19937-64。

由於梅森旋轉演算法是利用線性反饋移位暫存器(LFSR)產生隨機數的,所以我們先來認識線性反饋移位暫存器。

首先,移位暫存器包括兩個部分

    (1)級,每一級包含一個位元,比如11010110是一個8級的移位暫存器產生的

    (2)反饋函式,線性反饋移位暫存器的反饋函式是線性的,非線性反饋移位暫存器的反饋函式是非線性的

一個級的移位暫存器產生的序列的最大週期為,當然這個最大週期跟反饋函式有很大關係,線性反饋函式實

際上就是這個級的移位暫存器選取“某些位”進行異或後得到的結果,這裡的“某些位”的選取很重要,得到線性反饋

函式之後,把這個移位暫存器的每次向右移動一位,把最右端的作為輸出,把“某些位”的異或結果作為輸入放到最左

端的那位,這樣所有的輸出對應一個序列,這個序列叫做M序列,是最長線性移位暫存器序列的簡稱。

上面“某些位”的選取問題還沒有解決,那麼應該選取哪些位來進行異或才能保證最長週期為,這是一個很重要

的問題。選取的“某些位”構成的序列叫做抽頭序列,理論表明,要使LFSR得到最長的週期,這個抽頭序列構成的多項

式加1必須是一個本原多項式,也就是說這個多項式不可約,比如。

下面以一個4位的線性反饋移位暫存器為例說明它的工作原理。

如果的值分別是1 0 0 0,反饋函式選取,那麼得到如下序列

可以看出周長為15。在這一個週期裡面涵蓋了開區間內的所有整數,並且都是沒有固定順序出現的,有

很好的隨機性。

之前說過,梅森旋轉演算法的週期為,那麼說明它是一個19937級的線性反饋移位暫存器,實際上基於32位

的MT19937-32只需要用到32位,那麼為什麼要選擇周長為的演算法呢? 那是因為這樣做隨機性很好。

梅森旋轉演算法是基於線性反饋移位暫存器的一直進行移位旋轉,週期為一個梅森素數,果然是名副其實。

梅森旋轉演算法(Mersenne twister)是一個偽隨機數發生演算法。由松本真和西村拓士[1]在1997年開發,基於有限二進位制欄位上的矩陣線性遞迴。可以快速產生高質量的偽隨機數, 修正了古典隨機數發生演算法的很多缺陷。

梅森旋轉演算法是R,Python,Ruby,IDL,Free Pascal,PHP,Maple,Matlab,GMP和GSL的預設偽隨機數產生器。從C++11開始,C++也可以使用這種演算法。在Boost C++,Glib和NAG數值庫中,作為外掛提供。 在SPSS中,梅森選旋轉演算法是兩個PRNG中的一個:另一個是產生器僅僅為保證舊程式的相容性,梅森旋轉被描述為”更加可靠“。梅森旋轉在SAS中同樣是PRNG中的一個,另一個產生器是舊時的且已經被棄用。

最為廣泛使用Mersenne Twister的一種變體是MT19937,可以產生32位整數序列。具有以下的優點:

有219937 − 1的非常長的週期。在許多軟體包中的短週期—232 隨機數產生器在一個長週期中不能保證生成隨機數的質量。[2
在1 ≤ k ≤ 623的維度之間都可以均等分佈(參見定義).
除了在統計學意義上的不正確的隨機數生成器以外, 在所有偽隨機數生成器法中是最快的(當時)
演算法詳細

本演算法基於標準(線性)旋轉反饋移位暫存器(twisted generalised feedback shift register/TGFSR)產生隨機數

演算法中用到的變數如下所示:
·w:長度(以bit為單位)
·n:遞迴長度
·m:週期引數,用作第三階段的偏移量
·r:低位掩碼/低位要提取的位數
·a:旋轉矩陣的引數
·f:初始化梅森旋轉鏈所需引數
·b,c:TGFSR的掩碼
·s,t:TGFSR的位移量
·u,d,l:額外梅森旋轉所需的掩碼和位移量


MT19937-32的引數列表如下:
·(w, n, m, r) = (32, 624, 397, 31)
·a = 9908B0DF(16)
·f = 1812433253
·(u, d) = (11, FFFFFFFF16)
·(s, b) = (7, 9D2C568016)
·(t, c) = (15, EFC6000016)
·l = 18

MT19937-64的引數列表如下:
·(w, n, m, r) = (64, 312, 156, 31)
·a = B5026F5AA96619E9(16)
·f = 6364136223846793005
·(u, d) = (29, 555555555555555516)
·(s, b) = (17, 71D67FFFEDA6000016)
·(t, c) = (37, FFF7EEE00000000016)
·l = 43
參考連結:

https://github.com/xuwei-k/tinymt

https://en.wikipedia.org/wiki/Mersenne_Twister#TinyMT

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

https://cs.gmu.edu/~sean/research/mersenne/MersenneTwister.java

https://cs.gmu.edu/~sean/research/mersenne/MersenneTwisterFast.java

http://commons.apache.org/proper/commons-rng/