如何在Z3py中创建一个约束来检查另一个的排列列表?

时间:2015-02-06 02:21:25

标签: python z3 z3py

我是Z3py的初学者,我一直在努力解决这个问题近一个星期......我找不到足够的信息来帮助我在教程中找到一个好的例子(功能存在)可以帮我。

2 个答案:

答案 0 :(得分:4)

免责声明:如果您的问题完全您正在努力使用Z3py对问题进行编码,那么我的建议不会帮助您,因为它们是关于Z3py。但是,我认为你的问题实际上更为根本。

答案:对Z3 / SMTLIB中的列表进行公理化并不是直截了当的,特别是因为你的公理化需要一个良好的触发策略(模式),(forall-quantified)公理,这样你的公理化就不会产生匹配的循环。

我建议查看Boogie prelude of Dafny,看看 序列的公理化是怎样的。 Dafny是一个自动软件验证程序,Boogie是一种中间验证语言。 Boogie的语法很容易理解(对于熟悉SMTLIB语法的人来说),你应该能够用表达序列排列的公理(或多个公理)来扩展现有的序列公理化。

其他灵感来源可能是thisthis论文,两者都讨论了公理触发器和匹配循环。

答案 1 :(得分:-1)

W̶o̶w̶,̶̶w̶h̶a̶t̶̶t̶h̶e̶̶h̶e̶c̶k̶.̶.̶.̶.̶̶T̶h̶a̶t̶̶l̶i̶t̶e̶r̶a̶t̶u̶r̶e̶̶l̶i̶i̶nrognrogive这个问题是否要求进行纯粹的符号比较?如果不是这样,这个(更基本的)答案可能会提供一些有用的信息。

如果您只想找到唯一值的已知列表的特定排列,则可能无需进行公理化就可以删除。

只需生成O(n²)对等式,然后将它们成组添加为n形式的AtLeast(…, 1)约束。代码示例会更好地解释:

from itertools import combinations
import z3

solver = z3.Solver()

source_list = ['tau', 'eta', 'mu']
permuted = z3.Strings(['X', 'Y', 'Z'])

for var1, var2 in combinations(permuted, 2):
    solver.add(var1 != var2)

#-- here's where we do O(n²) pairwise EQs
for var_ref in permuted:
    possible_assigns = [(var_ref == z3.StringVal(s)) for s in source_list]
    solver.add(z3.AtLeast(*possible_assigns, 1))

#-- TODO: add here the rest of constraints that matter to you

#-- start search
while solver.check() == z3.sat:
    model = solver.model()
    print(model)
    this_solution = z3.And(*[
        var_ref == z3.StringVal(model[var_ref].as_string())
        for var_ref in permuted
        ])
    solver.append(z3.Not(this_solution))

print("No more solutions.")

#-- output:
# [Z = tau, X = mu, Y = eta]
# [Z = tau, X = eta, Y = mu]
# [Z = mu, X = eta, Y = tau]
# [Z = eta, X = mu, Y = tau]
# [Z = mu, X = tau, Y = eta]
# [Z = eta, X = tau, Y = mu]
# No more solutions.

如果允许permuted列表包含重复项,则需要进行一些调整。

如果两个列表都位于“ in-z3”中,则此方法将无效。有关该情况,请参阅Malte的答案。