Is there a way to save the random state in the golang math/rand package?
I would like to serialize it and store it for later use, but the random state is an interface and the concrete struct underneath the interface is unexported (so json.Marshall apparently cannot be used).
As an alternative to saving the rand.Source object, I thought about just saving the underlying int64 seed value. You can set it with rand.Seed, but I don't see a way to obtain the seed value so that it can be retained for later use.
You can make your own random number source which can be marshalled.
One way would be to simply copy the code from http://golang.org/src/math/rand/rng.go and adapt it by adding code that can marshal the state in whatever way you want. That'll give you your own rand.Source that you can use in rand.New(myRandSource) to generate random numbers.
As you already noted, the math/rand package does not give you insight into the current state (seed) of the (pseudo-)random number generator. If you would need this, you would have to implement it on your own (as mentioned by Anonymous).
If you would: Ok, let's say you know that the internal state of the random number generator is equivalent to where a seed value of 1234 would be set. How is this better than if the seed is any other concrete or "random" number?
Here's a tip how to "simulate" access to the seed value of the generator:
Let's say you've already created your Rand object, you've set it up and used it (already generated some random numbers). This Rand object may as well be the default/global of the math/rand package, it doesn't have to be a distinct Rand.
You reach a point where you would like to save the "sate" of the random number generator in order so that later you can repeat the exact pseudo-random sequence from this point. This would need to get the current seed, and later when you want to repeat the sequence from this point, you would just set the stored seed to the Rand object. Problem: the seed you can't access.
But what you can do is set a new seed and then you know that the internal seed is the one you just set! So to simulate a GetSeed() (on the default Rand of the math/rand package):
func GetSeed() int64 {
seed := time.Now().UnixNano() // A new random seed (independent from state)
rand.Seed(seed)
return seed
}
To simulate a GetSeed() or any Rand (not the default one):
func GetSeed2(r rand.Rand) int64 {
seed := time.Now().UnixNano() // A new random seed (independent from state)
r.Seed(seed)
return seed
}
Preserving the "pseudo" part of the randomness
The above proposed GetSeed() uses the current time to "re-seed" the Rand object. This will alter the pseudo-random sequence based on the time it was called at. This may or may not be ok (in most of the times this is not a problem).
But if it is, we can avoid this if we use the Rand object itself to designate the new seed like this (by doing this the new seed will only depend on the current state - the current seed):
func GetSeed() int64 {
seed := rand.Int63() // A new pseudo-random seed: determined by current state/seed
rand.Seed(seed)
return seed
}
func GetSeed2(r rand.Rand) int64 {
seed := r.Int63() // A new pseudo-random seed: determined by current state/seed
r.Seed(seed)
return seed
}
Notes:
The GetSeed() functionality is designed to used occasionally, e.g. when you want to save a game. Normal usage would be to generate thousands of random numbers and call GetSeed() once only.
As Anonymous pointed out, with the current algorithm of the pseudo-random number generator, in some extreme situations (for example you call GetSeed() after each generated random number) this may result in a cycle in the generated random numbers and would return the previously generated sequence of random numbers. The length of the sequence may be around a couple of thousands. Here is an example of this where the length of the sequence is 8034: Repetition Go Playground Example.
But again: this is not a normal usage, GetSeed() is called intentionally after each random number generation; and this only applies if you use Rand itself to generate the new seed. If you re-seed your Rand object with the current time for example, repetition will not occur.
Related
There is a filter in WEKA in the preprocess tab named Randomized. The definition of this filter is Randomly shuffles the order of instances passed through it. The filter has a parameter called randomseed which is by default set as 42.
I found some definition of randomseed sunch as A random seed (or seed state, or just seed) is a number (or vector) used to initialize a pseudorandom number generator.
Seed function is used to save the state of a random function, so that it can generate same random numbers on multiple executions of the code on the same machine or on different machines (for a specific seed value). The seed value is the previous value number generated by the generator.
The number "42" was apparently chosen as a tribute to the "Hitch-hiker's Guide" books by Douglas Adams, as it was supposedly the answer to the great question of "Life, the universe, and everything" as calculated by a computer (named "Deep Thought") created specifically to solve it.
All those answers on the internet made me more confused.
I cannot understand what randomseed will do with random shuffle? Thus this means, 42 instances will take from the beginning of the instances and shuffle. Then again 42 instances will be taken and shuffled and the process will continue till the end?
The seed value simply initializes the java.util.Random object that generates the sequence of pseudo random numbers used for randomization.
A different seed value will result in a different sequence, therefore resulting in a different randomization of rows in your dataset.
The Randomize filter initializes such a Random object and then calls the randomize method of the weka.core.Instances object it currently holds. The code of the randomize method (at time of writing this is Weka 3.9.6) looks like this:
public void randomize(Random random) {
for (int j = numInstances() - 1; j > 0; j--) {
swap(j, random.nextInt(j + 1));
}
}
All options of option-handling classes in Weka have a default value. In case of the Randomize filter, the seed value has the default value of 42. It could have been anything, but someone was a fan of the Hitchhiker's Guide to the Galaxy and chose that value.
For security, I need to use 256 bits input as the rand seed, but it seems there is no satisfied API or functions, for example, in Golang std library, the seed should be int64, or 64 bits integer.
// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
// if seeded by Seed(1). Seed values that have the same remainder when
// divided by 2³¹-1 generate the same pseudo-random sequence.
// Seed, unlike the Rand.Seed method, is safe for concurrent use.
func Seed(seed int64) { globalRand.Seed(seed) }
above code is just an inappropriate example, you can ignore it,
crypto/rand is much safer, as we can see in the std library doc.
Is there a way to use 256 bits rand seeds in Golang?
THANKS A LOT !!!
Is there a way to use 256 bits rand seeds in [math/rand] Go[]?
No, for obvious reasons.
Some low-level languages like C require the programmer to set seed (usually srand(time(0)) if the user wants a different sequence of random numbers whenever the program runs. If it is not set, the program generates the same sequence of random numbers for each run.
Some high-level languages automatically set the seed if it is not set at first.
In Julia, if I want to generate a new sequence of random numbers each time, should I call srand()?
If you call Julia's srand() without providing a seed, Julia will use system entropy for seeding (essentially using a random seed).
On startup (specifically during initialisation of the Random module), Julia calls srand() without arguments. This means the global RNG is initialised randomly.
That means there's usually no need to call srand() in your own code unless you want to make the point that your random results are not meant to be reproducible.
Julia seeds the random number generator automatically, you use srand with a known seed, in order to recreate the same pseudo random sequence deterministically (useful for testing for example), but if you want to generate a different random sequence each time, all you need is to call rand.
help?> srand
search: srand sprand sprandn isreadonly StepRange StepRangeLen ClusterManager AbstractRNG AbstractUnitRange CartesianRange
srand([rng=GLOBAL_RNG], seed) -> rng
srand([rng=GLOBAL_RNG]) -> rng
Reseed the random number generator: rng will give a reproducible sequence
of numbers if and only if a seed is provided. Some RNGs
don't accept a seed, like RandomDevice. After the call to srand, rng is
equivalent to a newly created object initialized with the
same seed.
I am using the rgsl library in Rust that wraps functions from the C GSL math libraries. I was using a random number generator function, but I am always getting the same exact value whenever I generate a new random number. I imagine that the number should vary upon each run of the function. Is there something that I am missing? Do I need to set a new random seed each time or such?
extern crate rgsl;
use rgsl::Rng;
fn main() {
rgsl::RngType::env_setup();
let t = rgsl::rng::default();
let r = Rng::new(&t).unwrap()
let val = rgsl::randist::binomial::binomial(&r, 0.01f64, 1u32);
print!("{}",val);
}
The value I keep getting is 1, which seems really high considering the probability of obtaining a 1 is 0.01.
The documentation for env_setup explains everything you need to know:
This function reads the environment variables GSL_RNG_TYPE and GSL_RNG_SEED and uses their values to set the corresponding library variables gsl_rng_default and gsl_rng_default_seed
If you don’t specify a generator for GSL_RNG_TYPE then gsl_rng_mt19937 is used as the default. The initial value of gsl_rng_default_seed is zero.
(Emphasis mine)
Like all software random number generators, this is really an algorithm that produces pseudo random numbers. The algorithm and the initial seed uniquely identify a sequence of these numbers. Since the seed is always the same, the first (and second, third, ...) number in the sequence will always be the same.
So if I want to generate a new series of random numbers, then I need to change the seed each time. However, if I use the rng to generate a set of random seeds, then I will get the same seeds each time.
That's correct.
Other languages don't seem to have this constraint, meaning that the seed can be manually set if desired, but is otherwise is random.
A classical way to do this is to seed your RNG with the current time. This produces an "acceptable" seed for many cases. You can also get access to true random data from the operating system and use that as a seed or mix it in to produce more random data.
Is there no way to do this in Rust?
This is a very different question. If you just want a random number generator in Rust, use the rand crate. This uses techniques like I described above.
You could even do something crazy like using random values from the rand crate to seed your other random number generator. I just assumed that there is some important reason you are using that crate instead of rand.
I came across an article about Car remote entry system at http://auto.howstuffworks.com/remote-entry2.htm In the third bullet, author says,
Both the transmitter and the receiver use the same pseudo-random number generator. When the transmitter sends a 40-bit code, it uses the pseudo-random number generator to pick a new code, which it stores in memory. On the other end, when the receiver receives a valid code, it uses the same pseudo-random number generator to pick a new one. In this way, the transmitter and the receiver are synchronized. The receiver only opens the door if it receives the code it expects.
Is it possible to have two PRNG functions producing same random numbers at the same time?
In PRNG functions, the output of the function is dependent on a 'seed' value, such that the same output will be provided from successive calls given the same seed value. So, yes.
An example (using C#) would be something like:
// Provide the same seed value for both generators:
System.Random r1 = new System.Random(1);
System.Random r2 = new System.Random(1);
// Will output 'True'
Console.WriteLine(r1.Next() == r2.Next());
This is all of course dependent on the random number generator using some sort of deterministic formula to generate its values. If you use a so-called 'true random' number generator that uses properties of entropy or noise in its generation, then it would be very difficult to produce the same values given some input, unless you're able to duplicate the entropic state for both calls into the function - which, of course, would defeat the purpose of using such a generator...
In the case of remote keyless entry systems, they very likely use a PRNG function that is deterministic in order to take advantage of this feature. There are many ICs that provide this sort of functionality to produce random numbers for electronic circuits.
Edit: upon request, here is an example of a non-deterministic random number generator which doesn't rely upon a specified seed value: Quantum Random Number Generator. Of course, as freespace points out in the comments, this is not a pseudorandom number generator, since it generates truly random numbers.
Most PRNGs have an internal state in the form of a seed, which they use to generate their next values. The internal logic goes something like this:
nextNumber = function(seed);
seed = nextNumber;
So every time you generate a new number, the seed is updated. If you give two PRNGs that use the same algorithm the same seed, function(seed) is going to evaluate to the same number (given that they are deterministic, which most are).
Applied to your question directly: the transmitter picks a code, and uses it as a seed. The receiver, after receiving it, uses this to seed its generator. Now the two are aligned, and they will generate the same values.
As Erik and Claudiu have said, ad long as you seed your PRNG with the same value you'll end up with the same output.
An example can be seen when using AES (or any other encryption algorithm) as the basis of your PRNG. As long as you keep using an inputs that match on both device (transmitter and receiver) then the outputs will also match.