在状态计算中“不断转动曲柄”的有效方法

2024-02-03

我有一个有状态的进程,被建模为i -> RWS r w s a。我想给它一个输入cmds :: [i];目前我做的是批发:

    let play = runGame theGame . go
          where
            go [] = finished
            go ((v, n):cmds) = do
                end1 <- stepWorld
                end2 <- ite (SBV.isJust end1) (return end1) $ stepPlayer (v, n)
                ite (SBV.isJust end2) (return end2) $ go cmds

我可以尝试搜索预定大小的输入,如下所示:

    result <- satWith z3{ verbose = True } $ do
        cmds <- mapM sCmd [1..inputLength]
        return $ SBV.fromMaybe sFalse $ fst $ play cmds

然而,这给了我 SBV 本身可怕的性能,即在调用 Z3 之前(我可以看到情况是这样,因为verbose输出显示了之前花费的所有时间(check-sat)称呼)。这甚至与inputLength设置为较小的值,例如 4。

然而,随着inputLength设置为1或2,整个过程非常敏捷。所以这让我希望有一种方法可以运行SBV来获得单步行为的模型i -> s -> (s, a),然后告诉 SMT 求解器继续迭代该模型n不同的is.

这就是我的问题:在这样的有状态计算中,我想要将 SMT 变量作为输入提供给状态计算,有没有办法让SMT求解器转动曲柄以避免SBV的不良性能?

我想一个简化的“模型问题”如果我有一个函数f :: St -> St,和一个谓词p :: St -> SBool,我想解决n :: SInt这样p (iterateN n f x0),假设使用 SBV 执行此操作的推荐方法是什么Mergeable St?

EDIT: 我已经上传了完整的代码到Github https://github.com/gergoerdi/scottcheck/tree/8ceaa0a7cb21681de12de79f1d9e2ed14d0b3d99但请记住,这不是一个最小化的例子;事实上,它还不是非常好的 Haskell 代码。


完整的符号执行

如果没有看到我们可以执行的完整代码,就很难发表意见。 (当您发布人们可以实际运行的代码段时,堆栈溢出效果最好。)但是,指数复杂性的一些明显迹象正在您的程序中蔓延。考虑您发布的以下片段:

        go [] = finished
        go ((v, n):cmds) = do
                end1 <- stepWorld
                end2 <- ite (SBV.isJust end1) (return end1) $ stepPlayer (v, n)
                ite (SBV.isJust end2) (return end2) $ go cmds

如果您使用具体值进行编程,这看起来像是“线性”行走。但请记住,ite构造必须在每个步骤中“评估”两个分支。并且你有一个嵌套的 if:这就是为什么你的速度呈指数减慢,每次迭代的速度减慢为 4 倍。正如您所观察到的,这种情况很快就会失控。 (思考这个问题的一种方法是 SBV 必须run每个步骤中这些嵌套 if 的所有可能结果。您可以绘制调用树以查看其呈指数增长。)

在不知道您的详细信息的情况下stepWorld or stepPlayer很难提出任何替代方案。但最重要的是,您希望消除这些调用ite尽可能多,并将它们推到递归链中尽可能低的位置。也许连续传递风格会有所帮助,但这一切都取决于这些操作的语义是什么,以及您是否可以成功“推迟”决策。

查询方式

但是,我确实相信您尝试的更好方法是实际使用 SBVquery模式。在这种模式下,你可以not在调用求解器之前首先象征性地模拟一切。相反,您逐渐向求解器添加约束,查询可满足性,并根据获得的值采取不同的路径。我相信这种方法最适合您的情况,您可以动态探索“状态空间”,同时也可以一路做出决策。文档中有一个这样的例子:六角拼图 http://hackage.haskell.org/package/sbv-8.7/docs/Documentation-SBV-Examples-Puzzles-HexPuzzle.html。特别是,search https://github.com/LeventErkok/sbv/blob/master/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs#L91-L125函数展示了如何在增量模式下使用求解器一次一次移动一步(使用push/pop).

