使用 Z3Py 将 Z3 CNF 公式转换为列表列表表示
Converting Z3 CNF formula into list-of-lists representation using Z3Py
给定 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 公式的列表列表表示?
无论如何我都不是 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 问题。
没有模式匹配,但 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 is_"。
请注意,我的实现 returns 变量名称列表而不是 Z3 变量本身。那是因为 Christoph Wintersteiger's 警告。如果您打算对这些列表进行任何处理,符号 __eq__
很可能不是您想要的。
我不知道你要解决什么问题,但如果你自己生成 CNF,请考虑从一开始就以列表的列表形式生成它们。将列表的列表转换为 Z3 表达式比反过来更容易。
给定 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 公式的列表列表表示?
无论如何我都不是 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 问题。
没有模式匹配,但 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 is_"。
请注意,我的实现 returns 变量名称列表而不是 Z3 变量本身。那是因为 Christoph Wintersteiger's 警告。如果您打算对这些列表进行任何处理,符号 __eq__
很可能不是您想要的。
我不知道你要解决什么问题,但如果你自己生成 CNF,请考虑从一开始就以列表的列表形式生成它们。将列表的列表转换为 Z3 表达式比反过来更容易。