Is there anyway to calculate the next seed knowing the previous seed? - python

I'm trying to develop a program in Python to predict the outcome of a Pseudo Random Number Generator.
I already have a program that gets the seed of the previously generated number using seed = random.getstate(). My question is whether there is any way to calculate the next seed that will be used, so I can predict the next number.

The reason that pseudorandom number generators are so named is that they're deterministic; they generate a sequence of numbers that appear to be random, but which aren't really. If you start a PRNG with the same seed, you'll get the same sequence every time.
I already have a programm that gets the seed of the previous generated number using seed = random.getstate()
You're not really getting a seed here, but rather the internal state of the PRNG. You could save that state and set it again later. That could be useful for testing, or just to continue with the same sequence.
Now, my question is if there is anyway to calculate the next seed that will be used, so I can predict the number.
Again, not really a seed, which is the initial value that you supply to start a PRNG sequence. What you're getting is the internal state of the PRNG. But yes, if you have that state, then it's trivial to predict the next number: just call random.setstate(...) with the state that you got, generate the next number, and then call random.setstate(...) again to put the PRNG back in the same state so that it'll again generate that same number.

Related

In what situations do we specifiy a static seed value when using the random module in Python? [duplicate]

From the docs:
random.seed(a=None, version=2) Initialize the random number generator.
If a is omitted or None, the current system time is used. If
randomness sources are provided by the operating system, they are used
instead of the system time (see the os.urandom() function for details
on availability).
But...if it's truly random...(and I thought I read it uses Mersenne, so it's VERY random)...what's the point in seeding it? Either way the outcome is unpredictable...right?
The default is probably best if you want different random numbers with each run. If for some reason you need repeatable random numbers, in testing for instance, use a seed.
The module actually seeds the generator (with OS-provided random data from urandom if possible, otherwise with the current date and time) when you import the module, so there's no need to manually call seed().
(This is mentioned in the Python 2.7 documentation but, for some reason, not the 3.x documentation. However, I confirmed in the 3.x source that it's still done.)
If the automatic seeding weren't done, you'd get the same sequence of numbers every time you started your program, same as if you manually use the same seed every time.
But...if it's truly random
No, it's pseudo random. If it uses Mersenne Twister, that too is a PRNG.
It's basically an algorithm that generates the exact same sequence of pseudo random numbers out of a given seed. Generating truly random numbers requires special hardware support, it's not something you can do by a pure algorithm.
You might not need to seed it since it seeds itself on first use, unless you have some other or better means of providing a seed than what is time based.
If you use the random numbers for things that are not security related, a time based seed is normally fine. If you use if for security/cryptography, note what the docs say: "and is completely unsuitable for cryptographic purposes"
If you want to reproduce your results, you seed the generator with a known value so you get the same sequence every time.
A Mersenne twister, the random number generator, used by Python is seeded by the operating system served random numbers by default on those platforms where it is possible (Unixen, Windows); however on other platforms the seed defaults to the system time which means very repeatable values if the system time has a bad precision. On such systems seeding with known better random values is thus beneficial. Note that on Python 3 specifically, if version 2 is used, you can pass in any str, bytes, or bytearray to seed the generator; thus taking use of the Mersenne twister's large state better.
Another reason to use a seed value is indeed to guarantee that you get the same sequence of random numbers again and again - by reusing the known seed. Quoting the docs:
Sometimes it is useful to be able to reproduce the sequences given by
a pseudo random number generator. By re-using a seed value, the same
sequence should be reproducible from run to run as long as multiple
threads are not running.
Most of the random module’s algorithms and seeding functions are
subject to change across Python versions, but two aspects are
guaranteed not to change:
If a new seeding method is added, then a backward compatible seeder will be offered.
The generator’s random() method will continue to produce the same sequence when the compatible seeder is given the same seed.
For this however, you mostly want to use the random.Random instances instead of using module global methods (the multiple threads issue, etc).
Finally also note that the random numbers produced by Mersenne twister are unsuitable for cryptographical use; whereas they appear very random, it is possible to fully recover the internal state of the random generator by observing only some hundreds of values from the generator. For cryptographical algorithms, you want to use the SystemRandom class.
In most cases I would say there is no need to care about. But if someone is really willing to do something wired and (s)he could roughly figure out your system time when your code was running, they might be able to brute force replay your random numbers and see which series fits. But I would say this is quite unlikely in most cases.

Python Random Function without using ANY libraries or modules

I was wondering if there was any way to generate a random number, from 1 to 9, without using external libraries, even if they are included with Python.This is a dumb reason, but my editor doesn't allow any libraries, so I need a way to get randomness without libraries.
You need something to start with. Random numbers can be spawned from the last the few digits in the milliseconds value from the system's timestamp. Then you can manipulate them a little and tadah : a different random number every time.
You can implement a random number generator in plain Python, but they all need a seed. The reason Xorshift always returned the same sequence to #yuwe is that it's always getting the same seed. Same seed => same sequence of pseudo-random numbers.
Getting a suitable seed is not possible without resorting to external entropy sources, be it the current time in microseconds, the current process ID, the number of bytes sent over the network since the last reboot, mouse movements, what have you.

Storing a Random state

I'm designing a program which:
Includes randomness
Can stop executing and save its state at certain points (in XML)
Can start executing starting from a saved state
Is deterministic (so the program can run from the same state twice and produces the same result)
The problem here is saving the randomness. I can initialize it at start, but from state to state I may generate anywhere from 0 to 1000 random numbers.
Therefore, I have 3 options I can see:
Store the seed, and number of times a number has been randomly generated, then when loading the state, run the random number generator that many times.
On state save, increment the seed by N
On state save, randomly generate the next seed
The problem with option 1 is the run time, and is pretty infeasible.
However, I'm unsure whether 2 or 3 will produce good random results. If I run two random generators, one seeded with X, the other seeded with X+1, how different will their results be? What if the first is seeded with X, and the second is seeded with X.random()?
In case it makes a difference, I'm using Python 3.
You can save the state of the PRNG using random.getstate() (then, e.g., use pickle to save it to disk. Later, a random.setstate(state) will return your PRNG to exactly the state it was in.

Should I seed the random number generator?

From the docs:
random.seed(a=None, version=2) Initialize the random number generator.
If a is omitted or None, the current system time is used. If
randomness sources are provided by the operating system, they are used
instead of the system time (see the os.urandom() function for details
on availability).
But...if it's truly random...(and I thought I read it uses Mersenne, so it's VERY random)...what's the point in seeding it? Either way the outcome is unpredictable...right?
The default is probably best if you want different random numbers with each run. If for some reason you need repeatable random numbers, in testing for instance, use a seed.
The module actually seeds the generator (with OS-provided random data from urandom if possible, otherwise with the current date and time) when you import the module, so there's no need to manually call seed().
(This is mentioned in the Python 2.7 documentation but, for some reason, not the 3.x documentation. However, I confirmed in the 3.x source that it's still done.)
If the automatic seeding weren't done, you'd get the same sequence of numbers every time you started your program, same as if you manually use the same seed every time.
But...if it's truly random
No, it's pseudo random. If it uses Mersenne Twister, that too is a PRNG.
It's basically an algorithm that generates the exact same sequence of pseudo random numbers out of a given seed. Generating truly random numbers requires special hardware support, it's not something you can do by a pure algorithm.
You might not need to seed it since it seeds itself on first use, unless you have some other or better means of providing a seed than what is time based.
If you use the random numbers for things that are not security related, a time based seed is normally fine. If you use if for security/cryptography, note what the docs say: "and is completely unsuitable for cryptographic purposes"
If you want to reproduce your results, you seed the generator with a known value so you get the same sequence every time.
A Mersenne twister, the random number generator, used by Python is seeded by the operating system served random numbers by default on those platforms where it is possible (Unixen, Windows); however on other platforms the seed defaults to the system time which means very repeatable values if the system time has a bad precision. On such systems seeding with known better random values is thus beneficial. Note that on Python 3 specifically, if version 2 is used, you can pass in any str, bytes, or bytearray to seed the generator; thus taking use of the Mersenne twister's large state better.
Another reason to use a seed value is indeed to guarantee that you get the same sequence of random numbers again and again - by reusing the known seed. Quoting the docs:
Sometimes it is useful to be able to reproduce the sequences given by
a pseudo random number generator. By re-using a seed value, the same
sequence should be reproducible from run to run as long as multiple
threads are not running.
Most of the random module’s algorithms and seeding functions are
subject to change across Python versions, but two aspects are
guaranteed not to change:
If a new seeding method is added, then a backward compatible seeder will be offered.
The generator’s random() method will continue to produce the same sequence when the compatible seeder is given the same seed.
For this however, you mostly want to use the random.Random instances instead of using module global methods (the multiple threads issue, etc).
Finally also note that the random numbers produced by Mersenne twister are unsuitable for cryptographical use; whereas they appear very random, it is possible to fully recover the internal state of the random generator by observing only some hundreds of values from the generator. For cryptographical algorithms, you want to use the SystemRandom class.
In most cases I would say there is no need to care about. But if someone is really willing to do something wired and (s)he could roughly figure out your system time when your code was running, they might be able to brute force replay your random numbers and see which series fits. But I would say this is quite unlikely in most cases.

Seeding random in django

In a view in django I use random.random(). How often do I have to call random.seed()?
One time for every request?
One time for every season?
One time while the webserver is running?
Don't set the seed.
The only time you want to set the seed is if you want to make sure that the same events keep happening. For example, if you don't want to let players cheat in your game you can save the seed, and then set it when they load their game. Then no matter how many times they save + reload, it still gives the same outcomes.
Call random.seed() rarely if at all.
To be random, you must allow the random number generator to run without touching the seed. The sequence of numbers is what's random. If you change the seed, you start a new sequence. The seed values may not be very random, leading to problems.
Depending on how many numbers you need, you can consider resetting the seed from /dev/random periodically.
You should try to reset the seed just before you've used up the previous seed. You don't get the full 32 bits of randomness, so you might want to reset the seed after generating 2**28 numbers.
It really depends on what you need the random number for. Use some experimentation to find out if it makes any difference. You should also consider that there is actually a pattern to pseudo-random numbers. Does it make a difference to you if someone can possible guess the next random number? If not, seed it once at the start of a session or when the server first starts up.
Seeding once at the start of the session would probably make the most sense, IMO. This way the user will get a set of pseudo-random numbers throughout their session. If you seed every time a page is served, they aren't guaranteed this.

Categories

Resources