我不确定这种执行模型是否符合您游戏中的逻辑。希望它至少能给你一个想法。但我过去在增量方法方面很幸运,您可以通过避免在将内容发送到 z3 之前做出所有选择来增量地探索如此大的搜索空间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在状态计算中“不断转动曲柄”的有效方法 的相关文章

  • 导入 Haskell 模块

    我是哈斯克尔的新手 为什么当我尝试使用时Days from Data Time我收到此错误 Could not find module Data Time It is a member of the hidden package time
  • 为什么 Parsec 的 sepBy 停止并且不解析所有元素?

    我正在尝试解析一些逗号分隔的字符串 该字符串可能包含也可能不包含具有图像尺寸的字符串 例如 hello world 300x300 good bye world 我写了下面的小程序 import Text Parsec import qua
  • 这个记忆的斐波那契函数是如何工作的?

    在我正在做的函数式编程课程的当前练习作业中 我们必须制作给定函数的记忆版本 为了解释记忆化 给出以下示例 fiblist fibm x x lt 0 fibm 0 0 fibm 1 1 fibm n fiblist n 1 fiblist
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 纯函数怎么能做IO呢?

    我最近了解到莫纳德随机数 http hackage haskell org package MonadRandom 0 1 13 docs Control Monad Random Class html t 3aMonadRandom图书馆
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • Haskell 入门

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 几天来 我一直试图理解 Haskell 中的函数式编程范例 我通过阅读教程和观看截屏视频
  • 用于遇到 [...] 的 Haskell Parsec 解析器

    我正在尝试使用 Parsec 在 Haskell 中编写一个解析器 目前我有一个可以解析的程序 test x 1 2 3 end 执行此操作的代码如下 testParser do reserved test v lt identifier
  • 如何在haskell中获取变量名称

    我来到 haskell 时有一些 c 背景知识 想知道是否有类似的 define print a printf s d n a a int a 5 print a 应该打印 a 5 这是 augustss 提到的 TH 解决方案 LANGU
  • 如何通过“cabal build”或“stack build”构建带有图标的项目

    我想构建一个带有图标的可执行文件 通过谷歌搜索 我发现这里的说明 https wiki haskell org Setting an executable icon 但它只能通过编译源文件来工作ghc 如果我想构建一个具有可执行文件的项目c
  • 带有 RankNTypes 扩展的奇怪类型推断

    我正在尝试在 Haskell 中尝试 System F 类型 并通过以下方式实现了自然数的 Church 编码type 当加载这段代码时 OPTIONS GHC Wall LANGUAGE RankNTypes type CNat fora
  • 如何在Haskell中实现词法分析器和解析器

    我在这里得到了这段代码 它是用Haskell结构的命令式编程语言编写的程序 所以问题是 我如何为这种语言实现词法分析器和解析器 该程序被定义为一系列语句有 6 种类型 goto write stop if goto 和 int int n
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 我是否需要采取明确的操作来促进与持久数据结构的共享?

    我来自命令式背景 正在尝试实现一个简单的不相交集 并集查找 数据结构 以获得在 Haskell 中创建和修改 持久 数据结构的一些练习 目标是有一个简单的实现 但我也关心效率 我的问题与此相关 首先 我创建了一个按等级并集的不相交集森林实现
  • 关于“没有绑定的类型签名”的错误

    我在 Haskell 中遇到 ASCII 问题 fromEnum Char gt Int toEnum Int gt Char offset Int offset fromEnum A fromEnum a toUpper Char gt
  • 在另一个字符串中查找子字符串的索引 Haskell

    我要创建一个带有两个参数 字符串 的函数 该函数应查看第一个参数是否是第二个参数的子字符串 如果是这种情况 它将返回每个出现的元组 其中包含子字符串的起始索引和子字符串的结尾索引 例如 f String gt String gt Int I
  • 约束包如何工作?

    背后的想法数据 约束 Forall http hackage haskell org packages archive constraints 0 3 2 doc html src Data Constraint Forall html据我
  • 如何在haskell中用另一个字符串替换一个字符串

    我想用不同的字符串替换输入文件中的字符串 我正在寻找一种方法 但似乎我只能逐个字符地更改字符串 例如在我下面的代码中 replace String gt String replace replace x xs if x then y rep
  • 在 Haskell 中获取玫瑰树的根

    最近我开始学习 Haskell 并在以下练习中遇到困难 Write functions root Rose a gt a and children Rose a gt Rose a that return the value stored

随机推荐