Blame view

semantics/validation.py 11.6 KB
Bartłomiej Nitoń authored
1
2
# -*- coding: utf-8 -*-
Bartłomiej Nitoń authored
3
4
from django.db.models import Max
Bartłomiej Nitoń authored
5
from dictionary.models import Lemma, reflex_phrase_types
Bartłomiej Nitoń authored
6
from semantics.models import LexicalUnitExamples
Bartłomiej Nitoń authored
7
from semantics.utils import get_structural_matching_frame
Bartłomiej Nitoń authored
8
9

def validate_frames(lemma_id):
Bartłomiej Nitoń authored
10
    lemma = Lemma.objects.get(id=lemma_id)
Bartłomiej Nitoń authored
11
    visible_frames = lemma.entry_obj.visible_frames()
Bartłomiej Nitoń authored
12
    error_msg = u''
Bartłomiej Nitoń authored
13
14
    for frame in visible_frames.all():
        error_msg = frame_valid(lemma, frame, visible_frames)
Bartłomiej Nitoń authored
15
16
17
18
        if error_msg:
            break
    return error_msg
Bartłomiej Nitoń authored
19
def frame_valid(lemma, frame, frames):
Bartłomiej Nitoń authored
20
21
22
23
    error_msg = ''
    complements = frame.complements.all()
    if not arguments_exists(complements):
        error_msg = u'Semantyka: Rama semantyczna %d jest pusta.' % frame.id
Bartłomiej Nitoń authored
24
25
    elif not lexical_units_exists(frame):
        error_msg = u'Semantyka: Rama semantyczna %d nie ma dodanych znaczeń.' % frame.id
Bartłomiej Nitoń authored
26
    elif not frame.opinion_selected():
Bartłomiej Nitoń authored
27
        error_msg = u'Semantyka: Rama semantyczna %d nie ma wybranej opinii.' % frame.id
Bartłomiej Nitoń authored
28
29
30
31
32
33
34
35
    elif not roles_unique(complements):
        error_msg = u'Semantyka: Rama semantyczna %d nie zawiera unikalnych ról.' % frame.id
    elif not arguments_pinned(complements):
        error_msg = u'Semantyka: Rama semantyczna %d zawiera argumenty, które nie są powiązane z żadnym schematem.' % frame.id
    elif not preferences_selected(complements):
        error_msg = u'Semantyka: Rama semantyczna %d zawiera argumenty bez zdefiniowanych preferencji selekcyjnych.' % frame.id
    elif not examples_added(frame):
        error_msg = u'Semantyka: Rama semantyczna %d nie ma dopiętych przykładów.' % frame.id
Bartłomiej Nitoń authored
36
    elif duplicates_exists(frame, frames):
Bartłomiej Nitoń authored
37
        error_msg = u'Semantyka: Rama semantyczna %d posiada duplikaty.' % frame.id
Bartłomiej Nitoń authored
38
39
    elif not schemas_reflex_agreed(lemma, frame):
        error_msg = u'Semantyka: Rama semantyczna %d ma dopięte elementy o niezgodnej zwrotności.' % frame.id
Bartłomiej Nitoń authored
40
41
    elif nonch_pinned(frame):
        error_msg = u'Semantyka: Rama semantyczna %d jest dopięta do typu frazy nonch.' % frame.id
Bartłomiej Nitoń authored
42
43
    elif multiplied_same_arg_in_schema(frame):
        error_msg = u'Semantyka: Rama semantyczna %d posiada argument wielokrotnie powiązany z tym samym schematem.' % frame.id
Bartłomiej Nitoń authored
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    # phraseologic
    elif multiword_only_frame_connected_to_not_phr_schema(frame):
        error_msg = u'Semantyka: Rama semantyczna %d (o samych wielosłownych znaczeniach) może być podłączona jedynie do schematów frazeologicznych.' % frame.id
    elif not multiword_frame_connected_to_at_least_one_phr_schema(frame):
        error_msg = u'Semantyka: Rama semantyczna %d (posiadająca wielosłowne znaczenie) musi zostać podłączona do co najmniej jednego schematu frazeologicznego.' % frame.id
    elif not frame_is_using_phraseologic_phr_type(frame):
        error_msg = u'Semantyka: Rama semantyczna %d podłączona do schematu frazeologicznego musi wykorzystywać co najmniej jeden zleksykalizowany typ frazy.' % frame.id
    elif not multiword_frame_has_lemma(frame):
        error_msg = u'Semantyka: Rama semantyczna %d musi posiadać rolę Lemma.' % frame.id
    elif singleword_only_frame_has_lemma(frame):
        error_msg = u'Semantyka: Rama semantyczna %d nie powinna posiadać roli Lemma.' % frame.id
    elif not lemma_always_pinned(frame):
        error_msg = u'Semantyka (rama %d): Rola Lemma, dla ram o samych znaczeniach wielosłownych, musi być zawsze realizowana w podłączonych schematach.' % frame.id
