Esta página aún no se ha traducido para esta versión. Puede ver la versión más reciente de esta página en inglés.

Crear y controlar una secuencia de números aleatorios

La clase RandStream le permite crear una secuencia de números aleatorios. Esto resulta útil por varias razones. Por ejemplo, si quiere generar valores aleatorios sin que afecte al estado de la secuencia global. Puede que en una simulación le interese separar las fuentes de aleatoriedad. O puede que necesite utilizar un algoritmo de generación diferente al que utiliza el software de MATLAB® al iniciarse. Con el constructor RandStream puede crear su propia secuencia, establecer las propiedades grabables y utilizarlas para generar números aleatorios. Puede controlar la secuencia que cree de la misma manera que controla la secuencia global. Incluso puede sustituir la secuencia global por la secuencia que cree.

Para crear una secuencia, utilice el constructor RandStream.

myStream=RandStream('mlfg6331_64');
rand(myStream,1,5)

ans =

    0.6530    0.8147    0.7167    0.8615    0.0764

La secuencia aleatoria myStream actúa de forma independiente a la secuencia global. Las funciones rand, randn y randi seguirán extrayendo de la secuencia global y no afectarán a los resultados de los métodos RandStream rand, randn y randi aplicados a myStream.

Puede hacer que myStream sea la secuencia global con el método RandStream.setGlobalStream.

RandStream.setGlobalStream(myStream)
RandStream.getGlobalStream

ans = 

mlfg6331_64 random stream (current global stream)
             Seed: 0
  NormalTransform: Ziggurat

RandStream.getGlobalStream==myStream

ans =

     1

Subsecuencias

Puede que desee volver a una parte anterior de una simulación. Una secuencia aleatoria se puede controlar haciendo que salte a puntos de control fijos, llamados subsecuencias. La propiedad Substream le permite saltar hacia delante y hacia atrás entre subsecuencias múltiples. Para utilizar la propiedad Substream, cree una secuencia con un generador que admita subsecuencias. (Consulte Elegir un generador de números aleatorios para obtener una lista de algoritmos de generación y sus propiedades).

stream=RandStream('mlfg6331_64');
RandStream.setGlobalStream(stream)

El valor inicial de Substream es 1.

stream.Substream

ans =

     1

Las subsecuencias son útiles en cálculos de serie. Las subsecuencias pueden recrear una simulación completa o parte de ella regresando a un punto de control particular de una secuencia. Por ejemplo, se pueden usar en bucles.

for i=1:5
    stream.Substream=i;
    rand(1,i)
end

ans =
    0.6530

ans =
    0.3364    0.8265

ans =
    0.9539    0.6446    0.4913

ans =
    0.0244    0.5134    0.6305    0.6534

ans =
    0.3323    0.9296    0.5767    0.1233    0.6934

Cada una de estas subsecuencias puede reproducir su iteración de bucle. Por ejemplo, puede volver a la quinta subsecuencia. El resultado devolverá los mismos valores que la quinta salida anterior.

stream.Substream=5;
rand(1,5)

ans =

    0.3323    0.9296    0.5767    0.1233    0.6934

Elegir un generador de números aleatorios

MATLAB ofrece varias opciones de algoritmos de generación. La siguiente tabla resume las propiedades esenciales de los algoritmos de generación y las palabras clave que se usan para crearlos. Para recuperar una lista de todos los algoritmos de generación disponibles, utilice el método RandStream.list.

Palabra claveGeneradorSoporte de secuencias y subsecuencias múltiplesPeriodo aproximado con plena precisión
mt19937arMersenne twister (se utiliza de forma predeterminada al iniciar MATLAB)No219937-1
dsfmt19937Mersenne twister rápido orientado a SIMD No219937-1
mcg16807Generador congruencial multiplicativoNo231-2
mlfg6331_64Generador de Fibonacci retardado multiplicativo2124 (251 secuencias de longitud 272)
mrg32k3aGenerador combinado múltiple recursivo2191 (263 secuencias de longitud 2127)
philox4x32_10Generador Philox 4x32 con 10 rondas2193 (264 secuencias de longitud 2129)
threefry4x64_20Generador Threefry 4x64 con 20 rondas2514 (2256 secuencias de longitud 2258)
shr3congGenerador de registro de desplazamientos sumado a un generador lineal congruencialNo264
swb2712Generador modificado de resta con préstamoNo21492

Los generadores mcg16807, shr3cong y swb2712 son compatibles con versiones anteriores de MATLAB. mt19937ar y dsfmt19937 están diseñados principalmente para aplicaciones secuenciales. Los generadores restantes proporcionan soporte específico para la generación de números aleatorios paralela.

