我有一个建模为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
不同i
的 s 迭代该模型。
所以这是我的问题:在这样的有状态计算中,我想将SMT 变量作为输入提供给有状态计算,有没有办法让 SMT 求解器转动曲柄以避免 SBV 的不良性能?
我想一个简化的“模型问题”是如果我有一个函数f :: St -> St
和一个谓词p :: St -> SBool
,我想解决n :: SInt
这样p (iterateN n f x0)
的问题,假设用 SBV 做这件事的推荐方法是什么Mergeable St
?
编辑:我已将整个代码上传到 Github,但请记住这不是一个最小化的示例;事实上,它甚至还不是很好的 Haskell 代码。