Reputation: 1301
In julia, the seed for the global RNG can be set with
srand(SEED)
How can I retrieve the seed or current state of the global RNG, e.g. again at a later point?
The goal is to get the state of the RNG at any given point in time, and recreate it in a different session, without knowing the initial seed or all calls to RNG that happened in the meanwhile.
For example, R allows access to the current seed through
.Random.seed
I was hoping that an equivalent way would exist in julia.
Upvotes: 10
Views: 2723
Reputation: 983
Since the other answers to this question concern old versions of Julia and don't work any more, I decided to post a new answer.
In Julia version >= 1.0, the field Base.Random.GLOBAL_RNG
no longer exists.
In Julia 1.0 there is a field Random.GLOBAL_RNG
in the Random
package (which is no longer part of Base
). Retrieving the seed from there and setting it like described in the answer https://stackoverflow.com/a/47900426/3180809 does not work any more.
In Julia 1.4 and 1.5 there is the function Random.default_rng()
. I managed to get the desired behaviour of saving and reinstating the state of the Random generator with the following code there:
julia> import Random
julia> Random.seed!(1);
julia> rand(Int)
6592875438459116351
julia> rng = copy(Random.default_rng());
julia> rand(Int)
1969495256574935408
julia> Random.seed!(2);
julia> rand(Int)
6712802529292398593
julia> copy!(Random.default_rng(), rng);
julia> rand(Int)
1969495256574935408
In Julia 1.0, Random.GLOBAL_RNG
can be used instead of Random.default_rng()
to get the same result.
I came up with this solution after going through the Julia source code, so I don't know how stable this solution will again be across version.
(The function Random.default_rng()
is neither exported nor documented.)
I did not succeed in extracting only the seed as a single number that can be used in a call to Random.seed!
to reinstate a state of a running random number generator. I would also be interested in suggestions or discussions whether this is possible.
Upvotes: 0
Reputation: 10147
You should get the seed like this
reinterpret(Int32, Base.Random.GLOBAL_RNG.seed)
Test:
julia> srand(123456789);
julia> reinterpret(Int32, Base.Random.GLOBAL_RNG.seed)
1-element Array{Int32,1}:
123456789
For saving an restoring the full rng state you can do the simple thing and just store the whole Base.Random.GLOBAL_RNG
object. An easy way would be using JLD package.
In my private package I do manually save/read the rng state to HDF5, see here.
EDIT: This of course a more explicit version of @IainDunning's answer
Upvotes: 4
Reputation: 728
For better control when using a random generator in functions and in general,
RND = srand(0)
function coolfun()
println(RND.idx)
output = srand(RND, 100)
...
end
Upvotes: 0
Reputation: 18217
Using a specialized MersenneTwister with an explicit variable (instead of the hidden global one provided by the default random values functions), the functionality you require can be provided:
newmt = Base.Random.MersenneTwister(123)
randvec = [rand(newmt) for i=1:100]
# save state now
savestate = deepcopy(newmt.state)
randvec2 = [rand(newmt) for i=1:20]
# rewind state to old state
newmt.state = savestate
randvec3 = [rand(newmt) for i=1:20]
if randvec2==randvec3
println("works!")
end
The deepcopy
threw me off for a second there. Also, it would have been easier to access the global random generator state, but it might require ccall
ing libdSFMT library (see random.jl
and dSFMT.jl
in Base
.
Upvotes: 2
Reputation: 11664
Base.Random.RANDOM_SEED
is your friend for getting the seed:
julia> srand(10)
julia> Base.Random.RANDOM_SEED
1-element Array{Uint32,1}:
0x0000000a
julia> srand(1)
julia> Base.Random.RANDOM_SEED
1-element Array{Uint32,1}:
0x00000001
julia> srand(0xF)
julia> Base.Random.RANDOM_SEED
1-element Array{Uint32,1}:
0x0000000f
This isn't documented, but the source is easy enough to read. I'm not sure how to get the current state of the RNG, but it might be in the dSFMT
module
Upvotes: 6
Reputation: 15693
An obvious solution is to save the seed value before you call srand(seed)
.
Alternatively, if you know the RNG being used, and it isn't cryptographically secure, then you can calculate the values from the pseudo-random numbers it produces. For example, see Cracking a linear congruential generator
Upvotes: 0