Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Nombres al´ eatoires
Vincent Nozick
Vincent Nozick Nombres al´eatoires 1 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Pour quoi faire?
• Simulation physique.
• Etude de probabilit´ ´ e.
• Jeux.
• Algorithmes stochastiques* : - Quick sort.
- Lancer de rayons.
• Autres ...
* comportement d´ etermin´ e par une entr´ ee + un nombre al´ eatoire.
Vincent Nozick Nombres al´eatoires 2 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Qualit´ es requises
• Vitesse.
• Simplicit´ e.
• Robustesse (ne se coince pas).
• Ne repr´ esente pas une suite logique apparente.
• Reproductible.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Qualit´ es requises
“Ne pr´ esente pas de suite logique apparente” :
L’important ici n’est pas le nombre g´ en´ er´ e mais la suite de nombres g´ en´ er´ ee.
Pour un bon g´ en´ erateur, on esp` ere que la probabilit´ e pour un nombre
y de succ´ eder ` a un nombre x est la mˆ eme pour tout les y (sur un
intervalle donn´ e).
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Familles de g´ en´ erateurs
M´ ecanismes physiques :
• Pile ou face.
• Loto.
• L’heure.
• Le temps ´ ecoul´ e entre 2 “bips” d’un compteur Geiger.
• ...
Vincent Nozick Nombres al´eatoires 5 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Familles de g´ en´ erateurs
M´ ecanismes physiques :
• Pile ou face.
• Loto.
• L’heure.
• Le temps ´ ecoul´ e entre 2 “bips” d’un compteur Geiger.
• ...
coˆ uteux, ne peut pas reproduire la mˆ eme suite.
Vincent Nozick Nombres al´eatoires 5 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Familles de g´ en´ erateurs
G´ en´ erateurs pseudo-al´ eatoires :
• Fonctions d´ eterministes : - soit x
iun ´ etat x
i+1= f (x
i) - x
0= graine (seed)
• Une p´ eriode p (x i = x i+p ).
• Parfois : une phase de d´ emarrage.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
G´ en´ erateurs ` a congruence lin´ eaire
• Linear Congruencial Generator → LCG.
• Tr` es simple.
• Tr` es utilis´ e.
• Un des mieux connu.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
G´ en´ erateurs ` a congruence lin´ eaire
D´ efinition :
x n+1 = (a.x n + b) mod m s’´ ecrit LCG(m,a,b,x 0 ) Exemple :
LCG(5,2,1,0) → x n+1 = (2x n + 1) mod 5 0, 1, 3, 2, 0, ...
Vincent Nozick Nombres al´eatoires 8 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
G´ en´ erateurs ` a congruence lin´ eaire
Propri´ et´ e :
• Une graine x 0 .
• Une p´ eriode p < m la plus grande possible.
• Une phase de d´ emarrage la plus petite possible.
• Un LCG est dit : - mixte si b > 0 - multiplicatif si b = 0
Vincent Nozick Nombres al´eatoires 9 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
G´ en´ erateurs ` a congruence lin´ eaire
P´ eriode :
Si p = m, alors on peut choisir arbitrairement x 0 car toutes les valeurs enti` eres entre 0 et m − 1 sont prises exactement une fois par cycle.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
G´ en´ erateurs ` a congruence lin´ eaire
Th´ eor` eme :
Un LCG est de p´ eriode maximal (p = m) ssi :
• m et b sont premiers entre eux.
• tout nombre premier qui divise m divise aussi a − 1.
• si 4 divise m, alors 4 divise a − 1.
Attention :
une longue p´ eriode est n´ ecessaire mais pas suffisante pour consid´ erer
qu’un g´ en´ erateur est bon.
G´ en´ erateurs ` a congruence lin´ eaire
P´ eriode de d´ emarrage : Exemple :
LCG(24,2,1,0) x n+1 = (2x n + 1) mod 24
d´ emarrage
z }| { 0, 1, 3, 7, 15,
| {z }
p´ eriode
7, ...
Vincent Nozick Nombres al´eatoires 12 / 39
LCG multiplicatifs
s’´ ecrit MLCG(m,a,x 0 ) x n+1 = ax n mod m
Ils sont tr` es utilis´ es car ils pr´ esentent l’avantage d’´ economiser une addition par rapport aux LCG mixtes.
Vincent Nozick Nombres al´eatoires 13 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
LCG multiplicatifs
Th´ eor` eme :
Un MLCG est de p´ eriode maximal (p = m) ssi :
• m est premier.
• m − 1 est le plus petit entier k tel que (a k − 1) mod m = 0.
Exemple :
x n+1 = (16807x n ) mod (2 31 − 1) Apple CarbonLib x n+1 = (214013x n + 2531011) mod 2 32 Microsoft Visual C x n+1 = (134775813x n + 1) mod 2 32 Delphi, virtual Pascal x n+1 = (1103515245x n + 12345) mod 2 32 glibc (gcc)
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
LCG
Probl` eme :
“Never use a generator principally based on a linear congruential generator (LCG) or a multiplicative linear congruential generator (MLCG)”.
Numerical Recipes, 3rd edition
“Never use the built-in generators in the C and C++ languages, especially rand and srand. These have no standard implementation and are often badly flawed”.
Numerical Recipes, 3rd edition
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Xorshift
• Compos´ e de 3 XORs et 3 shifts → tr` es rapide et tr` es l´ eger.
• P´ eriode maximale -1.
• Marsaglia, publi´ e en 2003.
Vincent Nozick Nombres al´eatoires 16 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Xorshift
XOR ?
x y x ∧ y
0 0 0
0 1 1
1 0 1
1 1 0
unsigned int x,y,z;
...
z ← x ∧ y;
→ on applique l’op´ erateur XOR ` a chaque bit de x, y et z.
Vincent Nozick Nombres al´eatoires 17 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Xorshift
Initialisation : unsigned int x 6= 0 Update : x ← x ∧ (x >> a 1 )
x ← x ∧ (x << a 2 ) x ← x ∧ (x >> a 3 )
• p´ eriode : 2 64 − 1 pour les architectures 64 bits
• rapide (le plus rapide va seulement 2,5 fois plus vite)
• pour obtenir un nombre entre 1 et n : rand()%(n-1)
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Xorshift
Exemple :
x = 0001 0100 = (20) 10 x∧ = x >> 3
x >> 3 = 0000 0010
0001 0100 ∧ 0000 0010 = 0001 0110 x∧ = x << 2
x << 2 = 0101 1000
0001 0110 ∧ 0101 1000 = 0100 1110 x∧ = x >> 4
x >> 4 = 0000 0100
0100 1110 ∧ 0000 0100 = 0100 1010 = (74)
10→ suivant(20) = 74
Xorshift
Extension avec un LCG
u n s i g n e d l o n g r a n d o m 6 4 ( c o n s t u n s i g n e d l o n g u , v , w ){
u = u * 2 8 6 2 9 3 3 5 5 5 7 7 7 9 4 1 7 5 7 LL + 7 0 4 6 0 2 9 2 5 4 3 8 6 3 5 3 0 8 7 LL ; v ^= v > > 17;
v ^= v < < 31;
v ^= v > > 8;
w = 4 2 9 4 9 5 7 6 6 5 U *( w & 0 x f f f f f f f f ) + ( w > > 3 2 ) ; u n s i g n e d l o n g x = u ^ ( u < < 2 1 ) ;
x ^= x > > 35;
x ^= x < < 4;
r e t u r n ( x + v ) ^ w ; }
Recommand´ e par Numerical Recipes, 3rd edition.
Vincent Nozick Nombres al´eatoires 20 / 39
Mersenne Twister
• Makoto Matsumoto et Takuji Nishimura, 1998.
(actualis´ e r´ ecemment)
• Bas´ e sur un xorshift.
• Tr` es utilis´ e.
• Tr` es rapide.
• P´ eriode = 2 19937 − 1 (plus de 10 6001 ).
• On trouve une impl´ ementation tr` es facile d’emploi sur le net.
Vincent Nozick Nombres al´eatoires 21 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Tester un g´ en´ erateur
Pour savoir si un g´ en´ erateur est bon, on peut :
• Regarder sa p´ eriode : - pas trop petite.
- trop grande (10
100), ¸ ca ne sert ` a rien.
• V´ erifier s’il ne satisfait pas une distribution particuli` ere.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Test χ 2
f : [[0, m]] → [[0, m]]
f(x) = suivant(x)
On divise le carr´ e en k carr´ es ´ egaux et on compte le nombre de points dans chaque carr´ e.
→ la r´ epartition doit ˆ etre homog` ene.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Test spectral
f : [[0, m]] → [[0, m]]
f (x) = suivant(x)
D´ etermine ` a quelle densit´ e un k−tuple correspond ` a un hyperplan
`
a k dimension.
Vincent Nozick Nombres al´eatoires 24 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Test spectral
Pour les LCG : 2D
f : [[0, m]] → [[0, m]]
f(x) = suivant(x)
→ On voit des droites
Vincent Nozick Nombres al´eatoires 25 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Test spectral
Pour les LCG : 2D
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Test spectral
Pour les LCG : 3D
→ On voit des plans
Test Diehard
• Birthday spacings : s´ electionne des points al´ eatoires sur un grand in- tervalle. L’espace entre les points doit satisfaire des propri´ et´ es statis- tiques.
• Permutations : g´ en` ere 5 nombres al´ eatoires cons´ ecutifs. Leur or- donnancement (120 possibilit´ es) doit ˆ etre ´ equiprobable.
• Rang de matrice : g´ en` ere al´ eatoirement des matrices. Le rang des matrices doit satisfaire des propri´ et´ es statistiques.
• Test du singe : consid` ere une s´ equence al´ eatoire comme des “mots”
et compte les recouvrements de mots.
Vincent Nozick Nombres al´eatoires 28 / 39
Test Diehard
• Count the 1s : converti une s´ equence al´ eatoire en “mots” et compte les occurrences du mot “words”.
• Place de parking : g´ en` ere al´ eatoirement des cercles unitaires dans un carr´ e de 100×100. Si un nouveau cercle en recouvre un autre, recommencer. Apr` es 12 000 essais, les tentatives r´ eussies doivent satisfaire une distribution normale.
• Distance min : g´ en` ere 8000 points al´ eatoires dans un carr´ e 10.000
2. La distance min par paires doit satisfaire des propri´ et´ es statistiques.
Vincent Nozick Nombres al´eatoires 29 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Distribution uniforme :
R´ esultat par d´ efaut avec les m´ ethodes pr´ ec´ edentes.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Distribution normale : (gaussienne)
p(x) = 1
σ √
2π e −
12(
x−µσ)
2→ g´ en´ er´ ee ` a partir d’une distribution uniforme
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Conversion : distribution uniforme → normale Algorithm 1: Forme cart´ esienne
input: moyenne µ et variance σ repeat
x = random() x ∈ [−1, 1]
y = random() y ∈ [−1, 1]
s = x 2 + y 2 until s ≤ 1 u = µ + xσ
r −2 ln s
s et v = µ + yσ
r −2 ln s s
Vincent Nozick Nombres al´eatoires 32 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Conversion : distribution uniforme → normale Algorithm 2: Forme polaire
input: moyenne µ et variance σ
x = random() x ∈]0, 1]
y = random() y ∈]0, 1]
r = σ √
−2 ln x φ = 2πy
u = µ + r cos(φ) et v = µ + r sin(φ)
Vincent Nozick Nombres al´eatoires 33 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Remarque : Distribution uniforme → normale
La forme cart´ esienne n’utilise pas de fonctions trigonom´ etriques (as- sez coˆ uteuses) mais rejette environ 21, 46% des candidats issus de la distribution uniforme.
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Distributions
Distribution de poisson :
p(k) = e −λ λ k
k! λ ≥ 0
Distributions
Conversion : distribution uniforme → poisson Algorithm 3: Loi de poisson
input: λ s = λ r = −1
while s ≥ 0 do r = r + 1
x = random() x ∈]0, 1]
s = s + log(x) end
return r
Vincent Nozick Nombres al´eatoires 36 / 39
En C++ (11) : les g´ en´ erateurs
# i n c l u d e < random >
std :: d e f a u l t _ r a n d o m _ e n g i n e m y G e n e r a t o r ();
int m y V a l u e = m y G e n e r a t o r ();
• std::default_random_engine selection de la stl, usage basique
• std::mt19937_64 Mersenne Twister 64 bits
• std::ranlux24_base subtract-with-carry sur 24-bit
• ...
Vincent Nozick Nombres al´eatoires 37 / 39
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++
Les distributions
# i n c l u d e < random >
std :: m t 1 9 9 3 7 _ 6 4 m y G e n e r a t o r ();
std :: u n i f o r m _ r e a l _ d i s t r i b u t i o n < float > m y D i s t r i b u t i o n (1 ,6);
f l o a t m y V a l u e = m y D i s t r i b u t i o n ( m y G e n e r a t o r );
• std::uniform_int_distribution<int>(min,max) distribution uniforme enti` ere entre min et max
• std::uniform_real_distribution<float>(min,max) distribution uniforme flottante entre min et max
• std::normal_distribution<double>(mean,stdev) distribution normale (gaussienne)
• std::poisson_distribution<int>
distribution de Poisson
• ...
Introduction LCG Xorshift Mersenne Twister Tester un g´en´erateur Les distributions En C++