Introducción
Las pruebas de validación de números pseudoaleatorios permiten verificar
si una secuencia generada cumple con las propiedades estadísticas de la
aleatoriedad. La prueba de Kolmogorov-Smirnov compara
la distribución acumulada de los números generados con la distribución
teórica uniforme. Los Run tests analizan la secuencia
de números para detectar patrones o repeticiones, evaluando la
independencia entre ellos. La prueba Poker examina
grupos de dígitos para verificar si las frecuencias de combinaciones
siguen las esperadas en un comportamiento aleatorio. Estas pruebas
ayudan a determinar la calidad y confiabilidad de un generador de
números pseudoaleatorios.
Es una prueba no paramétrica que mide la máxima diferencia entre la
distribución acumulada empírica de los datos y la distribución acumulada
teórica (en este caso, uniforme).
Permite verificar si los números generados siguen efectivamente la
distribución uniforme esperada.
Uso en R:
x <- runif(1000) ks.test(x, “punif”, 0, 1)
Ejemplo: Pruebas estadísticas para validez
de los geneadores de números Pseudoaleatorios (GNP)
Para la validez estadística de los GNP, vamos a generar 50 números
Pseudoaleatorios con el método congruencial lineal mixto. probaremos la
aleatoriedad mediante la prueba χ2 y la prueba de kolmogorov-Smirnoff ,
y para la prueba de independencia estadística aplicaremos las pruebas de
las Corridas.
Generando los 50 números U_i Pseudoaleatorios con el método secuencial mixto
a <- 10400
c <- 2567
m <- 30439403
X_n <- 44 # semilla
random.number<-numeric(50) # vector numérico de longitud 50
for (i in 1:50)
{X_n<-(a*X_n+c)%%m
random.number[i]<-X_n/m # números en el intervalo [0,1]
}
random.number
## [1] 0.01511748 0.22185376 0.27918570 0.53135267 0.06783277 0.46088460
## [7] 0.19989840 0.94345914 0.97514836 0.54305743 0.79736866 0.63415472
## [13] 0.20914280 0.08521330 0.21841128 0.47740601 0.02261122 0.15675938
## [19] 0.29765620 0.62455502 0.37230960 0.01993965 0.37242997 0.27179074
## [25] 0.62382593 0.78979558 0.87413436 0.99740777 0.04086966 0.04453083
## [31] 0.12075723 0.87528004 0.91254290 0.44621430 0.62883779 0.91313059
## [37] 0.55821328 0.41819979 0.27792004 0.36846639 0.05056180 0.84280207
## [43] 0.14166086 0.27302599 0.47033281 0.46132620 0.79252461 0.25603134
## [49] 0.72597288 0.11801536
# Probando si los U_i provienen de una uniforme [0,1]
test_ks <- ks.test(random.number,"punif",0,1)
test_ks
##
## Exact one-sample Kolmogorov-Smirnov test
##
## data: random.number
## D = 0.14259, p-value = 0.2376
## alternative hypothesis: two-sided
# Decision
test_ks$p.value # P válido
## [1] 0.2375759
ifelse(test_ks$p.value < 0.05, " Los u_i no siguen una distribución uniforme","Los u_i siguen la distribución uniforme [0,1]") #
## [1] "Los u_i siguen la distribución uniforme [0,1]"
De acuerdo a está prueba, se comprobó que los datos siguen una distribución uniforme.
Es una prueba no paramétrica que evalúa la secuencia de observaciones
para determinar si el orden es aleatorio.
Detecta patrones de rachas de valores mayores o menores a la media, lo
cual permite comprobar la independencia de los números generados.
Uso en R:
library(randtests) x <- runif(100) runs.test(x)
library(tseries)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
diff(random.number) # halla la diferencia entre un valor y el otro en un vector
## [1] 0.206736282 0.057331939 0.252166969 -0.463519899 0.393051828
## [6] -0.260986196 0.743560739 0.031689222 -0.432090932 0.254311229
## [11] -0.163213943 -0.425011916 -0.123929500 0.133197980 0.258994731
## [16] -0.454794793 0.134148163 0.140896817 0.326898823 -0.252245420
## [21] -0.352369953 0.352490323 -0.100639227 0.352035189 0.165969648
## [26] 0.084338776 0.123273410 -0.956538110 0.003661176 0.076226396
## [31] 0.754522814 0.037262853 -0.466328594 0.182623490 0.284292796
## [36] -0.354917309 -0.140013488 -0.140279755 0.090546355 -0.317904592
## [41] 0.792240275 -0.701141215 0.131365126 0.197306826 -0.009006616
## [46] 0.331198414 -0.536493275 0.469941543 -0.607957521
S<-ifelse(diff(random.number) > 0, 1,0) # secuencia de ceros y unos
S
## [1] 1 1 1 0 1 0 1 1 0 1 0 0 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 0 1 1 0 0 0
## [39] 1 0 1 0 1 1 0 1 0 1 0
runs.test(as.factor(S))
##
## Runs Test
##
## data: as.factor(S)
## Standard Normal = 1.5929, p-value = 0.1112
## alternative hypothesis: two.sided
# devuelve 1 si el número es mayor que el anterior y 0 en caso contrario.
# Detectar cambios
cambios <- abs(diff(S))
# Contar las corridas
corridas <- sum(cambios)+1
corridas
## [1] 30
Como resultado obtuvimos un total de 30 corridas
Los números pseudoaleatorios ui se agrupan en combinaciones de varios dígitos decimales (típicamente grupos de 5 decimales). Los grupos de dígitos se clasifican de manera similar a las manos en el juego de póker:
Todo diferente (TD): Ningún decimal se repite en el grupo (Ej: 0.12345). la probabilidad de este evento es: P(TD)=0.3024
Un par (1p): Un decimal aparece dos veces y los demás son diferentes (Ej: 0.14345). P(1p)=0.5040
Dos pares (2p): Dos decimales aparecen dos veces cada uno (Ej: 0.14224). P(2p)=0.1080
Tercia (T): Un decimal aparece tres veces, y los otros dos son diferentes (Ej:0.41443). P(T)=0.0720
Full House (FH): Un dígito aparece tres veces y otro dígito dos veces (Ej: 0.32223). P(FH)=0.0090
Poker (p): Un dígito aparece cuatro veces (Ej: 0.55515). P(p)=0.0045
Quintilla: Todos los dígitos son iguales (Ej: 0.11111). P(Q)=0.0001
library(randtoolbox)
## Cargando paquete requerido: rngWELL
## This is randtoolbox. For an overview, type 'help("randtoolbox")'.
poker.test(random.number,nbcard=5)
##
## Poker test
##
## chisq stat = 2.7, df = 4, p-value = 0.61
##
## (sample size : 50)
##
## observed number 0 0 4 6 0
## expected number 0.016 0.96 4.8 3.8 0.38