在 OCaml 的 StdLib 中序列化“模块随机”的当前状态

Posted

技术标签:

【中文标题】在 OCaml 的 StdLib 中序列化“模块随机”的当前状态【英文标题】:Serializing the current state of "Module Random" in OCaml's StdLib 【发布时间】:2020-09-27 15:32:07 【问题描述】:

我一定已经阅读了标准库模块 RandomRandom.State 上的 OCaml 手册页六次(可能更频繁),但我不知道如何序列化 PRNG 的当前内部状态.

这是我目前学到的:

模块RandomRandom.State 都在外部抽象/不透明的状态下运行。

两个模块都提供了两个/三个初始化器,但函数导出当前状态...我看不到它们:(

我能做什么?请帮忙!

【问题讨论】:

【参考方案1】:

您可以使用Marshal 模块对状态进行序列化(和反序列化),例如,

let save_random_state out = 
   Marshal.to_channel out (Random.get_state ()) []

let load_random_state inp = 
   Random.set_state (Marshal.from_channel inp)

但是,如果您只是希望Random 模块生成相同的伪随机数序列,则最好使用相同的状态进行初始化,即使用相同的种子,例如,如果您将启动您的程序与,

let () = Random.set_state (Random.State.make [|42|])

您将获得程序的确定性行为,因为Random 模块将始终生成相同的数字。

【讨论】:

在初始化期间播种很好,但它不能恢复长时间的计算(当最初的 UNIX 进程早已不复存在并且已经启动一个新进程以完成一些部分完成的工作时) . 所以计划看起来像s |> Marshal.to_string |> Z.of_bits 以将该状态转换为 Zarith 大整数。相当多的工作,但可以理解。谢谢。 我认为这是个坏主意。同样,如果您只想控制状态,请使用Random.set_state 并将您的状态放在那里。如果您的状态(又名种子)表示为 Z.t 数字,则将其转换为字节数组并将此数组用作种子。 你是对的! from Random.state to Z.t 不是一个好主意。动态类型的救援:) 我的 Prolog 的 random:setrand/1 谓词将同时使用 Prolog 原子(用于精确表示 Random.States)和 Prolog 数字(整数/浮点数);第一个可以精确复制以前的状态,后者是为了方便(以亚秒精度的 UNIX 时间播种)。谢谢! 顺便说一句。这就像 SICStus Prolog 所做的那样。 Prolog 实现者中的一句谚语是这样的:在不确定的情况下,就像 SICStus 一样。哈哈,只是认真的:)

以上是关于在 OCaml 的 StdLib 中序列化“模块随机”的当前状态的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ocaml 中使用多核进行蒙特卡罗模拟?

在 ocaml 中定义树 + 指向其子树的指针

Ocaml:在参数类型中使用记录和变体

如何在 utop 中重新加载 OCaml 模块

如何在OCaml中编译多个文件?

如何在 OCaml 中删除字符串的所有字符