Bartłomiej Nitoń authored
58
59
60
61
62
    return error_msg

def arguments_exists(complements):
    return complements.exists()
Bartłomiej Nitoń authored
63
64
65
def lexical_units_exists(frame):
    return frame.lexical_units.exists()
Bartłomiej Nitoń authored
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def roles_unique(complements):
    roles = set()
    for complement in complements:
        role_ids = [role.id for role in complement.roles.all()]
        role_ids.sort()
        role = tuple(role_ids)
        if role in roles:
            return False
        else:
            roles.add(role)
    return True

def arguments_pinned(complements):
    for compl in complements:
        if not compl.realizations.exists():
            return False
    return True

def preferences_selected(complements):
    for complement in complements:
Bartłomiej Nitoń authored
86
87
88
        if complement.realizations.exists() and complement.has_only_phraseologic_realizations():
            pass
        elif not preference_valid(complement):
Bartłomiej Nitoń authored
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
            return False
    return True

def preference_valid(complement):
    preference = complement.selective_preference
    if preference is None:
        return False
    generals = preference.generals
    synsets = preference.synsets
    relations = preference.relations
    synset_relations = preference.synset_relations
    if generals.count() + synsets.count() + relations.count() + synset_relations.count() > 0:
        return True
    return False

def examples_added(frame):
    for lexical_unit in frame.lexical_units.all():
        if LexicalUnitExamples.objects.filter(lexical_unit=lexical_unit).exists():
            return True
    return False
Bartłomiej Nitoń authored
110
111
112
113
114
115
def duplicates_exists(frame, frames):
    # frazeologicznych ram nie sprawdzamy
    if frame.complements.filter(roles__role='Lemma').exists():
        return False

    frames_to_check = frames.exclude(id=frame.id)
Bartłomiej Nitoń authored
116
    if get_structural_matching_frame(frames_to_check, frame):
Bartłomiej Nitoń authored
117
118
119
        return True
    return False
Bartłomiej Nitoń authored
120
def schemas_reflex_agreed(lemma, frame):
Bartłomiej Nitoń authored
121
    agreed = True
Bartłomiej Nitoń authored
122
123
    complements = frame.complements.all()
    lexical_units = frame.lexical_units.all()
Bartłomiej Nitoń authored
124
125
126
127
128
    for schema in lemma.frames.all():
        schema_agreed = False
        for lex_unit in lexical_units:
            if schema_lex_unit_reflex_agree(lex_unit, schema, complements):
                schema_agreed = True
Bartłomiej Nitoń authored
129
                break
Bartłomiej Nitoń authored
130
131
132
133
        if not schema_agreed:
            agreed = False
            break
    return agreed
Bartłomiej Nitoń authored
134
Bartłomiej Nitoń authored
135
136
137
def schema_lex_unit_reflex_agree(lexical_unit, schema, complements):
    if complements.filter(realizations__frame=schema).exists():
        if (not reflex_with_self_mark_agreed(lexical_unit, schema) and 
Bartłomiej Nitoń authored
138
            not (lexical_unit.is_reflexive() and not lexical_unit.is_new() and
Bartłomiej Nitoń authored
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
             reflex_with_phrase_types_agreed(lexical_unit, schema, complements))):
            return False
    return True

def reflex_with_self_mark_agreed(lexical_unit, schema):
    schema_self_mark = schema.get_char_value('ZWROTNOŚĆ').value
    if not lexical_unit.is_reflexive() == bool(schema_self_mark):
        return False
    return True

def reflex_with_phrase_types_agreed(lexical_unit, schema, complements):
    max_alternations = complements.all().aggregate(Max('realizations__alternation'))['realizations__alternation__max']
    for alternation in range(1, max_alternations+1):
        if not reflex_with_alternation_phrase_types_agreed(complements, schema, alternation):
            return False
    return True

def reflex_with_alternation_phrase_types_agreed(complements, schema, alternation):
    for compl in complements:
        if compl.realizations.filter(argument__type__in=reflex_phrase_types(),
                                     alternation=alternation,
                                     frame=schema).exists():
Bartłomiej Nitoń authored
161
162
163
164
            return True
    return False

def nonch_pinned(frame):
Bartłomiej Nitoń authored
165
    if frame.complements.filter(realizations__argument__text_rep='nonch').exists():
Bartłomiej Nitoń authored
166
167
168
        return True
    return False
Bartłomiej Nitoń authored
169
170
def multiplied_same_arg_in_schema(frame):
    for compl in frame.complements.all():
Bartłomiej Nitoń authored
171
172
173
174
175
176
177
178
        if compl.roles.filter(role='Lemma').exists():
            continue
        else:
            for real in compl.realizations.all():
                same_frame_realizations = compl.realizations.filter(frame=real.frame,
                                                                    alternation=real.alternation)
                if same_frame_realizations.exclude(position=real.position).exists():
                    return True
