Skip to content

Read strict-rule antecedents as sets to stop ASPIC+ argument multiplication - #104

Merged
ctoth merged 3 commits into
mainfrom
fix/aspic-rule-sets
Sep 28, 2026
Merged

ctoth merged 3 commits into
mainfrom
fix/aspic-rule-sets

Conversation

@ctoth

@ctoth ctoth commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Implements the maintainer's decision on #102 (options A1 + A2): rule antecedents (strict and defeasible) are read as sets.

Change

Rule.__post_init__ canonicalises the antecedents of every rule. It drops repeated literals and stores the remaining ones sorted. As a result:

  • A2: ~q, ~q -> p becomes ~q -> p.
  • A1: permuted strict rules with the same antecedent set and consequent are equal Rule values, so frozensets of rules merge them.

Defeasible rules get the same set reading (maintainer follow-up decision, commit 17d7df7); named defeasible rules stay distinct by n(r), so undercuts still target them.

Why at rule construction: it is the one place every producer passes through. That covers hand-built ArgumentationSystems, transposition_closure (which rebuilds rules), Datalog grounding and ABA frameworks. Canonicalising at system construction would miss rules used outside a system (the ABA frameworks), and would let two differently-ordered Rule values that mean the same rule compare unequal.

Convention: M&P 2018 Def 5 (p.9) and Prakken 2010 Def 3.6 build A1..An -> φ from a rule φ1..φn -> φ and don't settle whether the antecedents are a sequence or a set. The set reading is a chosen convention, documented in the Rule docstring and recorded on #102.

Effect on the #102 theory

18,850 → 98 arguments, and about 306M → 7,226 attack pairs. The pinned operational contract (at most 200 arguments and at most 20,000 attack pairs) now passes, and its xfail(strict=True) marker is removed.

Tests (tests/structured/aspic/test_aspic_rule_sets.py)

  • Set reading pinned:
    • a repeated literal is dropped;
    • permuted strict rules are one rule;
    • defeasible rules: repeated antecedents dropped, permuted unnamed rules equal, named rules distinct by name;
    • ~q, ~q -> p over two ~q arguments builds 2 arguments for p, not 4.
  • A1 property: a permuted duplicate strict rule adds only clone arguments. Grounded, complete, preferred and stable extensions are unchanged up to clones, compared as sets of conclusions per extension. The generator makes the duplicated rule fire, so every example contains clones.
  • Producer audit:

Closes #102

🤖 Generated with Claude Code

https://claude.ai/code/session_01V4tAVyyKcs1sYcsEzL7Bzg

ctoth and others added 2 commits September 27, 2026 13:16
…tion

Per the maintainer's decision on #102, strict-rule antecedents are read
as a set: Rule.__post_init__ drops repeated literals and stores the rest
in canonical order, so permuted strict rules with the same antecedent set
and consequent are one rule value, and frozensets of rules merge them.
Defeasible rules keep their antecedent sequence and stay distinct by
name. Canonicalising at rule construction means every producer
(transposition_closure, Datalog grounding, hand-built systems, ABA rules)
gets the same reading with no per-producer code.

On the #102 theory this takes build_arguments from 18,850 arguments
(~306M attack pairs) to 98 arguments and 7,226 attack pairs, so the
pinned operational contract now passes and loses its xfail marker.

Tests pin the set reading (repeated literal dropped, permuted rules equal,
defeasible rules untouched, ~q, ~q -> p no longer squares arguments), show
by property that a permuted duplicate only adds clones and leaves every
semantics' extensions unchanged up to clones, and audit producers:
Datalog grounding merges permuted bodies while keeping both source ids,
and transposition_closure emits canonical rules.

Closes #102

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4tAVyyKcs1sYcsEzL7Bzg
Maintainer decision on #102: the set reading applies to defeasible rules
as well. A repeated antecedent literal is dropped and unnamed defeasible
rules with the same antecedent set and consequent merge; named rules stay
distinct by n(r), so undercutting still targets the named rule. Without
this, `q, q => p` still built one p-argument per ordered pair of
q-arguments.

Replaces the test that pinned the sequence reading for defeasible rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4tAVyyKcs1sYcsEzL7Bzg
@ctoth
ctoth merged commit db0eaad into main Sep 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ASPIC compute_attacks blows up on cyclic strict rules: 4 premises, 14 rules give 18,850 arguments and ~8.7M rebuttals

1 participant