Z3在PDR引擎中产生意外结果

Z3在PDR引擎中产生意外结果,z3,Z3,我正在验证用同步编程语言编写的方程的属性,通过使用PDR引擎将所述语言编译为Z3。我使用一周前从Github的主分支编译的Z34.5.1 出于好奇,我使用了中提出的从同步语言Lustre到Z3的一个派生翻译(但没有必要阅读它来理解我想做什么) 我对以下程序有一个问题,它返回sat,而我认为它应该返回unsat: (declare-var out Int) (declare-var next_out Int) (declare-var mem Int) (declare-var next_mem

我正在验证用同步编程语言编写的方程的属性,通过使用PDR引擎将所述语言编译为Z3。我使用一周前从Github的主分支编译的Z34.5.1

出于好奇,我使用了中提出的从同步语言Lustre到Z3的一个派生翻译(但没有必要阅读它来理解我想做什么)

我对以下程序有一个问题,它返回
sat
,而我认为它应该返回
unsat

(declare-var out Int)
(declare-var next_out Int)
(declare-var mem Int)
(declare-var next_mem Int)
(declare-var ok Bool)
(declare-var next_ok Bool)
(declare-rel Init (Int Int Bool))
(declare-rel Trans (Int Int Bool Int Int Bool))
(declare-rel Main (Int Int Bool))
(declare-rel Error ())

(rule (=> (= mem 0) (Init out mem ok)))
(rule (=> (and (= next_ok (>= next_out 0))
               (= next_mem (+ mem 1))
               (= next_out mem))
          (Trans out mem ok next_out next_mem next_ok)))
(rule (=> (and (Init out mem ok)
               (Trans out mem ok next_out next_mem next_ok))
          (Main next_out next_mem next_ok)))
(rule (=> (and (Trans out mem ok next_out next_mem next_ok)
               (Main out mem ok))
          (Main next_out next_mem next_ok)))
(rule (=> (and (Main out mem ok)
               (not ok))
          Error))

(query Error :print-certificate true)
我会尽量简化我的意图,这样你就不用看论文了。我们定义了三个序列
mem
out
ok
,以便:

forall n > 0. mem(n) = mem(n - 1) + 1 with mem(0) = 0
and           out(n) = mem(n - 1)
and           ok(n) = out(n) >= 0 
我们想证明所有n>0的
。正常(n)=真

在Z3程序中,您可以将
mem
out
ok
视为
n-1处序列的值(或包含序列先前值的存储器)和
next.*
视为
n
处的值

Init
关系表明初始方程是正确的(即
n=0
的方程),在我们的例子中,只有
mem=0
,而
out
ok
是自由的(这是规则1)。
Trans
关系确定了
n
-th值和
n-1
-th值之间的关系是正确的(这是规则2)

Main
关系表明,对于某个
n>0
,序列的值与给定的方程一致(我不确定这是最好的解释方法,如果不清楚,请告诉我)。因此,规则3规定,如果
n=0
处的存储器之间的关系以及这些存储器与
n=1
处的新值之间的关系是正确的,那么我们得到
n=1
的一组一致的值。规则4规定,如果我们在
n
处有一组连贯的序列值,并且它们与
n+1
处的值之间的关系是正确的,那么我们在
n+1
处得到一组新的连贯序列值

最后一条规则是我们要检查的属性:给定一组一致的值,我们不能让
ok
为false

当我运行此程序时,我得到:

sat
(and (Main!slice!1 false) (not (>= (:var 5) 0)) (Main!slice!1 true))
我不明白为什么。我错过什么了吗

编辑

我继续研究这个问题,试图理解Z3是如何处理我给他的东西的

我使用选项
fixedpoint.xform.inline\u eager=false运行它,这(我想)会使它的内联更少。当使用详细级别1运行时,我发现在第一次应用
N7datalog15mk_rule_inlinerE
后,我有5条规则,而不是3条(完整输出见下文)。我还得到了以下结果:

unsat
(define-fun I ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (>= x!1 0))
(define-fun T ((x!0 Int) (x!1 Int) (x!2 Bool) (x!3 Int) (x!4 Int) (x!5 Bool)) Bool
  (and (<= (+ x!1 (* (- 1) x!4)) (- 1)) (= x!5 (>= x!1 0))))
(define-fun M ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (and x!2 (>= x!1 1)))
使用
z3-smt2-v:1 fixedpoint.xform.inline\u eager=false运行

(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...6 rules 0s)
(transform N7datalog27mk_quantifier_instantiationE...no-op 0s)
(transform N7datalog8mk_scaleE...no-op 0s)
(transform N7datalog18mk_karr_invariantsE...no-op 0s)
(transform N7datalog14mk_array_blastE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog12mk_bit_blastE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...5 rules 0s)
(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...5 rules 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...5 rules 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog8mk_sliceE...no-op 0s)
Entering level 1
Entering level 2
Entering level 3
(define-fun Init ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (>= x!1 0))
(define-fun Main ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (and (>= x!1 1) x!2))
(define-fun Trans ((x!0 Int)
 (x!1 Int)
 (x!2 Bool)
 (x!3 Int)
 (x!4 Int)
 (x!5 Bool)) Bool
  (and (<= (+ x!1 (* (- 1) x!4)) (- 1)) (= x!5 (>= x!1 0))))
unsat
(define-fun Init ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (>= x!1 0))
(define-fun Main ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (and x!2 (>= x!1 1)))
(define-fun Trans ((x!0 Int)
 (x!1 Int)
 (x!2 Bool)
 (x!3 Int)
 (x!4 Int)
 (x!5 Bool)) Bool
  (and (<= (+ x!1 (* (- 1) x!4)) (- 1)) (= x!5 (>= x!1 0))))
(转换N7datalog13mk_coi_filterE…无操作0)
(转换N7datalog25mk_interp_tail_simplifierE…6个规则0)
(转换N7datalog27mk_量词_实例化…无操作0)
(转换N7datalog8mk_缩放…无操作0)
(转换N7datalog18mk_karr_不变量…无操作0)
(转换N7datalog14mk_阵列_爆炸…无操作0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog12mk_位\u爆破…无操作0)
(转换N7datalog15mk_规则\u内联…5个规则0)
(转换N7datalog13mk_coi_filterE…无操作0)
(转换N7datalog25mk_interp_tail_simplifierE…5个规则0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog15mk_规则_内联线…无操作0)
(转换N7datalog13mk_coi_filterE…无操作0)
(转换N7datalog25mk_interp_tail_simplifierE…5个规则0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog15mk_规则_内联线…无操作0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog15mk_规则_内联线…无操作0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog15mk_规则_内联线…无操作0)
(转换N7datalog22mk_包含检查…无操作0)
(转换N7datalog8mk_切片…无操作0)
进入一级
进入二级
进入三级
(定义fun Init((x!0 Int)(x!1 Int)(x!2 Bool))Bool
(>=x!10))
(定义趣味主打((x!0 Int)(x!1 Int)(x!2 Bool))Bool
(和(>=x!11)x!2))
(定义趣味转换((x!0 Int)
(x!1整数)
(x!2布尔)
(x!3 Int)
(x!4 Int)
(x!5 Bool)Bool
(和(=x!10)))
未售出
(定义fun Init((x!0 Int)(x!1 Int)(x!2 Bool))Bool
(>=x!10))
(定义趣味主打((x!0 Int)(x!1 Int)(x!2 Bool))Bool
(和x!2(>=x!1)))
(定义趣味转换((x!0 Int)
(x!1整数)
(x!2布尔)
(x!3 Int)
(x!4 Int)
(x!5 Bool)Bool
(和(=x!10)))

此行为是由于一个现已修复的错误造成的。讨论中包含对其进行更正的提交

(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...6 rules 0s)
(transform N7datalog27mk_quantifier_instantiationE...no-op 0s)
(transform N7datalog8mk_scaleE...no-op 0s)
(transform N7datalog18mk_karr_invariantsE...no-op 0s)
(transform N7datalog14mk_array_blastE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog12mk_bit_blastE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...5 rules 0s)
(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...5 rules 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...5 rules 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog15mk_rule_inlinerE...no-op 0s)
(transform N7datalog22mk_subsumption_checkerE...no-op 0s)
(transform N7datalog8mk_sliceE...no-op 0s)
Entering level 1
Entering level 2
Entering level 3
(define-fun Init ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (>= x!1 0))
(define-fun Main ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (and (>= x!1 1) x!2))
(define-fun Trans ((x!0 Int)
 (x!1 Int)
 (x!2 Bool)
 (x!3 Int)
 (x!4 Int)
 (x!5 Bool)) Bool
  (and (<= (+ x!1 (* (- 1) x!4)) (- 1)) (= x!5 (>= x!1 0))))
unsat
(define-fun Init ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (>= x!1 0))
(define-fun Main ((x!0 Int) (x!1 Int) (x!2 Bool)) Bool
  (and x!2 (>= x!1 1)))
(define-fun Trans ((x!0 Int)
 (x!1 Int)
 (x!2 Bool)
 (x!3 Int)
 (x!4 Int)
 (x!5 Bool)) Bool
  (and (<= (+ x!1 (* (- 1) x!4)) (- 1)) (= x!5 (>= x!1 0))))