我在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的结果。给定更复杂的断言,这将发生(并且在我的情况下发生)。
这是怎么做到的?
答案 0 :(得分:4)
为简化起见,您需要同时添加A
和B
。以下脚本使用检查简化结果中的每个断言e
是否等于集edel
中的任何断言B
的想法,如果是,则不包括e
在简化的结果中,所有这些都是在使用A
和B
进行初始简化之后完成的。您当然也可以通过指针从简化结果中删除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]