Spaces:
Sleeping
Sleeping
youssef
commited on
Commit
·
ab9e430
1
Parent(s):
8bdd43d
added deepcopies to fix normal attack generation
Browse files- aba/aba_builder.py +21 -20
- aba/aba_framework.py +28 -12
- aba/parsing.py +11 -6
- aba/test.py +78 -0
aba/aba_builder.py
CHANGED
|
@@ -11,10 +11,10 @@ import os
|
|
| 11 |
def build_aba_framework(doc_path: str) -> ABAFramework:
|
| 12 |
"""
|
| 13 |
Build an ABAFramework object from a structured document.
|
| 14 |
-
|
| 15 |
Args:
|
| 16 |
doc_path (str): Path to the document to parse.
|
| 17 |
-
|
| 18 |
Returns:
|
| 19 |
ABAFramework: An ABAFramework instance containing:
|
| 20 |
- language (Set[Literal]): Set of Literal objects.
|
|
@@ -22,7 +22,7 @@ def build_aba_framework(doc_path: str) -> ABAFramework:
|
|
| 22 |
- assumptions (Set[Literal]): Set of assumptions.
|
| 23 |
- contraries (Set[Contrary]): Set of contraries.
|
| 24 |
- preferences (Dict[Literal, Set[Literal]]): Preference mappings.
|
| 25 |
-
|
| 26 |
Example:
|
| 27 |
>>> aba = build_aba_framework("./backend/doc.txt")
|
| 28 |
>>> isinstance(next(iter(aba.language)), Literal)
|
|
@@ -33,20 +33,20 @@ def build_aba_framework(doc_path: str) -> ABAFramework:
|
|
| 33 |
# Parse the document
|
| 34 |
language_parse, assumptions_parse, contraries_parse, rules_parse, preferences_parse = parse_doc(
|
| 35 |
doc_path)
|
| 36 |
-
|
| 37 |
# Initialize containers
|
| 38 |
language: Dict[str, Literal] = {}
|
| 39 |
rules: Set[Rule] = set()
|
| 40 |
contraries: Set[Contrary] = set()
|
| 41 |
assumptions: Set[Literal] = set()
|
| 42 |
preferences: Dict[Literal, Set[Literal]] = {}
|
| 43 |
-
|
| 44 |
# Language: build Literal objects
|
| 45 |
for lit in language_parse:
|
| 46 |
language[lit] = Literal(lit)
|
| 47 |
-
|
| 48 |
language_set: Set[Literal] = set(language.values())
|
| 49 |
-
|
| 50 |
# Rules: convert parsed structure into Rule objects
|
| 51 |
for rule in rules_parse:
|
| 52 |
r_id = next(iter(rule))
|
|
@@ -54,29 +54,30 @@ def build_aba_framework(doc_path: str) -> ABAFramework:
|
|
| 54 |
body_atoms = rule[r_id][head]
|
| 55 |
body_literals = {language[i] for i in body_atoms if i in language}
|
| 56 |
rules.add(Rule(r_id, language[head], body_literals))
|
| 57 |
-
|
| 58 |
# Contraries: build Contrary objects
|
| 59 |
for lit1, lit2 in contraries_parse:
|
| 60 |
contraries.add(Contrary(language[lit1], language[lit2]))
|
| 61 |
-
|
| 62 |
# Assumptions: convert to set of Literal
|
| 63 |
for lit in assumptions_parse:
|
| 64 |
assumptions.add(language[lit])
|
| 65 |
-
|
| 66 |
# Preferences: merge all preference dictionaries and convert to Literal objects
|
| 67 |
for pref_dict in preferences_parse:
|
| 68 |
for lit_str, less_preferred_strs in pref_dict.items():
|
| 69 |
if lit_str in language:
|
| 70 |
lit_obj = language[lit_str]
|
| 71 |
# Convert string literals to Literal objects
|
| 72 |
-
less_preferred_objs = {
|
| 73 |
-
|
|
|
|
| 74 |
# Merge with existing preferences for this literal
|
| 75 |
if lit_obj in preferences:
|
| 76 |
preferences[lit_obj].update(less_preferred_objs)
|
| 77 |
else:
|
| 78 |
preferences[lit_obj] = less_preferred_objs
|
| 79 |
-
|
| 80 |
# Build ABA framework
|
| 81 |
aba_framework = ABAFramework(
|
| 82 |
language=language_set,
|
|
@@ -85,7 +86,7 @@ def build_aba_framework(doc_path: str) -> ABAFramework:
|
|
| 85 |
contraries=contraries,
|
| 86 |
preferences=preferences
|
| 87 |
)
|
| 88 |
-
|
| 89 |
return aba_framework
|
| 90 |
|
| 91 |
|
|
@@ -93,26 +94,26 @@ def prepare_aba_plus_framework(aba_framework: ABAFramework) -> ABAFramework:
|
|
| 93 |
"""
|
| 94 |
Prepare an ABA framework for ABA+ by ensuring it's atomic and generating
|
| 95 |
all necessary components.
|
| 96 |
-
|
| 97 |
Args:
|
| 98 |
aba_framework: The ABA framework to prepare
|
| 99 |
-
|
| 100 |
Returns:
|
| 101 |
ABAFramework: The prepared framework (modified in place)
|
| 102 |
"""
|
| 103 |
-
|
| 104 |
# Generate arguments for atomic framework
|
| 105 |
print("\nGenerating arguments for atomic framework...")
|
| 106 |
aba_framework.arguments.clear()
|
| 107 |
aba_framework.generate_arguments()
|
| 108 |
print(f"Generated {len(aba_framework.arguments)} arguments")
|
| 109 |
-
|
| 110 |
# Generate standard attacks
|
| 111 |
print("\nGenerating standard attacks for atomic framework...")
|
| 112 |
aba_framework.attacks.clear()
|
| 113 |
aba_framework.generate_attacks()
|
| 114 |
print(f"Generated {len(aba_framework.attacks)} attacks\n")
|
| 115 |
-
|
| 116 |
return aba_framework
|
| 117 |
|
| 118 |
|
|
@@ -140,4 +141,4 @@ def build_aba_framework_from_text(text: str) -> ABAFramework:
|
|
| 140 |
except OSError:
|
| 141 |
pass
|
| 142 |
|
| 143 |
-
return aba
|
|
|
|
| 11 |
def build_aba_framework(doc_path: str) -> ABAFramework:
|
| 12 |
"""
|
| 13 |
Build an ABAFramework object from a structured document.
|
| 14 |
+
|
| 15 |
Args:
|
| 16 |
doc_path (str): Path to the document to parse.
|
| 17 |
+
|
| 18 |
Returns:
|
| 19 |
ABAFramework: An ABAFramework instance containing:
|
| 20 |
- language (Set[Literal]): Set of Literal objects.
|
|
|
|
| 22 |
- assumptions (Set[Literal]): Set of assumptions.
|
| 23 |
- contraries (Set[Contrary]): Set of contraries.
|
| 24 |
- preferences (Dict[Literal, Set[Literal]]): Preference mappings.
|
| 25 |
+
|
| 26 |
Example:
|
| 27 |
>>> aba = build_aba_framework("./backend/doc.txt")
|
| 28 |
>>> isinstance(next(iter(aba.language)), Literal)
|
|
|
|
| 33 |
# Parse the document
|
| 34 |
language_parse, assumptions_parse, contraries_parse, rules_parse, preferences_parse = parse_doc(
|
| 35 |
doc_path)
|
| 36 |
+
|
| 37 |
# Initialize containers
|
| 38 |
language: Dict[str, Literal] = {}
|
| 39 |
rules: Set[Rule] = set()
|
| 40 |
contraries: Set[Contrary] = set()
|
| 41 |
assumptions: Set[Literal] = set()
|
| 42 |
preferences: Dict[Literal, Set[Literal]] = {}
|
| 43 |
+
|
| 44 |
# Language: build Literal objects
|
| 45 |
for lit in language_parse:
|
| 46 |
language[lit] = Literal(lit)
|
| 47 |
+
|
| 48 |
language_set: Set[Literal] = set(language.values())
|
| 49 |
+
|
| 50 |
# Rules: convert parsed structure into Rule objects
|
| 51 |
for rule in rules_parse:
|
| 52 |
r_id = next(iter(rule))
|
|
|
|
| 54 |
body_atoms = rule[r_id][head]
|
| 55 |
body_literals = {language[i] for i in body_atoms if i in language}
|
| 56 |
rules.add(Rule(r_id, language[head], body_literals))
|
| 57 |
+
|
| 58 |
# Contraries: build Contrary objects
|
| 59 |
for lit1, lit2 in contraries_parse:
|
| 60 |
contraries.add(Contrary(language[lit1], language[lit2]))
|
| 61 |
+
|
| 62 |
# Assumptions: convert to set of Literal
|
| 63 |
for lit in assumptions_parse:
|
| 64 |
assumptions.add(language[lit])
|
| 65 |
+
|
| 66 |
# Preferences: merge all preference dictionaries and convert to Literal objects
|
| 67 |
for pref_dict in preferences_parse:
|
| 68 |
for lit_str, less_preferred_strs in pref_dict.items():
|
| 69 |
if lit_str in language:
|
| 70 |
lit_obj = language[lit_str]
|
| 71 |
# Convert string literals to Literal objects
|
| 72 |
+
less_preferred_objs = {
|
| 73 |
+
language[lp] for lp in less_preferred_strs if lp in language}
|
| 74 |
+
|
| 75 |
# Merge with existing preferences for this literal
|
| 76 |
if lit_obj in preferences:
|
| 77 |
preferences[lit_obj].update(less_preferred_objs)
|
| 78 |
else:
|
| 79 |
preferences[lit_obj] = less_preferred_objs
|
| 80 |
+
|
| 81 |
# Build ABA framework
|
| 82 |
aba_framework = ABAFramework(
|
| 83 |
language=language_set,
|
|
|
|
| 86 |
contraries=contraries,
|
| 87 |
preferences=preferences
|
| 88 |
)
|
| 89 |
+
|
| 90 |
return aba_framework
|
| 91 |
|
| 92 |
|
|
|
|
| 94 |
"""
|
| 95 |
Prepare an ABA framework for ABA+ by ensuring it's atomic and generating
|
| 96 |
all necessary components.
|
| 97 |
+
|
| 98 |
Args:
|
| 99 |
aba_framework: The ABA framework to prepare
|
| 100 |
+
|
| 101 |
Returns:
|
| 102 |
ABAFramework: The prepared framework (modified in place)
|
| 103 |
"""
|
| 104 |
+
|
| 105 |
# Generate arguments for atomic framework
|
| 106 |
print("\nGenerating arguments for atomic framework...")
|
| 107 |
aba_framework.arguments.clear()
|
| 108 |
aba_framework.generate_arguments()
|
| 109 |
print(f"Generated {len(aba_framework.arguments)} arguments")
|
| 110 |
+
|
| 111 |
# Generate standard attacks
|
| 112 |
print("\nGenerating standard attacks for atomic framework...")
|
| 113 |
aba_framework.attacks.clear()
|
| 114 |
aba_framework.generate_attacks()
|
| 115 |
print(f"Generated {len(aba_framework.attacks)} attacks\n")
|
| 116 |
+
|
| 117 |
return aba_framework
|
| 118 |
|
| 119 |
|
|
|
|
| 141 |
except OSError:
|
| 142 |
pass
|
| 143 |
|
| 144 |
+
return aba
|
aba/aba_framework.py
CHANGED
|
@@ -10,6 +10,7 @@ Features:
|
|
| 10 |
- Provides visualization of attack graphs using PyVis.
|
| 11 |
"""
|
| 12 |
|
|
|
|
| 13 |
from .argument import Argument
|
| 14 |
from .contrary import Contrary
|
| 15 |
from .literal import Literal
|
|
@@ -189,7 +190,7 @@ class ABAFramework:
|
|
| 189 |
|
| 190 |
# ------------------------- ABA Methods -------------------------
|
| 191 |
|
| 192 |
-
def transform_aba(self) ->
|
| 193 |
"""
|
| 194 |
Transforms the ABA framework to ensure it is both non-circular and atomic.
|
| 195 |
|
|
@@ -204,12 +205,15 @@ class ABAFramework:
|
|
| 204 |
print("\n ------- Transforming ABA framework -------\n")
|
| 205 |
if self.is_aba_circular():
|
| 206 |
print("The ABA Framework is circular\n")
|
| 207 |
-
self.make_aba_not_circular()
|
| 208 |
elif not self.is_aba_atomic():
|
| 209 |
print("The ABA Framework is not atomic\n")
|
| 210 |
-
self.make_aba_atomic()
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
-
def make_aba_atomic(self) ->
|
| 213 |
"""
|
| 214 |
Transforms the ABA framework into an atomic one.
|
| 215 |
|
|
@@ -236,6 +240,8 @@ class ABAFramework:
|
|
| 236 |
R = { a <- xd }
|
| 237 |
Contraries = { xd̄ = xnd, xnd̄ = x }
|
| 238 |
"""
|
|
|
|
|
|
|
| 239 |
new_language = set(self.language)
|
| 240 |
new_assumptions = set(self.assumptions)
|
| 241 |
new_rules = set()
|
|
@@ -265,10 +271,16 @@ class ABAFramework:
|
|
| 265 |
new_rules.add(Rule(rule.rule_name, rule.head, new_body))
|
| 266 |
|
| 267 |
# Step 3: Update framework
|
| 268 |
-
self.language = new_language
|
| 269 |
-
self.assumptions = new_assumptions
|
| 270 |
-
self.rules = new_rules
|
| 271 |
-
self.contraries = new_contraries
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
| 273 |
def is_aba_atomic(self) -> bool:
|
| 274 |
"""
|
|
@@ -335,7 +347,7 @@ class ABAFramework:
|
|
| 335 |
return True # Cycle found
|
| 336 |
return False # No cycles
|
| 337 |
|
| 338 |
-
def make_aba_not_circular(self) ->
|
| 339 |
"""
|
| 340 |
Transforms the ABA framework to a non-circular one by renaming heads and bodies of rules.
|
| 341 |
|
|
@@ -368,7 +380,7 @@ class ABAFramework:
|
|
| 368 |
x1 <- a
|
| 369 |
x <- a
|
| 370 |
"""
|
| 371 |
-
|
| 372 |
k = len(self.language) - len(self.assumptions)
|
| 373 |
new_language = set(self.language)
|
| 374 |
new_rules = set()
|
|
@@ -395,8 +407,12 @@ class ABAFramework:
|
|
| 395 |
new_rule_name = f"{rule.rule_name}_{i+1}"
|
| 396 |
new_rules.add(Rule(new_rule_name, new_head, new_body))
|
| 397 |
|
| 398 |
-
|
| 399 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
|
| 401 |
# ------------------------- ABA+ Methods -------------------------
|
| 402 |
|
|
|
|
| 10 |
- Provides visualization of attack graphs using PyVis.
|
| 11 |
"""
|
| 12 |
|
| 13 |
+
from copy import deepcopy
|
| 14 |
from .argument import Argument
|
| 15 |
from .contrary import Contrary
|
| 16 |
from .literal import Literal
|
|
|
|
| 190 |
|
| 191 |
# ------------------------- ABA Methods -------------------------
|
| 192 |
|
| 193 |
+
def transform_aba(self) -> "ABAFramework":
|
| 194 |
"""
|
| 195 |
Transforms the ABA framework to ensure it is both non-circular and atomic.
|
| 196 |
|
|
|
|
| 205 |
print("\n ------- Transforming ABA framework -------\n")
|
| 206 |
if self.is_aba_circular():
|
| 207 |
print("The ABA Framework is circular\n")
|
| 208 |
+
return self.make_aba_not_circular()
|
| 209 |
elif not self.is_aba_atomic():
|
| 210 |
print("The ABA Framework is not atomic\n")
|
| 211 |
+
return self.make_aba_atomic()
|
| 212 |
+
else:
|
| 213 |
+
print("The ABA Framework is already non-circular and atomic\n")
|
| 214 |
+
return deepcopy(self)
|
| 215 |
|
| 216 |
+
def make_aba_atomic(self) -> "ABAFramework":
|
| 217 |
"""
|
| 218 |
Transforms the ABA framework into an atomic one.
|
| 219 |
|
|
|
|
| 240 |
R = { a <- xd }
|
| 241 |
Contraries = { xd̄ = xnd, xnd̄ = x }
|
| 242 |
"""
|
| 243 |
+
new_framework = deepcopy(self)
|
| 244 |
+
|
| 245 |
new_language = set(self.language)
|
| 246 |
new_assumptions = set(self.assumptions)
|
| 247 |
new_rules = set()
|
|
|
|
| 271 |
new_rules.add(Rule(rule.rule_name, rule.head, new_body))
|
| 272 |
|
| 273 |
# Step 3: Update framework
|
| 274 |
+
# self.language = new_language
|
| 275 |
+
# self.assumptions = new_assumptions
|
| 276 |
+
# self.rules = new_rules
|
| 277 |
+
# self.contraries = new_contraries
|
| 278 |
+
new_framework.language = new_language
|
| 279 |
+
new_framework.assumptions = new_assumptions
|
| 280 |
+
new_framework.rules = new_rules
|
| 281 |
+
new_framework.contraries = new_contraries
|
| 282 |
+
|
| 283 |
+
return new_framework
|
| 284 |
|
| 285 |
def is_aba_atomic(self) -> bool:
|
| 286 |
"""
|
|
|
|
| 347 |
return True # Cycle found
|
| 348 |
return False # No cycles
|
| 349 |
|
| 350 |
+
def make_aba_not_circular(self) -> "ABAFramework":
|
| 351 |
"""
|
| 352 |
Transforms the ABA framework to a non-circular one by renaming heads and bodies of rules.
|
| 353 |
|
|
|
|
| 380 |
x1 <- a
|
| 381 |
x <- a
|
| 382 |
"""
|
| 383 |
+
new_copy = deepcopy(self)
|
| 384 |
k = len(self.language) - len(self.assumptions)
|
| 385 |
new_language = set(self.language)
|
| 386 |
new_rules = set()
|
|
|
|
| 407 |
new_rule_name = f"{rule.rule_name}_{i+1}"
|
| 408 |
new_rules.add(Rule(new_rule_name, new_head, new_body))
|
| 409 |
|
| 410 |
+
# self.language = new_language
|
| 411 |
+
# self.rules = new_rules
|
| 412 |
+
new_copy.language = new_language
|
| 413 |
+
new_copy.rules = new_rules
|
| 414 |
+
|
| 415 |
+
return new_copy
|
| 416 |
|
| 417 |
# ------------------------- ABA+ Methods -------------------------
|
| 418 |
|
aba/parsing.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import re
|
| 2 |
from typing import List, Tuple, Dict, Set
|
| 3 |
|
|
|
|
| 4 |
def _parse_list(content: str) -> List[str]:
|
| 5 |
"""
|
| 6 |
Parse a string representing a list of literals into a Python list of strings.
|
|
@@ -23,6 +24,7 @@ def _parse_list(content: str) -> List[str]:
|
|
| 23 |
return []
|
| 24 |
return [x.strip() for x in content.split(",") if x.strip()]
|
| 25 |
|
|
|
|
| 26 |
def _parse_rule_line(line: str) -> Dict[str, Dict[str, Set[str]]]:
|
| 27 |
"""
|
| 28 |
Parse a single rule line of the form [rX]: head <- body.
|
|
@@ -45,14 +47,15 @@ def _parse_rule_line(line: str) -> Dict[str, Dict[str, Set[str]]]:
|
|
| 45 |
return {r_id: {head: body_atoms}}
|
| 46 |
return {}
|
| 47 |
|
|
|
|
| 48 |
def _parse_pref_line(line: str) -> Dict[str, Set[str]]:
|
| 49 |
"""
|
| 50 |
Parse a preference line of the form:
|
| 51 |
- PREF: a,b > c,d > e
|
| 52 |
- PREF: a,b > c and a > d
|
| 53 |
-
|
| 54 |
Supports multiple chains joined by "and".
|
| 55 |
-
|
| 56 |
Returns:
|
| 57 |
Dict[str, Set[str]]: Dictionary mapping each element to all elements
|
| 58 |
that come after it in the preference chain(s).
|
|
@@ -83,6 +86,7 @@ def _parse_pref_line(line: str) -> Dict[str, Set[str]]:
|
|
| 83 |
|
| 84 |
return pref_dict
|
| 85 |
|
|
|
|
| 86 |
def parse_doc(path: str) -> Tuple[
|
| 87 |
List[str],
|
| 88 |
List[str],
|
|
@@ -120,13 +124,13 @@ def parse_doc(path: str) -> Tuple[
|
|
| 120 |
contraries: List[Tuple[str, str]] = []
|
| 121 |
rules: List[Dict[str, Dict[str, Set[str]]]] = []
|
| 122 |
preferences: List[Dict[str, Set[str]]] = []
|
| 123 |
-
|
| 124 |
with open(path, "r") as f:
|
| 125 |
for line in f:
|
| 126 |
line = line.strip()
|
| 127 |
if not line:
|
| 128 |
continue
|
| 129 |
-
|
| 130 |
if line.startswith("L:"):
|
| 131 |
language = _parse_list(line.split(":", 1)[1])
|
| 132 |
elif line.startswith("A:"):
|
|
@@ -143,12 +147,13 @@ def parse_doc(path: str) -> Tuple[
|
|
| 143 |
pref_dict = _parse_pref_line(line)
|
| 144 |
if pref_dict:
|
| 145 |
preferences.append(pref_dict)
|
| 146 |
-
|
| 147 |
return language, assumptions, contraries, rules, preferences
|
| 148 |
|
| 149 |
|
| 150 |
if __name__ == "__main__":
|
| 151 |
-
language, assumptions, contraries, rules, preferences = parse_doc(
|
|
|
|
| 152 |
print("Language:", language)
|
| 153 |
print("Assumptions:", assumptions)
|
| 154 |
print("Contraries:", contraries)
|
|
|
|
| 1 |
import re
|
| 2 |
from typing import List, Tuple, Dict, Set
|
| 3 |
|
| 4 |
+
|
| 5 |
def _parse_list(content: str) -> List[str]:
|
| 6 |
"""
|
| 7 |
Parse a string representing a list of literals into a Python list of strings.
|
|
|
|
| 24 |
return []
|
| 25 |
return [x.strip() for x in content.split(",") if x.strip()]
|
| 26 |
|
| 27 |
+
|
| 28 |
def _parse_rule_line(line: str) -> Dict[str, Dict[str, Set[str]]]:
|
| 29 |
"""
|
| 30 |
Parse a single rule line of the form [rX]: head <- body.
|
|
|
|
| 47 |
return {r_id: {head: body_atoms}}
|
| 48 |
return {}
|
| 49 |
|
| 50 |
+
|
| 51 |
def _parse_pref_line(line: str) -> Dict[str, Set[str]]:
|
| 52 |
"""
|
| 53 |
Parse a preference line of the form:
|
| 54 |
- PREF: a,b > c,d > e
|
| 55 |
- PREF: a,b > c and a > d
|
| 56 |
+
|
| 57 |
Supports multiple chains joined by "and".
|
| 58 |
+
|
| 59 |
Returns:
|
| 60 |
Dict[str, Set[str]]: Dictionary mapping each element to all elements
|
| 61 |
that come after it in the preference chain(s).
|
|
|
|
| 86 |
|
| 87 |
return pref_dict
|
| 88 |
|
| 89 |
+
|
| 90 |
def parse_doc(path: str) -> Tuple[
|
| 91 |
List[str],
|
| 92 |
List[str],
|
|
|
|
| 124 |
contraries: List[Tuple[str, str]] = []
|
| 125 |
rules: List[Dict[str, Dict[str, Set[str]]]] = []
|
| 126 |
preferences: List[Dict[str, Set[str]]] = []
|
| 127 |
+
|
| 128 |
with open(path, "r") as f:
|
| 129 |
for line in f:
|
| 130 |
line = line.strip()
|
| 131 |
if not line:
|
| 132 |
continue
|
| 133 |
+
|
| 134 |
if line.startswith("L:"):
|
| 135 |
language = _parse_list(line.split(":", 1)[1])
|
| 136 |
elif line.startswith("A:"):
|
|
|
|
| 147 |
pref_dict = _parse_pref_line(line)
|
| 148 |
if pref_dict:
|
| 149 |
preferences.append(pref_dict)
|
| 150 |
+
|
| 151 |
return language, assumptions, contraries, rules, preferences
|
| 152 |
|
| 153 |
|
| 154 |
if __name__ == "__main__":
|
| 155 |
+
language, assumptions, contraries, rules, preferences = parse_doc(
|
| 156 |
+
"./backend/data/simple_plus2AND.txt")
|
| 157 |
print("Language:", language)
|
| 158 |
print("Assumptions:", assumptions)
|
| 159 |
print("Contraries:", contraries)
|
aba/test.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Main entry point for generating and analyzing an ABA+ framework.
|
| 3 |
+
|
| 4 |
+
This script:
|
| 5 |
+
1. Builds an ABA framework from a text specification.
|
| 6 |
+
2. Prints the original (classical) ABA framework.
|
| 7 |
+
3. Prepares the framework for ABA+ (atomic transformation + argument/attack generation).
|
| 8 |
+
4. Generates ABA+ components (assumption combinations, normal/reverse attacks).
|
| 9 |
+
5. Prints the resulting ABA+ framework components.
|
| 10 |
+
6. Plots the ABA+ attack graph between sets of assumptions.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
from copy import deepcopy
|
| 14 |
+
from aba.aba_builder import build_aba_framework, prepare_aba_plus_framework
|
| 15 |
+
from aba.aba_utils import print_aba_plus_results
|
| 16 |
+
from aba.aba_framework import ABAFramework
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def testABA(aba_framework: ABAFramework):
|
| 20 |
+
|
| 21 |
+
copy_framework = deepcopy(aba_framework)
|
| 22 |
+
|
| 23 |
+
transformed_framework: ABAFramework = copy_framework.transform_aba()
|
| 24 |
+
print("\n ------- Transformed ABA framework -------\n ")
|
| 25 |
+
print(transformed_framework)
|
| 26 |
+
|
| 27 |
+
# Generate arguments
|
| 28 |
+
transformed_framework.generate_arguments()
|
| 29 |
+
gen_args = transformed_framework.arguments
|
| 30 |
+
print("\n ------- Generated arguments -------\n ")
|
| 31 |
+
print(gen_args)
|
| 32 |
+
|
| 33 |
+
# Generate attacks
|
| 34 |
+
transformed_framework.generate_attacks()
|
| 35 |
+
attacks = transformed_framework.attacks
|
| 36 |
+
print("\n ------- Generated attacks -------\n ")
|
| 37 |
+
print(attacks, "\n")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def testABAPlus(aba_framework: ABAFramework):
|
| 41 |
+
|
| 42 |
+
# === Step 2: Prepare the framework for ABA+ ===
|
| 43 |
+
|
| 44 |
+
aba_framework: ABAFramework = prepare_aba_plus_framework(aba_framework)
|
| 45 |
+
|
| 46 |
+
# === Step 3: Generate ABA+ components ===
|
| 47 |
+
print("\n" + "=" * 50)
|
| 48 |
+
print("Generating ABA+ Components")
|
| 49 |
+
print("=" * 50)
|
| 50 |
+
aba_framework.make_aba_plus()
|
| 51 |
+
|
| 52 |
+
# === Step 4: Print ABA+ results ===
|
| 53 |
+
print_aba_plus_results(aba_framework)
|
| 54 |
+
return aba_framework
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def main():
|
| 58 |
+
"""
|
| 59 |
+
Main function to generate and analyze an ABA+ framework.
|
| 60 |
+
"""
|
| 61 |
+
# === Step 1: Build the ABA framework from input file ===
|
| 62 |
+
print("\n" + "=" * 50)
|
| 63 |
+
print("Building ABA+ Framework")
|
| 64 |
+
print("=" * 50)
|
| 65 |
+
|
| 66 |
+
# Build framework from the given input specification file
|
| 67 |
+
aba_framework = build_aba_framework("aba\exemples\exemple.txt")
|
| 68 |
+
print(f"\n ------- Original ABA framework -------\n{aba_framework}")
|
| 69 |
+
|
| 70 |
+
base_framework = deepcopy(aba_framework)
|
| 71 |
+
testABA(base_framework)
|
| 72 |
+
|
| 73 |
+
aba_for_plus = deepcopy(aba_framework)
|
| 74 |
+
testABAPlus(aba_for_plus)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
if __name__ == "__main__":
|
| 78 |
+
main()
|