Z3:是否可以简化部分断言?

时间:2014-02-11 12:18:22

标签: z3 smt

我在Windows 7以及64位Java 7上使用Z3版本4.3.2 64位的Java-API,但我不认为Java是回答这个问题的必要条件。

现在我正在使用以下Java代码来简化我在Z3中断言的一部分:

Tactic simplifyTactic = ctx.mkTactic("ctx-solver-simplify");
Goal goal = ctx.mkGoal(true, false, false);
goal.add(bel.toArray(new BoolExpr[0])); // bel is List<BoolExpr>
ApplyResult applyResult = simplifyTactic.apply(goal);

到目前为止,我已经过滤了要简化的断言,然后使用上面的代码进行简化,它按预期工作。

经过一些测试后,我得出的结论是,我还需要插入模型的过滤断言(其中包含一些元信息,如基数)。

是否有可能简化某些断言集A,而另一组断言B仍被视为但未被更改?

以下示例可能会稍微澄清一下这个问题:

(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(declare-const d Bool)

(assert (=> a c)); member of set A
(assert (=> b d)); member of set A
(assert a); member of set A

; member of set B
(assert 
    (<= 
        (+ (ite (= c true) 1 0) (ite (= d true) 1 0))
        1
    )
)

; member of set B
(assert 
    (>= 
        (+ (ite (= c true) 1 0) (ite (= d true) 1 0))
        1
    )
)

(apply ctx-solver-simplify)

如果Z3执行此SMT-LIB V2代码,结果为:

(goals 
    (goal 
        c 
        (not b) 
        a 
        (<= (+ (ite (= c true) 1 0) (ite (= d true) 1 0)) 1) 
        :precision precise :depth 1
    ) 
)

对于这个简单的例子,结果非常好。约束(前三个断言(我的集合A))已按预期简化。以下两个断言(带有我的基数信息(集B))也被简化了。现在,我想要Z3做的是简化,但没有混合集合A和B的结果。给定更复杂的断言,这将发生(并且在我的情况下发生)。

这是怎么做到的?

1 个答案:

答案 0 :(得分:4)

为简化起见,您需要同时添加AB。以下脚本使用检查简化结果中的每个断言e是否等于集edel中的任何断言B的想法,如果是,则不包括e在简化的结果中,所有这些都是在使用AB进行初始简化之后完成的。您当然也可以通过指针从简化结果中删除B中的所有断言,但如果B中的断言被转换,则可能会失败(就像我在运行您的示例时的情况一样) z3py而不是Z3的SMT接口),所以这可以证明断言是否与脚本相同。

它还检查B中所有断言的连接。一般来说,您可能必须考虑其排列(例如,B中断言的对,三元组等的连接),这可能使其不切实际,但也许它可以用于您的目的。它适用于提供的示例。这是z3py中的脚本(链接到rise4fun:http://rise4fun.com/Z3Py/slY6):

a,b,c,d = Bools('a b c d')
g = Goal()

A = []
A.append(Implies(a, c))
A.append(Implies(b, d))
A.append(a)

B = []
B.append((If(c == True, 1, 0) +  (If(d == True, 1, 0))) <=  1 )
B.append((If(c == True, 1, 0) +  (If(d == True, 1, 0))) >=  1 )

g.add(A)
g.add(B)

#t = Tactic('simplify')
#print t(g) # note difference

t = Tactic('ctx-solver-simplify')
ar = t(g)
print ar # [[c, Not(b), a, If(d, 1, 0) <= 0]]

s = Solver()
s.add(A)
result = []
for e in ar[0]: # iterate over expressions in result
  # try to prove equal
  s.push()
  s.add(Not(e == And(B))) # conunction of all assertions in B
  satres = s.check()
  s.pop()
  if satres == unsat:
    continue

  # check each in B individually
  for edel in B:
    # try to prove equal
    s.push()
    s.add(Not(e == edel))
    satres = s.check()
    s.pop()
    if satres != unsat:
      result.append(e)
      break

print result # [c, Not(b), a]