メルセンヌ・ツイスタ

メルセンヌ・ツイスタ (Mersenne twister、通称MT) は擬似乱数列生成器 (PRNG) の1つである。1996年に国際会議で発表されたもので（1998年1月に論文掲載）松本眞と西村拓士による。既存の疑似乱数列生成手法にある多くの欠点がなく、高品質の疑似乱数列を高速に生成できる。考案者らによる実装が修正BSDライセンスで公開されている。 「メルセンヌ・ツイスタ」は厳密にはある手法に基づいた乱数列生成式（あるいは生成法）の族を指し、内部状態の大きさや周期は設定可能である。以下の長所と短所では、メルセンヌ・ツイスタ自体、よく使われている生成法のMT19937、さらにその実装について、区別することなく述べている。 219937-1 (≒4.315×106001) という長い周期が証明されている。 この周期は、名前の由来にもなっているように（24番目の）メルセンヌ素数であり、保証されているいくつかの特徴はメルセンヌ素数を内部的に使用していることによって達成されている。実際上、これ以上の長い周期の擬似乱数を使用する理由はない。 高次元（623次元）に均等分布する（線形合同法#短所参照）。 このことは出力中の連続する値間の相関性が無視できる程度しかないということを意味する。例えば、32ビット版のメルセンヌ・ツイスタを複数回呼び出して64ビット、128ビットなどの疑似乱数として利用しても統計的に安全である。 統計的に不適当な疑似乱数しか生成しない疑似乱数列生成器を除けば、あらゆる擬似乱数生成法の中でもっとも速い（当時）。 近年、統計的な問題が少なく、メルセンヌ・ツイスタよりも高速な擬似乱数列生成器がいくつか考案されている。疑似乱数の生成速度を優先する場合は、これらの生成器が役に立つ可能性がある。メルセンヌ・ツイスタの利点は、長周期性と均等性、および既に広範に使われテストされていることである（ただしCPUごとに最適化されたコードであれば、現時点でもメルセンヌ・ツイスタは十分に速い[要出典]）。 出力の中のすべてのビットが統計的に十分ランダムである。 メルセンヌ・ツイスタの前身GFSRはそうではなかった。以下に詳述 メルセンヌ・ツイスタの手法を、以前の生成法に関連付けて表現すると、一般・フィードバック・シフト・レジスタ (General Feedback Shift Register) をひねって (Twisted) 調律した (Tempered) もの（略してTTGFSR）となる（実際に、元はそのように呼んでいた）。GFSRではワード中の各ビットは独立していたが、「ひねる」ことによって各ビットの周期が合わさって長い周期を実現できるようになっている。「調律」は生成された疑似乱数のワードのうち数ビットだけを取り出したときの高次元超立方体への均等分布を改良して理論値に近づけるための工夫である（メルセンヌ・ツイスタは「調律」がなくても623次元超立方体に均等分布する）。ここまでは先行するTT800と同様であるが、メルセンヌ・ツイスタでは、状態空間が長方形から1ビットだけ突き出した（あるいは31ビット欠けた）形をしている点に特徴がある。これは19937÷32が623余り1であることによる。このような状態空間をとることによって219937-1という周期を実現している。 多くのアプリケーションにとって、メルセンヌ・ツイスタは優れた疑似乱数生成法である。しかしながら、実際にプログラムで利用するにあたっては、いくつか留意すべき点がある。 暗号論的擬似乱数列生成器 (CSPRNG) ではない。 メルセンヌ・ツイスタは線形漸化式によって生成されるため、他の一般の疑似乱数生成法と同様に予測可能である。従って暗号用途で利用するには同様に、暗号学的ハッシュ関数のような非可逆な操作を通さなければならない。CryptMTやFubukiはメルセンヌ・ツイスタをベースとしているが、単純にその出力を鍵ストリームとして平文と合成しているわけではない。 内部ベクトルが大きい メルセンヌ・ツイスタは内部に623個の32ビット長の状態ベクトルを持つ。つまり、一般的な擬似乱数列生成器と比較して動作に必要なメモリ量（ワーキングメモリ）が大きい。開発者による実装では32ビット版で624ワード（2496バイト）のワーキングメモリを要する。 第三者による高速化を狙った実装（並列計算を行うなど）は、より多くのワーキングメモリを要する（例えば倍の4992バイトなど）。 内部ベクトルを初期化するシード（乱数種）として19936ビットという長い乱数が必要となるため、シードや物理乱数を擬似乱数や暗号学的ハッシュ関数で伸長し、場合によってはさらにシードや物理乱数でベクトルを撹拌することでこの問題と後述する0の量を解決する必要がある。 （当然であるが）メルセンヌ・ツイスタを初期化する擬似乱数にメルセンヌ・ツイスタを用いることはできない。初期化に使用するメルセンヌ・ツイスタを初期化する長いベクトルが用意できないからである。 開発者が公開しているコードでは、単一の32ビット値からなるシードを用いた別の擬似乱数による初期化処理と、固定値で初期化したベクトルを任意個数の32ビット値からなる初期化鍵で撹拌する初期化処理が実装されている。 短い乱数や時刻情報を元に初期化したメルセンヌ・ツイスタはその出力を調べることでシードを推測できる可能性が指摘されているなど、初期化に使用する情報量が少ない場合、問題が生じる場合がある。 もっとも、メルセンヌ・ツイスタ以前の「良い」擬似乱数列生成器はさらに大きなワーキングメモリを必要とするものがあるため、メルセンヌ・ツイスタは比較的効率が高いと言える。 初期状態空間に0が多いと、しばらくの間出力にも0が多くなる。 これは線形フィードバックシフトレジスタに共通する問題点である。この原因は、大きな配列の数か所を参照して1か所を書き換えるため、全体を書き換えるのに時間がかかることと、状態遷移関数が線形であるために、参照した数か所が全て0の場合、出力も0になるためである。 初期化処理で、状態空間に0が多くならないようにすればよい。 考案者らが提供している実装では、初期化に内部状態空間の小さな擬似乱数生成系を利用しているので（その小ささゆえに、全て0といったような列は生成し得ないので）これは問題とならない。独自の初期化処理を使用する場合には問題が発生する可能性がある。 この問題に関する改善をした擬似乱数列生成器にWELLなどがある。 なお、上記の欠点のうち、内部ベクトルの大きさや零超過状態からの回復速度の問題は、SIMD-oriented Fast Mersenne Twister (SFMT) で改善されている。 一部のプログラミング言語では、デフォルトの擬似乱数列生成器としてメルセンヌ・ツイスタが標準ライブラリに取り入れられている。そのような言語の例として、 Python,Ruby,R,PHP,MATLAB, C++（C++11から） がある。 その他のプログラミング言語におけるライブラリの例として、以下が挙げられる： ：ABAP ：ActionScript 1 AS3-Utilities：ActionScript 3.0 ：Ada ：C++ ：C and C++ ：C++ RandomLib：C++ Mersenne Twister in Clojure：Clojure ：Clean ：C++ Sony Cell Broadband Engine ：C# jmt.lisp  : Common Lisp random.d：D sfmt-erlang：Erlang MT.E：Euphoria NtRand：Excel addin ：Forth ：Fortran 95 Mersenne Twister：F# GNU Scientific Library ：Haskell mersenne-random-pure64：Haskell MersenneTwister.java：Java Mersenne Twister in Java Script：JavaScript mersenne-twister.js：JavaScript lrandom：Lua ：Mitrion-C ：Pascal/FreePascal/Delphi Math-Random-MT-Auto：Perl mersenne_twister.php：PHP 5.3.0 Random Number Generation：R Mersenne twister in REALbasic：REALbasic ：Standard ML ：SIMUL8 MersenneTwister.scala：Scala ：VBA Mersenne Twister in BASIC：Visual Basic 開発当初は Primitive Twisted Generalized Feedback Shift Register Sequence という名前であったが、ドナルド・クヌースに「名前が長すぎる」と言われたため、現在の名前に変更した。 Mersenne Twister の略称 MT には、開発者の名前「まこと」と「たくじ」のイニシャルという意味もこめられている。[17] の動画の質疑応答部分を参照。