A lightweight solver for Dung-style abstract argumentation framework (AF) semantics: conflict-free, admissible, complete, preferred, grounded, and stable. Available for Python (this package) and TypeScript.
uv add afsolveror with pip:
pip install afsolverfrom afsolver import ArgumentationFramework
af = ArgumentationFramework(
arguments=["a", "b", "c"],
attacks=[("a", "b"), ("b", "a"), ("c", "b")], # a<->b mutual attack, c attacks b
)
af.preferred() # [frozenset({'a', 'c'})]
af.grounded() # frozenset({'a', 'c'})
af.extensions() # dict with all six semantics at oncearguments is optional — if omitted, arguments are inferred from the
attacks pairs:
af = ArgumentationFramework(attacks=[("b", "a"), ("c", "b"), ("d", "c")])
af.arguments # ('b', 'a', 'c', 'd')Attack pairs can be tuples or lists — both are accepted and normalized to tuples internally.
ArgumentationFramework(arguments=(), attacks=())
| Method | Returns |
|---|---|
.conflict_free() |
list[frozenset] — conflict-free sets |
.admissible() |
list[frozenset] — admissible sets |
.complete() |
list[frozenset] — complete extensions |
.preferred(contains=None) |
list[frozenset] — preferred (maximal admissible) extensions, optionally restricted to those containing all arguments in contains |
.grounded() |
frozenset — the (unique) grounded extension |
.stable() |
list[frozenset] — stable extensions |
.minimal_admissible(contains=None) |
list[frozenset] — non-empty admissible sets minimal by set inclusion, optionally restricted to those containing all arguments in contains |
.extension(name) |
dispatch to any of the six semantics above by string name |
.extensions() |
dict[str, ...] — all six semantics computed at once |
With no contains argument, returns all preferred extensions. Pass
contains to restrict the result to only those that include a given
argument (or set of arguments):
af = ArgumentationFramework(
["a", "b", "c", "d", "e"],
[("b", "a"), ("c", "b"), ("d", "b"), ("c", "e"), ("e", "c")],
)
af.preferred() # [{'a', 'c', 'd'}, {'a', 'd', 'e'}]
af.preferred(contains=["a", "c"]) # [{'a', 'c', 'd'}]With no contains argument, returns the smallest non-trivial admissible
sets overall. Pass contains to restrict the result to the smallest
admissible sets that include a given argument (or set of arguments):
af = ArgumentationFramework(
["a", "b", "c", "d", "e"],
[("b", "a"), ("c", "b"), ("d", "b"), ("c", "e"), ("e", "c")],
)
af.minimal_admissible() # [{'c'}, {'d'}, {'e'}]
af.minimal_admissible(contains=["a"]) # [{'a', 'c'}, {'a', 'd'}]The empty set is always excluded — it's trivially admissible and a subset of everything else, so including it would hide the smallest non-trivial results.
uv sync # install project + dev dependencies
uv run pytest -q # run tests
uv build # build sdist + wheelA TypeScript port with the same API (in camelCase) lives in ts/,
managed with bun instead of uv. See ts/README.md
for install and usage.