我有一个符号枚举,如下所示:
data State = Start | Dot
mkSymbolicEnumeration ''State定义了用于计算一个状态在序列中是否有效的函数(相对于前一个状态),这样sDot只应该在sStart之前,而sStart只应该前面有sDot -在理论上,这意味着我们的序列中永远不应该有两个连续的sStart或sDot:
validSequence :: SList State -> SInteger -> SBool
validSequence seq i = case seq .!! i of
sStart -> p1 .== sDot -- sStart can only be preceded by sDot
sDot -> p1 .== sStart -- sDot can only be preceded by sStart
where p1 = seq .!! (i-1)然后,声明两组约束。第一个声明seq的长度应该是n,第二个组的状态比每一个具有i /= 0的seq !! i都要满足validSequence。
-- sequence should be of length n
constrain $ L.length seq .== fromIntegral n
-- apply a validSequence constraint for every i in [1..n]
mapM_ (constrain . (validSequence seq) . fromIntegral) [1..n]当我将这个模块加载到ghci中时,我得到的结果与我所期望的不同:
runSMT $ answer 10
-- expecting this: [Dot, Start, Dot, Start, Dot, Start, Dot, Start, Dot, Start]
-- or this: [Start, Dot, Start, Dot, Start, Dot, Start, Dot, Start, Dot]
-- actual result: [Dot, Dot, Dot, Dot, Dot, Dot, Dot, Dot, Dot, Dot]我不明白的是:
Dot Start 只应遵循的约束?validSequence**?** 中做错什么了吗?mapM_ 调用?完整的可复制代码如下(需要SBV库):
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
module Sandbox where
import Data.SBV
import Data.SBV.Control
import Data.SBV.List ((.!!))
import qualified Data.SBV.List as L
data State = Start | Dot
mkSymbolicEnumeration ''State
validSequence :: SList State -> SInteger -> SBool
validSequence seq i = case seq .!! i of
sStart -> p1 .== sDot -- sStart can only be preceded by sDot
sDot -> p1 .== sStart -- sDot can only be preceded by sStart
where p1 = seq .!! (i-1)
answer :: Int -> Symbolic [State]
answer n = do
seq <- sList "seq"
-- sequence should be of length n
constrain $ L.length seq .== fromIntegral n
-- apply a validSequence constraint for every i in [1..n]
mapM_ (constrain . (validSequence seq) . fromIntegral) [1..n]
query $ do cs <- checkSat
case cs of
Unk -> error "Solver returned unknown!"
DSat{} -> error "Unexpected dsat result!"
Unsat -> error "Solver couldn't find a satisfiable solution"
Sat -> getValue seq发布于 2020-10-26 13:56:45
validSequence :: SList State -> SInteger -> SBool
validSequence seq i = case seq .!! i of
sStart -> p1 .== sDot -- sStart can only be preceded by sDot
sDot -> p1 .== sStart -- sDot can only be preceded by sStart
where p1 = seq .!! (i-1)等于
validSequence :: SList State -> SInteger -> SBool
validSequence seq i = case seq .!! i of
_ -> p1 .== sDot
where p1 = seq .!! (i-1)因为sStart是一个名,如果是一个新的局部变量,它与同名的任何其他变量没有任何关系。打开GHC中的警告时,应报告此名称隐藏。
我不能建议如何解决这个问题,因为我不熟悉SBV。特别是,我看不出您要做的检查(seq .!! i) == sStart是否可以在Haskell级别执行,或者必须在SBV级别执行,以便生成要传递给SMT解决程序的正确公式。
也许您需要类似于(伪代码)的内容:
validSequence seq i =
(p2 .== sStart .&& p1 .== sDot) .||
(p1 .== sStart .&& p2 .== sDot)
where p1 = seq .!! (i-1)
p2 = seq .!! i编辑:基于上述伪代码的实际工作实现,但遵循SBV的DSL:
validSequence :: SList State -> SInteger -> SBool
validSequence seq i =
ite (cur .== sStart) (prev `sElem` [sDot])
$ ite (cur .== sDot) (prev `sElem` [sStart])
sFalse
where cur = seq .!! i
prev = seq .!! (i-1)https://stackoverflow.com/questions/64538406
复制相似问题