鉴于CNF中的Z3公式,是否可以使用Z3Py将其转换为列表列表表示?我想这样做是为了更容易访问和操纵文字。如果Python是一种函数式语言,我可能会做类似
的事情def cnf2list(fm) :
match fm with
| And(P,Q) -> cnf2list(P) + cnf2list(Q)
| P -> clause2list(P)
def clause2list(fm) :
match fm with
| Or(P,Q) -> clause2list(P) + clause2list(Q)
| P -> [P]
但我不确定我能用Python做到这一点。是否可以像上面那样执行模式匹配(或者使用一些完全不同的方法)来获得Z3 CNF公式的列表表示?
答案 0 :(得分:2)
没有模式匹配,但z3py允许检查Z3表达式:
def clause2list(expr):
if z3.is_const(expr):
return [str(expr)]
elif z3.is_or(expr):
return [atom for disjunct in expr.children()
for atom in clause2list(disjunct)]
else:
assert False, ('not supported', expr)
x, y, z = z3.Bools('x y z')
print(clause2list(z3.Or(x, y, z)))
# ['x', 'y', 'z']
支持否定,连词以及真假文字留作练习:) 见z3.py,ctrl-f" def是_"。
请注意,我的实现返回变量名列表而不是Z3变量本身。这是因为Christoph Wintersteiger's警告。如果您打算对这些列表进行任何处理,则符号__eq__
很可能不是您想要的。
我不知道您要解决的问题是什么,但如果您自己生成CNF,请考虑从一开始就以列表列表形式生成它们。将列表列表转换为Z3表达式比使用其他方法更容易。
答案 1 :(得分:1)
我无论如何都不是Python专家,只是简单地在表达式周围加上括号[...]然后使用+运算符进行连接确实会构造一些列表,例如:
from z3 import *
x = Int('x')
y = Int('y')
z = Int('z')
print(x)
print(y)
print(z)
lst = [x] + [y]
print(lst)
s = sum(lst)
print(s)
lst.reverse()
print(lst)
print(x in lst)
但是,元素比较似乎会产生一些意想不到的结果,例如:
print(z in lst)
print(lst.count(x))
此时我不确定我是否以意想不到的方式使用Python列表,或者这是否是Z3 Python API问题。