如何检测或证明递归关系是使用Z3的周期序列?

时间:2018-04-16 09:15:58

标签: recursion z3 z3py

如何检测或证明此递归关系定义了周期性序列。

这是一个例子A> 0是固定的

enter image description here

其中A,x是自然数,函数f返回自然值。

你能建议任何检测这种类型的递归关系的方法是周期序列吗?我试过跟踪SMT(Z3)程序来检测这种复发(如果我错了请纠正我)

s=Solver()
s.add(A>0)
s.add(ForAll([n],Implies(n>=0,y4(n1 + 1) == If(y4(n)<=A,y4(n) + 1,y4(n)-1))))
s.add(y4(0) == 0)
s.add(Not(ForAll([n],Exists([k],Implies(And(k>0,n>=0),y4(n)==y4(n+k))))))

查询返回"unsat"。但是我发现,对于跟随查询Z3,返回相同的结果"unsat"

s=Solver()
s.add(A>0)
s.add(ForAll([n],Implies(n>=0,y4(n1 + 1) == If(y4(n)<=A,y4(n) + 1,y4(n)+2))))
s.add(y4(0) == 0)
s.add(Not(ForAll([n],Exists([k],Implies(And(k>0,n>=0),y4(n)==y4(n+k))))))

请指出我的查询中有什么问题?如何检测或证明递归关系的另一种可能方式是周期序列?

2 个答案:

答案 0 :(得分:1)

也许

(declare-fun f (Int Int) Int)

(assert (forall ((a Int)) (= (f 0 a) 0)))
(assert (forall ((x Int) (a Int)) (=> (and (>= x 0) (>= a 0) (> (f x a) a)) (= (f (+ x 1) a) (- (f x a) 1)))))
(assert (forall ((x Int) (a Int)) (=> (and (>= x 0) (>= a 0) (<= (f x a) a)) (= (f (+ x 1) a) (+ (f x a) 1)))))
(assert (forall ((x Int) (y Int) (a Int)) (=> (and (>= x 0) (> y x) (>= a 0)) (not (= (f x a) (f y a))))))
(check-sat)

虽然没有说f是周期性的。

答案 1 :(得分:1)

请始终在样品中包含完整代码;因为你所提供的并不是人们运行和观察的有效代码。

假设您的代码实际上是以下内容:

from z3 import *
s=Solver()
A=Int('A')
n=Int('n')
k=Int('k')
y4 = Function('f', IntSort(), IntSort())
s.add(A>0)
s.add(ForAll([n],Implies(n>=0,y4(n + 1) == If(y4(n)<=A,y4(n) + 1,y4(n)-1))))
s.add(y4(0) == 0)
s.add(Not(ForAll([n],Exists([k],Implies(And(k>0,n>=0),y4(n)==y4(n+k))))))

您可以通过添加以下内容来了解​​Z3的产品:

print s.sexpr()
print s.check()

如果您运行此脚本,则会获得:

(declare-fun A () Int)
(declare-fun f (Int) Int)
(assert (> A 0))
(assert (forall ((n Int))
  (let ((a!1 (= (f (+ n 1)) (ite (<= (f n) A) (+ (f n) 1) (- (f n) 1)))))
    (=> (>= n 0) a!1))))
(assert (= (f 0) 0))
(assert (let ((a!1 (forall ((n Int))
             (exists ((k Int))
               (=> (and (> k 0) (>= n 0)) (= (f n) (f (+ n k))))))))
  (not a!1)))

unsat

你可以看到问题;你的最后一个断言说存在n,这样对于所有k周期都不会成立。 (因为你放了一个Not包装器。)显然,那是unsat

在更惯用的Z3中,我按如下方式对您的问题进行编码:

from z3 import *

s = Solver ()

A = Int ('A')
s.add(A > 0)

f = Function('f', IntSort(), IntSort())
x = Int ('x')

s.add(f(0) == 0)
s.add(ForAll(x, Implies(x >= 0, f(x + 1) == If(A >= f(x), f(x)+1, f(x)-1))))

k = Int('k')
s.add(ForAll(x, Exists(k, f(x+k) == f(x))))

print s.sexpr()
print s.check()

但期待Z3证明这将是天真的。的确,当我运行它时,我得到了:

(declare-fun A () Int)
(declare-fun f (Int) Int)
(assert (> A 0))
(assert (= (f 0) 0))
(assert (forall ((x Int))
  (let ((a!1 (= (f (+ x 1)) (ite (>= A (f x)) (+ (f x) 1) (- (f x) 1)))))
    (=> (>= x 0) a!1))))
(assert (forall ((x Int)) (exists ((k Int)) (= (f (+ x k)) (f x)))))

 [Ctrl-C]

在这种情况下,建模对我来说是正确的,但Z3无法回答,所以我不得不在一段时间后按Ctrl-C停止它。

但好处是你可以把SMTLib放在一个文件中,最后附上一个(check-sat),然后按如下方式运行Z3:

z3 -v:10 a.smt2 a.smt2

它会给你打印很多关于它正在做什么的步骤。我的猜测是它在量词实例化过程中丢失了。典型的解决方案是提供量词模式,但我不清楚在这种情况下它们会是什么。这里有一些例子 http://ericpony.github.io/z3py-tutorial/advanced-examples.htm虽然可能有所帮助。