导向z3';s验证搜索

导向z3';s验证搜索,z3,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

我试图让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
(定义娱乐记录功率((x!1 Int)(x!2 Int))Int
(若(
(和(>=B0)(>=C0))
(=(战俘a(+b c))(*(战俘a c)(战俘a b)))
:模式((电源a(+b c()()())))
; 小箱子
(assert(forall((a Int))(=1(pow a 0)))
(assert(for all((a Int))(=a(pow a 1)))
(断言(对于所有((a Int))(=(*a)(pow a 2)))
(断言(对于所有((a Int))(=(*a a)(pow a 3)))
; 我们的问题
(声明常量x Int)
(声明常量i Int)
(断言(>=i0))
; 通过拆分和2的小案例,这应该是不可证明的
(断言(不是((*(*x)(pow xi))(pow x(+i2()))
(检查sat);超时
我是否错误地使用了模式,是否有一种方法可以为校对搜索提供更有力的提示,或者有一种更简单的方法可以实现我想要的功能?

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

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

(set-option :auto_config false)
(set-option :smt.mbqi false)
接下来,我引入了一个意想不到的
plus
函数,并将
+
的每个应用程序替换为
plus
。这足以使您的断言得到验证(即,yield
unsat
)。当然,您也可以根据
+
公理化,即

(declare-fun plus (Int Int) Int)

(assert (forall ((a Int) (b Int)) 
  (! (= (plus a b) (+ a b))
   :pattern ((plus a b)))))
但是您的断言已经在没有
plus
的定义公理的情况下进行了验证