为什么Z3没有使用数组和量词来解决这个简单的脚本?

时间:2018-01-11 08:55:42

标签: z3

这是一个小的Z3问题,它在本地构建的Z3 4.6.0和https://rise4fun.com/z3/tutorial上返回未知(超时):

(declare-const m1 (Array String Int))
(declare-const m2 (Array String Int))
(declare-const c Int)
(assert (or (= c 11) (= c 12)))
(assert (forall ((x String)) (= (select m1 x) 0)))
(assert (= (select m2 "0") 42))
(assert (forall ((x String)) (or (= x "0") (= (select m2 x) 0))))
(assert (= m2 (ite (= c 11) (store m1 "1" 100) (store m1 "0" 42))))
(check-sat)

我很好奇为什么z3无法证明这一点。 Z3如何处理这个问题,是否有办法确定Z3正在尝试做什么?当我使用-v:15运行时,我看到如下输出:

(smt.restarting :propagations 0 :decisions 903 :conflicts 1 :restart 100 :agility 0.00)
(smt.mbqi)
(smt.propagate-values)
(smt.nnf-cnf)
(smt.reduce-asserted)
(smt.lift-ite)
(smt.maximizing-bv-sharing)
(smt.reduce-asserted)
(smt.simplifier-done)
(smt.searching)
(smt.simplifying-clause-set :num-deleted-clauses 84)
(smt.propagate-values)
(smt.nnf-cnf)
(smt.reduce-asserted)
(smt.lift-ite)
(smt.maximizing-bv-sharing)
(smt.reduce-asserted)
(smt.simplifier-done)
(smt.searching)
(smt.mbqi :failed k!8)
(smt.propagate-values)
(smt.nnf-cnf)
(smt.reduce-asserted)
(smt.lift-ite)
(smt.maximizing-bv-sharing)
(smt.reduce-asserted)
(smt.simplifier-done)
(smt.searching)
(smt.simplifying-clause-set :num-deleted-clauses 82)
(smt.propagate-values)
(smt.nnf-cnf)
(smt.reduce-asserted)
(smt.lift-ite)
(smt.maximizing-bv-sharing)
(smt.reduce-asserted)
(smt.simplifier-done)
(smt.searching)
(smt.mbqi :failed k!10)
(smt.restarting :propagations 0 :decisions 946 :conflicts 1 :restart 100 :agility 0.00)
^C(tactic-exception "canceled")

我不完全确定该输出的内容。有没有办法在这些点上看到有关Z3状态的更多信息?

当我稍微改变问题时,它会立即完成:

(declare-const m1 (Array String Int))
(declare-const m2 (Array String Int))
(declare-const c Int)
(assert (= c 12)) ; or (= c 11)
(assert (forall ((x String)) (= (select m1 x) 0)))
(assert (= (select m2 "0") 42))
(assert (forall ((x String)) (or (= x "0") (= (select m2 x) 0))))
(assert (= m2 (ite (= c 11) (store m1 "1" 100) (store m1 "0" 42))))
(check-sat)

可以解决第一个问题(同时让c不确定地解决),同时仍然要求m1对于所有值都是0而m2除了" 0"之外的所有值都是0,例如通过采用适当的策略或量词模式?

1 个答案:

答案 0 :(得分:1)

对于声明常量数组,您应该更喜欢const结构,而不是通过量词。也就是说,替换:

(assert (forall ((x String)) (= (select m1 x) 0)))

使用:

(assert (= m1 ((as const (Array String Int)) 0)))

您会注意到z3现在可以轻松处理您的查询。

Z3指南中解释了常量数组:https://rise4fun.com/z3/tutorialcontent/guide#h26