import logging import morfeusz2 from entries.phrase_descriptions.descriptions import make_phraseologisms from importer.Phrase import Case, Preposition, Modification, Words, NP, LexNP, PrepNP, LexPrepNP, AdjP, LexAdjP, PActP, LexPActP, Compar, LexCompar, Fixed from importer.Position import Position from importer.Global import get_current_entry class RealisationDescriptionError(Exception): pass morfeusz = morfeusz2.Morfeusz(generate=False, analyse=True, expand_tags=True) SYNSET_KILL_LIST = ( 5564, # forma skupienia substancji-1 (miksować na masę/pianę/sok/.../formę skupienia substancji 24299, # kopytny-1 kopytowiec-1 (w: potratować) 87011, # wyrywanie-1 (w: wyplenić, upierdliwe gerundium, bierzemy herbicyd-1 środek chwastobójczy-1) 102594, # GERUNDIUM-1 ) UNIT_KILL_LIST = ( ('członek', '3'), # część ciała-1 ('pani', '2'), # kobieta-1 ('pan', '2'), # mężczyzna-1 ('rodzaj', '1'), ('twarz', '3'), # wersja-1 ('rzeczownik własny', '1'), # nazwa własna-1 ('środek lokomocji', '1',), # środek transportu-1 ('ojciec', '3',), # autor-1, twórca-1 ('dyscyplina sportu', '1'), # dyscyplina sportowa-1 ('siedzenie', '7'), # pupa-1 itd. ('jednostka odległości', '1'), # jednostka długości ('przyrząd sportowy', '1'), # sprzęt sportowy ('środek spożywczy', '1'), # produkt spożywczy ('płód', '3'), # wytwór umysłu-1 ('działanie prawne', '1'), # czynność prawna ('CO2', '1'), ('ditlenek węgla', '1'), # dwutlenek węgla-1 ('forma fizyczna', '1'), ('sprawność fizyczna', '1'), # kondycja fizyczna ('surowiec energetyczny', '1'), # paliwo kopalne ('C', '6'), ('°C', '1'), ('celsjusz', '1'), # stopień Celsjusza ('akt', '4'), # ceremoniał-1, obrządek-1, ... ('uniemożliwianie', '1'), # udaremnianie-1 ('zły czyn', '1'), # zły uczynek ('dzieło literackie', '1'), # utwór literacki ('profesor nadzwyczajny', '1'), # profesor zwyczajny ('nauka', '1'), ('dziedzina wiedzy', '1'), # dyscyplina naukowa ('ciąg wydarzeń', '1'), # ciąg zdarzeń ('zaburzenie', '1'), ('naruszenie', '2'), ('przekroczenie', '3'), ('złamanie', '2'), # uchybienie-1 wykroczenie-1 ('agent gospodarczy', '1'), ('jednostka gospodarcza', '1'), # podmiot gospodarczy ('obróbka termiczna', '1'), # obróbka cieplna ('praca', '6'), # dzieło-2 ('pojazd kolejowy', '1'), # pojazd szynowy-1 ('aromaty', '1'), # wonności-1 ('pojazd kosmiczny', '1'), # statek kosmiczny-1 ('splot wydarzeń', '1'), # zbieg okoliczności ('raz', '2'), # cios-1, uderzenie-10 ('zainteresowanie', '2'), ('inklinacja', '2'), # przychylność-2 sympatia-1 ) SYNSET2LEMMA = { #człowiek-1, istota ludzka-1, jednostka-2, osoba-1 6047 : 'LUDZIE', # TODO? heurystyka: wszystkie lu > 2(3?) słów -> przejdź do hiponimu/hiperonimu? # człowiek ze względu na pełnioną funkcję-1 6822 : 'LUDZIE', # człowiek ze względu na swoje zajęcie-1 6797 : 'LUDZIE', # człowiek ze względu na relacje społeczne-1 6775 : 'LUDZIE', # człowiek o określonej narodowości, przynależności państwowej-1 20542 : 'LUDZIE', # człowiek charakteryzowany ze względu na kwalifikacje-1 6779 : 'LUDZIE', # człowiek, który coś robi-1 241977 : 'LUDZIE', # miejsce ze względu na przeznaczenie-1 25121 : 'MIEJSCE', # miejsce wyróżniające się z całości obiektu-1 105470 : 'MIEJSCE', # rzecz oceniana negatywnie-1 26983 : 'ALL', # rzecz oceniana pozytywnie-1 31937 : 'ALL', # własność komunikatu, wypowiedzi-1 39190 : 'ALL', # zbiór obiektów - kolekcja elementów-1 103163 : 'ALL', # doświadczenie negatywnego uczucia-1 97278 : 'ALL', # GERUNDIUM OD CZASOWNIKA DYNAMICZNEGO (AKCJA)-1 102592 : 'ALL', } SYNSET_MAP = { # przeważnie sensowniejsze są hiponimy # człowiek płci żeńskiej-1 -> kobieta-1 225273 : 129, # człowiek, który wykonuje czynności religijne-1 -> kapłan-1 239405 : 683, # człowiek płci męskiej-1 -> mężczyzna-1 225272 : 6709, # pracownik służby zdrowia-1 -> doktor-1 lek.-1 lekarz-1 6379 : 597, # człowiek ukarany-1 -> skazaniec-1 skazany-1 41644 : 7909, # placówka służby zdrowia-1 -> lecznica-2 przychodnia-1 4821 : 8858, # pojazd nawodny lub podwodny-1 -> statek-1 225184 : 7354, # pojazd o przeznaczeniu wojskowym-1 -> pojazd wojskowy-1 227639 : 225095, # narzędzie do łowienia-1 -> wędka-1> 42387 : 14273, # urządzenie wspomagające proces liczenia-1 -> liczydło-1 237614 : 17750, # zdarzenie oceniane negatywnie-1 -> cios-2 dramat-3 nieszczęście-1 tragedia-1 zguba-1 27419 : 1911, # czynność o charakterze sakralnym-1 -> akt-4 ceremoniał-1 obrządek-1 obrzęd-1 ryt-2 rytuał-1 105440 : 6566, # zrobienie czegoś niezgodnego z prawem lub z normami społecznymi-1 -> naruszenie-2 przekroczenie-3 uchybienie-1 wykroczenie-1 zaburzenie-1 złamanie-2 99630 : 99214, # instrument dęty blaszany-1 -> róg-5 waltornia-1 233727 : 25206, # jednostka miary kąta-1 -> deg-1 stopień-6 °-1 41774 : 41779, # czynność o charakterze fizjologicznym-1 -> czynność-1 # (tutaj hiponimy się nie nadają: respiracja-1, plozja-1> 105442 : 10765, # zamachowiec-samobójca-1 -> zamachowiec-1 80502 : 18234, # gracz w karty-1 -> gracz-1> 59620 : 969, # sztuczne źródło światła-1 -> światło-10 źródło światła-1> 227275 : 5519, # czytnik kodu paskowego-1 skaner do kodów kreskowych-1 -> czytnik-1 237869 : 13600, # środek transportu publicznego-1 -> środek lokomocji-1 środek transportu-1 228654 : 8674, # sposób poruszania się-1 -> sposób-1> 238882 : 8194, # właściwość zdarzenia, sytuacji-1 -> atrybut-1 cecha-1 przymiot-1 własność-2 właściwość-1 5479 : 323, # cecha żywego organizmu-1 -> cecha-1 36346 : 323, # echa uwarunkowana kulturowo-1 -> cecha-1 249629 : 323, # zawodnik w drużynie-1 -> zawodnik-1 234138 : 4286, # metryczna jednostka masy-1 -> jednostka masy-1 231263 : 7946, # część garderoby-1 element garderoby-1 element ubioru-1 sztuka odzieży-1 -> strój-1 ubiór-1 ubranie-3 # meronimia 227081 : 3289, # żywienie do kogoś pozytywnych uczuć-1 -> inklinacja-2 przychylność-2 sympatia-1 zainteresowanie-2 # zupełnie niepowiązany synset, żywienie... jest z hierarchii GERUNDIUM 81622 : 3367, } LEMMA_KILLLIST = ('odzieża',) def get_interps(word, lemma=None, tag_constraints=None): interps = set() for i, j, (orth, base, tag, p, k) in morfeusz.analyse(word): tag_elems = set(tag.split(':')) base = base.split(':')[0] if base not in LEMMA_KILLLIST and (not lemma or base == lemma) and (not tag_constraints or tag_elems.issuperset(tag_constraints)): interps.add((base, tag)) return interps def get_adj_lemma(word): interps = get_interps(word, tag_constraints=['adj']) lemmata = set(lemma for lemma, tag in interps) degrees = set(tag.split(':')[4] for lemma, tag in interps) assert(len(lemmata) == 1) assert(len(degrees) == 1) return lemmata.pop(), degrees.pop() def get_pact_lemma(word): interps = get_interps(word, tag_constraints=['pact']) lemmata = set(lemma for lemma, tag in interps) assert(len(lemmata) == 1) return lemmata.pop() def get_subst_lemma(word, case): if (word, case) == ('zbrodni', 'gen'): # nie: zbrodzień return 'zbrodnia', 'sg' interps = get_interps(word, tag_constraints=['subst', case]) lemmata = set(lemma for lemma, tag in interps) nums = set(tag.split(':')[1] for lemma, tag in interps) try: assert(len(lemmata) == 1) except: print(word, case, interps) raise # TODO? heurystyka dla liczby, np. ‹sztuka *odzieży*› return lemmata.pop(), 'sg' if 'sg' in nums else 'pl' def adj2adv(lemma): if lemma.endswith('ny'): return lemma[:-1] + 'ie' 1/0 ''' def get_degree(word): interps = morfeusz.analyse(word) adj_tags = [interp[2][2] for interp in interps if interp[2][2].startswith('adj:')] degrees = set(tag.split(':')[4] for tag in adj_tags) assert(len(degrees) == 1) return degrees.pop() ''' ''' def get_num(word, case): interps = morfeusz.analyse(word) subst_tags = [interp[2][2] for interp in interps if interp[2][2].startswith('subst:')] nums = set(tag.split(':')[1] for tag in subst_tags if case in tag) # TODO heuristic return 'sg' if 'sg' in nums else 'pl' ''' GERUNDS = { 'przyrządzanie', 'szarpnięcie', } GENDER = { 'braterstwo' : 'n', 'DNA' : 'n', 'narzeczeństwo' : 'n', 'burda' : 'f', 'nuda' : 'f', 'pasza' : 'f', 'przekora' : 'f', 'reżyser' : 'f', # grl pwr! 'sędzia' : 'f', 'włóczęga' : 'f', 'aspirant' : 'm1', 'bojownik' : 'm1', 'champion' : 'm1', 'członek' : 'm1', # członek rodziny 'faworyt' : 'm1', 'gad' : 'm1', 'głąb' : 'm1', 'idol' : 'm1', 'informator' : 'm1', 'inicjator' : 'm1', 'mediator' : 'm1', 'orzeł' : 'm1', 'pilot' : 'm1', 'poseł' : 'm1', 'pośrednik' : 'm1', 'prekursor' : 'm1', 'profesor' : 'm1', 'przewodnik' : 'm1', 'reprezentant' : 'm1', 'śpiewak' : 'm1', 'tchórz' : 'm1', 'tłumacz' : 'm1', 'zbieg' : 'm1', 'blues' : 'm2', # czuje bluesa 'całus' : 'm2', 'całusek' : 'm2', 'czort' : 'm2', 'diabeł' : 'm2', 'drapieżnik' : 'm2', 'fioł' : 'm2', 'grzyb' : 'm2', 'guz' : 'm2', 'kaduk' : 'm2', 'kogut' : 'm2', 'konik' : 'm2', 'kopniak' : 'm2', 'kosz' : 'm2', 'kot' : 'm2', 'koziołek' : 'm2', 'lód' : 'm2', 'Oscar' : 'm2', 'pająk' : 'm2', 'papieros' : 'm2', # pies aportujący, nie pałujący 'pies' : 'm2', 'pion' : 'm2', # szachowy 'samiec' : 'm2', 'ssak' : 'm2', 'świr' : 'm2', # dostać świra 'wąż' : 'm2', 'zając' : 'm2', 'ziemniak' : 'm2', 'dobry' : 'm3', 'antytalent' : 'm3', 'aparat' : 'm3', 'asfalt' : 'm3', 'bas' : 'm3', 'bełkot' : 'm3', 'beton' : 'm3', 'bis' : 'm3', 'blog' : 'm3', 'bodziec' : 'm3', 'bruderszaft' : 'm3', 'but' : 'm3', 'bzik' : 'm3', 'cep' : 'm3', 'chichot' : 'm3', 'czubek' : 'm3', 'drapak' : 'm3', 'drut' : 'm3', 'dzień' : 'm3', # nie f 'dół' : 'm3', 'e-mail' : 'm3', 'fart' : 'm3', 'fenomen' : 'm3', 'figiel' : 'm3', 'flak' : 'm3', 'flis' : 'm3', 'galop' : 'm3', 'gnat' : 'm3', 'grill' : 'm3', 'grzmot' : 'm3', 'ideał' : 'm3', 'klawisz' : 'm3', 'klops' : 'm3', 'kołek' : 'm3', 'kozioł' : 'm3', 'Księżyc' : 'm3', 'kuksaniec' : 'm3', 'kurek' : 'm3', 'lek' : 'm3', 'licencjat' : 'm3', 'link' : 'm3', 'łeb' : 'm3', 'marsz' : 'm3', 'mat' : 'm3', 'mejl' : 'm3', 'metal' : 'm3', 'mikser' : 'm3', 'minus' : 'm3', 'młot' : 'm3', 'model' : 'm3', 'news' : 'm3', 'odpowiednik' : 'm3', 'operator' : 'm3', 'palec' : 'm3', 'paluch' : 'm3', 'pas' : 'm3', 'plaster' : 'm3', 'plus' : 'm3', 'pomruk' : 'm3', 'popłoch' : 'm3', 'post' : 'm3', 'powód' : 'm3', 'rapsod' : 'm3', 'ryj' : 'm3', 'Rzym' : 'm3', 'sen' : 'm3', 'skręt' : 'm3', 'smród' : 'm3', 'sport' : 'm3', 'stop' : 'm3', 'strach' : 'm3', 'sygnalizator' : 'm3', 'szampan' : 'm3', 'talent' : 'm3', 'wist' : 'm3', 'walkower' : 'm3', 'wał' : 'm3', 'wyż' : 'm3', 'zajob' : 'm3', 'ząb' : 'm3', 'zwiastun' : 'm3', } def get_gender(interps): # TODO? forms = set(form for form, tag in interps) if len(forms) == 1 and list(forms)[0] in GENDER: return GENDER[forms.pop()] genders = set(tag.split(':')[3] for form, tag in interps) try: assert(len(genders) == 1) return genders.pop() except: print(interps) def get_simplified_tags(word): tags = set() for interp in morfeusz.analyse(word): tag = interp[2][2].split(':') pos = tag[0] if pos in ('subst', 'ger'): # POS + case tags.add('{}:{}'.format(tag[0], tag[2])) elif pos == 'prep': # POS + case tags.add('prep:{}'.format(tag[1])) else: tags.add(pos) return tags def make_comprepnp(comprep, words, num, mod): dummy_id = None np = NP(Case('gen'), dummy_id) lexnp = LexNP(np, num, words, mod, dummy_id) phrases = set(make_phraseologisms(lexnp, None, None)) assert(len(phrases) == 1) return ['{} {}'.format(comprep, phrases.pop())] def make_compar(compar, words, num, mod, controller): dummy_id = None #if not controller: # raise RealisationDescriptionError('no controller for {}'.format(compar)) if controller: controller_case = controller.getCase() else: pos, lemma = get_current_entry()._pos, get_current_entry()._base if pos == 'verb': controller_case = 'nom' # najczęściej chyba nom lub acc, ale trzeba coś wybrać if pos == 'noun': controller_case = 'gen' # degradacja kogoś jako kogoś itp. if pos in ('adj', 'adv'): controller_case = 'nom' # analogiczny jak coś itp. logging.warning('{}: no controller for {}; assuming {}.'.format(lemma, compar, controller_case)) np = NP(Case(controller_case), dummy_id) lexnp = LexNP(np, num, words, mod, dummy_id) return LexCompar(compar, [lexnp], dummy_id) def make_adjp_mod(word): dummy_id = None adjp = AdjP(Case('agr'), dummy_id) lemma, degree = get_adj_lemma(word) words = Words('concat', 'xor', [lemma]) lex_adjp = LexAdjP(adjp, 'agr', 'agr', degree, words, NATR, None) mod_position = Position(None, None, None, [lex_adjp], dummy_id) return Modification('ratr1', [mod_position]) def make_pactp_mod(word): dummy_id = None pactp = PActP(Case('agr'), dummy_id) lemma = get_pact_lemma(word) words = Words('concat', 'xor', [lemma]) lex_pactp = LexPActP(pactp, 'agr', 'agr', 'aff', words, '', NATR, None) mod_position = Position(None, None, None, [lex_pactp], dummy_id) return Modification('ratr1', [mod_position]) def make_npgen_mod(word): dummy_id = None np = NP(Case('gen'), dummy_id) lemma, num = get_subst_lemma(word, 'gen') words = Words('concat', 'xor', [lemma]) lex_np = LexNP(np, num, words, NATR, None) mod_position = Position(None, None, None, [lex_np], dummy_id) return Modification('ratr1', [mod_position]) def make_prepnp_mod(word, prep, case): dummy_id = None prepnp = PrepNP(Preposition(prep, Case(case)), dummy_id) lemma, num = get_subst_lemma(word, case) words = Words('concat', 'xor', [lemma]) lex_prepnp = LexPrepNP(prepnp, num, words, NATR, None) mod_position = Position(None, None, None, [lex_prepnp], dummy_id) return Modification('ratr1', [mod_position]) def make_fixed_mod(text): dummy_id = None fixed = Fixed(None, text, dummy_id) mod_position = Position(None, None, None, [fixed], dummy_id) return Modification('ratr1', [mod_position]) NATR = Modification('natr', None) JAKIS = make_adjp_mod('jakiś') PREDEF2LEMMA = { 'CECHA' : { 'adjp' : ('jakiś', None, 'sg', 'adj', NATR), '_' : ('cecha', 'f', 'sg', 'subst', JAKIS), }, 'CZAS' : { '_' : ('moment', 'm3', 'sg', 'subst', JAKIS), }, 'CZEMU' : { '_' : ('powód', 'm3', 'sg', 'subst', JAKIS), }, 'CZYNNOŚĆ' : { '_' : ('czynność', 'f', 'sg', 'subst', JAKIS), }, 'DOBRA' : { '_' : ('dobra', 'n', 'pl', 'subst', JAKIS), }, 'ILOŚĆ' : { '_' : ('ilość', 'f', 'sg', 'subst', JAKIS), }, 'ISTOTY' : { '_' : ('istota', 'f', 'sg', 'subst', JAKIS), }, 'JADŁO' : { '_' : ('pożywienie', 'n', 'sg', 'subst', JAKIS), }, # Ela proponowała: sytuacja, ale wtedy mamy np. absolutorium za jakąś sytuację i wygląda dziwnie 'KIEDY' : { '_' : ('czas', 'm3', 'sg', 'subst', JAKIS), }, 'KOMUNIKAT' : { '_' : ('komunikat', 'm3', 'sg', 'subst', JAKIS), }, 'KONCEPCJA' : { '_' : ('koncepcja', 'f', 'sg', 'subst', JAKIS), }, 'LUDZIE' : { 'possp' : ('czyjś', None, 'sg', 'adj', NATR), '_' : ('ktoś', 'm1', 'sg', 'subst', NATR), }, 'MIEJSCE' : { '_' : ('miejsce', 'n', 'sg', 'subst', JAKIS), }, 'OBIEKTY' : { '_' : ('obiekt', 'm3', 'sg', 'subst', JAKIS), }, 'OTOCZENIE' : { '_' : ('otoczenie', 'n', 'sg', 'subst', JAKIS), }, # PODMIOTY -> LUDZIE #'PODMIOTY' : { # 'possp' : ('czyjś', 'sg', 'adj', NATR), # '_' : ('ktoś', 'sg', 'subst', NATR), #}, 'POŁOŻENIE' : { '_' : ('położenie', 'n', 'sg', 'subst', JAKIS), }, 'SYTUACJA' : { '_' : ('sytuacja', 'f', 'sg', 'subst', JAKIS), }, 'WYTWÓR' : { '_' : ('wytwór', 'm3', 'sg', 'subst', JAKIS), }, 'ALL' : { '_' : ('coś', 'n', 'sg', 'subst', NATR), } } PREDEFXP = { 'caus' : { 'LUDZIE' : 'z czyjegoś powodu', 'ISTOTY' : 'z powodu jakiejś istoty', 'ALL' : 'z jakiegoś powodu', }, 'dest' : { 'LUDZIE' : 'dla kogoś', 'ALL' : 'w jakimś celu', }, 'mod' : { 'ISTOTY' : 'w jakiś sposób', 'ALL' : 'w jakiś sposób', }, 'instr' : { 'LUDZIE' : 'z czyjąś pomocą', 'ISTOTY' : 'z pomocą jakiejś istoty', 'ALL' : 'za pomocą czegoś', }, 'abl' : { 'LUDZIE' : 'od kogoś', 'ISTOTY' : 'od jakiejś istoty', 'ALL' : 'skądś', }, 'adl' : { 'LUDZIE' : 'do kogoś', 'ISTOTY' : 'do jakiejś istoty', 'MIEJSCE' : 'dokądś', 'ALL' : 'dokądś', }, 'locat' : { 'LUDZIE' : 'u kogoś', 'ISTOTY' : 'u jakiejś istoty', 'MIEJSCE' : 'gdzieś', 'ALL' : 'gdzieś', }, 'perl' : { 'LUDZIE' : 'po kimś', # „jak żebrak, jak bandyta czołgam się *pod nimi*” – to raczej nie powinno być xp(perl), tylko prepnp; ale coś muszę przypisać, więc „po kimś”, bo jeśli już, to coś/ktoś może przejść/chodzić po kimś... 'ISTOTY' : 'po jakieś istocie', 'ALL' : 'którędyś', }, 'temp' : { 'LUDZIE' : 'kiedyś', # np. bezprawie 'ALL' : 'kiedyś', }, 'dur' : { 'ALL' : 'przez jakiś czas', }, }