z3中GADT的异常行为,其值等于每个整数

时间:2019-02-07 18:31:54

标签: python z3 z3py

对于对z3或对它的怪癖感兴趣的人有更深的了解,这将是一个正确的问题。

您好,我正在运行以下测试以了解GADT如何在z3 python中工作。值unfoo(bar(foo(b)))似乎等于任何整数?是这样吗?

以下是有效的测试-您能帮助解释一下为什么起作用吗?

import pytest
from z3 import Datatype, Solver, IntSort, Int

def test_stackoverflow():
    FooBar = Datatype('FooBar')
    FooBar.declare('foo', ('unfoo', IntSort()))
    FooBar.declare('bar', ('unbar', FooBar))
    FooBar = FooBar.create()

    foo = FooBar.foo
    unfoo = FooBar.unfoo
    bar = FooBar.bar
    unbar = FooBar.unbar

    solver = Solver()
    solver.push()
    a = Int('a')
    b = Int('b')
    solver.add(a == unfoo(bar(foo(b))))
    assert str(solver.check()) == "sat"
    model = solver.model()
    assert model.evaluate(a).as_long() == 1
    assert model.evaluate(b).as_long() == 0
    solver.pop()

1 个答案:

答案 0 :(得分:1)

这确实令人困惑,但是我认为z3做正确的事。

如果我们转储生成的SMT-Lib,则更容易看到发生了什么。 (在致电print solver.sepxr()之前先添加check。)我得到:

(declare-datatypes ((FooBar 0)) (((foo (unfoo Int)) (bar (unbar FooBar)))))
(declare-fun b () Int)
(declare-fun a () Int)
(assert (= a (unfoo (bar (foo b)))))

需要一些凝视,但这是其中涉及的类型:

  • bInt
  • (foo b)FooBar,但特别是它具有构造函数foo
  • (bar (foo b))FooBar,但特别是它具有构造函数bar
  • (unfoo (bar (foo b))Int,但是它将unfoo选择器应用于由bar构造的对象。

其中存在一个问题:您已经用其他构建的术语“破坏了”术语。

针对此类情况的典型“ SMTLib”答案是“未指定”。就是说,逻辑不保证什么成立,因此允许求解器以其想要的任何方式实例化。因此,您得到的模型是正确的;虽然有点令人困惑。

要更好地了解这一点,请想象您将如何使用Haskell这样的语言进行编码:

data FooBar = Foo {unfoo :: Int} | Bar {unbar :: FooBar}
check a b = a == unfoo (Bar (Foo b))

让我们尝试:(ghci是Haskell解释器):

ghci> check 1 0
*** Exception: No match in record selector unfoo

啊!它告诉我们,我们搞砸了。我们可以解决吗?我们开始:

data FooBar = Foo Int | Bar {unbar :: FooBar}

unfoo :: FooBar -> Int
unfoo (Foo i) = i
unfoo (Bar _) = 1  -- Conveniently pick the result here!

check a b = a == unfoo (Bar (Foo b))

我们得到:

ghci> check 1 0
True

Voila!请注意,我是如何自己定义unfoo才能使其“令人满意”的。

本质上,z3做同样的事情。由于unfoo析构函数应用于用bar构造的事物的指定不足,因此它只是选择一种使问题可满足的解释。综上所述,当您定义诸如unfoo之类的析构函数时,您要说的是:

  • 如果您收到一个foo值,请告诉我里面的内容
  • 如果您收到非foo的值,请随便给我;只要它的类型正确并且满足我的其他限制条件即可。

这正是Z3为您所做的。我希望这很清楚。很棒的例子!