mjarosie
mjarosie

Reputation: 4553

How to "stash" random state generator state

I'm seeding a random number generator for reproducible results with:

import random

SEED = 32412542
random.seed(SEED)

I'd like to make it return "non-reproducible" random values for only one part of a program, as in:

import random

SEED = 32412542
random.seed(SEED)

my_list = [1, 2, 3, 4, 5]

res = random.sample(my_list, len(my_list))  # I would like result of this to be the same between runs of the program.

# Do some reproducible calculations, such as training neural network.
print(res)  # E.g. prints [3, 2, 4, 1, 5]

# What to do here?
res = random.sample(my_list, len(my_list))  # I would like result of this to be different between runs.

# Do some non-reproducible calculations, such as picking neural network parameters randomly.
print(res)  # Prints some random order.

res = random.sample(my_list, len(my_list))  # I would like result of this to be the same between runs of the program.

# Do some reproducible calculations, such as training neural network.
print(res)  # E.g. prints [2, 3, 1, 4, 5]

What I came up with so far is to seed with no parameter right before I'd like it to become non-reproducible and then re-seed with the SEED value afterwards:

import random

SEED = 32412542
random.seed(SEED)

my_list = [1, 2, 3, 4, 5]

res = random.sample(my_list, len(my_list))
print(res)  # Prints: [3, 2, 4, 1, 5]

random.seed()
res = random.sample(my_list, len(my_list))
print(res)  # Prints some random order.

random.seed(SEED)
res = random.sample(my_list, len(my_list))
print(res)  # Prints: [3, 2, 4, 1, 5], so exactly what has been printed before.

The problem is that after re-seeding, exactly the same set of random values is produced (obviously - in the end that's the purpose of seeding with a specific value), which I don't want to happen. I'd like to somehow restore the previous state of the random generator. Is that possible?

Upvotes: 1

Views: 392

Answers (1)

Bakuriu
Bakuriu

Reputation: 101959

You cannot do this using the random functions but you can by creating an instance of the Random class. As the documentation states:

Class Random can also be subclassed if you want to use a different basic generator of your own devising: in that case, override the random(), seed(), getstate(), and setstate() methods. Optionally, a new generator can supply a getrandbits() method — this allows randrange() to produce selections over an arbitrarily large range.

Example:

>>> import random
>>> r = random.Random()
>>> r.randint(1, 1000)
545
>>> r.randint(1, 1000)
349
>>> r.randint(1, 1000)
745
>>> r.randint(1, 1000)
792
>>> state = r.getstate()
>>> r.randint(1, 1000)
52
>>> r.randint(1, 1000)
799
>>> r.randint(1, 1000)
586
>>> r.randint(1, 1000)
581
>>> r.setstate(state)
>>> r.randint(1,1000)
52
>>> r.randint(1,1000)
799
>>> r.randint(1,1000)
586
>>> r.randint(1,1000)
581

Actually you can even using the functions from the random module, my bad:

random.getstate() Return an object capturing the current internal state of the generator. This object can be passed to setstate() to restore the state.

random.setstate(state) state should have been obtained from a previous call to getstate(), and setstate() restores the internal state of the generator to what it was at the time getstate() was called.

Upvotes: 2

Related Questions