Según la aplicación, puede que ciertos generadores sean más rápidos o devuelvan valores con mayor precisión. Todos los generadores de números seudoaleatorios se basan en algoritmos deterministas y todos fallarán en una prueba suficientemente específica de aleatoriedad. Una forma de comprobar los resultados de la simulación Monte Carlo es volver a ejecutar la simulación con dos o más algoritmos de generación; la oferta de generadores que le ofrece MATLAB le permite hacerlo. Aunque al usar generadores diferentes es poco probable que los resultados difieran en más de un error de muestra de Monte Carlo, en la literatura hay ejemplos en los que este tipo de validación ha dado lugar a fallos en un algoritmo de generación concreto (consulte [13] para obtener un ejemplo).

Algoritmos de generación

mt19937ar

El Mersenne twister, como se describe en [11], tiene periodo 2199371 y cada valor U(0,1) se crea con números enteros de 32 bits. Los posibles valores son múltiplos de 253 en el intervalo (0,1). Este generador no es compatible con secuencias ni subsecuencias múltiples. El algoritmo randn que se utiliza de forma predeterminada para las secuencias mt19937ar es el algoritmo zigurat [7], pero con el generador mt19937ar debajo. Nota: Este generador es idéntico al que utiliza la función rand a partir de la Versión 7 de MATLAB, que se activa con rand('twister',s).

dsfmt19937

El Mersenne twister rápido orientado a SIMD de precisión doble, como se describe en [12], es una implementación más rápida del algoritmo Mersenne twister. El periodo es 2199371 y los posibles valores son múltiplos de 252 en el intervalo (0,1). De forma nativa, el generador produce valores de precisión doble en [1,2), que se transforman para crear valores U(0,1). Este generador no es compatible con secuencias ni subsecuencias múltiples.

mcg16807

Un generador congruencial multiplicativo de 32 bits, como se describe en [14], con multiplicador a=75, módulo m=2311. Este generador tiene un periodo de 2312 y no admite secuencias ni subsecuencias múltiples. Cada valor U(0,1) se crea con un número entero de 32 bits a partir del generador, los valores posibles son múltiplos de (2311)1 estrictamente dentro del intervalo (0,1). El algoritmo randn que se utiliza de forma predeterminada para las secuencias mcg16807 es el algoritmo polar (que se describe en [1]). Nota: Este generador es idéntico al que usan las funciones rand y randn a partir de la Versión 4 de MATLAB, que se activa con rand('seed',s) o con randn('seed',s).

mlfg6331_64

Un generador de Fibonacci retardado multiplicativo de 64 bits, como se describe en [10], con retardos l=63, k=31. Este generador es similar al MLFG implementado en el paquete SPRNG. Tiene un periodo de aproximadamente 2124. Admite hasta 261 secuencias paralelas, a través de la parametrización, y 251 subsecuencias, cada una de longitud 272. Cada valor U(0,1) se crea con un número entero de 64 bits a partir del generador; los valores posibles son múltiplos de 264 estrictamente dentro del intervalo (0,1). El algoritmo randn que se utiliza de forma predeterminada para las secuencias mlfg6331_64 es el algoritmo zigurat [7], pero con el generador mlfg6331_64 debajo.

mrg32k3a

Un generador combinado múltiple recursivo de 32 bits, como se describe en [2]. Este generador es similar a CMRG implementado en el paquete RngStreams. Tiene un periodo de hasta 2191 y admite hasta 263 secuencias paralelas, a través de la parametrización, cada una de longitud 2127. También admite 251 subsecuencias, cada una de una longitud 276. Cada valor U(0,1) se crea con dos números enteros de 32 bits a partir del generador; los valores posibles son múltiplos de 253 estrictamente dentro del intervalo (0,1). El algoritmo randn que se utiliza de forma predeterminada para las secuencias mrg32k3a es el algoritmo zigurat [7], pero con el generador mrg32k3a debajo.

philox4x32_10

Un generador 4 por 32 con 10 rondas, como se describe en [15]. Este generador utiliza una red Feistel y multiplicación de números enteros, y está específicamente diseñado para alto rendimiento en sistemas altamente paralelos como las GPU. Tiene un periodo de 2193 (264 secuencias de longitud 2129).

threefry4x64_20

Un generador 4 por 64 con 20 rondas, como se describe en [15]. Este generador es una adaptación no criptográfica del cifrado de bloque Threefish a partir de la función hash Skein. Tiene un periodo de 2514 (2256 secuencias de longitud 2258).

shr3cong

