Arrays Z3中的量词和数组

Arrays Z3中的量词和数组,arrays,z3,quantifiers,Arrays,Z3,Quantifiers,Z3使用数组上的量词回答未知代码: (declare-const ia Int) (declare-const ib Int) (declare-const la Int) (declare-const lb Int) (declare-const A (Array Int Int)) (declare-const a (Array Int Int)) (declare-const b (Array Int Int)) (assert (exists ((ia_1

Z3使用数组上的量词回答未知代码:

(declare-const ia Int)
(declare-const ib Int)
(declare-const la Int)
(declare-const lb Int)
(declare-const A (Array Int Int))
(declare-const a (Array Int Int))
(declare-const b (Array Int Int))

(assert 
    (exists 
        ((ia_1 Int) (ia_2 Int) (ib_1 Int) (la_0 Int) (lb_0 Int) (A_0 (Array Int Int)) (a_0 (Array Int Int)) (b_0 (Array Int Int)))
        (and (= ia ia_2) (= ib ib_1) (= la la_0) (= lb lb_0) (= A A_0) (= a a_0) (= b b_0) (= ia_1 0) (= ib_1 0) (< ia_1 la_0) (< ib_1 lb_0) (< (select a_0 ia_1) (select b_0 ib_1)) (= ia_2 (+ ia_1 1)))))

(assert 
    (not 
        (exists 
            ((ia_1 Int) (ib_1 Int) (la_0 Int) (lb_0 Int) (A_0 (Array Int Int)) (a_0 (Array Int Int)) (b_0 (Array Int Int)))
            (and (= ia ia_1) (= ib ib_1) (= la la_0) (= lb lb_0) (= A A_0) (= a a_0) (= b b_0) (= ib_1 0)))))

(check-sat)
在这种情况下,有没有办法获得正确答案


编辑:如果将约束=ia_1 0添加到第二个连词中,则Z3使用sat正确回答。

此处,unknown是正确答案。一般来说,数组上的量词是不可判定的,至少在进一步的假设下是不可判定的。Z3放弃了这个例子,因为它的默认量词实例化启发法没有选择正确的实例化模式。有关更多信息,请参阅上的部分

我们可以指定自己的实例化模式来帮助Z3,或者我们至少可以重述这个问题,以便启发式算法自动找到正确的模式。在本例中,我成功地重写了第二个量词,如下所示:

(assert 
    (forall ((la_0 Int) (lb_0 Int) (A_0 (Array Int Int)))
            (and 
                (= A A_0) 
                (= la la_0) 
                (= lb lb_0)
                (forall ((b_0 (Array Int Int)) (ib_1 Int))
                    (and 
                        (= b b_0)
                        (= ib ib_1)
                        (= ib_1 0)
                        (forall ((a_0 (Array Int Int)) (ia_1 Int))
                            (not (and (= ia ia_1) (= a a_0))))                       
                        )))))

每个子量词的参数越少,我认为它越有可能找到有用的东西,但这当然并不总是足够的。

这里,unknown是一个正确的答案。一般来说,数组上的量词是不可判定的,至少在进一步的假设下是不可判定的。Z3放弃了这个例子,因为它的默认量词实例化启发法没有选择正确的实例化模式。有关更多信息,请参阅上的部分

我们可以指定自己的实例化模式来帮助Z3,或者我们至少可以重述这个问题,以便启发式算法自动找到正确的模式。在本例中,我成功地重写了第二个量词,如下所示:

(assert 
    (forall ((la_0 Int) (lb_0 Int) (A_0 (Array Int Int)))
            (and 
                (= A A_0) 
                (= la la_0) 
                (= lb lb_0)
                (forall ((b_0 (Array Int Int)) (ib_1 Int))
                    (and 
                        (= b b_0)
                        (= ib ib_1)
                        (= ib_1 0)
                        (forall ((a_0 (Array Int Int)) (ia_1 Int))
                            (not (and (= ia ia_1) (= a a_0))))                       
                        )))))

每个子量词的参数越少,它就越有可能找到一些有用的东西,但这当然并不总是足够的。

尽管如此,我认为我可能通过不到处传播一些否定来加强它!谢谢你的回答,但正如你提到的,你的重写并不等同于OP第二个断言中的否定。同样,我对你的命题仍然有一个未知的答案。另外,我的意思是正确的答案,因为可以证明OP中两个断言的结合是不正确的,而不是Z3工作不正常。在玩了一点Z3之后,通过删除第一个断言的量词,并从第二个断言中删除not,我得到了sat答案。既然我基本上是在试图证明逻辑结果,那么我应该尝试用一个否定的表达式来获得一个未回答的答案吗?这个否定的表达式即使在传播到子表达式时也会给出未知的结果,或者我应该对此感到高兴吗?尽管如此,我认为我可能通过不在这里和那里传播几个否定来加强它!谢谢你的回答,但正如你提到的,你的重写并不等同于OP第二个断言中的否定。同样,我对你的命题仍然有一个未知的答案。另外,我的意思是正确的答案,因为可以证明OP中两个断言的结合是不正确的,而不是Z3工作不正常。在玩了一点Z3之后,通过删除第一个断言的量词,并从第二个断言中删除not,我得到了sat答案。既然我基本上是在试图证明逻辑结果,我应该尝试用一个否定的表达式来获得一个未回答的答案,即使在将否定传播到子表达式中时,该表达式也会给出未知的结果,还是我应该对此感到高兴?