为什么 smtlib/z3/cvc4 允许多次声明同一个常量?

Why does smtlib/z3/cvc4 allow to declare the same constant more than once?

我对 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) ... The command reports an error if a function symbol with name f is already present in the current signature.

所以 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。如果我用同样的sort,那么就会报错(那太好了,希望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")

谢谢。

在 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 中所述,将来可能会删除此限制。