How to Generate the Same Random Number Sequence Over Multiple Types of Compilers and Kernels with <Random>

How to generate the same random number sequence over multiple types of compilers and kernels with random?

To remove a variable from the problem, try looking at the outputs from your random number engine, rather than feeding it into a distribution.

I just looked at a few documentation pages for uniform_int_distribution, and it does not give any statement about how the outputs from the uniform random number generator are used. I'm not sure what the standard says.

I predict that you are getting the same outputs from your mersenne twister, but you're feeding those outputs into two inequivalent implementations of uniform_int_distribution.

If this is true, then to get the same random number sequence, you're going to have to use an external implementation of the distribution functions to ensure that you get the same results on all systems.

C++ how to produce random sequence completely determined by seed independent of compiler or operating system

The difference lies in the fact that uniform_int_distribution is implemented differently in different implementations of the C++ standard library. Note that it's not the "compiler" or the "operating system" that decides which algorithm is used. In fact, C++ distribution classes, such as uniform_int_distribution, have no standard implementation. See also this question.

On the other hand, random engines such as mt19937 do have a guaranteed implementation; they will return the same pseudorandom numbers for the same seed in all compliant C++ library implementations. (The exception is default_random_engine.) You can see this for yourself by replacing dist(mt) with mt() in the code you give in your question. See also this question.

Why is the sequence produced by this random number generator always the same?

in general a pseudo-random generator takes a seed.

if you never change the seed, you get always the same pseudo-random output/sequence.

edit: I insist on the word pseudo-random (somtimes pseudo-chaos) instead of the abusivily used random

edit2: there should be the c++11 solution to you problem in this other question (look at @R. Martinho Fernandes 's answer)

If we seed c++11 mt19937 as the same on different machines, will we get the same sequence of random numbers

The generator will generate the same values.

The distributions may not, at least with different compilers or library versions. The standard did not specify their behaviour to that level of detail. If you want stability between compilers and library versions, you have to roll your own distribution.

Barring library/compiler changes, that will return the same values in the same sequence. But if you care write your own distribution.

...

All PRNGs have patterns and periods. mt19937 is named after its period of 2^19937-1, which is unlikely to be a problem. But other patterns can develop. MT PRNGs are robust against many statistical tests, but they are not crytographically secure PRNGs.

So it being a problem if you run for months will depend on specific details of what you'd find to be a problem. However, mt19937 is going to be a better PRNG than anything you are likely to write yourself. But assume attackers can predict its future behaviour from past evidence.

How to generate a random int in C?

Note: Don't use rand() for security. If you need a cryptographically secure number, see this answer instead.

#include <time.h>
#include <stdlib.h>

srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.

On Linux, you might prefer to use random and srandom.

C++11 random number distributions are not consistent across platforms -- what alternatives are there?

I have created my own C++11 distributions:

template <typename T>
class UniformRealDistribution
{
public:
typedef T result_type;

public:
UniformRealDistribution(T _a = 0.0, T _b = 1.0)
:m_a(_a),
m_b(_b)
{}

void reset() {}

template <class Generator>
T operator()(Generator &_g)
{
double dScale = (m_b - m_a) / ((T)(_g.max() - _g.min()) + (T)1);
return (_g() - _g.min()) * dScale + m_a;
}

T a() const {return m_a;}
T b() const {return m_b;}

protected:
T m_a;
T m_b;
};

template <typename T>
class NormalDistribution
{
public:
typedef T result_type;

public:
NormalDistribution(T _mean = 0.0, T _stddev = 1.0)
:m_mean(_mean),
m_stddev(_stddev)
{}

void reset()
{
m_distU1.reset();
}

template <class Generator>
T operator()(Generator &_g)
{
// Use Box-Muller algorithm
const double pi = 3.14159265358979323846264338327950288419716939937511;
double u1 = m_distU1(_g);
double u2 = m_distU1(_g);
double r = sqrt(-2.0 * log(u1));
return m_mean + m_stddev * r * sin(2.0 * pi * u2);
}

T mean() const {return m_mean;}
T stddev() const {return m_stddev;}

protected:
T m_mean;
T m_stddev;
UniformRealDistribution<T> m_distU1;
};

The uniform distribution seems to deliver good results and the normal distribution delivers very good results:

100000 values -> 68.159% within 1 sigma; 95.437% within 2 sigma; 99.747% within 3 sigma

The normal distribution uses the Box-Muller method, which according to what I have read so far, is not the fastest method, but it runs more that fast enough for my application.

Both the uniform and normal distributions should work with any C++11 engine (tested with std::mt19937) and provides the same sequence on all platforms, which is exactly what I wanted.

Deterministic random number generator tied to instance (thread independent)

Your compiler most likely already has something very like Boost.Random.

C++0x includes a <random> header which is based on Boost.Random (with a few tweaks here and there).

Before then, TR1, a set of "semi-standard" libraries was available for most compilers as well, which contains nearly the same <random> header.



Related Topics



Leave a reply



Submit