指导z3的证明搜索

时间:2018-05-13 09:30:01

标签: z3

我试图让z3工作(大部分时间)用于非常简单的非线性整数算术问题。不幸的是,我在取幂时遇到了一些问题。我希望能够处理像x ^ {a + b + 2} =(x * x * x ^ {a} * x {b})这样的问题。我只需要处理非负指数。

我尝试将取幂作为递归函数重新定义(以便它只允许为任何非正指数返回1)并使用模式来促进z3推断x ^ {a + b} = x ^ {a} * x ^ {b},但它似乎无法正常工作 - 我还在超时。

(define-fun-rec pow ((x!1 Int) (x!2 Int)) Int
  (if (<= x!2 0) 1 (* x!1 (pow x!1 (- x!2 1)))))
; split +
(assert (forall ((a Int) (b Int) (c Int)) 
  (! (=> 
      (and (>= b 0) (>= c 0)) 
      (= (pow a (+ b c)) (* (pow a c) (pow a b)))) 
   :pattern ((pow a (+ b c))))))

; small cases
(assert (forall ((a Int)) (= 1 (pow a 0))))
(assert (forall ((a Int)) (= a (pow a 1))))
(assert (forall ((a Int)) (= (* a a) (pow a 2))))
(assert (forall ((a Int)) (= (* a a a) (pow a 3))))

; Our problem
(declare-const x Int)
(declare-const i Int)
(assert (>= i 0))

; This should be provably unsat, by splitting and the small case for 2
(assert (not (= (* (* x x) (pow x i)) (pow x (+ i 2)))))

(check-sat) ;times out

我是否错误地使用了模式,是否有办法为证明搜索提供更强的提示,或者更容易实现我想要的方式?

1 个答案:

答案 0 :(得分:3)

模式(也称为触发器)可能只包含未解释的函数。由于+是一个解释函数,因此你基本上提供了一个无效的模式,在这种情况下几乎任何事情都可能发生。

作为第一步,我禁用了Z3的自动配置功能以及基于MBQI的量词实例化:

(set-option :auto_config false)
(set-option :smt.mbqi false)

接下来,我介绍了一个未解释的plus函数,并将+的每个应用程序替换为plus。这足以使你的断言验证(即收益unsat)。你当然也可以用plus来区分+,即

(declare-fun plus (Int Int) Int)

(assert (forall ((a Int) (b Int)) 
  (! (= (plus a b) (+ a b))
   :pattern ((plus a b)))))

但是如果没有plus的定义公理,你的断言就已经验证了。