Sequential generation of random numbers on platforms with boost :: random
We have been using boost :: random for some time in our projects. The recently failed test unit interested me in one of its properties: the sequence of numbers generated in different versions of Boost may differ depending on the distribution used.
This behavior does not seem consistent across all distributions. In most cases, uniform distributions using RNGs with the same seed give the same results. Other distributions, such as normal
, lognormal
, binomial
and discrete
can show these differences.
I put together a simple C ++ program that shows the problem:
#include <iostream>
#include <boost/random.hpp>
#include <stdint.h>
void uniform() {
uint32_t seed = 42;
boost::mt19937 rng(seed);
boost::random::uniform_real_distribution<double> distro(0., 1.);
std::cout << "uniform" << std::endl;
for (int i=0; i<10; ++i) {
std::cout << distro(rng) << std::endl;
}
}
void normal() {
uint32_t seed = 42;
boost::mt19937 rng(seed);
boost::random::normal_distribution<double> distro(0., 1.);
std::cout << "normal" << std::endl;
for (int i=0; i<10; ++i) {
std::cout << distro(rng) << std::endl;
}
}
void discrete() {
uint32_t seed = 42;
boost::mt19937 rng(seed);
std::vector<double> P;
P.push_back(0.3);
P.push_back(0.4);
P.push_back(0.3);
boost::random::discrete_distribution<uint64_t> distro(P.begin(), P.end());
std::cout << "discrete" << std::endl;
for (int i=0; i<10; ++i) {
std::cout << distro(rng) << std::endl;
}
}
int main() {
uniform();
normal();
discrete();
}
This simple program will show different number sequences for Boost 1.56 (runs on OSX):
uniform
0.37454
0.796543
0.950714
0.183435
0.731994
0.779691
0.598658
0.59685
0.156019
0.445833
normal
-0.638714
-0.836808
-0.400566
-0.869232
-0.972045
-0.758932
-1.30435
1.22996
0.249399
0.286848
discrete
1
2
2
1
0
0
0
2
1
2
Or with Boost 1.50 (works on Ubuntu 12.10):
uniform
0.37454
0.796543
0.950714
0.183435
0.731994
0.779691
0.598658
0.59685
0.156019
0.445833
normal
-1.25821
1.2655
0.606347
-0.19401
-0.196366
-1.72826
-1.09713
-0.783069
0.604964
0.90255
discrete
2
1
2
1
1
0
1
1
0
1
Note that even distribution works as expected: i.e. the same seed generates a consistent sequence of numbers in both versions. Normal and discrete distributions do not behave the same.
Is there a way to "fix" this? That is, they have different platforms, generate exactly the same sequence regardless of the boost version?
source to share
it looks like boost :: random does not guarantee that you will get the same sequence of numbers for certain seeds with different versions.
eg. in version 1.56 they changed the algorithm for generating normal distributed random numbers from Box-Muller method to Ziggurat method:
https://github.com/boostorg/random/commit/f0ec97ba36c05ef00f2d29dcf66094e3f4abdcde
This method is faster, but it also creates different sequences of numbers.
Similar changes were probably made for other distributions as well. Equal distribution still produces the same result as the output of the base rng, which is mersenne twister 19937 by default.
source to share