Está en la página 1de 7

Generadores

Algoritmos y
Estructura de
Datos I

1
Generadores
Actualmente, son muchas las aplicaciones que tienen los números
aleatorios. Si analizamos el mundo real, encontramos que ocurren eventos
de manera aleatoria constantemente. Incluso, nosotros, los humanos, nos
comportamos de manera aleatoria: usamos números aleatorios en los
juegos de azar, en las finanzas, en el ámbito informático, etcétera.

Particularmente, a nosotros nos interesa el contexto informático, en donde


los números aleatorios toman un rol de gran importancia, ya que se
necesitan para los modelos de simulaciones, para generar las pruebas de
los sistemas y de los aplicativos, para los algoritmos criptográficos, los
algoritmos de búsqueda y de ordenamiento, entre otros.

En esta lectura, hablaremos de cómo podemos hacer para generar


números aleatorios. Sorprendentemente, esta no es una tarea sencilla y
existen unos pocos generadores buenos. Particularmente, desarrollaremos
un generador de congruencia lineal, que permite generar números
aleatorios con una distribución uniforme.

Números aleatorios
Antes de comenzar explicando cómo podemos generar los números
aleatorios, debemos saber qué son.

Un número aleatorio es un número generado al azar, que responde a una


distribución de probabilidad.

En general, si no se indica qué distribución tiene, se asume que es una


distribución uniforme continua.

Un generador produce
una secuencia de Generación de números aleatorios
números
pseudoaleatorios.
Mientras más Como un número aleatorio es generado al azar, se dice que los algoritmos,
propiedades cumplan en realidad, generan números pseudoaleatorios, debido a que no son
respecto de los realmente aleatorios, sino que responden a una fórmula y al proceso del
números aleatorios, algoritmo, para la generación de dicho número.
mejores números
pseudoaleatorios
producirán. Analicemos algunas formas en que se pueden generar estos números
pseudoaleatorios.

2
Una manera corresponde a usar el reloj del sistema. Si usamos el valor de
los segundos para arrojar un número aleatorio cuando se lo solicite,
podríamos considerar que queremos generar números aleatorios binarios;
es decir, ceros y unos. Si usamos los segundos del reloj, podemos utilizar su
paridad: ante un número par, arrojamos un 0 y, ante un impar, un 1.

Sin embargo, al generar una secuencia de números aleatorios, tendríamos


un problema. Si nuestro algoritmo se ejecuta a una velocidad mayor o igual
que un segundo, pueden ocurrir dos casos: obtendremos una secuencia de
números donde se repetirían los ceros y, luego, los unos en el caso de que
la velocidad sea mayor que un segundo, u obtendremos un cero alternado
de un uno consecutivamente, en caso de que durara lo mismo. Si viéramos
esa secuencia de números, no los consideraríamos aleatorios.

Esto nos hace pensar que podríamos solucionar dicho problema usando
una unidad de tiempo más pequeña: en vez de segundos, podríamos usar
microsegundos. Pero esto no resuelve el problema del todo: la secuencia
de números generada no será aleatoria. Necesitamos que cumpla con
ciertas propiedades, para que podamos obtener un buen conjunto de
números pseudoaleatorios.

Podríamos querer generar un conjunto de números aleatorios


comprendidos entre un rango. Así, por ejemplo, podríamos querer generar
valores aleatorios entre 0 y 999 cumpliendo una distribución uniforme, si
consideramos que un número posee la misma probabilidad de ocurrencia
que cualquier otro. Para poder resolver este problema, se debe cumplir
con las siguientes propiedades:

 La probabilidad de ocurrencia del primer número es igual para cualquier


valor comprendido en el rango.
 La probabilidad de ocurrencia del i-ésimo número es igual para
cualquier valor comprendido en el rango.
 Si sumamos dos valores consecutivos, el valor resultante tiene la misma
probabilidad de ser par como impar.
 Al generar una cierta cantidad de números aleatorios, existirán
duplicados. Se estima que, ante 1000 números aleatorios, 368 números
no aparecerían.

Si asumimos que el rango va de 0 a 999, la media esperada para todos los


números será de 499,5.

Al hacer la secuencia de números aleatorios usando el reloj del sistema,


podemos notar que no se cumplen algunas propiedades. En estos casos, se
dice que han fallado dos pruebas estadísticas.

3
Los generadores de números aleatorios nunca son perfectos. En general,
cumplen algunas propiedades, pero fallan otras pruebas estadísticas. En
función de ello, podremos distinguir cuál es mejor o peor.

Generador de congruencia lineal


