List Z3列表包含函数公理化的不同方法

List Z3列表包含函数公理化的不同方法,list,encoding,z3,axiom,List,Encoding,Z3,Axiom,将列表()上的contains操作公理化为 使Z3 4.0能够反驳该断言 (declare-const x Int) (assert (Seq.in nil x)) (check-sat) ; UNSAT, as expected 在我看来,这相当于公理化 (assert (forall ((xs (List Int)) (e Int)) (ite (= xs nil) (= (Seq.in xs e) false) (= (Seq.in xs e)

将列表()上的contains操作公理化为

使Z3 4.0能够反驳该断言

(declare-const x Int)
(assert (Seq.in nil x))
(check-sat) ; UNSAT, as expected
在我看来,这相当于公理化

(assert (forall ((xs (List Int)) (e Int))
  (ite (= xs nil)
    (= (Seq.in xs e) false)
    (=
      (Seq.in xs e)
      (or
        (= e (head xs))
        (Seq.in (tail xs) e))))))
结果为
未知


这可能是触发器的问题,还是列表域有什么特定的东西可以解释行为的差异?

您在rise4fun的脚本禁用了
:mbqi
引擎。因此,Z3将尝试仅使用电子匹配来解决这些问题。当没有提供模式(aka触发器)时,Z3将为我们推断触发器。Z3使用许多启发式方法来推断模式/触发器。其中一个与您的脚本相关,并解释正在发生的事情。Z3永远不会选择产生“匹配循环”的模式/触发器。我们说模式/触发器P为量词Q生成匹配循环,而Q的实例将为P生成新的匹配。 让我们考虑量词

(assert (forall ((xs (List Int)) (e Int))
  (ite (= xs nil)
    (= (Seq.in xs e) false)
    (=
      (Seq.in xs e)
      (or
        (= e (head xs))
        (Seq.in (tail xs) e))))))
Z3不会选择
(xs e中的Seq.in)
作为此量词的模式/触发器,因为它将生成匹配循环。假设我们有一个基本项
(a b中的顺序)
。该术语与模式
(xs e中的Seq.in)匹配
。用
a
实例化量词将
b
产生术语
(Seq.in(tail a)b)
,该术语也与模式
(Seq.in xs e)
匹配。 用
(tail a)
b
实例化量词将产生术语
(Seq.in(tail(tail a))b)
,该术语也与模式
(Seq.in xse)
相匹配,依此类推

在搜索过程中,Z3将使用多个阈值阻止匹配循环。但是,性能通常会受到影响。因此,默认情况下,Z3不会选择
(xse中的Seq.in)
作为模式。相反,它将选择
(Seq.in(tail xs)e)
。此模式不会生成匹配循环,但也会阻止Z3证明第二个和第三个查询不可满足。 电子匹配引擎的任何限制通常由
:mbqi
引擎处理。但是,脚本中禁用了
:mbqi

如果在脚本中为第二个和第三个查询提供模式。Z3将证明所有示例都是
unsat
。以下是您使用显式模式/触发器的示例:

即使不使用模式,第一个示例也会通过,因为只需要第一个量词就可以证明示例是
unsat

(assert (forall ((e Int))
  (not (Seq.in nil e))))

请注意,
(nile中的Seq.in)
是这个量词的完美模式,它是Z3选择的模式。

我无法重现您描述的行为。这两个示例都为我返回了
unsat
。以下是示例:,忽略上面的注释。我没有注意到您禁用了
:mbqi
引擎。非常感谢您的解释,我不知道Z3会避免产生匹配循环的模式。如果没有提供,人们可以看到Z3选择的图案吗?例如,通过将它们打印到stdio?否。在Z34.0中没有检索推断模式的好方法。我同意这是有用的信息。我将在下一版本中添加此功能。
(assert (forall ((e Int))
  (not (Seq.in nil e))))