From ffd8e900adb354632f2184bed1aa52d459a21926 Mon Sep 17 00:00:00 2001 From: Erickson Silva Date: Mon, 23 Feb 2015 23:15:00 -0300 Subject: [PATCH] Refatora completamente o aplicador de regras --- src/new/AplicaRegras.py | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/new/TraduzSentencas.py | 1 - 2 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 src/new/AplicaRegras.py diff --git a/src/new/AplicaRegras.py b/src/new/AplicaRegras.py new file mode 100644 index 0000000..642c3dd --- /dev/null +++ b/src/new/AplicaRegras.py @@ -0,0 +1,343 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +import platform +import xml.etree.ElementTree as ET +from os.path import expanduser +from collections import deque +from LerDicionarios import * +from Iterator import * +from StringAux import * +from ConverteExtenso import * +from nltk_tgrep import tgrep_positions, tgrep_nodes +from nltk import ParentedTree, Tree, draw + +class AplicaRegras(object): + + # inicializa todos as variaveis + def __init__(self): + self.__root = self.get_root() + self.dicionarios = LerDicionarios() + self.__especificos = {"advt":self.verificar_adv_tempo, "v":self.verificar_vb_infinitivo, "x":self.verificar_preposicao, + "c":self.verificar_subst_genero, "a":self.verificar_artigo, "l":self.verificar_vb_ligacao, + "i":self.verificar_adv_intensidade, "vbi":"zero", "n":self.verificar_vb_muda_negacao, "abmn":"zero", + "adji":"zero","adjn":"zero", "advi":"zero"} + + def get_root(self): + if platform.system() == 'Windows': + return ET.parse(expanduser("~")+'\\vlibras-translate\data\\regras.xml').getroot() + return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() + + def aplicar_regras_morfo(self, lista, sint=False): + self.lista = list(lista) + self.quantidade_iter_pular = 0 + self.lista_corrigida = [] + + it = Iterator() + it.load(self.lista) + + while(it.has_next()): + #if self.quantidade_iter_pular > 0: + # self.quantidade_iter_pular-=1 + # continue + + for morpho in self.__root.findall('morphological'): + self.has_rule = False + for rule in morpho.findall('rule'): # procura a tag rule + if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): + count = int(rule.find('count').text) + self.lista_iteracoes = [] + if count == 1: + self.lista_iteracoes = [it.get_token()] + else: + try: + self.lista_iteracoes = it.get_interval(count) + it.skip(count-1) + #self.quantidade_iter_pular = count-1 + except: + continue + + self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) + if rule.get('name') == self.nome_regra: # verifica se a regra é aplicavel e a mesma esta ativa + self.has_rule = True + self.lista_iteracao_regra = count * [None] + self.count_iteracao_regra = -1 + + print "REGRA MORFOLÓGICA: " + rule.get('name') + + for classe in rule.iter('class'): # for nas tags class + + title = classe.find('title') + newpos = classe.find('newpos') + newprop = classe.find('newprop') + newtoken = classe.find('newtoken') + newtokenpos = classe.find('newtokenpos') + self.specific = classe.find('specific') + + self.count_iteracao_regra += 1 + tupla = self.lista_iteracoes[self.count_iteracao_regra] + + if self.specific is not None: + self.specific = self.__especificos[self.specific.text](tupla[0]) + if self.specific == False: + self.has_rule = False + self.quantidade_iter_pular = 0 + break + + if newprop is not None: + self.lista_iteracao_regra.append([self.specific,newprop.text]) + + if newtoken is not None and newpos is not None: + if newtokenpos is not None: + lista_merge = count * [None] + lista_merge[int(newpos.text)] = tupla[0] + lista_merge[int(newtokenpos.text)] = newtoken.text + merge_tokens = " ".join(lista_merge) + self.lista_iteracao_regra.append([merge_tokens, title.text]) + else: + self.lista_iteracao_regra.append([tupla[0] + " " + newtoken.text, title.text]) + + elif newpos is not None: + if newpos.text == "-1": + self.lista_corrigida.append(None) + continue + else: + self.lista_iteracao_regra[int(newpos.text)] = tupla + + elif newtoken is not None: + tokenAnterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] + ticketAnterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] + if newtokenpos is not None and newtokenpos.text == "0": + self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + " " + tokenAnterior, ticketAnterior] + else: + self.lista_iteracao_regra[self.count_iteracao_regra] = [tokenAnterior + " " + newtoken.text, ticketAnterior] + + #self.lista_corrigida.append(filter(None, self.lista_iteracao_regra)[0]) + #se ele acho uma regra, então quebra o laço e vai para o token seguinte + if self.has_rule: + self.lista_corrigida.append(self.lista_iteracao_regra) + break + + if (self.has_rule == False): + self.lista_corrigida.append(it.get_token()) #se nao achou regra, entao adiciona a tupla original + if sint: + return self.lista_corrigida + return filter(None, self.lista_corrigida) + + + def aplicar_regras_sint(self, lista, arvore): + p_arvore = ParentedTree.convert(arvore) + self.adaptar_regras_morfo_arvore(lista, p_arvore) + for morpho in self.__root.findall('syntactic'): + for rule in morpho.findall('rule'): # procura a tag rule + nome_regra = self.corrigir_anotacao(rule.get('name')) + regra = self.separar_regra(nome_regra) + node = tgrep_nodes(p_arvore, regra[0], search_leaves=False) + if node: + print "REGRA SINTÁTICA: " + rule.get('name') + node_esq = tgrep_nodes(node[0], regra[1], search_leaves=False) + node_esq_pos = tgrep_positions(node[0], regra[1], search_leaves=False) + node_dir = tgrep_nodes(node[0], regra[2], search_leaves=False) + node_dir_pos = tgrep_positions(node[0], regra[2], search_leaves=False) + p_arvore.remove(p_arvore[node_esq_pos]) + if node_esq and node_dir: + subnodes = node_esq + node_dir + for subnode in subnodes: + self.alteracoes_nao_implementadas = [] + # modelo: [['node_esq', ['token', 'ticket']],['node_dir', ['token', 'ticket']]] + for classe in rule.iter('class'): + title = classe.find('title') + if subnode.label() == title.text: + newpos = classe.find('newpos') + newprop = classe.find('newprop') + newtoken = classe.find('newtoken') + newtokenpos = classe.find('newtokenpos') + self.specific = classe.find('specific') + + lista_alter_temp_node = [] + + if self.specific is not None: + self.specific = self.__especificos[self.specific.text](subnode.leaves()[0]) + if self.specific is False: + self.has_rule = False + break + + if newprop is not None: + self.lista_alter_temp_node.append([self.specific,newprop.text]) + ''' + if newtoken is not None and newpos is not None: + if newtokenpos is not None: + lista_merge = count * [None] + lista_merge[int(newpos.text)] = tupla[0] + lista_merge[int(newtokenpos.text)] = newtoken.text + merge_tokens = " ".join(lista_merge) + self.lista_iteracao_regra.append([merge_tokens, title.text]) + else: + self.lista_iteracao_regra.append([tupla[0] + " " + newtoken.text, title.text]) + + elif newpos is not None: + if newpos.text == "-1": + self.lista_corrigida.append(None) + continue + else: + self.lista_iteracao_regra[int(newpos.text)] = tupla + + elif newtoken is not None: + tokenAnterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] + ticketAnterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] + if newtokenpos is not None and newtokenpos.text == "0": + self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + " " + tokenAnterior, ticketAnterior] + else: + self.lista_iteracao_regra[self.count_iteracao_regra] = [tokenAnterior + " " + newtoken.text, ticketAnterior] + ''' + return p_arvore + + def adaptar_regras_morfo_arvore(self, lista, arvore): + lista_pos_arv = [] + for tupla in lista: + string_grep = self.corrigir_anotacao(tupla[1]) + " < " + tupla[0].lower() + node = tgrep_positions(arvore, string_grep) + if node[0] in lista_pos_arv: + node.reverse() + lista_pos_arv.append(node[0]) + morfo = self.aplicar_regras_morfo(lista, sint=True) + for i in range(0, len(morfo)): + if morfo[i] is None: + arvore[lista_pos_arv[i][:-1]] = None + else: + arvore[lista_pos_arv[i]].set_label(self.corrigir_anotacao(morfo[i][1])) + arvore[lista_pos_arv[i]][0] = morfo[i][0] + nodes_none = tgrep_positions(arvore, 'None') + for node in nodes_none: + arvore[node[:-1]].remove(None) + + def corrigir_anotacao(self, anotacao): + split = anotacao.split('_') + for i in range(0, len(split)): + split[i] = split[i].replace('-','_') + return "-".join(split) + + def separar_regra(self, regra): + split = regra.split("(") + split[1] = split[1].replace(")","").split("-") + rev = list(split[1]) + rev.reverse() + split.append(rev) + split[1] = ' $ '.join(split[1]) + split[2] = ' $ '.join(split[2]) + return split + + def gerar_nome_regra(self, lista): + self.__nomeRegra = [] + for t in lista: + self.__nomeRegra.append(t[1]) + return "_".join(self.__nomeRegra) + + def verificar_adv_tempo(self, token): + for tupla in self.lista: + if self.dicionarios.has_adverbio_tempo(tupla[0]): + return self.verificar_vb_infinitivo(token) + return False + + def verificar_vb_infinitivo(self, token): + if self.dicionarios.has_verbo_infinitivo(token): + return self.dicionarios.get_verbo_infinitivo(token) + return False + + def verificar_preposicao(self, token): + return self.dicionarios.has_preposicao(token) + + def verificar_subst_genero(self, token): + return self.dicionarios.has_subst_2_generos(token) + + def verificar_artigo(self, token): + return self.dicionarios.has_artigo(token) + + def verificar_vb_ligacao(self, token): + return self.dicionarios.has_verbo_ligacao(token) + + def verificar_adv_intensidade(self, token): + return self.dicionarios.has_adverbio_intensidade(token) + + def verificar_vb_muda_negacao(self, token): + if self.dicionarios.has_verbo_muda_negacao(token): + return self.dicionarios.get_verbo_muda_negacao(token) + return False + + def simplificar_sentenca(self, lista): + it = Iterator() + it.load(lista) + num = False + nova_lista = [] + while(it.has_next()): + token = it.get_word() + tag = it.get_ticket() + + if tag == "NUM": + num = True + + if tag[-2:] == "-P": + singular = self.analisar_plural(token) + nova_lista.append([singular,tag]) + else: + nova_lista.append(it.get_token()) + + if num: return self.converter_extenso(nova_lista) + return nova_lista + + def analisar_plural(self, token): + if(token[-3:] == "OES" or token[-2:] == "AES" or token[-2:] == "AOS"): + return token[0:-3]+"AO" + elif(token[-3:] == "RES" or token[-2:] == "ZES" or token[-2:] == "NES"): + return token[0:-2] + elif(token[-3:] == "SES"): + #TODO: Algumas palavras possuem marcações gráficas na raiz singular. Ex: Gás – Gases + return token[0:-2] + elif(token[-2:] == "NS"): + return token[0:-2]+"M" + elif(token[-3:] == "EIS"): + return token[0:-3]+"IL" + elif(token[-2:] == "IS"): + if(token[-3] == "A" or token[-3] == "E" or token[-3] == "O" or token[-3] == "U"): + return token[0:-2]+"L" + return token + elif(token[-1] == "S"): + #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc + return token[0:-1] + else: + return token + + def converter_extenso(self, lista): + lista_aux = [] + index_deleted = [] + count = 0 + is_running = False + + for i in range(0, len(lista)): + token = lista[i][0] + tag = lista[i][1] + if tag == "NUM": + if (is_running is False and len(lista_aux) == count): + lista_aux.append([i,[token]]) + is_running = True + else: + lista_aux[count][1].append(token) + index_deleted.append(i) + elif (is_running): + if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): + index_deleted.append(i) + else: + is_running = False + count += 1 + + for i in lista_aux: + ext = extenso(' '.join(i[1])) + lista[i[0]] = [ext, "NUM"] + + deque((list.pop(lista, i) for i in sorted(index_deleted, reverse=True)), maxlen=0) + return lista diff --git a/src/new/TraduzSentencas.py b/src/new/TraduzSentencas.py index d22c3e9..d0bd656 100644 --- a/src/new/TraduzSentencas.py +++ b/src/new/TraduzSentencas.py @@ -38,5 +38,4 @@ def gerar_analise(sentenca): analise = aplic_regras.aplicar_regras_morfo(morfologica) else: analise = aplic_regras.aplicar_regras_sint(morfologica, analise) - analise = aplic_regras.simplificar_sentenca(analise) return aplic_sinonimos.aplicar_sinonimos(analise) \ No newline at end of file -- libgit2 0.21.2