Multiplicera-med-bär pseudoslumptalsgenerator
Inom datavetenskap är multiplicera-med-bära (MWC) en metod som uppfanns av George Marsaglia för att generera sekvenser av slumpmässiga heltal baserat på en initial uppsättning från två till många tusen slumpmässigt valda frövärden. De främsta fördelarna med MWC-metoden är att den åberopar enkel datorheltalsaritmetik och leder till mycket snabb generering av sekvenser av slumptal med enorma perioder, från cirka 2 till .
Som med alla pseudoslumptalsgeneratorer är de resulterande sekvenserna funktioner av de angivna frövärdena.
Allmän teori
En MWC-generator är en speciell form av Lehmer-slumptalsgenerator som möjliggör effektiv implementering av en primtalsmodulen mycket större än maskinordsstorleken.
Normala Lehmer-generatorimplementationer väljer en modul nära maskinordstorleken. En MWC-generator bibehåller istället sitt tillstånd i bas , så att multiplicera med görs implicit genom att skifta ett ord. Basen är vanligtvis vald för att vara lika med datorns ordstorlek, eftersom detta gör aritmetik modulo trivial. Detta kan variera från för en mikrokontroller till . (Den här artikeln använder som exempel.)
Värdena för initialtillstånd ("frö") är godtyckliga, förutom att de inte får vara alla noll, inte heller alla vid de högsta tillåtna värdena ( och ). (Detta görs vanligtvis genom att välja mellan 1 och ). MWC-sekvensen är då en sekvens av par bestämd av
Detta kallas en lag-1 MWC-sekvens. Ibland föredras en udda bas, i vilket fall kan användas, vilket är nästan lika enkelt att implementera. En lag- -sekvens är en generalisering av lag-1-sekvensen som tillåter längre perioder. Lag- MWC-sekvensen är då en sekvens av par (för bestäms av
och MWC-generatorns utgång är sekvensen av ,
I det här fallet får initialtillståndsvärdena ("seed") inte bara vara noll eller och .
MWC-multiplikatorn och eftersläpning bestämmer modulen . I praktiken väljs Om modulen är primtal, är perioden för en lag- MWC-generator i storleksordningen i den multiplikativa gruppen av tal modulo . Även om det är teoretiskt möjligt att välja en icke-primmodul, eliminerar en primemodul möjligheten att det initiala fröet delar en gemensam divisor med modulen, vilket skulle minska generatorns period.
Eftersom 2 är en kvadratisk rest av tal av formen , kan inte vara en primitiv rot av . Därför har MWC-generatorer med bas sina parametrar valda så att deras period är ( ab r −1)/2. Detta är en av svårigheterna som användningen av b = 2 k − 1 övervinner.
Den grundläggande formen av en MWC-generator har parametrarna a , b och r , och r +1 tillståndsord. Tillståndet består av r rester modulo b
- 0 0 ≤ x , x 1 , x 2 ,..., x r −1 < b,
och a carry c r −1 < a .
Även om teorin för MWC-generatorer tillåter a > b , väljs a nästan alltid mindre för att underlätta implementeringen.
Tillståndstransformationsfunktionen för en MWC-generator är ett steg i Montgomery- reduktionsmodulo p . Tillståndet är ett stort heltal med det mest signifikanta ordet c n −1 och det minst signifikanta ordet x n − r . Varje steg, x n − r ·( ab r −1) läggs till detta heltal. Detta görs i två delar: −1· x n − r läggs till x n − r , vilket resulterar i ett minst signifikanta ord på noll. Och för det andra a · x n − r till bäraren. Detta gör heltalet ett ord längre, vilket ger två nya mest signifikanta ord x n och c n .
Hittills har detta helt enkelt lagt till en multipel av p till tillståndet, vilket resulterar i en annan representant för samma restklass modulo p . Men till sist flyttas staten ned ett ord, dividerat med b . Detta förkastar det minst signifikanta ordet noll (som i praktiken aldrig beräknas alls) och multiplicerar effektivt tillståndet med b −1 (mod p ).
är en multiplicera-med-bär-generator en Lehmer-generator med modul p och multiplikator b −1 (mod p ). Detta är samma sak som en generator med multiplikator b , men som producerar utdata i omvänd ordning, vilket inte påverkar kvaliteten på de resulterande pseudoslumptalen.
Couture och L'Ecuyer har bevisat det överraskande resultatet att gittret som är associerat med en multiplicera-med-bär-generator är mycket nära det gitter som är associerat med Lehmer-generatorn som den simulerar. Således kan de matematiska tekniker som utvecklats för Lehmer-generatorer (såsom spektraltestet) tillämpas på multiplicera-med-bära-generatorer.
Effektivitet
En linjär kongruentialgenerator med bas b = 2 32 implementeras som
där c är en konstant. Om a ≡ 1 (mod 4) och c är udda, kommer den resulterande bas-2 32 kongruentialsekvensen att ha period 2 32 .
Detta kan beräknas med endast de låga 32 bitarna av produkten av a och det aktuella x . Men många mikroprocessorer kan beräkna en fullständig 64-bitars produkt på nästan samma tid som de låga 32 bitarna. Faktum är att många beräknar 64-bitarsprodukten och ignorerar sedan den övre halvan.
En lag-1 multiplicera-med-bär-generator tillåter oss att göra perioden till nästan 2 63 genom att använda nästan samma datoroperationer, förutom att den övre halvan av 64-bitarsprodukten inte ignoreras efter att produkten har beräknats. Istället beräknas en 64-bitars summa och den övre halvan används som ett nytt bärvärde c snarare än den fasta additiva konstanten för standardkongruentialsekvensen: Beräkna ax + c i 64 bitar, använd sedan den övre halvan som den nya c , och nedre halvan som det nya x .
Val av multiplikator
Med multiplikator en specificerad, omvandlas varje par av ingångsvärden x , c till ett nytt par,
Om x och c inte båda är noll, kommer perioden för den resulterande multiplicera-med-bär-sekvensen att vara i storleksordningen b = 2 32 i den multiplikativa gruppen av rester modulo ab r − 1 , det vill säga den minsta n så att b n ≡ 1 (mod ab r − 1).
Om p = ab r − 1 är primtal, så garanterar Fermats lilla teorem att ordningen för vilket element som helst måste dela p − 1 = ab r − 2, så ett sätt att säkerställa en stor ordning är att välja a så att p är en " säkert primtal ", det vill säga både p och ( p − 1)/2 = ab r /2 − 1 är primtal. I ett sådant fall, för b = 2 32 och r = 1, kommer perioden att vara ab r /2 − 1, närmar sig 2 63 , vilket i praktiken kan vara en acceptabelt stor delmängd av antalet möjliga 32-bitarspar ( x , c ).
Närmare bestämt, i ett sådant fall delar ordningen för alla element p − 1, och det finns bara fyra möjliga divisorer: 1, 2, ab r /2 − 1 eller ab r − 2. De två första gäller endast för element 1 och −1, och kvadratiska ömsesidighetsargument visar att det fjärde alternativet inte kan tillämpas på b , så bara det tredje alternativet finns kvar.
Följande är några maximala värden för a för datorapplikationer som uppfyller ovanstående säkra primära villkor, för lag-1-generatorer:
Bitar i en | b | Maximalt a så att ab −1 är ett säkert primtal | Period |
---|---|---|---|
15 | 2 16 | 2 15 −50 = 32,718 | 1,072,103,423 |
16 | 2 16 | 2 16 −352 = 65,184 | 2,135,949,311 |
31 | 2 32 | 2 31 −563 = 2 147 483 085 | 4,611,684,809,394,094,079 |
32 | 2 32 | 2 32 −178 = 4,294,967,118 | 9,223,371,654,602,686,463 |
64 | 2 64 | 2 64 −742 = 18,446,744,073,709,550,874 | 2 63 (2 64 −742)−1 ≈ 1,701 × 10 38 |
128 | 2 128 | 2 128 -10 408 | 2 127 (2 128 −10 408)−1 ≈ 5,790 × 10 76 |
256 | 2 256 | 2 256 −9166 | 2 255 (2 256 −9166)−1 ≈ 6,704 × 10 153 |
512 | 2 512 | 2 512 -150 736 | 2 511 (2 512 −150 736)−1 ≈ 8,988 × 10 307 |
Medan ett säkert primtal säkerställer att nästan alla element i gruppen har en stor order, är perioden för generatorn specifikt storleksordningen b . För små moduler kan mer beräkningsmässigt dyra metoder användas för att hitta multiplikatorer a där perioden är ab /2 − 1. Följande är återigen maxvärden för a av olika storlekar.
Bitar i en | b r |
Maximalt a så att b har ordningen ab r /2−1 |
Period |
---|---|---|---|
8 | 2 8 | 2 8 −7 = 249 | 31,871 |
8 | (2 8 ) 2 = 2 16 | 2 8 −32 = 224 | 7,340,031 |
15 | 2 16 | 2 15 −29 = 32,739 | 1 072 791 551 |
16 | 2 16 | 2 16 −22 = 65 514 | 2,146,762,751 |
8 | (2 8 ) 4 = 2 32 | 2 8 −64 = 192 | 412,316,860,415 |
15 | (2 16 ) 2 = 2 32 | 2 15 −26 = 32,742 | 70,312,909,602,815 |
16 | (2 16 ) 2 = 2 32 | 2 16 −2 = 65 534 | 140,733,193,388,031 |
31 | 2 32 | 2 31 -68 = 2 147 483 580 | 4,611,685,872,398,499,839 |
32 | 2 32 | 2 32 −76 = 4,294,967,220 | 9,223,371,873,646,018,559 |
8 | (2 8 ) 8 = 2 64 | 2 8 −41 = 215 | 2 63 (2 8 −41)−1 ≈ 1,983 × 10 21 |
15 | (2 16 ) 4 = 2 64 | 2 15 −50 = 32,718 | 2 63 (2 15 −50)−1 ≈ 3,018 × 10 23 |
16 | (2 16 ) 4 = 2 64 | 2 16 −56 = 65 480 | 2 63 (2 16 −56)−1 ≈ 6,039 × 10 23 |
31 | (2 32 ) 2 = 2 64 | 2 31 -38 = 2 147 483 610 | 2 63 (2 31 −38)−1 ≈ 1,981 × 10 28 |
32 | (2 32 ) 2 = 2 64 | 2 32 −43 = 4,294,967,253 | 2 63 (2 32 −43)−1 ≈ 3,961 × 10 28 |
63 | 2 64 | 2 63 −140 = 9 223 372 036 854 775 668 | 2 63 (2 63 −140)−1 ≈ 8,507 × 10 37 |
64 | 2 64 | 2 64 −116 = 18 446 744 073 709 551 500 | 2 63 (2 64 −116)−1 ≈ 1,701 × 10 38 |
MWC-generatorer som upprepade decimaler
Utsignalen från en multiplicera-med-bär-generator är ekvivalent med radix - b expansionen av en bråkdel med nämnaren p = ab r − 1. Här är ett exempel för det enkla fallet med b = 10 och r = 1, så resultatet är en återkommande decimal .
Börjar med , MWC-sekvensen
producerar denna sekvens av tillstånd:
- 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, ...
med period 22. Betrakta bara sekvensen av x i :
- 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,...
Observera att om dessa upprepade segment av x -värden sätts i omvänd ordning :
vi får expansionen j /( ab −1) med a =7, b =10, j=10 :
Detta är sant i allmänhet: Sekvensen av x s som produceras av en fördröjnings MWC -generator:
när den sätts i omvänd ordning, kommer det att vara radix- b expansionen av en bråkdel j /( ab r − 1) för ungefär 0 < j < ab r .
Ekvivalens till linjär kongruentialgenerator
Om vi fortsätter med exemplet ovan, om vi börjar med och genererar den vanliga kongruentialsekvensen
- ,
vi får period 22-sekvensen
- 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,...
och den sekvensen, reducerad mod 10, är
- 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,...
samma sekvens av x som resulterar från MWC-sekvensen.
Detta är sant i allmänhet (men tydligen bara för lag-1 MWC-sekvenser [ citat behövs] ) :
Givet initialvärden , sekvensen som härrör från fördröjningen- 1 MWC-sekvens
är exakt Lehmer slumptalsgeneratorns utgångssekvens y n = ay n − 1 mod ( ab − 1), reducerad modulo b .
0 Att välja ett annat initialvärde y roterar bara cykeln av x .
Kompletterande-multiplicera-med-bär-generatorer
Att fastställa perioden för en lag- r MWC-generator innebär vanligtvis att man väljer multiplikator a så att p = ab r − 1 är primtal. Sedan måste p − 1 faktoriseras för att hitta ordningen för b mod p . Om p är ett säkert primtal är detta enkelt, och ordningen för b blir antingen p − 1 eller ( p − 1)/2. I andra fall p − 1 vara svårt att faktorisera.
Algoritmen tillåter emellertid också en negativ multiplikator. Detta leder till en liten modifiering av MWC-proceduren och ger en modul p = | − ab r − 1 | = ab r + 1. Detta gör p − 1 = ab r lätt att faktorisera, vilket gör det praktiskt att fastställa perioden för mycket stora generatorer.
Den modifierade proceduren kallas komplementär-multiplicera-med-bära (CMWC), och inställningen är densamma som för lag- r MWC: multiplikator a , bas b och r + 1 frön,
- 0 x , x 1 , x 2 −1 , ..., xr och c r −1 .
Modifieringen är till generering av ett nytt par ( x , c ). Om du arrangerar om beräkningen för att undvika negativa tal, kompletteras det nya x- värdet genom att subtrahera det från b − 1:
Den resulterande sekvensen av x : n som produceras av CMWC RNG kommer att ha period i storleksordningen b i den multiplikativa gruppen av rester modulo ab r +1, och de utgående x : en, i omvänd ordning, kommer att bilda basen b expansionen av j /( ab r +1) för några 0 < j < ab r .
Användning av lag- r CMWC gör det mycket lättare att hitta perioder för r så stora som 512, 1024, 2048, etc. (Att göra r till en potens av 2 gör det något enklare att komma åt element i arrayen som innehåller den r senaste x s .)
En annan fördel med denna modifierade procedur är att perioden är en multipel av b , så utmatningen är exakt likafördelad mod b . (Den ordinarie MWC producerar under hela sin period varje möjlig utdata lika många gånger förutom att noll produceras en gång mindre, en bias som är försumbar om perioden är tillräckligt lång.)
En nackdel med CMWC-konstruktionen är att, med en tvåkraftsbas, är den maximalt uppnåbara perioden mindre än för en MWC-generator av liknande storlek; du förlorar flera bitar. Således är en MWC-generator vanligtvis att föredra för små fördröjningar. Detta kan åtgärdas genom att använda b = 2 k −1, eller välja en fördröjning ett ord längre för att kompensera.
Några exempel: Med b = 2 32 och a = 109111 eller 108798 eller 108517, perioden för lag-1024 CMWC
kommer att vara en ·2 32762 = ab 1024 /64, cirka 10 9867 .
Med b = 2 32 och a = 3636507990 är p = ab 1359 − 1 ett säkert primtal, så MWC-sekvensen baserad på det a har perioden 3636507990·2 43487 ≈ 10 13101 .
Med b = 2 32 kan en CMWC RNG med nära rekordperiod baseras på primtal p = 15455296 b 42658 + 1. Ordningen på b för det primtal är 241489·2 1365056 ≈ 10 410928 .
Mer allmänna moduler
MWC-modulen för ab r −1 är vald för att göra beräkningen särskilt enkel, men för med sig vissa nackdelar, särskilt att perioden är högst halva modulen. Det finns flera sätt att generalisera detta, till priset av fler multiplikationer per iteration.
Först är det möjligt att lägga till ytterligare termer till produkten, vilket ger en modul av formen a r b r + a s b s −1. Detta kräver beräkning av c n b + x n = a r x n − r + a s x n − s . (Bären är begränsad till ett ord om a r + a s ≤ b .)
0000 Detta löser dock inte periodproblemet, som beror på modulens låga bitar. Lyckligtvis tillåter Montgomery-reduktionsalgoritmen andra moduler, så länge de är relativt prime till basen b , och detta kan tillämpas för att tillåta en modul av formen a r b r − a , för ett brett spektrum av värden a . Goresky och Klapper utvecklade teorin om dessa generaliserade multiplicera-med-bär-generatorer, och bevisade särskilt att om man väljer ett negativt a och a r – a < b är bärvärdet alltid mindre än b , vilket gör implementeringen effektiv. Den mer allmänna formen av modulen förbättrar också kvaliteten på generatorn, även om man inte alltid kan få full period.
För att implementera en Goresky-Klapper-generator förberäknar man a -1
0 (mod b ), och ändrar iterationen enligt följande:
I det vanliga fallet att b = 2 k måste a vara udda för att inversen ska existera . 0
Genomförande
Följande är en implementering av CMWC-algoritmen i programmeringsspråket C. Dessutom ingår i programmet ett exempel på initieringsfunktion. I denna implementering är basen 2 32 −1 och eftersläpning r =4096. Perioden för den resulterande generatorn är cirka .
0
// C99 Komplementär multiplicera med bärgenerator #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> // Hur många bitar i rand()? // https://stackoverflow.com/a/27593398 #define LOG_1(n) (((n) >= 2) ? 1 : 0) #define LOG_2(n) (((n) >= 1<<2 ) ? (2 + LOG_1((n)>>2)) : LOG_1(n)) #define LOG_4(n) (((n) >= 1<<4) ? (4 + LOG_2((n)>> 4)) : LOG_2(n)) #define LOG_8(n) (((n) >= 1<<8) ? (8 + LOG_4((n)>>8)) : LOG_4(n)) #define LOG (n) (((n) >= 1<<16) ? (16 + LOG_8((n)>>16)) : LOG_8(n)) #define BITS_TO_REPRESENT(n) (LOG(n) + !! ( (n) & ((n) - 1))) #if ((RAND_MAX | (RAND_MAX >> 1)) != RAND_MAX) #error "förväntade ett RAND_MAX som är 2^n - 1!" #endif #define RAND_BITS BITS_TO_REPRESENT(RAND_MAX) // CMWC - arbetsdelar #define CMWC_CYCLE 4096 // som Marsaglia rekommenderar #define CMWC_C_MAX 809430660 // som Marsaglia rekommenderar struct Q uint32_W_Ct ; uint32_t c ; // måste begränsas med CMWC_C_MAX osignerad i ; }; // Samla 32 bitar av rand(). Du uppmuntras att använda en bättre källa istället. uint32_t rand32 ( void ) { uint32_t resultat = rand (); för ( int bits = RAND_BITS ; bitar < 32 ; bitar += RAND_BITS ) resultat = resultat << RAND_BITS | rand (); returnera resultat ; } // Initiera tillståndet med seed void initCMWC ( struct cmwc_state * state , unsigned int seed ) { srand ( seed ); för ( int i = ; i < CMWC_CYCLE ; i ++ ) tillstånd -> Q [ i ] = rand32 (); gör state -> c = rand32 (); while ( tillstånd -> c >= CMWC_C_MAX ); state -> i = CMWC_CYCLE - 1 ; } // CMWC-motor uint32_t randCMWC ( struct cmwc_state * state ) //EDITED parameter * state saknades { uint64_t const a = 18782 ; // som Marsaglia rekommenderar uint32_t const m = 0xfffffffe ; // som Marsaglia rekommenderar uint64_t t ; uint32_t x ; tillstånd -> i = ( tillstånd -> i + 1 ) & ( CMWC_CYCLE - 1 ); t = a * tillstånd -> Q [ tillstånd -> i ] + tillstånd -> c ; /* Låt c = t / 0xffffffff, x = t mod 0xffffffff */ state -> c = t >> 32 ; x = t + tillstånd -> c ; if ( x < tillstånd -> c ) { x ++ ; tillstånd -> c ++ ; } returnera tillstånd -> Q [ tillstånd -> i ] = m - x ; } int main () { struct cmwc_state cmwc ; unsigned int seed = tid ( NULL ); initCMWC ( & cmwc , frö ); printf ( "Slumpmässig CMWC: %u \n " , randCMWC ( & cmwc )); }
Följande är implementeringar av småtillstånd MWC-generatorer med 64-bitars utgång med 128-bitars multiplikationer.
// C99 + __uint128_t MWC, 128 bitar av tillstånd, period ca. 2^127 /* Tillståndet får varken vara noll, eller x = 2^64 - 1, c = MWC_A1 - 1. Villkoret 0 < c < MWC_A1 - 1 är alltså tillräckligt. */ uint64_t x , c = 1 ; #define MWC_A1 0xff3a275c007b8ee6 uint64_t inline next () { const __uint128_t t = MWC_A1 * ( __uint128_t ) x + c ; c = t >> 64 ; returnera x = t ; }
// C99 + __uint128_t MWC, 256 bitar av tillstånd, period ca. 2^255 /* Tillståndet får varken vara noll, eller x = y = z = 2^64 - 1, c = MWC_A3 - 1. Villkoret 0 < c < MWC_A3 - 1 är alltså tillräckligt. */ uint64_t x , y , z , c = 1 ; #define MWC_A3 0xff377e26f82da74a uint64_t inline next () { const __uint128_t t = MWC_A3 * ( __uint128_t ) x + c ; x = y ; y = z ; c = t >> 64 ; returnera z = t ; }
Följande är implementeringar av småtillstånd Goresky-Klappers generaliserade MWC-generatorer med 64-bitars utdata med 128-bitars multiplikationer.
0
// C99 + __uint128_t Goresky-Klapper GMWC, 128 bitar av tillstånd, period ca. 2^127 /* Tillståndet får varken vara noll eller x = 2^64 - 1, c = GMWC_A1 + GMWC_MINUS_A0. Villkoret 0 < c < GMWC_A1 + GMWC_MINUS_A0 är således tillräckligt. */ uint64_t x = , c = 1 ; #define GMWC_MINUSA0 0x7d084a4d80885f #define GMWC_A0INV 0x9b1eea3792a42c61 #define GMWC_A1 0xff002aae7d81a646 uint64_t inline _GM_1 ( A __t inline _ __t ) __uint128_t ) x + c ; x = GMWC_A0INV * ( uint64_t ) t ; c = ( t + GMWC_MINUSA0 * ( __uint128_t ) x ) >> 64 ; returnera x ; }
// C99 + __uint128_t Goresky-Klapper GMWC, 256 bitar av tillstånd, period ca. 2^255 /* Tillståndet får varken vara noll, eller x = y = z = 2^64 - 1, c = GMWC_A3 + GMWC_MINUS_A0. Villkoret 0 < c < GMWC_A3 + GMWC_MINUS_A0 är således tillräckligt. */ uint64_t x , y , z , c = 1 ; /* Tillståndet kan seedas med vilken uppsättning värden som helst, inte alla nollor. */ #define GMWC_MINUSA0 0x54c3da46afb70f #define GMWC_A0INV 0xbbf397e9a69da811 #define GMWC_A3 0xff963a86efd088a2 uint64_t inline nästa ( ) _A_GM int128_t ) x + c ; x = y ; y = z ; z = GMWC_A0INV * ( uint64_t ) t ; c = ( t + GMWC_MINUSA0 * ( __uint128_t ) z ) >> 64 ; returnera z ; }
Användande
På grund av enkelheten och hastigheten är CMWC känt för att användas i spelutveckling, särskilt i moderna roguelike -spel. Det är informellt känt som Mother of All PRNGs, ett namn som ursprungligen myntades av Marsaglia själv. I libtcod ersatte CMWC4096 MT19937 som standard PRNG.
Se även
- Marsaglia, George (4 juli 2003). "Xorshift RNGs" . Journal of Statistical Software . 8 (14): 1–6. doi : 10.18637/jss.v008.i14 .
- Marsaglia, George (oktober 2005). "Om slumpmässigheten hos Pi och andra decimalexpansioner" . Interstat . CiteSeerX 10.1.1.694.4783 .
- Press, William H. ; Teukolsky, Saul A. ; Vetterling, William T.; Flannery, Brian P. (2007). "Avsnitt 7.1.2.B Multiplicera med bär (MWC)" . Numeriska recept: The Art of Scientific Computing (3:e upplagan). New York: Cambridge University Press. ISBN 978-0-521-88068-8 .