Based on the argumentation framework theory, I'm trying to encode the admissible sets using the Z3Py prover. However, I have run into some problems and would appreciate any pointers on how to improve it.
Based on the definition from Wikipedia, a set of arguments E is admissible if and only if it is conflict-free and all its arguments are acceptable with respect to E.
Based on the following directed graph with arguments: a, b, c, d, e and relations: (a, d), (a, b), (b, c), (c, b), (c, d), (e, a) the correct solution for admissible sets is: [], [e], [c], [c, e], [b, e], [b, d, e]
I started playing with Z3Py but have a problem encoding this.
So far I have this:
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)
When executed it gives me following solutions: [], [c], [d], [b, d], [b, d, e], where only 3 of them are correct:
- [b, d] is incorrect since d can't defend itself (e is defender of d)
- [d] again incorrect since d can't defend itself
- [e] is missing
- [c, e] is missing
- [b, e] is missing
Any help would be appreciated.