Gaucheのmath.mt-randomにバグがあるかどうか検証
結論: なんか別のバグが見付かったが、偏りの方は起こってなさそう。
(または、自分の書いたコード側に問題があるか)
頭と腹はずっと痛くて、全然眠れない。
この前のノロっぽい症状だ。
寝れないので、検証方法を考えてみた。
要は、同じ数値が連続で出る可能性が高いという事は、エントロピーが低いという事で、データ圧縮が可能である可能性が高い、という事になる。
そこで、以下のような一行スクリプトで比較してみる事にした。
SEED=98765; gosh -umath.mt-random -e" (let1 mt (make <mersenne-twister> :seed $SEED) (let loop ((i 1000000)) (write (mt-random-integer mt 9)) (if (zero? i) (exit) (loop (- i 1))))) "|bzip2 -9|wc -c; gosh -umath.mt-random -e" (let1 mt (make <mersenne-twister> :seed $SEED) (let loop ((i 1000000)) (write (inexact->exact (floor (* 9 (mt-random-real0 mt))))) (if (zero? i) (exit) (loop (- i 1))))) "|bzip2 -9|wc -c
最初に、mt-random-integerが生成した、0-8の数値しか出ない文字列をbzip2 -9にかけた後のサイズを表示し、次に、同様にmt-random-real0が生成した文字列を表示させる。
これをSEEDの値を変更して何回か実行し、常にmt-random-integerの方が数値が小さいなら、バグがあると考えてよさそうだ。多分。
やってみた。
SEED=98765; 411261 411098 SEED=987654321; 411195 411434 SEED=9876543211; 411354 411290 SEED=9754321113; 411354 411290 SEED=9999955511111; 411354 411290
有意な差は見られないようだ……と思っていたが、なんか途中から様子がおかしい。
SEED値に関わらず、一定の値が出ているようだ。
SEED=9999955511111; echo $SEED; gosh -umath.mt-random -e" (let1 mt (make <mersenne-twister> :seed $SEED) (let loop ((i 10)) (write (mt-random-integer mt 9)) (if (zero? i) (exit) (loop (- i 1))))) "; echo; gosh -umath.mt-random -e" (let1 mt (make <mersenne-twister> :seed $SEED) (let loop ((i 10)) (write (inexact->exact (floor (* 9 (mt-random-real0 mt))))) (if (zero? i) (exit) (loop (- i 1))))) "; echo;
SEED=9999955511111; echo $SEED; 9999955511111 01857476028 08770851848 SEED=99999555111119; echo $SEED; 99999555111119 01857476028 08770851848
どうやら、これが原因のようだ?
これっぽい。
しかし、mt-lib.stubの該当箇所を見る限りでは、直ってるっぽいように見える。
そして、自分の書いた初期化コードでは
(define *mt* (receive (epoch micro) (sys-gettimeofday) (make <mersenne-twister> :seed (+ epoch micro (sys-getpid)))))
のようになっているので、まだbignumに到達していないと思し、実際にコンソールから試行しても、ちゃんと乱数を返しているように見える。
結局、偏りの方は謎のまま。
とりあえず、bignumの方だけ報告して寝よう。