为什么 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
。此函数可以对任何类型的对象(Int
、Bool
、Real
等)进行操作,但它始终被称为 distinct
。 (我们没有 distinct-int
、distinct-bool
等)解算器通过做一些分析来“区分”你的意思,但如果它不能,你可以帮助它连同一个as
声明也是如此。所以,理论符号可以这样重载,=
、+
、*
等也是如此。当然,SMTLib不是 允许用户定义此类重载名称,但正如文档第 91 页脚注 29 中所述,将来可能会删除此限制。
我对 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
话虽如此,我同意你引用的文件部分对此不是很清楚,也许可以使用一些澄清文本。
关于允许这种用法的动机是什么:有两个主要原因。第一个是简化 SMTLib 的生成。请注意,SMTLib 通常不适合手写。它通常由在底层使用 SMT 求解器的更高级别的系统生成。因此,当您将 SMTLib 用作高级系统和求解器本身之间的中间语言时,只要它们可以通过显式排序注释进行区分,就可以灵活地允许符号共享名称。但是,当您手动编写 SMTLib 时,如果可以的话,您可能应该避免这种重复,如果没有别的,为了清楚起见。
第二个原因是允许使用有限形式的“重载”。例如,考虑 SMTLib 函数 distinct
。此函数可以对任何类型的对象(Int
、Bool
、Real
等)进行操作,但它始终被称为 distinct
。 (我们没有 distinct-int
、distinct-bool
等)解算器通过做一些分析来“区分”你的意思,但如果它不能,你可以帮助它连同一个as
声明也是如此。所以,理论符号可以这样重载,=
、+
、*
等也是如此。当然,SMTLib不是 允许用户定义此类重载名称,但正如文档第 91 页脚注 29 中所述,将来可能会删除此限制。