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

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 cabal-packages

    在一个目录中包含多个 cabal 软件包的推荐方法是什么 Why 我有一个包含许多可分离模块的旧项目 由于最初它们只形成一个程序 因此将它们放在同一目录中以便于编译非常方便 而且现在仍然如此 Options 只是忍受并将所有内容 包括保存内
  • Haskell GHC:具有 N 个构造函数的模式匹配的时间复杂度是多少?

    假设我们有以下 Haskell data T T0 T1 T2 TN toInt T gt Int toInt t case t of T0 gt 0 T1 gt 1 T2 gt 2 TN gt N 这里使用什么算法来执行模式匹配 我看到两
  • 仪器化状态单子

    我正在努力给予Monad and MonadState的实例State 计算的数量 gt gt return get and put运营 data Counts Counts binds Int returns Int gets Int p
  • 当单态限制打开*时,如何解决歧义问题?

    因此 在学习 Haskell 时 我很快就遇到了可怕的单态限制 在 ghci 中 Prelude gt let f print show Prelude gt f 5
  • 如何向 Scotty 中间件添加基本身份验证?

    我目前正在制作 Scotty API 但找不到任何 basicAuth 实现的示例 Wai Middleware HttpAuth 具体来说 我想将基本身份验证标头 用户 通行证 添加到我的某些端点 即以 admin 开头的端点 我已经设置
  • Haskell 二进制解析

    我一直在尝试在 haskell 中实现一个协议解析器 而且我对这门语言还很陌生 特别是当涉及到 monad 时 我一直在使用binary 0 5 0 2 并描述了协议的标头和所有有效负载 我想要解析的消息如下所示 header payloa
  • 如何、为什么以及何时使用“.Internal”模块模式?

    我在上面看到了几个包裹hackage http hackage haskell org packages archive pkg list html其中包含模块名称 Internal作为他们的姓氏组成部分 例如Data ByteString
  • 'lens' 的阴谋集团依赖性解析失败

    我刚刚做了一个阴谋更新并尝试从 hackage 安装 lens 这给了我以下错误 cabal install j lens Resolving dependencies Configuring dlist 0 7 0 1
  • 如何将只缓存某些内容的字段添加到ADT?

    我经常需要向 ADT 添加字段 仅记住一些冗余信息 但我还没有完全弄清楚如何又好又高效地做到这一点 说明问题的最好方法是举个例子 假设我们正在使用无类型 lambda 项 type VSym String data Lambda Var V
  • 对元组列表进行排序的函数 - Haskell

    抱歉 这个简单的问题只是我对 haskell 非常陌生 我正在尝试编写一个函数 order 它将对另一个函数 Frequency 生成的元组列表进行排序 频率计算列表中不同元素的数量 a给出一个这样的结果 比如 gt 频率 aabbbccc
  • 存在函数依赖关系时类型推断如何工作

    考虑下面的代码 LANGUAGE MultiParamTypeClasses FlexibleInstances FunctionalDependencies UndecidableInstances FlexibleContexts cl
  • 反应性香蕉时间延迟

    我已经查阅了文档反应香蕉 http hackage haskell org package reactive banana 而且我找不到指定明确时间延迟的方法 举例来说 我想采取Event t a并将其所有发生的事件移至未来 1 秒 或获取
  • 为什么 exceptT 没有 MonadMask 实例?

    爱德华 克梅特例外情况图书馆不提供单子掩码 https www stackage org haddock lts 7 18 exceptions 0 8 3 Control Monad Catch html t MonadMask实例为Ex
  • 什么是阴谋地狱?

    在阅读有关 阴谋地狱 的内容时 我有点困惑 因为这个词的含义太多了 我猜最初 Cabal Hell 指的是钻石依赖问题 该问题是通过限制构建计划在每个构建计划中只有任何包的单个版本来解决的 一个包的两个不同版本不能存在于单个构建计划中 正如
  • 嵌套在其他 monad 中的 IO 操作未执行

    我有一个 foobar IO ParseResult String String ParseResult 是一个在这里定义的 monad https hackage haskell org package haskell src exts
  • 管道中缺少 ResourceT 实例

    我在尝试使用时遇到奇怪的错误ResourceT http hackage haskell org package conduit 1 0 9 1 docs Data Conduit html t 3aResourceT来自管道 1 0 9
  • Haskell 和 Idris 之间的区别:类型宇宙中运行时/编译时的反映

    因此 在 Idris 中 编写以下内容是完全有效的 item b Bool gt if b then Nat else List Nat item True 42 item False 1 2 3 cf https www youtube
  • Haskell 中的类型化抽象语法和 DSL 设计

    我正在 Haskell 中设计 DSL 我想要进行赋值操作 像这样的东西 下面的代码只是为了在有限的上下文中解释我的问题 我没有类型检查 Stmt 类型 data Stmt forall a Assign String Exp a Assi
  • 使用 Haskell 将函数注入到 Java .class 文件中

    我使用 Haskell 编写了一个 Java 字节码解析器 它工作得很好 然而下一步让我完全难住了 我的 Haskell 程序需要修改 class 文件 以便在执行时 Java 程序打印 输入 此处的方法名称 在执行方法之前 并且 退出 此
  • Haskell 排列库函数 - 请澄清一下?

    这是代码permutationsHaskell 中的函数Data List module permutations a gt a permutations xs0 xs0 perms xs0 where perms perms t ts i

随机推荐