【发布时间】:2019-01-24 17:19:21
【问题描述】:
我正在尝试使用 SBV Library(版本 7.12)解决以下涉及 Haskell 中祖先关系的 csp:
给我所有不是斯蒂芬后裔的人的集合。
我的解决方案(见下文)得到以下异常
*** Exception: SBV.Mergeable.List: No least-upper-bound for lists of differing size (1,0)
问题:是否可以使用 SBV / 使用 SMT Solver 解决此类约束,如果 - 我需要如何制定问题?
我的解决方案尝试:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveAnyClass #-}
module Main where
import Data.SBV
data Person
= Mary
| Richard
| Claudia
| Christian
| Stephen
mkSymbolicEnumeration ''Person
-- symbolic shorthands for person constructors
[mary, richard, claudia, christian, stephen] =
map literal [Mary, Richard, Claudia, Christian, Stephen]
childOf :: [(Person, Person)]
childOf = [
(Mary, Richard) ,
(Richard, Christian),
(Christian, Stephen)]
getAncestors :: Person -> [Person]
getAncestors p = go childOf p []
where
go [] _ acc = nub acc
go ((p1, p2): rels) a acc
| p1 == p = go rels p (p2:acc) ++ getAncestors p2
| otherwise = go rels a acc
-- symbolic version of getAncestors
getSAncestors :: SBV Person -> [SBV Person]
getSAncestors p = ite (p .== mary) (map literal (getAncestors Mary))
$ ite (p .== richard) (map literal (getAncestors Richard))
$ ite (p .== claudia) (map literal (getAncestors Claudia))
$ ite (p .== christian) (map literal (getAncestors Christian))
(map literal (getAncestors Stephen))
cspAncestors :: IO AllSatResult
cspAncestors = allSat $ do
(person :: SBV Person) <- free_
constrain $ bnot $ stephen `sElem` (getSAncestors person)
非常感谢!
【问题讨论】:
-
您可以为每一对人创建一个
SBool,表示一个人是否是另一个人的祖先,递归地约束他们,并使用sat来获取值。但这并不能真正让你到达你想去的地方(即以有意义的方式使用象征性的人)。但是...如果您已经有一个非符号程序来计算您关心的事物(即getAncestors),为什么还要使用 SAT 求解器? -
@DanielWagner 我想使用 sbv (smt/sat) 解决这个问题,因为它是更大 csp 的一部分——我的目标是在 sbv 的 Symbolic Monad 中组合地制定整个问题。您能否解释一下为什么上述问题的表述不起作用?我认为它与 sbv 试图合并/统一调用“getAncestors”的结果有关,但我不明白为什么首先需要这样的合并(因为列表中的所有值都应该是符号常量)...