使用Z3Py将Z3 CNF公式转换为列表列表表示

时间:2016-06-07 02:27:15

标签: z3 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公式的列表表示?

2 个答案:

答案 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问题。