Bartłomiej Nitoń authored
179
180
    return False
Bartłomiej Nitoń authored
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# phraseologic
def multiword_only_frame_connected_to_not_phr_schema(frame):
    if (frame.multiword_meanings_only() and 
        frame.complements.filter(realizations__frame__phraseologic=False).exists()):
        return True
    return False

def multiword_frame_connected_to_at_least_one_phr_schema(frame):
    valid = False
    if not frame.has_multiword_meaning():
        valid = True
    elif (frame.has_multiword_meaning() and 
        frame.complements.filter(realizations__frame__phraseologic=True).exists()):
        valid = True
    return valid

def frame_is_using_phraseologic_phr_type(frame):
    phr_connected_schemata = frame.connected_schemata().filter(phraseologic=True)
    for schema in phr_connected_schemata:
        schema_ok = False
        for compl in frame.complements.all():
            for real in compl.realizations.filter(frame=schema):
                if real.argument.is_phraseologic():
                    schema_ok = True
                    break
            if schema_ok:
                break
        if not schema_ok:
            return False
    return True

def multiword_frame_has_lemma(frame):
    valid = False
    if not frame.has_multiword_meaning():
        valid = True
    elif (frame.has_multiword_meaning() and frame.role_exists('Lemma')):
        valid = True
    return valid

def singleword_only_frame_has_lemma(frame):
    if(not frame.has_multiword_meaning() and frame.role_exists('Lemma')):
        return True
    return False

def lemma_always_pinned(frame):
    if frame.role_exists('Lemma') and frame.multiword_meanings_only():
        lemma_arg = frame.complements.get(roles__role='Lemma')
        connected_schemata = frame.connected_schemata()
        for schema in connected_schemata:
            if not lemma_arg.realizations.filter(frame=schema).exists():
                return False
    return True
Bartłomiej Nitoń authored
235
236
237
238
239
240
241
242
def validate_schemas(lemma_id):
    error_msg = ''
    lemma = Lemma.objects.get(id=lemma_id, old=False)
    if not all_schemas_used(lemma):
        error_msg = u'Semantyka nie wykorzystuje wszystkich poprawnych schematów walencyjnych.'
    return error_msg

def all_schemas_used(lemma):
Bartłomiej Nitoń authored
243
    frames = lemma.entry_obj.visible_frames()
Bartłomiej Nitoń authored
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
    schemas = lemma.frames
    for schema in schemas.all():
        if not schema_is_bad(lemma, schema) and not schema_used(schema, frames):
            return False
    return True

def schema_is_bad(lemma, schema):
    schema_opinion = lemma.frame_opinions.get(frame=schema)
    if schema_opinion.value.short == 'bad':
        return True
    return False

def schema_used(schema, frames):
    for frame in frames:
        if frame.complements.filter(realizations__frame=schema).exists():
            return True
    return False

def validate_lexical_units(lemma_id):
    error_msg = ''
    lemma = Lemma.objects.get(id=lemma_id, old=False)
Bartłomiej Nitoń authored
265
    lexical_units = lemma.entry_obj.meanings
Bartłomiej Nitoń authored
266
267
    for lex_unit in lexical_units.all():
        if not examples_reflex_agreed(lex_unit):
Bartłomiej Nitoń authored
268
            error_msg = u'Semantyka: Znaczenie %s ma podpięte przykłady o niezgodnej zwrotności.' % unicode(lex_unit)
Bartłomiej Nitoń authored
269
270
271
272
        elif hanging_meaning(lex_unit):
            error_msg = u'Semantyka: Znaczenie %s nie jest reprezentowane przez żadną ramę semantyczną.' % unicode(lex_unit)
        if error_msg:
            break
Bartłomiej Nitoń authored
273
274
275
276
277
278
    return error_msg

def examples_reflex_agreed(lexical_unit):
    lex_examples = LexicalUnitExamples.objects.filter(lexical_unit=lexical_unit)
    for lex_example in lex_examples:
        schema_reflex = lex_example.example.frame.get_char_value('ZWROTNOŚĆ').value
Bartłomiej Nitoń authored
279
280
        if (not (lexical_unit.is_reflexive() == bool(schema_reflex)) and 
            not (lexical_unit.is_reflexive() and not lexical_unit.is_new() and
Bartłomiej Nitoń authored
281
                 lex_example.example.arguments.filter(arguments__type__in=reflex_phrase_types()).exists())):
Bartłomiej Nitoń authored
282
283
            return False
    return True
Bartłomiej Nitoń authored
284
285
286
287
288
289

def hanging_meaning(lexical_unit):
    if lexical_unit.luid < 0 and not lexical_unit.actual_frames().exists():
        return True
    return False