首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell SBV中的状态序列不满足约束

Haskell SBV中的状态序列不满足约束
EN

Stack Overflow用户
提问于 2020-10-26 13:47:48
回答 1查看 67关注 0票数 0

我有一个符号枚举,如下所示:

代码语言:javascript
复制
data State = Start | Dot
mkSymbolicEnumeration ''State

定义了用于计算一个状态在序列中是否有效的函数(相对于前一个状态),这样sDot只应该在sStart之前,而sStart只应该前面有sDot -在理论上,这意味着我们的序列中永远不应该有两个连续的sStartsDot

代码语言:javascript
复制
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 /= 0seq !! i都要满足validSequence

代码语言:javascript
复制
-- 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中时,我得到的结果与我所期望的不同:

代码语言:javascript
复制
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库):

代码语言:javascript
复制
{-# 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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-26 13:56:45

代码语言:javascript
复制
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)

等于

代码语言:javascript
复制
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解决程序的正确公式。

也许您需要类似于(伪代码)的内容:

代码语言:javascript
复制
validSequence seq i = 
    (p2 .== sStart .&& p1 .== sDot) .||
    (p1 .== sStart .&& p2 .== sDot)
   where p1 = seq .!! (i-1)
         p2 = seq .!! i

编辑:基于上述伪代码的实际工作实现,但遵循SBV的DSL:

代码语言:javascript
复制
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)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64538406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档