在Z3中创建传递和非自反函数

时间:2019-09-04 20:24:54

标签: z3

我正在尝试在Z3中创建一个可传递但不能自反的函数。即如果(transitive a b)(transitive b c)成立,则(transitive a c)应该成立,而(transitive a a)不成立。

我尝试通过以下5种“测试”方法进行操作。第一个操作符合我的预期,但是第二个操作失败并导致unknown

(declare-datatypes () ((T T1 T2 T3)))

(declare-fun f (T T) Bool)
(assert(f T1 T2))
(assert(f T2 T3))

; Make sure that f is not reflexive
(assert
  (forall ((x T))
    (not (f x x))))

; Now we create the transitivity function ourselves
(define-fun-rec transitive ((x T) (y T)) Bool
    (or 
        (f x y)
        (exists ((z T))
            (and 
                (f x z)
                (transitive z y)))))

; This works and gives sat
(push)
(assert (not (transitive T1 T1)))
(assert (not (transitive T2 T2)))
(assert (not (transitive T3 T3)))
(check-sat)
(pop)

; This fails with "unknown" and the verbose flag gives: (smt.mbqi "max instantiations 1000 reached")
(push)
(assert 
    (forall ((x T))
        (not (transitive x x))))
(check-sat)
(pop)

我的问题是:第二项测试与第一次测试有何不同?为什么最后一个给出unknown,而前面一个给出的效果很好?

1 个答案:

答案 0 :(得分:2)

“详细”消息是此处的提示。 mbqi代表基于模型的量化器实例化。这是SMT解决方案中处理量词的一种方法。在第一种情况下,MBQI设法找到一个模型。但是您的transitive函数对于MBQI来说太复杂了,因此它放弃了。增加限制可能无法解决问题,也不是长期解决方案。

长话短说,递归定义很难处理,而带量词的递归定义则更难。逻辑变得半定,而您则受试探法的支配。即使您找到了让z3为此计算模型的方法,它也将很脆弱。这些问题不适合SMT解决。最好使用适当的定理证明者,例如Isabelle,Hol,Coq,Lean。 Agda等。几乎所有这些工具都提供了“策略”来将子目标分派给SMT求解器,因此您可以两全其美。 (当然,您会失去完全的自动化功能,但是有了量词,您再也期待不到更好的了。)