El generador SHR3 de Marsaglia de registro de desplazamientos sumado a un generador lineal congruencial con multiplicador a=69069, sumando b=1234567 y módulo 232. SHR3 es un generador de registro de 3 desplazamientos definido como u=u(I+L13)(I+R17)(I+L5), donde I es el operador de identidad, L es el operador de desplazamiento hacia la izquierda y R es el operador de desplazamiento hacia la derecha. El generador combinado (la parte SHR3 se describe en [7]) tiene un periodo de aproximadamente 264. Este generador no es compatible con secuencias ni subsecuencias múltiples. Cada valor U(0,1) se crea con el número entero de 32 bits del generador; los valores posibles son todos los múltiplos de 232 estrictamente dentro del intervalo (0,1). El algoritmo randn que se utiliza por defecto para las secuencias shr3cong es la forma más temprana del algoritmo zigurat [9], pero con el generador shr3cong debajo. Este generador es idéntico al que utiliza la función randn a partir de la Versión 5 de MATLAB, que se activa con randn('state',s).

Nota

El generador SHR3 que se utiliza en [6] (1999) es diferente al que se usa en [7] (2000). MATLAB utiliza la versión más reciente del generador, que se presenta en [7].

swb2712

Un generador modificado de resta con préstamo, como se describe en [8]. Este generador es similar a un generador de Fibonacci retardado sumativo con retardos 27 y 12, pero está modificado para que tenga un periodo mucho más largo de aproximadamente 21492. El generador funciona de forma nativa con precisión doble para crear valores U(0,1) y son posibles todos los valores en el intervalo abierto (0,1). El algoritmo randn que se utiliza de forma predeterminada para las secuencias swb2712 es el algoritmo zigurat [7], pero con el generador swb2712 debajo. Nota: Este generador es idéntico al que utiliza la función rand a partir de la Versión 5 de MATLAB, que se activa con rand('state',s).

Algoritmos de transformación

Inversion

Computa una variación aleatoria normal aplicando la función de distribución acumulativa inversa normal estándar a una variación aleatoria uniforme. Cada valor normal consume exactamente un valor uniforme.

Polar

El algoritmo polar de rechazo, como se describe en [1]. De media, cada valor normal consume aproximadamente 1,27 valores uniformes.

Ziggurat

El algoritmo zigurat, como se describe en [7]. De media, cada valor normal consume aproximadamente 2,02 valores uniformes.

Referencias

[1] Devroye, L. Non-Uniform Random Variate Generation, Springer-Verlag, 1986.

[2] L’Ecuyer, P. “Good Parameter Sets for Combined Multiple Recursive Random Number Generators”, Operations Research, 47(1): 159–164. 1999.

[3] L'Ecuyer, P. and S. Côté. “Implementing A Random Number Package with Splitting Facilities”, ACM Transactions on Mathematical Software, 17: 98–111. 1991.

[4] L'Ecuyer, P. and R. Simard. “TestU01: A C Library for Empirical Testing of Random Number Generators,” ACM Transactions on Mathematical Software, 33(4): Article 22. 2007.

[5] L'Ecuyer, P., R. Simard, E. J. Chen, and W. D. Kelton. “An Objected-Oriented Random-Number Package with Many Long Streams and Substreams.” Operations Research, 50(6):1073–1075. 2002.

[6] Marsaglia, G. “Random numbers for C: The END?” Usenet posting to sci.stat.math. 1999. Available online at https://groups.google.com/group/sci.crypt/browse_thread/
thread/ca8682a4658a124d/
.

[7] Marsaglia G., and W. W. Tsang. “The ziggurat method for generating random variables.” Journal of Statistical Software, 5:1–7. 2000. Available online at https://www.jstatsoft.org/v05/i08.

[8] Marsaglia, G., and A. Zaman. “A new class of random number generators.” Annals of Applied Probability 1(3):462–480. 1991.

[9] Marsaglia, G., and W. W. Tsang. “A fast, easily implemented method for sampling from decreasing or symmetric unimodal density functions.” SIAM J.Sci.Stat.Comput. 5(2):349–359. 1984.

[10] Mascagni, M., and A. Srinivasan. “Parameterizing Parallel Multiplicative Lagged-Fibonacci Generators.” Parallel Computing, 30: 899–916. 2004.

[11] Matsumoto, M., and T. Nishimura.“Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudorandom Number Generator.” ACM Transactions on Modeling and Computer Simulation, 8(1):3–30. 1998.

[12] Matsumoto, M., and M. Saito.“A PRNG Specialized in Double Precision Floating Point Numbers Using an Affine Transition.” Monte Carlo and Quasi-Monte Carlo Methods 2008, 10.1007/978-3-642-04107-5_38. 2009.

[13] Moler, C.B. Numerical Computing with MATLAB. SIAM, 2004. Available online at https://www.mathworks.com/moler

[14] Park, S.K., and K.W. Miller. “Random Number Generators: Good Ones Are Hard to Find.” Communications of the ACM, 31(10):1192–1201. 1998.

[15] Salmon, J. K., M. A. Moraes, R. O. Dror, and D. E. Shaw. "Parallel Random Numbers: As Easy as 1, 2, 3." In Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11). New York, NY: ACM, 2011.

Consulte también

Temas relacionados