Z3 如果不存在值,则断言该值

Z3 如果不存在值,则断言该值,z3,Z3,我试图用Z3解决一个相当棘手的问题。这不太相关,但我正在使用.NET绑定以及最新的Z3夜间发布版 我已经总结了这个问题,但请记住,实际问题比这更复杂 在非常简短的语句中,可以选择数组的任何索引。然后我将1添加到其中,结果存储在数组的任何其他索引中。这是重复,因为经常需要。在这个过程的最后,我们选择了一个索引,我们断言它等于一个特定的值——这就是问题的症结所在 如果用户没有为计算中使用的索引赋值,则最终断言将始终成功。例如: (declare-const index1 Int) (declare-

我试图用Z3解决一个相当棘手的问题。这不太相关,但我正在使用.NET绑定以及最新的Z3夜间发布版

我已经总结了这个问题,但请记住,实际问题比这更复杂

在非常简短的语句中,可以选择数组的任何索引。然后我将1添加到其中,结果存储在数组的任何其他索引中。这是重复,因为经常需要。在这个过程的最后,我们选择了一个索引,我们断言它等于一个特定的值——这就是问题的症结所在

如果用户没有为计算中使用的索引赋值,则最终断言将始终成功。例如:

(declare-const index1 Int)
(declare-const index2 Int)
(declare-const index3 Int)

;Index2 is assigned a value according to user selections.
(assert (= index2 2))
;Index3 is assigned a value according to user selections.
(assert (= index3 5))   
;User chooses index3 to hold a result. 
(assert (= index3 (+ index1 index2)))

(check-sat)
(get-model)
此问题是可以满足的,并且导致
index1
具有值
3
index1+2=5
),但用户从未为
index1
指定值-这只是暗示

我不能直接断言
index1
的初始值应为
0
,因为在运行时,用户可以为
index1
分配不同的值


所以,当我从数组中选择一个索引,或者一个记录的选择器函数时,我想说,这个元素应该是0,除非它被覆盖。这就意味着上面的例子不满意。

您可以使用数组来存储值,并确保初始值为
0
。每次更新时,您都会得到一个经过修改的新阵列:

(declare-const array0 (Array Int Int))
(assert (= array0 ((as const (Array Int Int)) 0)))

(declare-const index1 Int)
(declare-const index2 Int)
(declare-const index3 Int)

;; Index2 is assigned a value according to user selections:
(declare-const array1 (Array Int Int))
(assert (= array1 (store array0 index2 2)))

;; Index3 is assigned a value according to user selections:
(declare-const array2 (Array Int Int))
(assert (= array2 (store array1 index3 5)))

;; final assert:
(assert (= (select array2 index3) (+ (select array2 index1) (select array2 index2))))
以下代码将“提取”相关值:

(check-sat)
(get-value (index1 index2 index3 (select array2 index1) (select array2 index2) (select array2 index3)))
注意我们如何使用
array2
,因为您有“两个”事务。通常,如果您有
N
用户选择,您将有
arrayN
。(如果您想阅读,这也被称为单一静态赋值形式。)

如果你试着这样做,z3会说:

sat
((index1 3)
 (index2 1)
 (index3 1)
 ((select array2 index1) 0)
 ((select array2 index2) 5)
 ((select array2 index3) 5))
啊,z3太聪明了!通过确保
index2
index3
相同,它找到了一个模型。我想你是有意让这些指数是不同的。让我们告诉z3事实确实如此:

(assert (distinct index1 index2 index3))
现在
(检查sat)
返回:

unsat

请注意,这只是解决此问题的一种方法。您还可以保持它的简单性,只需跟踪用户没有为哪些索引赋值并显式地将它们归零,就可以摆脱数组。但我认为基于数组的方法通常更容易使用。

对,这是关键!我只是使用store而不是select来为每个“事务”生成一个新数组。。。明亮的