在朱莉娅中取回RNG种子

时间:2014-10-17 11:50:50

标签: random julia

在朱莉娅,全球RNG的种子可以设置为

srand(SEED)

如何检索全局RNG的种子或当前状态,例如再来一次?

目标是在任何给定的时间点获取RNG的状态,并在不同的会话中重新创建它,而不知道同时发生的初始种子或对RNG的所有调用。

例如,R允许通过

访问当前种子
.Random.seed

我希望朱莉娅能有同等的方式。

6 个答案:

答案 0 :(得分:6)

Base.Random.RANDOM_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

这没有记录,但the source很容易阅读。我不知道如何获得RNG的当前状态,但它可能在dSFMT模块中

答案 1 :(得分:4)

你应该得到像这样的种子

reinterpret(Int32, Base.Random.GLOBAL_RNG.seed)

测试:

julia> srand(123456789);

julia> reinterpret(Int32, Base.Random.GLOBAL_RNG.seed)
1-element Array{Int32,1}:
 123456789

为了保存恢复完整的rng状态,你可以做一件简单的事情并只存储整个Base.Random.GLOBAL_RNG对象。一种简单的方法是使用JLD包。

在我的私人套餐中,我手动保存/读取rng状态为HDF5,请参阅here

编辑:这当然是@IainDunning答案的更明确版本

答案 2 :(得分:2)

使用具有显式变量的专用MersenneTwister(而不是默认随机值函数提供的隐藏全局变量),可以提供您需要的功能:

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

deepcopy把我扔了一秒钟。此外,访问全局随机生成器状态会更容易,但可能需要ccall libdSFMT库(请参阅random.jl中的dSFMT.jlBase

答案 3 :(得分:0)

一个明显的解决方案是在调用srand(seed)之前保存种子值。

或者,如果您知道正在使用的RNG,并且它不具有加密安全性,那么您可以根据它产生的伪随机数计算这些值。例如,请参阅Cracking a linear congruential generator

答案 4 :(得分:0)

为了更好地控制在函数中使用随机生成器,一般来说,

RND = srand(0)
function coolfun()
    println(RND.idx)
    output = srand(RND, 100)
    ...
end

答案 5 :(得分:0)

由于这个问题的其他答案涉及旧版本的 Julia 并且不再有效,我决定发布一个新答案。

在 Julia 版本 >= 1.0 中,字段 Base.Random.GLOBAL_RNG 不再存在。 在 Julia 1.0 中,Random.GLOBAL_RNG 包(不再是 Random 的一部分)中有一个字段 Base。从那里检索种子并按照答案 https://stackoverflow.com/a/47900426/3180809 中所述进行设置不再有效。

在 Julia 1.4 和 1.5 中有函数 Random.default_rng()。我设法使用以下代码获得了所需的保存和恢复随机生成器状态的行为:

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

在 Julia 1.0 中,可以使用 Random.GLOBAL_RNG 代替 Random.default_rng() 以获得相同的结果。

我在浏览了 Julia 源代码后想出了这个解决方案,所以我不知道这个解决方案在跨版本时的稳定性如何。 (函数 Random.default_rng() 既不导出也不记录。)

我没有成功地仅将种子提取为单个数字,该数字可用于调用 Random.seed! 以恢复正在运行的随机数生成器的状态。我也会对是否可行的建议或讨论感兴趣。