Julian
Julian

Reputation: 1301

Retrieve RNG seed in julia

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

Answers (6)

esel
esel

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

carstenbauer
carstenbauer

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

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

Dan Getz
Dan Getz

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 ccalling libdSFMT library (see random.jl and dSFMT.jl in Base.

Upvotes: 2

IainDunning
IainDunning

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

rossum
rossum

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

Related Questions