在SMT: check uniqueness and totality of function中,我给出了一个公理化的函数,并向Z3询问了一个模型。然而,因为在其中使用量词来解决某些事情一般是不可判定的,所以Z3超时。
这是一个修改版本,其中“int”案例被建模为单个值:
(declare-datatypes () ((ABC int error none)))
(declare-fun f (ABC ABC) ABC)
(assert (forall ((x ABC)) (=> (or (= x int) (= x error) (= x none)) (= (f none x) none))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error) (= x none)) (= (f x none) none))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error)) (= (f error x) error))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error)) (= (f x error) error))))
(assert (forall ((x ABC) (y ABC)) (=> (and (= x int) (= y int)) (= (f x y) int))))
(check-sat)
(get-model)
因为现在有很多案例,Z3会迅速给出答案:
sat
(model
(define-fun k!26 ((x!0 ABC)) ABC
(ite (= x!0 error) error
(ite (= x!0 int) int
none)))
(define-fun f!28 ((x!0 ABC) (x!1 ABC)) ABC
(ite (and (= x!0 error) (= x!1 int)) error
(ite (and (= x!0 int) (= x!1 error)) error
(ite (and (= x!0 error) (= x!1 error)) error
(ite (and (= x!0 int) (= x!1 int)) int
none)))))
(define-fun k!27 ((x!0 ABC)) ABC
(ite (= x!0 error) error
(ite (= x!0 int) int
none)))
(define-fun f ((x!0 ABC) (x!1 ABC)) ABC
(f!28 (k!27 x!0) (k!26 x!1)))
)
k!26
和k!27
实际上只返回他们的输入(通过检查所有三种情况很容易看出这一点)。是否可以通过自动消除这两个功能来简化模型?
最好我希望有类似下面的东西,虽然我看到这可能是不可能的:
(define-fun f ((x!0 ABC) (x!1 ABC)) ABC
(ite (or (= x!0 none) (= x!1 none)) none
(ite (or (= x!0 error) (= x!1 error)) error
int)))
我正在使用Z3Py,但欢迎一般Z3特定和Z3Py特定答案。
答案 0 :(得分:1)
我不认为你可以做很多事情来引导Z3在这里提供一个“更简单”的答案;因为生成的模型取决于证明是如何完成的,即使对问题进行简单的更改也会产生不可预测的结果。特别是,您获得的模型可能会随着Z3的下一个版本而改变。
话虽如此,一个常见的伎俩是模型中的cdt1003
个术语。由于您当前的问题仅涉及有限域,因此您可以枚举它。如果在脚本末尾添加以下行:
eval
然后Z3将打印:
(eval (f int int))
(eval (f int error))
(eval (f int none))
(eval (f error int))
(eval (f error error))
(eval (f error none))
(eval (f none int))
(eval (f none error))
(eval (f none none))
也许您可以使用该输出自己构建一个“更简单”的模型。当然,这仅在域有限时才有效;但您可以使用相同的技巧来评估输入域的“有趣”部分,具体取决于您的问题。