Multiplicación con acarreo

De Wikipedia, la enciclopedia libre

En ciencias de la computación, la multiplicación con acarreo (MWC de las siglas en inglés de multiply-with-carry) es un método creado por George Marsaglia para generar secuencias de números enteros aleatorios basados en un conjunto inicial de dos a miles de valores semilla seleccionados aleatoriamente. Las principales ventajas del método MWC son que usa simple aritmética computacional de enteros y produce una rápida generación de secuencias de números aleatorios con términos de gran tamaño, dentro del rango aproximado de 260 a 22000000.

Al igual que sucede con la mayoría de los generadores de números pseudoaleatorios, las secuencias resultantes están en función de los valores semilla seleccionados aleatoriamente.

Teoría general[editar]

Una secuencia MWC está basada en un módulo de aritmética en base b, usualmente b = 232, dado que dicho módulo en base b es automático en muchas computadoras. Sin embargo, a veces es usada una base b = 232 − 1, porque la aritmética para módulos 232 − 1 requiere solamente un ajuste simple hacia 232, y la teoría para las secuencia MWC basadas en módulos 232 presenta algunas dificultades muy molestas que pueden ser evitadas usando b = 232 − 1. En su forma más común, un generador lag-r MWC requiere una base b, un multiplicador a, y un conjunto de r+1 valores semilla aleatorios, consistente en r residuos de b,

x0, x1, x2 ,..., xr−1,

y un acarreo inicial cr−1 < a.

La secuencia lag-r MWC es entonces una secuencia de pares xncn determinada por

y la salida del generador MWC es la secuencia de x's,

xr, xr+1, xr+2,...

El período de un generador lag-r MWC es el orden de b en el grupo multiplicativo de números módulo abr − 1. Es habitual escoger a tal que p = abr − 1 es un primo para el cual el orden de b puede ser determinado. Ya que 2 es un residuo cuadrático de números de la forma 8k±1, b = 232 no puede ser una raíz primitiva de p = abr − 1. Por consiguiente no hay generadores MWC en base 232 que presentan el período máximo posible, una de las dificultades que el uso de b = 232 − 1 supera.

Un problema teórico con generadores MWC, indicado por Couture e l'Ecuyer (1997) es que los bits más significativos son levemente sesgados; los generadores de multiplicación con acarreo complementaria no comparten este problema: "Podemos ver que, para el MWC complementario, cada bit del valor de salida es justo, esto es, los dos dígitos binarios aparecerán con igual frecuencia en un período completo, una propiedad no compartida por generadores MWC." Los generadores de multiplicación con acarreo complementarios también requieren considerablemente más tiempo de cómputo por iteración, de tal manera que existe un compromiso de evaluar en dependencia de los requisitos de la implementación.

Comparación con generadores de congruencia lineales[editar]

Los generadores de congruencia lineales son implementados como

ya que la mayoría de los procesadores aritméticos son capaces de poner el multiplicador a y el x actual en registros de 32-bit, formando el producto en registros contiguos de 64 bits, y tomando los 32 bits inferiores como el producto, o sea, de forma

.

Agregando el c de 32-bit a esa mitad inferior se obtiene (ax+c) mod 232. Si a mod 8 es 1 o 5 y c es impar, la secuencia congruente resultante base 232 tendrá un período 232.

Un generador lag-1 de multiplicación con acarreo nos permite hacer el período aproximadamente 263 usando esas mismas operaciones computacionales, excepto que esta vez la mitad superior del producto de 64 bits es usada en vez de ignorada, después de que los 64 bits son formados. Es usado como un nuevo valor de acarreo c en vez del valor fijo de acarreo de la secuencia de congruencial estándar: tomando ax+c en 64-bits, luego formando un nuevo c con la mitad superior de esos 64 bits, y el nuevo x con la mitad inferior.

Con el multiplicador a especificado, cada par de valores de entrada x, c es convertido en un nuevo par,

Si x y c no son cero ambos, entonces el período de la secuencia de multiplicación con acarreo resultante será de orden b = 232 en el grupo multiplicativo de residuales módulo ab − 1, o sea, en menor n tal que bn = 1 mod (ab − 1). Si escogemos a entre 28 y 31 bits tal que ab−1 es un "primo seguro", que ambos ab − 1 y ab/2 − 1 son primos, entonces el período será ab/2 − 1, acercándose a 263, lo cual en la práctica puede ser un subconjunto aceptablemente grande de posibles pares (x, c) de números de 32.

A continuación algunos valores máximos de a para aplicaciones computacionales que satisfacen la condición de primo seguro citada anteriormente:

Bits en a b Máximo a tal que ab−1 es un Primo Seguro Período
15 216 215−50 = 32,718 1,072,103,423
16 216 216−352 = 65,184 2,135,949,311
31 232 231−563 = 2,147,483,085 4,611,684,809,394,094,079
32 232 232−178 = 4,294,967,118 9,223,371,654,602,686,463
64 264 264−742 = 18,446,744,073,709,550,874 170,141,183,460,469,224,887,945,252,369,640,456,191
128 2128 2128−10,408 2127(2128−10,408)−1
256 2256 2256−9166 2255(2256−9166)−1
512 2512 2512−150,736 2511(2512−150,736)-1

Sin embargo, como ser un primo seguro no afecta la aleatoriedad de la secuencia, simplemente se puede escoger a tal que el orden de b sea ab/2 − 1. La siguiente tabla refleja los valores máximos de a para varios tamaños.

