transform_frame.py 5.73 KB
#! /usr/bin/python3

from copy import copy, deepcopy

# changes role label of a single argument with the given label
class ArgumentChange():
    def __init__(self, role_tuple):
        self._roles = sorted(list(role_tuple))
        self._final_role = '_'.join(self._roles)

    def apply(self, frame, prefix):
        results = []
        for label in self._roles:
            if label in frame._arguments:
                for i in range(len(frame._arguments[label])):
                    new_frame = deepcopy(frame)
                    moved = new_frame._arguments[label].pop(i)
                    new_frame.add_argument(label + '^' + self._final_role, moved)
                    if len(new_frame._arguments[label]) == 0:
                        del new_frame._arguments[label]
                    if prefix == "":
                        results.append((label + "," + str(i), new_frame))
                    else:
                        results.append((prefix + '/' + label + "," + str(i), new_frame))
        return results
                
        
# changes role label of all arguments with the given label
class RoleChange():
    def __init__(self, role_tuple):
        self._roles = sorted(list(role_tuple))
        self._final_role = '_'.join(self._roles)
        
    def apply(self, frame, prefix):
        results = []
        present = [int(label in frame._arguments) for label in self._roles]
        count = sum(present)
        if count == 1:
            for label in self._roles:
                if label in frame._arguments:
                    new_frame = deepcopy(frame)
                    new_frame._arguments[label + '^' + self._final_role] = frame._arguments[label]
                    del new_frame._arguments[label]
                    if prefix == '':
                        results = [(label + '*', new_frame)]
                    else:
                        results = [(prefix + '/' + label + '*', new_frame)]
        return results
        
        
class Rule():
    def __init__(self, name, signature, changes_list):
        self._name = name
        self._signature = signature
        self._changes = []
        for type, change in changes_list:
            if type == 'argument':
                ch = ArgumentChange(change)
                self._changes.append(ch)
            elif type == 'role':
                ch = RoleChange(change)
                self._changes.append(ch)
            else:
                raise Error()

    def _clean(self, frame):
        static_arguments = copy(list(frame._arguments.keys()))
        for role in static_arguments:
            if '^' in role:
                old, new = role.split('^')
                if new not in frame._arguments:
                    frame._arguments[new] = []
                frame._arguments[new] += frame._arguments[role]
                del frame._arguments[role]
            
    def apply(self, frame):
        output = [('', frame)]
        for change in self._changes:
            results = []
            for prefix, partial_frame in output:
                results += change.apply(partial_frame, prefix)
            output = results
        for name, result in output:
            self._clean(result)
        return output

    def __str__(self):
        return self._name

    def sign(self):
        return self._signature

class TransformationRules():
    _rules = None

    _rules_factor = [
        ('', []),
        ('FT', [('argument', ['Factor', 'Theme'])]),
        ('FS', [('argument', ['Factor', 'Stimulus'])]),
        ('FIt', [('argument', ['Factor', 'Initiator'])]),
        ('FRc', [('argument', ['Factor', 'Recipient'])]),
    ]

    _rules_theme = [
        ('', []),
        ('RsT', [('argument', ['Result', 'Theme'])]),
        ('RcT', [('argument', ['Recipient', 'Theme'])]),
        ('PCT', [('argument', ['Purpose', 'Condition', 'Theme'])]),
    ]

    _rules_role = [
#         ('(ItE)*(TS)*', [('role', ['Initiator', 'Experiencer']),
        ('ItETS', [('role', ['Initiator', 'Experiencer']),                         
                         ('role', ['Theme', 'Stimulus'])]),
#        ('(TE)*(CS)*', [('role', ['Theme', 'Experiencer']),
        ('TECS', [('role', ['Theme', 'Experiencer']),
                        ('role', ['Condition', 'Stimulus'])]),
    ]
    
    _rules_mnis = [
        ('', []),
        ('MnIs', [('argument', ['Manner', 'Instrument'])]),
    ]
    
    _rules_msd = [
        ('', []),
        ('MsD', [('argument', ['Measure', 'Duration'])]),
    ]
    
    @classmethod
    def get_rules(cls):
        if cls._rules is None:
            rules = []
            for namef, rulef in cls._rules_factor:
                for namet, rulet in cls._rules_theme:
                    for namemn, rulemn in cls._rules_mnis:
                        for namems, rulems in cls._rules_msd:
                            name = namef + '/' + namet + '/' + namemn + '/' +namems
                            signature = namef.lower() + namet.lower() + namemn.lower() + namems.lower()
                            if signature == '':
                                signature = 'zero'
                            rule = rulef + rulet + rulemn + rulems
                            rules.append(Rule(name, signature, rule))
            for namer, ruler in cls._rules_role:
                for namemn, rulemn in cls._rules_mnis:
                    for namems, rulems in cls._rules_msd:
                        name = namer + '/' + namemn + '/' + namems
                        signature = namer.lower() + namemn.lower() + namems.lower()
                        rule = ruler + rulemn + rulems
                        rules.append(Rule(name, signature, rule))
            cls._rules = rules
        return cls._rules
    
    @classmethod
    def get_weight(cls, rule):
        return 1
        
if __name__ == '__main__':
    pass