Random 在julia中检索RNG种子

Random 在julia中检索RNG种子,random,julia,Random,Julia,在julia中,全局RNG的种子可以设置为 srand(SEED) 如何检索全局RNG的种子或当前状态(例如,稍后再次检索) 目标是在任何给定的时间点获取RNG的状态,并在不同的会话中重新创建它,而不知道初始种子或同时发生的对RNG的所有调用 例如,R允许通过访问当前种子 .Random.seed 我希望julia中会存在一种类似的方法。一个明显的解决方案是在调用srand(seed)之前保存种子值 或者,如果您知道正在使用的RNG,并且它在加密方面不安全,那么您可以根据它产生的伪随机数计算

在julia中,全局RNG的种子可以设置为

srand(SEED)
如何检索全局RNG的种子或当前状态(例如,稍后再次检索)

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

例如,R允许通过访问当前种子

.Random.seed

我希望julia中会存在一种类似的方法。

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


或者,如果您知道正在使用的RNG,并且它在加密方面不安全,那么您可以根据它产生的伪随机数计算值。例如,请参见

Base.Random.Random\u 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

这没有文档记录,但很容易阅读。我不确定如何获取RNG的当前状态,但它可能位于模块中,使用带有显式变量的专用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
ing libdSFMT库(请参阅
Base

中的
random.jl
dSFMT.jl
,以便在函数和一般情况下使用随机生成器时进行更好的控制

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

你应该像这样得到种子

reinterpret(Int32, Base.Random.GLOBAL_RNG.seed)
测试:

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

在我的私有包中,我手动将rng状态保存/读取到HDF5,请参阅


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

,因为这个问题的其他答案涉及朱莉娅的旧版本,不再适用,所以我决定发布一个新的答案

在Julia版本>=1.0中,字段
Base.Random.GLOBAL\u RNG
不再存在。 在Julia 1.0中,在
Random
包(不再是
Base
的一部分)中有一个字段
Random.GLOBAL\u RNG
。从该字段中检索种子并按答案中所述进行设置不再有效

在Julia 1.4和1.5中,有一个函数
Random.default\u 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\u RNG
代替
Random.default\u RNG()
来获得相同的结果

我在阅读了Julia的源代码后提出了这个解决方案,所以我不知道这个解决方案在不同版本中会有多稳定。 (函数
Random.default\u rng()
既不导出也不记录。)


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

@jurgemaister此部分涉及设置种子。我找不到任何提示jurgemaister:你似乎不理解设置种子和以后发现种子设置的区别。@jurgemaister我的问题与如何设置种子和如何生成随机数无关。我的问题是如何在某个时间点检索RNG的状态,例如我可以在不同的会话中重新创建相同的状态。正确阅读问题也很重要。Julia中的随机数生成使用Mersenne Twister库。现在可以通过
Base.Random.GLOBAL\u RNG.seed
,而不是
Base.Random.Random\u seed
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