Z3给出了PDR引擎的意外结果

时间:2017-10-06 10:58:29

标签: z3

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

为了您的好奇心,我使用this paper中提出的同步语言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)

我会尝试简化我的意图,因此您不必浏览论文。我们定义了三个序列memoutok,以便:

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 

我们想要证明forall n > 0. ok(n) = true

在Z3计划中,您可以将memoutok视为n - 1处的序列值(或包含之前值的记忆序列)和next_*作为n的值。

Init关系表明初始方程是正确的(即n = 0的方程式),在我们的例子中,我们只有mem = 0out和{{ 1}}是免费的(那是规则1)。 ok关系确定Trans - th值与n - th值之间的关系是正确的(即规则2)。

n - 1关系表明,对于某个Main,序列的值与给定的等式一致(我不确定这是最好的方法)解释它,如果不清楚,请告诉我)。因此,规则3指出,如果n > 0处的记忆与这些记忆之间的关系与n = 0处的新值之间的关系是正确的,那么我们会得到n = 1的一组连贯的值。 。规则4指出,如果我们在n = 1处有一组连贯的序列值,并且它们与n处的值之间的关系是正确的,那么我们在{{}处获得一组新的连贯序列值。 {1}}。

最后一条规则是我们要检查的属性:给定一组连贯的值,我们不能认为n + 1是假的。

当我跑步时,我得到:

n + 1

我无法理解为什么。我错过了什么吗?

修改

我继续研究这个问题,试图了解Z3对我给他的所做的事情。

我使用选项ok来运行它(我想)它使内联更少。在详细级别为1的情况下运行时,我看到在第一次应用sat (and (Main!slice!1 false) (not (>= (:var 5) 0)) (Main!slice!1 true)) 之后,我有5个规则而不是3个(请参阅下面的完整输出)。我也有以下结果:

fixedpoint.xform.inline_eager=false

这与原来的完全不同......所以,除非我对上面的选项有什么不对,我猜这是一个错误,所以我会打开一个问题。

完整输出

使用N7datalog15mk_rule_inlinerE

运行
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 <file> -smt2 -v:1

运行
(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...3 rules 0s)
(transform N7datalog13mk_coi_filterE...no-op 0s)
(transform N7datalog25mk_interp_tail_simplifierE...3 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...3 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...3 rules 0s)
Entering level 1
Entering level 2

2 query!0 closed
  true 1
 1 Main!slice!1 closed
   (not Main!slice!1_0_n) 182
  0 Main!slice!1 closed
    true 1
goals 0
sat
(and (Main!slice!1 false) (not (>= (:var 5) 0)) (Main!slice!1 true))

1 个答案:

答案 0 :(得分:0)

此行为是由于已修复的错误所致。讨论here包含纠正它的提交。