File size: 4,650 Bytes
ba9863e
 
 
 
 
 
 
 
 
 
 
 
 
ab9e430
ba9863e
 
ab9e430
ba9863e
 
 
 
 
 
 
ab9e430
ba9863e
 
 
 
 
 
 
 
 
 
ab9e430
ba9863e
 
 
 
 
 
ab9e430
ba9863e
 
 
ab9e430
ba9863e
ab9e430
ba9863e
 
 
 
 
 
 
ab9e430
ba9863e
 
 
ab9e430
ba9863e
 
 
ab9e430
ba9863e
 
 
 
 
 
ab9e430
 
 
ba9863e
 
 
 
 
ab9e430
ba9863e
 
 
 
 
 
 
 
ab9e430
ba9863e
 
 
 
 
 
 
ab9e430
ba9863e
 
ab9e430
ba9863e
 
 
ab9e430
ba9863e
 
 
 
 
ab9e430
ba9863e
 
 
 
 
ab9e430
ba9863e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ab9e430
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
from typing import Dict, Set
from .parsing import parse_doc
from .contrary import Contrary
from .literal import Literal
from .rule import Rule
from .aba_framework import ABAFramework
import tempfile
import os


def build_aba_framework(doc_path: str) -> ABAFramework:
    """
    Build an ABAFramework object from a structured document.

    Args:
        doc_path (str): Path to the document to parse.

    Returns:
        ABAFramework: An ABAFramework instance containing:
            - language (Set[Literal]): Set of Literal objects.
            - rules (Set[Rule]): Set of Rule objects.
            - assumptions (Set[Literal]): Set of assumptions.
            - contraries (Set[Contrary]): Set of contraries.
            - preferences (Dict[Literal, Set[Literal]]): Preference mappings.

    Example:
        >>> aba = build_aba_framework("./backend/doc.txt")
        >>> isinstance(next(iter(aba.language)), Literal)
        True
        >>> isinstance(next(iter(aba.rules)), Rule)
        True
    """
    # Parse the document
    language_parse, assumptions_parse, contraries_parse, rules_parse, preferences_parse = parse_doc(
        doc_path)

    # Initialize containers
    language: Dict[str, Literal] = {}
    rules: Set[Rule] = set()
    contraries: Set[Contrary] = set()
    assumptions: Set[Literal] = set()
    preferences: Dict[Literal, Set[Literal]] = {}

    # Language: build Literal objects
    for lit in language_parse:
        language[lit] = Literal(lit)

    language_set: Set[Literal] = set(language.values())

    # Rules: convert parsed structure into Rule objects
    for rule in rules_parse:
        r_id = next(iter(rule))
        head = next(iter(rule[r_id]))
        body_atoms = rule[r_id][head]
        body_literals = {language[i] for i in body_atoms if i in language}
        rules.add(Rule(r_id, language[head], body_literals))

    # Contraries: build Contrary objects
    for lit1, lit2 in contraries_parse:
        contraries.add(Contrary(language[lit1], language[lit2]))

    # Assumptions: convert to set of Literal
    for lit in assumptions_parse:
        assumptions.add(language[lit])

    # Preferences: merge all preference dictionaries and convert to Literal objects
    for pref_dict in preferences_parse:
        for lit_str, less_preferred_strs in pref_dict.items():
            if lit_str in language:
                lit_obj = language[lit_str]
                # Convert string literals to Literal objects
                less_preferred_objs = {
                    language[lp] for lp in less_preferred_strs if lp in language}

                # Merge with existing preferences for this literal
                if lit_obj in preferences:
                    preferences[lit_obj].update(less_preferred_objs)
                else:
                    preferences[lit_obj] = less_preferred_objs

    # Build ABA framework
    aba_framework = ABAFramework(
        language=language_set,
        rules=rules,
        assumptions=assumptions,
        contraries=contraries,
        preferences=preferences
    )

    return aba_framework


def prepare_aba_plus_framework(aba_framework: ABAFramework) -> ABAFramework:
    """
    Prepare an ABA framework for ABA+ by ensuring it's atomic and generating
    all necessary components.

    Args:
        aba_framework: The ABA framework to prepare

    Returns:
        ABAFramework: The prepared framework (modified in place)
    """

    # Generate arguments for atomic framework
    print("\nGenerating arguments for atomic framework...")
    aba_framework.arguments.clear()
    aba_framework.generate_arguments()
    print(f"Generated {len(aba_framework.arguments)} arguments")

    # Generate standard attacks
    print("\nGenerating standard attacks for atomic framework...")
    aba_framework.attacks.clear()
    aba_framework.generate_attacks()
    print(f"Generated {len(aba_framework.attacks)} attacks\n")

    return aba_framework


def build_aba_framework_from_text(text: str) -> ABAFramework:
    """
    Build an ABAFramework directly from raw text.
    Uses a temporary file internally to leverage build_aba_framework.

    Args:
        text (str): The ABA framework as raw text (e.g., uploaded via frontend).

    Returns:
        ABAFramework: The ABAFramework instance.
    """
    with tempfile.NamedTemporaryFile("w", delete=False, suffix=".txt", encoding="utf-8") as tmp:
        tmp.write(text)
        tmp_path = tmp.name

    try:
        aba = build_aba_framework(tmp_path)
    finally:
        # Cleanup temporary file
        try:
            os.remove(tmp_path)
        except OSError:
            pass

    return aba