证明任意基数的两位编码的注入性

时间:2018-08-16 23:48:29

标签: z3 smt

我想自动证明以下有关任意大小整数的陈述:

forall base a b c d,
0 <= a < base ->
0 <= b < base ->
0 <= c < base ->
0 <= d < base ->
base * a + b = base * c + d ->
b = d

这应等同于以下说法为unsat(假设生成此内容的crazy hacks是正确的):

(declare-const a Int)
(declare-const a0 Int)
(declare-const a1 Int)
(declare-const a2 Int)
(declare-const a3 Int)
(assert (not (or (not (and (<= 0 a0) (< a0 a)))
              (or (not (and (<= 0 a1) (< a1 a))) 
               (or (not (and (<= 0 a2) (< a2 a))) 
                (or (not (and (<= 0 a3) (< a3 a))) 
                 (or (not (= (+ ( * a a0) a1)
                             (+ ( * a a2) a3))) 
                     (= a1 a3))))))))
(check-sat)

如果我将其输入Z3,即使看起来很简单,它也会返回unknown

所以我的问题是:自动证明这一点的正确方法是什么? Z3是否有配置选项可以使它工作?我应该进行其他预处理吗?还是这个问题属于Z3的“专业领域”之外的一类问题,我应该使用其他工具吗?

更新:这是同一查询的可读性更高的版本,使用(implies A B)而不是(or (not A) B)

(declare-const a Int)
(declare-const a0 Int)
(declare-const a1 Int)
(declare-const a2 Int)
(declare-const a3 Int)
(assert (not (implies (and (<= 0 a0) (< a0 a))
              (implies (and (<= 0 a1) (< a1 a))
               (implies (and (<= 0 a2) (< a2 a))
                (implies (and (<= 0 a3) (< a3 a))
                 (implies (= (+ ( * a a0) a1) (+ ( * a a2) a3)) (= a1 a3))))))))
(check-sat)

1 个答案:

答案 0 :(得分:1)

由于您要进行乘法运算,因此问题是非线性的; SMT求解器通常无法处理非线性算法。 (Z3具有非线性推理引擎,但是由于不确定性,它肯定不能解决任意问题。)

如果您将base设置为给定的值,那么z3可以很轻松地解决您的问题。例如,添加:

(assert (= a 10))

使z3立即响应unsat

输入看起来也不必要地复杂;请记住,SMTLib具有隐含运算符,您可以只编写(or (not X) Y)而不是(implies X Y)来编写代码。