Bits en a b Máximo a tal que b tiene orden ab/2−1 Período
15 216 215−29 = 32,739 1,072,791,551
16 216 216−22 = 65,514 2,146,762,751
31 232 231−68 = 2,147,483,580 4,611,685,872,398,499,839
32 232 232−76 = 4,294,967,220 9,223,371,873,646,018,559
63 264 263−140 = 9,223,372,036,854,775,668 85,070,591,730,234,614,574,571,566,698,273,439,743
64 264 264−116 = 18,446,744,073,709,551,500 170,141,183,460,469,230,661,776,147,440,730,111,999

Se muestra una comparación de secuencias de congruentes y MWC para el simple caso de la aritmética módulo 10; donde los "registros" tienen un solo dígito, y los registros contiguos dos dígitos:

Comenzando con , la secuencia congruencial

tiene esta secuencia de registros contiguos:

y la secuencia de salida de x's, (el registro más a la derecha), tiene período 4:

Iniciando con , la secuencia MWC

tiene esta secuencia de registros contiguos:

10,01,07,49,67,55,40,04,28,58,61,13,22,16,43,25,37,52,19,64,34,31 10,01,07,...

con secuencia de salida de x's teniendo período 22:

0,1,7,9,7,5,0,4,8,8,1,3,2,6,3,5,7,2,9,4,4,1 0,1,7,9,7,5,0,...

Note que si esos segmentos repetidos de valores de x son colocados en orden inverso a partir de un ,

tenemos la expansión j/(ab−1) con a=7, b=10, j=31:

Esto es generalmente verdadero: La secuencia de x's producida por un generador lag-r MWC:

cuando lo ponemos en orden inverso, tendremos la expansión base-b de un racional j/(abr − 1) para algún 0 < j < abr.

Note además que si, empezando con , generamos la secuencia congruencial ordinaria

,

tenemos la secuencia de período 22

31,10,1,7,49,67,55,40,4,28,58,61,13,22,16,43,25,37,52,19,64,34, 31,10,1,7,...

y esa secuencia, reducida mod 10, es

1,0,1,7,9,7,5,0,4,8,8,1,3,2,6,3,5,7,2,9,4,4, 1,0,1,7,9,7,5,0,...

la misma secuencia de x's resultante de la secuencia MWC.

Generalmente esto es verdad, (pero aparentemente solo para secuencias lag-1 MWC):

Dados los valores iniciales , la secuencia resultante de la secuencia lag-1 MWC

es exactamente la secuencia congruencial yn = ayn − 1 mod(ab − 1), reducida módulo b. La elección del valor inicial y0 meramente rota el ciclo de x's.

Generadores de Multiplicación con Acarreo Complementaria[editar]

Estableciendo el período de un generador lag-r MWC usualmente implica escoger un multiplicador a tal que p=abr − 1 es primo. Si p es un primo seguro, entonces el orden de b será p − 1 or (p − 1)/2. De otro modo, es probable que p − 1 tendrá que ser factorizado para encontrar el orden de b mod p, and p = abr − 1 puede ser difícil de factorizar.

Pero un primo de la forma p = abr + 1 será p−1 fácil de factorizar, de esta manera una versión de multiplicación con acarreo que involucra el orden de b para un primo p = abr + 1 reducirá considerablemente el número de teoría computacional requerida establecer el período de una secuencia MWC.

Afortunadamente, una modificación leve del procedimiento MWC conduce a primos de la forma abr + 1. El nuevo procedimiento es llamado multiplicación con acarreo complementaria (CMWC de las siglas en inglés de complementary-multiply-with-carry ), y el esquema es el mismo que para el lag-r MWC: multiplicador a, base b, r + 1 semillas

x0, x1, x2,..., xr−1, y cr − 1.

Hay un cambio leve en la generación de un nuevo par (x, c):

Esto es, tomando el complemento, (b−1)−x, al formar el nuevo x.

La secuencia resultante de x`s producida por el CMWC RNG tendrá como período el orden de b en el grupo multiplicativo de residuales módulo abr+1, y la salida x`s, en orden inverso, formará la base b expansión de j/(abr+1) para algún 0<j<abr. Lo hace ligeramente más fácil (y más rápido) para ganar acceso a elementos en el array conteniendo a la r más reciente

El uso de lag-r CMWC hace mucho más fácil encontrar períodos para r`s tan largos como 512, 1024, 2048, etc. (Tomando r como una potencia de 2 hace ligeramente más fácil (y rápido) acceder a los elementos en el array conteniendo el r-ésimo más reciente x`s.)

Algunos ejemplos:

Con b=232, el período del lag-1024 CMWC

será a232762, acerca de 109867 para estos tres as: 109111 o 108798 o 108517.

Con b = 232 y a = 3636507990, p = ab1359 − 1 un primo seguro, entonces la secuencia MWC basada en esa a tiene período 3636507990243487 1013101.

Con b = 232, un CMWC RNG con período récord cercano puede basarse en el primo p = 15455296b42658 + 1. El orden de b para ese primo es 241489*21365056, cerca de 10410928.

Implementación[editar]

La implementación siguiente del algoritmo CMWC está en C (lenguaje de programación). Además, incluye en el programa una función de inicialización de muestra. En esta implementación lag r=4096 y el período del generador resultante es aproximadamente .

#include <stdint.h>

#define PHI 0x9e3779b9

static uint32_t Q[4096], c = 362436;

void init_rand(uint32_t x)
{
	int i;

	Q[0] = x;
	Q[1] = x + PHI;
	Q[2] = x + PHI + PHI;

	for (i = 3; i < 4096; i++)
		Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
}

uint32_t rand_cmwc(void)
{
	static uint32_t i = 4095;
	uint64_t t;

	i = (i + 1) & 4095;
	t = (18705ULL * Q[i]) + c;
	c = t >> 32;
	Q[i] = 0xfffffffe - t;

	return Q[i];
}

Véase también[editar]

Referencias[editar]