pythonnumpyrandom-seednumpy-random

Function that generates random numbers calls other function that generates random numbers with a seed, and seed seems to be used again


I am trying to generate a function which generate random numbers from a uniform distribution Number_Rand() and another one which generates a random number given a certain seed Number_Rand_Seed() - so that it will always be the same for a fixed seed. However, I call the function Number_Rand_Seed() inside Number_Rand(), and for some reason the seed is also used to generate random numbers in Number_Rand(), so that its output is always the same. Shouldn't the seed be a local variable inside Number_Rand_Seed()? And shouldn't the seed be "renewed" everytime I call a np.random function (see, e.g., this answer)? What should I do then to "renew" the seed inside Number_Rand() and ignore the seed of Number_Rand_Seed()?

Here is an example:

def Number_Rand_Seed():
    np.random.seed(300121)
    a = np.random.uniform(0, 10)
    return a

def Number_Rand():
    a = Number_Rand_Seed()
    b = np.random.uniform(0, 10)
    return a, b

for i in range(3):
    print(Number_Rand()) 

The output is

(9.354120260352017, 2.552916103146633)
(9.354120260352017, 2.552916103146633)
(9.354120260352017, 2.552916103146633)

but I wanted something like

(9.354120260352017, 8.823425849537022)
(9.354120260352017, 5.950595370176398)
(9.354120260352017, 9.992406389398592)

Solution

  • In recent numpy versions, you can create separate random number generators using np.random.default_rng.

    In the following I use that for a, while retaining the default for b:

    In [35]: def Number_Rand_Seed():
        ...:     rng = np.random.default_rng(300121)
        ...:     a = rng.uniform(0, 10)
        ...:     return a
        ...: 
        ...: def Number_Rand():
        ...:     a = Number_Rand_Seed()
        ...:     b = np.random.uniform(0, 10)
        ...:     return a, b
        ...: 
        ...: for i in range(3):
        ...:     print(Number_Rand())
        ...: 
    (9.98668624527619, 2.7036401003521817)
    (9.98668624527619, 9.154952983315784)
    (9.98668624527619, 1.413705001678095)
    In [36]: Number_Rand()
    Out[36]: (9.98668624527619, 5.274283695955279)
    

    Or define a "default" rng outside the function. The rng in Number_Rand_Seed is local, and doesn't interfere with the rng defined outside it. Of course the code would be clearer to humans if I used different names.

    ...: rng = np.random.default_rng()
    ...: def Number_Rand():
    ...:     a = Number_Rand_Seed()
    ...:     b = rng.uniform(0, 10)
    ...:     return a, b