Pseudojuhuslike arvude generaatorite koodi kirjutamisel peab teadma ka arvuti hingeelust!
Kõigepealt kontrolli, et Sul on korrektselt töötav generaator
LKG eelmisest praktikumist. Selleks võrdle käsu
LKG(6,seeme=15,a=17,b=3,m=256) tulemust allpool toodud
näitetulemusega:
## [1] 0.0078125 0.1445312 0.4687500 0.9804688 0.6796875 0.5664062
Kui väärtused on samad, siis on töötab generaator vähemalt toodud parameetrite korral õigest. Vaatleme aga nüüd SAS tarkvaras RANUNI käsuga kasutatavat generaatorit, mis vastab juhule \(a=397204094,b=0,m=2^{31}-1\). SAS tarkvara korral on seemne 10 korral selle generaatori tekitatud esimesed 8 väärtust \[ 0.8496257,\ 0.7008872,\ 0.9982431,\ 0.5939865,\ 0.2160258,\ 0.6927735,\ 0.4297917,\ 0.3169172\] Vaata, kas Sinu generaator annab täpselt samad arvud? Kui ei anna, siis katsu aru saada, milles on probleem. Vihje: uuri järgmiste käskude tulemusi:
print(397204094*1000000001,digits = 20)
print(2^53,digits=20)
print(2^53+1,digits=20)
Installeerige pakett gmp (Gnu Multiple Precision
arithmetics) ning laadi see käsuga library(gmp). Uuri
järgnevaid käske ning muuda nende abil oma generaatorit nii, et see
annaks õigeid tulemusi parameetrite a,b,m korral, mis on väiksemad kui
\(2^{53}\). Generaatori väljundiks
peaks ikka olema vektor \(n\)
reaalarvust 0 ja 1 vahel. Kontrolli, kas parandatud generaator annab
juhul \(a=397204094,b=0,m=2^{31}-1\)
õiged tulemused.
as.bigz(397204094)*1000000001
as.bigz(10001)%%276
as.numeric(as.bigz(10001)%%276)
Testimiseks on vaja teada, kuidas peaksid käituma juhuslikud arvud ehk sõltumatute katsete tulemused. Siis saame võrrelda pseudojuhuslike arvude käitumist juhuslike arvude käitumisega. Kui liiga erinevad, siis loeme generaatori halvaks.
Alustame lihtsa ideega, kus vaatleme mingi fikseeritud sündmuse toimumist juhuslikel katsetel. Fikseerime näiteks sündmuse \(A=\{0,2\leq X\leq 0,5\}\). Kui me sooritame sõltumatuid katseid \(n\) korda ja loeme kokku \(A\) toimumiste arvu \(N_A\), siis on teada, kuidas \(N_A\) peaks käituma. Mis on \(N_A\) jaotus?
Kasutame RANDU generaatorit (\(a=65539,b=0, m=2^{31}\)). Leia seemnest
1000 lähtudes genereeritud 100 pseudojuhusliku arvu põhjal sündmuse
\(A\) toimumiste arv. Kas see jäi
binoomjaotuse 0,025 ja 0,975 kvantiilide vahele? (Vihje: kasuks tuleb
käsk qbinom)
Päris juhuslike katsete korral peaks leitud arv jääma tõenäosusega 0,05 ka piiridest välja. Korda katset 200 korda (võtteks esimeseks seemneks 100 ja järgmistel kordadel viimasest generaatori väljastatud avule \(u_n\) vastav \(x_n\)) ning leia, mitu korda jäi leitud tulemus piiridest välja. Kui suur on tõenäosus, et see kordade arv erineks oodatavast väljajäämiste arvust vähemalt niipalju, kui praguse katse tulemus näitas?
Selle asemel, et vaadelda juhusliku suuruse sattumist ühte lõiku, võib vaadelda näiteks omavahel mittelõikuvate intervallide süsteemi, mis katavad kõik võimalused. Kui nüüd lugeda igasse intervalli sattuvate punktide arvud ühe katse põhjal, siis saame histogrammi.
hist ning tekitavate
lõikude süsteemi saab ise ette anda suvandiga
breaks=vektor_jaotuspunktidest. Genereeri seemnest 71293529
lähtuvalt 200 punkti ning tekita histogramm, kus on kujutatud
intervallidesse \([0,\frac{1}{6}),[\frac{1}{6},\frac{2}{6}),\ldots\)
sattumiste arve. Kuna intervallid on sama pikkusega ja randu peaks
väljastama lõigus [0,1] ühtlase jaotusega pseudojuhuslikke arve, on
veapiirid igasse lõiku sattuvate punktide arvule samad. Lisa graafikule
neile veapiiridele vastavad horisontaalsed sirged, mis annavad iga lõigu
korral teoreetilise jaotuse 0,025 ja 0,975 kvantiilid.Tulemus peaks välja nägema selline:
Hii-ruut test on oma olemuselt vahend selleks, et kontrollida lõpliku
arvu erinevate väärtustega juhusliku suuruse korral katsetulemuste
vastamist mingile fikseeritud jaotusele, mis diskreetsel juhul on
kirjeldatud paaridena \((v_i,p_i),\
i=1,\ldots,m\), kus \(v_i,\
i=1,\ldots,m\) on võimalikud väärtused ja \(p_i,\ i=1,\ldots,m\) on nende saamise
tõenäosused. Näiteks juhul, kui katseks on täringuvise ja tulemuseks
märgime silmade arvu, siis täringu aususe kontrollimiseks võime teha
\(n\) katset ning seejärel kontrollida,
kas kõikide tulemuste tõenäosus võiks olla \(\frac{1}{6}\). R-is tuleb \(\chi^2\) testi rakendamiseks lugeda kokku
erinevate väärtuste esinemiste arv (käsk table) ja siis
rakendada testi käsuga chisq.test(tabel, p=c(p1,..,pm)),
kus tabel on käsu table rakendamisel saadud
tulemus. Tõenäosused võib ära jätta, kui need on kõik võrdsed.
Testime lineaarset kongruentset generaatorit parameetritega \(a=697,\ b=67,\ m=1.6777216\times 10^{7}\).
Tekita seemnest 11 lähtuvalt 400 pseudojuhuslikku arvu. Korruta need
kuuega, liida 1 ja võta täisosa (kasuks tuleb funktsioon
floor). Esimesed 6 arvu peaks tulema
## [1] 1 2 6 4 3 1
Kontrolli \(\chi^2\)-testi abil, kas need võiksid olla ausa täringu abil saadud visete tulemuseks. (kontrolliks: testi \(p\) väärtuseks peaks tulema 0.4812). Mis oleks otsuseks juhul \(\alpha=0.5\)? Kui sageli me teeksima sellise \(\alpha\) korral ausa täringu visete põhjal vale otsuse? Mis on testi tulemuse põhjal otsuseks, kui nõuda, et ausa täringu puhul me teeks õige otsuse üheksal juhul kümnest (sama pika katseseeria korral)?
Kui me tahame \(\chi^2\)-testi kasutada selleks, et kontrollida katsetulemuste vastavust mingi konkreetse jaotusega juhusliku suuruse \(X\) sõltumatute katsete korral saadud väärtustele, siis valime mingid \(m\) vastastikku välistavat \(X\)-ga seotud sündmust, mis katavad kõik võimalused, ning võtame iga katse tulemuseks selle sündmuse järjekorranumbri, mis sellel katsel toimus. Näiteks võime valida sündmusteks Näiteks \(A_i=\{c_{i-1}< X\leq c_i\}\), kus \[-\infty = c_{0} < c_{1} < \ldots < c_{m-1} < c_{m} = \infty. \] Sel juhul on sündmuse \(A_i\) tõenäosus arvutatav juhusliku suuruse \(X\) jaotusfunktsiooni abil kujul \(p_i=P(A_i)=F(c_i)-F(c_{i-1})\). Nüüd võime \(\chi^2\)-testi abil kontrollida, kas vaadeldavate sündmuste toimumise sagedus on kooskõlas nende toimumise tõenäosustega.
Tekita käskudega
set.seed(20200918)
x <- rexp(500,rate=0.2)
pseudojuhuslikud arvud, mis peaks vastama eksponentjaotusele \(Exp(\frac{1}{5})\). Kontrolli nende arvude vastavust sellele jaotusele, vaadeldes piirkondadesse \(A_1=(-\infty,1]\), \(A_2=(1,2]\), \(A_3=(2,3]\),\(A_4=(3,4]\), \(\ldots\), \(A_{10}=(9,10]\), \(A_{11}=(10,\infty)\) sattumise vastavust vaadeldava jaotuse poolt määratud tõenäosustele. Milline on otsus, kui olulisuse nivooks valida 0.05?
Lahenduse skeem:
-Inf ja Inf. Arve ja vektoreid saab kokku
ühendada käsuga c()punif on
ühtlase jaotuse jaotusfunktsioon, pnorm on normaaljaotuse
jaotusfunktsioon, pexp on eksponentjaotuse jaotusfunktsioon
jne. Infot käsu võimalike parameetrite kohta saab kujul
?käsk.diff, mille rakendamisel
saame sündmustele vastavate tõenäosuste vektori.x pikkusega. Vektori
pikkust saab leida length() käsuga ning miinimumi jaoks on
min() funktsioon.cut, millele tuleb anda ette
sildistatav vektor ja piirkondi defineerivate punktide vektor.cut käsu tulemusele käsku table,
et lugeda kokku igasse osalõiku sattunud punktide arv. Seejäral rakeda
Hii-ruut testiOtsus valitud olulisuse nivool on …
Ülesanne 2.1 (0,5p) Kasuta praktikumi teises ülesandes parandatud LKG funktsiooni selleks, et tekitada SAS tarkvaras kasutatava RANUNI generaatori algoritmiga seemnest 535 lähtuvalt 1000 pseudojuhuslikku \(u_1,u_2,\ldots,u_{1000}\) arvu ning kirjeldada joonisel nende arvude sattumist vahemikesse \([0,0.3),\ [0.3,0.8],[0.8,1)\). Samal joonisel kujutada teoreetilised 0,1 ja 0,9 kvantiilid (mis on iga vahemiku jaoks erinevad). Kommenteeri tulemust - kas see katse tekitab mingeid kahtluseid generaatori korrektsuse osas või mitte.
Ülesanne 2.2 (0.5 punkti) Kasuta hii-ruut testi selleks, et kontrollida, kas pseudojuhuslike arvude \(y_i=\sqrt{u_i}\) (kus \(u_i\) on ülesandes 2.1 tekitatud väärtused) piirkondadesse \((-\infty,0.1]\), \((0.1,0.3],(0.3,0.5],(0.5,0.9],(0.9,\infty)\) sattunud katsetulemuste arv võib vastata jaotusfunktsiooniga \[F_Y(y)=\begin{cases} 0,& y<0,\\ a\,y^2+(1-a) y^4,& 0\leq y\leq 1,\\ 1,& y\geq 1 \end{cases}\] juhuslikule suurusele juhtudel \(a=0.8,\ a=0.9,\ a=1\). Vihje - kui tõenäosuste arvutamine vektorkäskude abil ei tööta, siis võib need arvutada ükshaaval (soovi korral kasutades for tsüklit).