How to let Boost :: random and Matlab produce the same random numbers

To test my C ++ code, I would like Boost :: Random and Matlab to produce the same random numbers.

So, for Boost, I use the code:

boost::mt19937 var(static_cast<unsigned> (std::time(0))); boost::uniform_int<> dist(1, 6); boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(var, dist); die.engine().seed(0); for(int i = 0; i < 10; ++i) { std::cout << die() << " "; } std::cout << std::endl; 

What produces (each program start):
4 4 5 6 4 6 4 6 3 4

And for matlab I use:

 RandStream.setDefaultStream(RandStream('mt19937ar','seed',0)); randi(6,1,10) 

What produces (each program start):
5 6 1 6 4 1 2 4 6 6

This is strange, since both use the same algorithm and the same seed. What am I missing?

It seems that Python (using numpy) and Matlab seems comparable in random homogeneous numbers: Matlab

RandStream.setDefaultStream (RandStream ('mt19937ar', 'seed', 203)); rand (1.10)

0.8479 0.1889 0.4506 0.6253 0.9697 0.2078 0.5944 0.9115 0.2457 0.7743

Python: random.seed (203); random.random (10)

array([ 0.84790006, 0.18893843, 0.45060688, 0.62534723, 0.96974765, 0.20780668, 0.59444858, 0.91145688, 0.24568615, 0.77430378])

C ++ boosts

0.8479 0.667228 0.188938 0.715892 0.450607 0.0790326 0.625347 0.972369 0.969748 0.858771

Which is identical to any other value of Python and Matlab ...

+4
source share
5 answers

I have to agree with the other answers, stating that these generators are not "absolute". They can give different results in accordance with the implementation. I think the easiest solution would be to implement your own generator. It may seem complicated (maybe a Mercedes twister, of course), but look at Xorshift , which is extremely simple but powerful. I am copying the C implementation specified in the Wikipedia link:

 uint32_t xor128(void) { static uint32_t x = 123456789; static uint32_t y = 362436069; static uint32_t z = 521288629; static uint32_t w = 88675123; uint32_t t; t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ (t ^ (t >> 8)); } 

To have the same seed, just supply any values ​​you want: int x, y, z, w (except (0,0,0,0)). You just have to be sure that Matlab and C ++ use 32 bits for these unsigned ints.

+4
source

Using type interface

 randi(6,1,10) 

will apply some kind of transformation on the original result of a random generator. This conversion is not generally trivial , and Matlab will almost certainly take a different choice step than Boost.

Try comparing the source data streams with the RNG - the probability that they are the same

+4
source

In case this helps anyone who is interested in the question:

To get the same behavior for the Twister algorithm:

  • Download the file http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c

  • Try the following:

     #include <stdint.h> // mt19937ar.c content.. int main(void) { int i; uint32_t seed = 100; init_genrand(seed); for (i = 0; i < 100; ++i) printf("%.20f\n",genrand_res53()); return 0; } 
  • Make sure that the same values ​​are created in Matlab:

     RandStream.setGlobalStream( RandStream.create('mt19937ar','seed',100) ); rand(100,1) 
  • randi() seems to be just ceil( rand()*maxval )

+3
source

Thanks to Fezvez's answer, I wrote xor128 in matlab:

 function [ w, state ] = xor128( state ) %XOR128 implementation of Xorshift % https://en.wikipedia.org/wiki/Xorshift % A starting state might be [123456789, 362436069, 521288629, 88675123] x = state(1); y = state(2); z = state(3); w = state(4); % t1 = (x << 11) t1 = bitand(bitshift(x,11),hex2dec('ffffffff')); % t = x ^ (x << 11) t = bitxor(x,t1); x = y; y = z; z = w; % t2 = (t ^ (t >> 8)) t2 = bitxor(t, bitshift(t,-8)); % t3 = w ^ (w >> 19) t3 = bitxor(w, bitshift(w,-19)); % w = w ^ (w >> 19) ^ (t ^ (t >> 8)) w = bitxor(t3, t2); state = [xyzw]; end 

You need to pass state to xor128 every time you use it. I wrote a β€œtester” function that simply returns a vector with random numbers. I tested 1000 numbers output by this function for values ​​output by cpp with gcc, and that is perfect.

 function [ v ] = txor( iterations ) %TXOR test xor128, returns vector v of length iterations with random number % output from xor128 % output v = zeros(iterations,1); state = [123456789, 362436069, 521288629, 88675123]; i = 1; while i <= iterations disp(i); [t,state] = xor128(state); v(i) = t; i = i + 1; end 
+1
source

I would be very careful, assuming that two different implementations of pseudo-random generators (albeit based on the same algorithms) give the same result. Maybe one of the implementations uses some kind of customization, therefore, it creates different results. If you need two equal "random" distributions, I suggest that you either pre-compute the sequence, save and access both C ++ and Matlab, or create your own generator. It would be quite easy to implement MT19937 if you use pseudocode on Wikipedia .

Make sure that both Matlab and C ++ codes work on the same architecture (that is, they both run on 32 or 64-bit) - using a 64-bit integer in one implementation, and 32-bit the whole in another lead to different results.

0
source

Source: https://habr.com/ru/post/972692/


All Articles