numpymatlabrandomrandom-seed

Matching numpy rand ndarrays with MATLAB


I'm trying to match randomly generated ndarrays from numpy with MATLAB.

import numpy as np

# Set the seed for NumPy's random generator
np.random.seed(42) #Mersenne Twister is default
    
# Generate complex random numbers
a = 16
b = 4
c = 10
x_py = np.random.rand(a, b, c) + 1j * np.random.rand(a, b, c)

Here's the MATLAB version:

% Set the seed for MATLAB's random generator
rng(42, 'twister')  % Use the Mersenne Twister algorithm

% Generate complex random numbers
a = 16;
b = 4;
c = 10;
x_ml = rand([a, b, c], 'like', 1i);

Now, although the seed and generator type are matched, the states don't match, so I wasn't able to match x_py and x_ml.

I know the easier way is to generate in MATLAB, save to file and import in Python, but I want to understand the difference between the way the two APIs work and how they can be tweaked to get a matching output.


Solution

  • This question is very similar to this other one, but with the addition that here we're dealing with 3D arrays and complex numbers.

    According to the other Q&A, MATLAB fills arrays column-wise while Python fills them row-wise. You need to transpose the result of the one to match the other. For 3D arrays, the indexing order in Python is [z,y,x], in MATLAB it is [y,x,z]. The storage order is reversed though, in MATLAB the y (first) index is the one that indexes contiguous memory addresses, whereas the x (last) index in Python does that. So we need to define the arrays with a different order for the sizes, and then permute the dimensions to make them match.

    The other issue is that in Python, np.random.rand(a, b, c) + 1j * np.random.rand(a, b, c) first generates all real values, then all imaginary values. In MATLAB, rand([a, b, c], 'like', 1i) will generate a real value, then an imaginary one, then a real one, etc.

    Putting it all together,

    x_ml = permute(rand([c, b, a]) + 1j * rand([c, b, a]), [2,1,3])
    

    produces the same array as x_py in the question.