Es uno de los generadores más usados y conocidos que existen. Es un
algoritmo que logra pasar varias pruebas estadísticas y que permite
conseguir distribuciones uniformes. No es el mejor de todos, pero es
recomendable su uso cuando se desea obtener una buena secuencia de
números aleatorios.

Este generador permite obtener una secuencia de valores:

X1, X2,…, Xi,…

Donde:

Xi+1=AXi(mod M)

Esto significa que calculamos el nuevo valor aleatorio Xi+1 en función del
valor aleatorio anterior Xi. Esto se realiza calculando el producto del valor
aleatorio anterior por una constante A, para, luego, dividirlo por M y, así,
obtener, finalmente, su resto.

Si analizamos esta expresión, podemos llegar a varias observaciones.

 Por un lado, como es dividido por M, podemos afirmar que el resultado


obtenido, finalmente, será menor que M.
 Además, podemos notar que es necesario un valor inicial X0 con el cual
podamos comenzar a calcular los valores aleatorios. Dicho valor es
llamado semilla.
 La observación anterior nos permite afirmar que si X0 =0, el generador
no producirá una secuencia de números aleatorios. En este caso,
producirá una secuencia de ceros. Es por esta razón que la semilla no
debería valer 0. La elección del valor de la semilla no debería ser
arbitraria, sino que debería ser un valor:

1≤ X0 <M

Además, si hacemos que M sea primo, nunca obtendremos un valor de Xi


que valga 0.

4
Este generador posee la propiedad de ser periódico, es decir, una vez que
se genera por segunda vez un mismo valor, la secuencia comienza a
repetirse por segunda, tal como fue generada anteriormente. Esto nos
permite arribar a otra observación:

 La secuencia se repite cada M-1 números. Este valor se denomina


período.

Si M es primo, son varios los valores de A que nos dan un


período completo de longitud M-1, y este tipo de generador
de números aleatorios se denomina generador de
congruencia lineal de período completo. Algunos valores de
A no dan un período completo. Por ejemplo, si A=5 y X0=1, la
secuencia tiene un período corto de solo cinco números:

5, 3, 4, 9, 1, 5, 3, 4,… (Weiss, 2013, p. 387).

Implementación

Para implementar este algoritmo, se deben tener algunos cuidados, ya que,


si aplicamos directamente la expresión propuesta, se pueden obtener
algunos problemas.

La expresión vista anteriormente se podría representar de esta manera:

x[i+1] = A * x[i] % M

Sin embargo, esta expresión no necesariamente funcionará si se la usa en


el código que se desarrolla.

Se ha estudiado y analizado cuidadosamente qué valores son convenientes


usar, de manera que se consiga una buena secuencia aleatoria que no sea
corta y que cumpla con los requisitos que se planteen. Así, se llegó a la
conclusión de que M debería ser un número primo de 31 bits, lo cual
permitiría obtener un período mayor. Asimismo, se concluyó que el valor
A=48271 es uno de los valores más apropiados. Se recomienda
ampliamente usar estas especificaciones, debido a que no es sencillo
obtenerlos y, si se experimentara, es factible encontrar que no se consiga
una aleatoriedad.

Ahora bien, como describimos anteriormente:

x[i+1] = A * x[i] % M

5
Entonces, también podríamos hacerlo de la siguiente manera:

x[i] = A * x[i] % M

Es decir, hacer que el nuevo valor sea sobrescrito usando el valor anterior.

Sin embargo, esta expresión no funcionará. En la mayoría de los lenguajes


de programación generará un desbordamiento, debido a la multiplicación
con enteros de 31 bits.

Es así como surge una expresión equivalente que realiza una reordenación
que permite realizar cálculos, sin peligro de desbordamiento.

Xi+1=A(Xi(mod Q)-R[Xi/Q]+M𝛿(Xi)

Donde Q y R corresponden al cociente y al resto, respectivamente, de


dividir M/A.

 El primer término siempre puede evaluarse, sin


desbordamiento.
 El segundo término se puede evaluar sin
desbordamiento, si R<Q.
 (Xi) se evalúa como 0, si el resultado de la
resta de los dos primeros términos es positivo y se evalúa
como 1, si el resultado de la resta es negativo.

Para los valores indicados de M y A, tenemos que


Q=44488 y R=3399. (Weiss, 2013, p. 388).

6
Referencias
Weiss, M. A. (2013). Aleatorización. En M. Martín-Romo (Ed.), Estructuras de
datos en Java (pp. 383-392). Madrid, ES: Pearson.

También podría gustarte