首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用SBV和Haskell证明符号理论

用SBV和Haskell证明符号理论
EN

Stack Overflow用户
提问于 2015-07-08 14:49:27
回答 2查看 631关注 0票数 12

我在Haskell中使用SBV (带有Z3后端)来创建一些理论证明。我想检查对于具有给定约束的所有xy (比如x + y = y + x,其中+是一个“加号运算符”,而不是加法),其他一些条件是否有效。我想定义关于+表达式的公理(比如结合性、恒等)。然后检查进一步的等式,比如检查a + (b + c) == (a + c) + b是否是有效的形式abc

我试着用这样的方法来完成它:

代码语言:javascript
复制
main = do
    let x = forall "x"
    let y = forall "y"
    out <- prove $ (x .== x)
    print "end"

但是,我们似乎不能对符号值使用.==运算符。这是缺少的功能还是错误的用法?我们能用SBV做这件事吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-08 23:40:48

通过使用未解释的分类和功能,这种推理是可能的。但是,请注意,关于这种结构的推理通常需要量化的公理,而SMT-求解器通常不太擅长用量词进行推理。

话虽如此,我还是这样做的,使用SBV。

首先,使用一些锅炉板代码来获得未解释的T类型。

代码语言:javascript
复制
{-# LANGUAGE DeriveDataTypeable #-}

import Data.Generics
import Data.SBV

-- Uninterpreted type T
data T = TBase () deriving (Eq, Ord, Data, Typeable, Read, Show)
instance SymWord T
instance HasKind T
type ST = SBV T

一旦这样做,您就可以访问未解释的类型T及其符号对应的ST。让我们声明pluszero,同样地,使用正确类型的未解释常量:

代码语言:javascript
复制
-- Uninterpreted addition
plus :: ST -> ST -> ST
plus = uninterpret "plus"

-- Uninterpreted zero
zero :: ST
zero = uninterpret "zero"

到目前为止,我们告诉SBV存在一个类型T、一个函数plus和一个常量zero;显然没有被解释。也就是说,SMT求解者除了假设它们有给定的类型之外,没有其他的假设。

我们先来证明一下0+x = x

代码语言:javascript
复制
bad = prove $ \x -> zero `plus` x .== x

如果您尝试这样做,您将得到以下响应:

代码语言:javascript
复制
*Main> bad
Falsifiable. Counter-example:
  s0 = T!val!0 :: T

SMT求解程序告诉您的是,该属性不保存,这里有一个不保存的值。值T!val!0是一个特定于Z3的响应;其他求解器可以返回其他内容。它本质上是T类型的居住者的内部标识符;除此之外,我们对它一无所知。当然,这并不是非常有用,因为您并不知道它为pluszero创建了哪些关联,但这是意料之中的。

为了证明这个属性,让我们再告诉SMT的求解者两件事。首先,plus是可交换的。第二,右边的zero并没有做任何事情。这些都是通过addAxiom调用完成的。不幸的是,您必须用SMTLib语法编写您的公理,因为SBV不支持(至少目前)支持使用Haskell编写的公理。注意,我们在这里切换到使用Symbolic monad:

代码语言:javascript
复制
good = prove $ do
         addAxiom "plus-zero-axioms"
                  [ "(assert (forall ((x T) (y T)) (= (plus x y) (plus y x))))"
                  , "(assert (forall ((x T)) (= (plus x zero) x)))"
                  ]
         x <- free "x"
         return $ zero `plus` x .== x

注意我们是如何告诉求解器x+y = y+xx+0 = x,并要求它证明0+x = x。以这种方式编写公理看起来很难看,因为您必须使用SMTLib语法,但这就是当前的状况。现在我们有:

代码语言:javascript
复制
*Main> good
Q.E.D.

量化的公理和未解释的类型/函数并不是通过SBV接口使用的最容易的东西,但是这样您可以从中获得一些里程。如果您在公理中大量使用量词,那么求解器不太可能回答您的查询,并且很可能会响应unknown。这一切都取决于你使用的求解者,以及证明这些属性的难度。

票数 12
EN

Stack Overflow用户

发布于 2015-07-08 17:25:37

您对API的使用并不完全正确。证明数学等式的最简单的方法是使用简单的函数。例如,无界整数上的结合性可以这样表示:

代码语言:javascript
复制
prove $ \x y z -> x + (y + z) .== (x + y) + (z :: SInteger)

如果您需要更多的编程接口(有时也需要),那么您可以使用Symbolic monad,这样:

代码语言:javascript
复制
plusAssoc = prove $ do x <- sInteger "x"
                       y <- sInteger "y"
                       z <- sInteger "z"
                       return $ x + (y + z) .== (x + y) + z

我建议浏览hackage站点中提供的许多示例,以熟悉API:https://hackage.haskell.org/package/sbv

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31296186

复制
相关文章

相似问题

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