Diese Frage betrifft die Ursprünge von zeitlichen Korrelationen, die man mit System.Random
beobachtet, wenn man aufeinanderfolgende Randome aus aufeinanderfolgenden Seeds erzeugt (wobei man die gleiche Anzahl von Generatoren verwirft) für jeden Samen).Zeitliche Korrelationen bei Verwendung von System.Random (nicht vorhanden bei Verwendung von System.Random.TF)
In Using mkStdGen from System.Random to generate random booleans Answer 1 und Using mkStdGen from System.Random to generate random booleans Answer 2 wurde vorgeschlagen (basierend auf dem Reddit-Artikel, auf den verwiesen wird), dass die ersten Generatoren verworfen werden sollten, um vernünftige Ergebnisse zu erhalten. Ich finde jedoch, dass unabhängig davon, wie viele Generatoren man verwirft, man, wenn man den zeitlichen Aspekt der Verteilung betrachtet, unerwünschte Ergebnisse erhält, wenn aufeinanderfolgende Zufallszahlen mit aufeinanderfolgenden Samen erzeugt werden (wobei einer dieselbe Anzahl von Erzeugern für jeden Samen verwirft).
Meine Frage ist, was ist es über die in eingesetzt Algorithmus System.Random
, die zwischen den verschiedenen Samen in der beschriebenen Weise in dieser zeitlichen Korrelation ergibt?
Wenn wir eine unendliche Folge von Zufall booleans erzeugen, dann ist die Wahrscheinlichkeit von P(n)
n
sukzessiven booleans erhalten, die mit dem gleichen Wert ist (beispielsweise die in [True,True,True]
[False,True,True,True,False]
) ist (1/2)^n
. Als schnelle Überprüfung haben wir die Normierungsbedingung:
P(1)+P(2)+....P(infty) = (1/2) + (1/2)^2 + ... = 1
den folgenden Code:
module Main where
import Data.List
import System.Random
generateNthGenerator startGen 0 = startGen
generateNthGenerator startGen n = generateNthGenerator newGen (n-1)
where newGen = snd $ ((random startGen) :: (Bool,StdGen))
better_mkStdGen generation seed =
generateNthGenerator (mkStdGen seed) generation
randomNums generation =
map (fst . random . (better_mkStdGen generation)) [0 .. maxBound] :: [Bool]
-- e.g. [True,True,False,False,False,True,True,True,False,False]
sortedLengthOfConsecutives num randList =
sort $ map length $ take num $ group randList
frequencyOfConsecutives sortedLengthOfCons =
map (\x -> (head x, length x)) $ group sortedLengthOfCons
results = frequencyOfConsecutives
$ sortedLengthOfConsecutives 10000
$ randomNums 10
main = do
print results -- [(8,1493),(9,8507)]
erzeugt jeder aufeinanderfolgenden boolean Generatoren aus den aufeinanderfolgenden Samen verwendet wird, verwirft 10 Generatoren bevor die resultierende Zufallsergebnis verwendet wird. Eine Folge von 10000 Zufallszahlen wird erzeugt, und so erwarten wir, dass ungefähr 5000 Booleans dem entgegengesetzten Boolean folgen (zB [True]
in), denn es gibt 2500 booleans, denen derselbe Boolesche gefolgt von dem entgegengesetzten boolean folgt (zB [True,True]
in [False,True,True,False]
), etwa 1250 boolesche Werte, die in 3s usw. gruppieren.
Also aus dem obigen Code erhalten wir 1493 8-Gruppen und 8507 9-Gruppen. Dies ist nicht das, was erwartet wird, und wir erhalten ähnliche Ergebnisse unabhängig davon, wie viele Generatoren verworfen werden (im obigen Beispiel ist die Anzahl der für jeden Seed verworfenen Generatoren 10). [Hinweis, wenn wir das gleiche Experiment mit tf-random
machen wir nicht das gleiche Verhalten, siehe später].
Wenn wir statt aufeinanderfolgende booleans erzeugen mit dem zuvor erzeugten Generator (was ich die Art und Weise erraten, in der sie ursprünglich verwendet wurde entwickelt, da random
selbst gibt einen neuen Generator), scheinen wir mehr vernünftige Ergebnisse zu erhalten :
module Main where
import Data.List
import System.Random
generateRandomInner gen =
let (randBool, newGen) = (random gen)::(Bool,StdGen)
in randBool:(generateRandomInner newGen)
generateRandoms seed =
let (randBool, newGen) = (random $ mkStdGen seed)::(Bool,StdGen)
in randBool:(generateRandomInner newGen)
seed = 0
randomNums = generateRandoms seed
sortedLengthOfConsecutives num randList =
sort $ map length $ take num $ group randList
frequencyOfConsecutives sortedLengthOfCons =
map (\x -> (head x, length x)) $ group sortedLengthOfCons
results = frequencyOfConsecutives
$ sortedLengthOfConsecutives 10000
$ randomNums
main = do
print results
--[(1,4935),(2,2513),(3,1273),(4,663),(5,308),
-- (6,141),(7,86),(8,45),(9,16),(10,12),(11,6),
-- (12,1),(13,1)]
So bekommen wir 4935 Singletons (entspricht etwa 0,5 * 10000), 2513 duples (entspricht etwa 0,5^2 * 10000), 1273 Tripel (entspricht in etwa 0,5^3 * 10000) usw., die, was wir erwarten von.
So scheint es, wenn wir (über System.Random
) eine Zufallssequenz erzeugen, wo jedes aufeinanderfolgende Zufall mit dem nachfolgenden Keim erzeugt wird, wobei wir die gleiche Anzahl von Generatoren für jeden Keim verwerfen, eine unerwünschte Korrelation besteht unabhängig von der Anzahl der verworfenen Generatoren .
Was ist das über die algorithmischen Eigenschaften der Zufallszahlenerzeugung von System.Random
, die in dieser Folge?
Beachten Sie, dass, wenn wir die fehlerhafte Methode, die oben mit tf-random
(Redditt Artikel) beschäftigen dann wir die erwarteten Ergebnisse erhalten:
module Main where
import Data.List
import System.Random
import System.Random.TF
generateNthGenerator startGen 0 = startGen
generateNthGenerator startGen n = generateNthGenerator newGen (n-1)
where newGen = snd $ ((random startGen) :: (Bool,TFGen))
better_mkStdGen generation seed =
generateNthGenerator (seedTFGen (0,0,0,seed)) generation
randomNums generation =
map (fst . random . (better_mkStdGen generation)) [0 .. maxBound] :: [Bool]
-- e.g. [True,True,False,False,False,True,True,True,False,False]
sortedLengthOfConsecutives num randList =
sort $ map length $ take num $ group randList
frequencyOfConsecutives sortedLengthOfCons =
map (\x -> (head x, length x)) $ group sortedLengthOfCons
results = frequencyOfConsecutives
$ sortedLengthOfConsecutives 10000
$ randomNums 10
main = do
print results
-- [(1,4867),(2,2573),(3,1243),(4,646),(5,329),
-- (6,176),(7,80),(8,43),(9,26),(10,10),(11,4),
-- (12,2),(19,1)]
dh 50% sind Singletons, 25% sind duples (Gruppen von 2) usw. ...
Danke für diese detaillierte Erklärung des Verhaltens des Generators. Ich muss die zufällige Quelle etwas näher betrachten. – artella