繁体   English   中英

在Z3Py中编码可允许的集合

[英]Encode admissible sets in Z3Py

基于论证框架理论,我试图使用Z3Py证明者对可允许集合进行编码。 但是,我遇到了一些问题,希望对如何改进它有任何建议。

根据Wikipedia的定义,当且仅当它没有冲突并且其所有参数对于E都是可接受的时,才可接受参数E的集合。

基于以下带有参数的有向图:a,b,c,d,e和关系:(a,d),(a,b),(b,c),(c,b),(c,d) ,(e,a)可接受集合的正确解是:[],[e],[c],[c,e],[b,e],[b,d,e]

我开始玩Z3Py,但是在编码时遇到了问题。

到目前为止,我有这个:

from z3 import *

a, b, c, d, e = Bools('a b c d e')
arguments = [a, b, c, d, e]
solver = Solver()
relations = [(a, d), (a, b), (b, c), (c, b), (c, d), (e, a)]

# ensure there are no conflicting arguments
for relation in relations:
    solver.append(Implies(relation[0], Not(relation[1])))

for argument in arguments:
    # if not attacked then removed any arguments attacked by this argument
    if len([item for item in relations if item[1] == argument]) == 0:
        solver.append([Not(attacked[1]) for attacked in relations if attacked[0] == argument])

    # if self attacking remove the argument
    if len([item for item in relations if item[1] == argument and item[0] == argument]) > 0:
        solver.append(Not(argument))

    # get all attackers
    attackers = [item[0] for item in relations if item[1] == argument]
    for attacker in attackers:
        # get defenders of the initial argument (arguments attacking the attacker)
        defenders = [item[0] for item in relations if item[1] == attacker]
        defending_z3 = []
        if len(defenders) > 0:
            for defender in defenders:
                if defender not in attackers:
                    defending_z3.append(defender)
            if len(defending_z3) > 0:
                solver.append(Implies(Or([defend for defend in defending_z3]), argument))
        else:
            solver.append(Not(argument))

# get solutions
solutions = []
while solver.check() == sat:
    model = solver.model()
    block = []
    solution = []
    for var in arguments:
        v = model.eval(var, model_completion=True)
        block.append(var != v)
        if is_true(v):
            solution.append(var)
    solver.add(Or(block))
    solutions.append(solution)

for solution in solutions:
    print(solution)

执行后,它为我提供以下解决方案:[],[c],[d],[b,d],[b,d,e],其中只有3个是正确的:

  1. [b,d]是错误的,因为d无法自卫(e是d的捍卫者)
  2. [d]再次不正确,因为d无法自卫
  3. [e]丢失
  4. [c,e]丢失
  5. [b,e]丢失

任何帮助,将不胜感激。

对于SMT解决来说,这确实是一个很大的问题,即使您拥有非常多的set,z3也将能够相对轻松地解决此类问题。

您的编码思路是正确的,但您正在混淆相等性:测试变量是否与另一个变量相同时,请务必小心。 为此,请使用Python的eq方法。 (如果使用== ,那么您将获得符号相等性测试,这不是您在这里要查找的。)

鉴于此,我倾向于将您的问题编写如下:

from z3 import *

a, b, c, d, e = Bools('a b c d e')
arguments = [a, b, c, d, e]
solver = Solver()
relations = [(a, d), (a, b), (b, c), (c, b), (c, d), (e, a)]

# No conflicting arguments
for relation in relations:
    solver.add(Not(And(relation[0], relation[1])))

# For each element, if it is attacked, then another element that
# attacks the attacker must be present:
for argument in arguments:
    # Find the attackers for this argument:
    attackers = [relation[0] for relation in relations if argument.eq(relation[1])]

    # We must defend against each attacker:
    for attacker in attackers:
        defenders = [relation[0] for relation in relations if relation[1].eq(attacker)]

        # One of the defenders must be included:
        solver.add(Implies(argument, Or(defenders)))

# Collect the solutions:
while solver.check() == sat:
    model = solver.model()
    block = []
    solution = []

    for var in arguments:
        v = model.eval(var, model_completion=True)
        block.append(var != v)
        if is_true(v):
            solution.append(str(var))

    solver.add(Or(block))
    solution.sort()
    print(solution)

希望代码应该易于理解。 如果没有,请随时提出具体问题。

当我运行它时,我得到:

[]
['c']
['c', 'e']
['e']
['b', 'e']
['b', 'd', 'e']

这似乎与您预期的解决方案相符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM