【问题标题】:Why does smtlib/z3/cvc4 allow to declare the same constant more than once?为什么 smtlib/z3/cvc4 允许多次声明同一个常量?
【发布时间】:2021-10-19 22:35:19
【问题描述】:

我对 smtlib 中的 declare-const 有疑问。

例如,

在z3/cvc4中,以下程序不报错:

C:\Users\Chansey>z3 -in
(declare-const x Int)
(declare-const x Bool)

在 smt-lib-reference 中,它说

(declare-fun f (s1 ... sn) s) ... 如果当前签名中已经存在名称为 f 的函数符号,该命令将报告错误。

所以s这个排序包含在x的整个签名中,对吗?

但是为什么会这样呢?背后的动机是什么?

据我了解,x 是变量标识符,通常(例如在某些通用编程语言中)我们不允许使用不同类型声明相同的变量。所以我觉得上面的代码最好报错。

我曾经想过也许z3/smtlib可以支持重定义?,但不是……

C:\Users\Chansey>z3 -in
(declare-const x Int)
(declare-const x Bool)
(assert (= x true))
(error "line 3 column 11: ambiguous constant reference, more than one constant with the same sort, use a qualified expre
ssion (as <symbol> <sort>) to disambiguate x")

那么上面的代码肯定是错的,为什么不早点报错呢?

PS。如果我用同样的排序,那么会报错(太好了,希望Bool的情况也能报错):

C:\Users\Chansey>z3 -in
(declare-fun x () Int)
(declare-fun x () Int)
(error "line 2 column 21: invalid declaration, constant 'x' (with the given signature) already declared")

谢谢。

【问题讨论】:

    标签: z3 smt cvc4 smt-lib


    【解决方案1】:

    在 SMTLib 中,符号不仅通过其名称来标识,而且还通过其排序来标识。正如您所观察到的,只要您有不同的类型,使用相同的名称就可以了。这是一个例子:

    (set-logic ALL)
    (set-option :produce-models true)
    (declare-fun x () Int)
    (declare-fun x () Bool)
    
    (assert (= (as x Int) 4))
    (assert (= (as x Bool) true))
    (check-sat)
    (get-model)
    (get-value ((as x Int)))
    (get-value ((as x Bool)))
    

    打印出来:

    sat
    (
      (define-fun x () Bool
        true)
      (define-fun x () Int
        4)
    )
    (((as x Int) 4))
    (((as x Bool) true))
    

    请注意我们如何使用as 构造来消除两个x 之间的歧义。这在http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2021-05-12.pdf的第 3.6.4 节中进行了解释

    话虽如此,我同意你引用的文件部分对此不是很清楚,也许可以使用一些澄清文本。

    关于允许这种用法的动机是什么:有两个主要原因。首先是简化生成 SMTLib。请注意,SMTLib 通常不是手写的。它通常由使用 SMT 求解器的高级系统生成。因此,当您将 SMTLib 用作高级系统和求解器本身之间的中间语言时,灵活地允许符号共享名称(只要它们可以通过显式排序注释区分)是有益的。但是,当您手动编写 SMTLib 时,您可能应该尽可能避免这种重复,以保持清晰。

    第二个原因是允许使用有限形式的“重载”。例如,想想 SMTLib 函数distinct。此函数可以对任何类型的对象(IntBoolReal 等)进行操作,但它始终称为distinct。 (我们没有distinct-intdistinct-bool 等。)求解器通过做一些分析“区分”你的意思,但如果它不能,你可以通过as 声明来帮助它也是。因此,理论符号可以通过这种方式重载,=+* 等也是如此。当然,SMTLib 不允许用户定义这样的重载名称,但正如文档在第 91 页的脚注 29 中所述,将来可能会删除此限制。

    【讨论】:

    • 解释非常清楚。非常感谢!
    • @chansey 添加了关于这种用法如何启用临时多态性的另一条注释,尽管此功能暂时仅保留给理论符号。 (但将来也可以放宽用户定义的符号。)
    • 您好,很抱歉再次打扰您。我似乎找到了一种暂时删除此功能的方法,例如(declare-const x Int) (declare-const x Bool)。我希望第二个声明返回一个错误。所以我可以将这两个声明重新定义为:(declare-fun x () Int) (assert (= (as x Int) x)) (declare-fun x () Bool) (assert (= (as x Bool) x)),然后按预期报错。您如何评价这种方法?是否可以将其用作希望符号只能在 SMT 社区中声明为唯一类型的约定?谢谢。
    • @chansey 我不确定。看起来 z3 和 cvc4 在这种情况下都会发出错误,但我不清楚这是否是标准要求的行为。也就是说,通过正确解析引用,不同的求解器可能会按原样接受它而不会抱怨。您可能想在 smt-lib 邮件列表中询问进一步说明:groups.google.com/g/smt-lib
    猜你喜欢
    • 1970-01-01
    • 2014-12-02
    • 2021-02-02
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 2020-08-10
    • 2018-07-29
    相关资源
    最近更新 更多