UNIVERSIDADE FEDERAL DE GOIÁS – CAMPUS CATALÃO
DEPARTAMENTO DE CIÊNCIAS DA COMPUTAÇÃO
Curso de Bacharelado em Ciências da Computação
PROVADOR DE TEOREMAS INTERATIVO CIRCUITOESTRUTURADO
Lucas Angelo da Silveira
CATALÃO – GO
2013
LUCAS ANGELO DA SILVEIRA
PROVADOR DE TEOREMAS INTERATIVO CIRCUITO ESTRUTURADO
Monografia apresentada ao Curso de Bacha-relado em Ciências da Computação da Uni-versidade Federal de Goiás – Campus Cata-lão, como requisito parcial para a obtenção doGrau de Bacharel em Ciências da Computa-ção.
Orientador:
Vaston Gonçalves da Costa
Área:
Teoria da Computação
CATALÃO – GO
2013
Silveira, Lucas Angelo daProvador de Teoremas interativo circuito Estruturado/ Lucas Angelo da Silveira.
– Catalão – GO, 2013.97 f. ; 30 cm.
Orientador: Vaston Gonçalves da Costa.
Monografia (Graduação) – Universidade Federal de Goiás – Campus Catalão,Departamento de Ciências da Computação, Curso de Ciências da Computação, 2013.
1. Provador de teoremas. 2. Cálculo de Sequentes. 3. Lógica Proposicional.4. Lisa. I. Costa, Vaston Gonçalves da. II. Universidade Federal de Goiás – CampusCatalão. Curso de Bacharelado em Ciências da Computação. III. Título.
LUCAS ANGELO DA SILVEIRA
PROVADOR DE TEOREMAS INTERATIVO CIRCUITO ESTRUTURADO
Monografia apresentada ao Curso de Bacha-relado em Ciências da Computação pela Uni-versidade Federal de Goiás – Campus Catalão.
Trabalho aprovado em 20 de março de 2013.
Área: Teoria da Computação
Vaston Gonçalves da CostaOrientador
Liliane do Nascimento ValeUFG - CAC
Luciana Vale Silva RabeloUFG - CAC
Catalão – GO
2013
Aos colegas do curso de Ciências da Computação do Campus Catalão da UFG, bem como
meus familiares e amigos mais próximos, agradeço pela força e a confiança que depositaram
em mim.
AGRADECIMENTOS
Agradeço ao orientador Dr. Vaston pela confiança e a paciência que teve comigo,
a Mr. Liliane que me ajudou em algumas fases da monografia mesmo não tendo nenhum
vínculo de orientação para comigo, seu profissionalismo é impressionante.
"Transportai um punhado de terra todos os dias e fareis uma montanha." (Confúcio)
RESUMO
SILVEIRA, L. A. DA. Provador de Teoremas interativo circuito Estruturado. 2013.97 f. Monografia (Graduação) – Departamento de Ciências da Computação, Universi-dade Federal de Goiás – Campus Catalão, Catalão – GO.
A pesquisa em lógica tem uma forte conexão com o desenvolvimento da Ciênciada Computação, podendo destacar o grande ferramental lógico necessário para a elabo-ração e construção de provadores de teoremas, os quais são de grande valia no processode verificação de sistemas computacionais e de bases de conhecimento. Neste trabalho,é apresentado o provador de teoremas LISA, baseado em cálculo de sequentes e voltadopara fórmulas do cálculo proposicional. O diferencial deste provador está na estruturade dados empregada e na preocupação dada a interface com o usuário. Pois, LISA tempor princípio auxiliar o ensino de lógica nos cursos introdutórios. O sistema LISA foidesenvolvido para poder ser acoplando num raciocinador automático após alguns apri-moramentos.
Palavras-chaves: Provador de teoremas, Cálculo de Sequentes, Lógica Proposicional,Lisa.
LISTA DE ILUSTRAÇÕES
Figura 1 – Modelo MVC do protótipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Figura 2 – Exemplo de um grafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Figura 3 – Exemplo de um grafo híbrido . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Figura 4 – Array E1 que armazena literais não negativos . . . . . . . . . . . . . . . . . . 52
Figura 5 – Array E2 que armazena literais negativos . . . . . . . . . . . . . . . . . . . . 52
Figura 6 – Interface do Provador Lisa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Figura 7 – Validando a entrada do usuário . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Figura 8 – Visualizando a entrada modificada do usuário . . . . . . . . . . . . . . . . . 60
Figura 9 – Informando o usúario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Figura 10 – Visualizando Prova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Figura 11 – Código em latex da Prova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Figura 12 – PDF da prova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
LISTA DE QUADROS
Quadro 1 – Requisito Validar Entrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Quadro 2 – Requisito Processar fórmula . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Quadro 3 – Requisito Visualizar Fórmula . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Quadro 4 – Requisito Rastro da Prova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Quadro 5 – Requisito Armazenamento do Rastro da Prova . . . . . . . . . . . . . . . . 44
LISTA DE ALGORITMOS
Algoritmo 1 – Algoritmo para inserção no grafo . . . . . . . . . . . . . . . . . . . . . . . 48
LISTA DE CÓDIGOS
Código 1 – Transformando o conectivo ∧: . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Código 2 – Transformando o conectivo →: . . . . . . . . . . . . . . . . . . . . . . . . . 50
Código 3 – Transformando o conectivo ↔: . . . . . . . . . . . . . . . . . . . . . . . . . 50
SUMÁRIO
1 Introdução 23
2 Fundamentação Teórica 27
2.1 Lógica Proposicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.1.1 Alfabeto da Lógica Proposicional . . . . . . . . . . . . . . . . . . . . . . 28
2.1.2 Fórmulas da Lógica Proposicional . . . . . . . . . . . . . . . . . . . . . 28
2.1.3 Sistema Dedutivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.2 Cálculo de Sequentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.2.1 Provas Formais e Conceitos Relacionados . . . . . . . . . . . . . . . . . 30
2.2.2 Exemplos de Provas em Cálculo de Sequentes . . . . . . . . . . . . . . 33
3 Revisão Bibliográfica 35
3.1 Provador de Teoremas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.2 Interesse por Provadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.3 Provadores mais conhecidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.3.1 E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3.2 Vampire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3.3 PVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3.4 Isabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.3.5 Provadores automáticos x semi-automáticos . . . . . . . . . . . . . . . 39
4 Provador Lisa 41
4.1 Requisitos de Sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.1.1 Especificação de requisitos do sistema com utilização de um formulário-
padrão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.1.2 Projeto de Arquitetura . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.1.3 Padrão de arquitetura MVC(Modelo-Visão-Controlador) . . . . . . . . 44
4.2 Linguagem de Programação Utilizada . . . . . . . . . . . . . . . . . . . . . . . . 45
4.3 Framework para Visualização de Grafos . . . . . . . . . . . . . . . . . . . . . . 46
4.4 Estrutura de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.4.1 Escolha da estrututra de dados . . . . . . . . . . . . . . . . . . . . . . . 47
4.4.2 A adaptação de um grafo híbrido . . . . . . . . . . . . . . . . . . . . . . 47
4.5 Especificação das Regras a Nível de Programador . . . . . . . . . . . . . . . . 49
4.5.1 Adaptando a Entrada do Usuário . . . . . . . . . . . . . . . . . . . . . . 49
4.5.2 Regras da disjunção ∨ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.5.2.1 ∨-esquerda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.5.2.2 Regras ∨-direita . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.5.3 Regras de Negação (¬) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.5.3.1 ¬-direita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.5.3.2 ¬-esquerda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.5.4 Gerenciando as Regras . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5 Utilização do Protótipo 57
5.1 Interface do Provador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2 Utiilizando o protótipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6 Conclusão 65
Referências 67
APÊNDICE A Quebra a fórmula de origem em subfórmulas 69
APÊNDICE B Regra OU a esquerda do Sequente 71
APÊNDICE C Complemento da regra OU a esquerda do Sequente 73
APÊNDICE D Regra do OU a direita do Sequente 75
APÊNDICE E Complemento da regra do OR a direita do Sequente 81
APÊNDICE F Regra negação a direita do Sequente 83
APÊNDICE G Regra a esquerda da negação 87
APÊNDICE H Gerenciador de regras 91
23
CA
PÍ
TU
LO 1
INTRODUÇÃO
Tradicionalmente, lógica é dita a arte (ou estudo) do raciocínio; para descrever lógica
segundo esta tradição, é necessário, portanto, saber o que vem a ser raciocínio. De acordo
com alguns pontos de vistas tradicionais, raciocínio consiste da construção encadeada de
entidade lingüísticas por meio de certas relações da forma "... segue de ....", este ponto de
vista é o que os livros textos clássicos de lógica adotam e, por consequência, grande parte
da comunidade científica, em particular os cientistas da computação. (ENDERTON, 2001; van
DALEN, D., 2004)
O estudo de lógica remonta à séculos, tendo como maiores divulgadores Sócrates,
Aristoteles e Platão, na história antiga, e se consagrando, na era moderna com os estudos de
Leibniz. (ENDERTON, 2001)
Leibniz propunha que o linguajar matemático, bem como o raciocínio matemático,
partisse de um base sólida e defendia que a Lógica deveria ser tal base. Esta proposta inicial
de Leibniz conseguiu adeptos que marcaram a história da Filosofia e da Matemática, Frege
e Peano. Os seus estudos receberam grandes contribuições de Russell, Hilbert e Bernays e,
em meados do século XX, a iniciativa de Leibniz se concretizou e os resultados propostos
por Gödel, para a incompletude da aritmética (contrariando a proposta de Hilbert) foram
imediatamente apreciados. (GABBAY; WOODS, 2004)
Lógica é amplamente empregada na Matemática e é um campo de estudo muito
forte da Filosofia. Uma disciplina que tem suas bases nas duas áreas de conhecimento que
estão presentes em quase todas as Ciências, não poderia deixar de influenciar estudos e pes-
quisas em grande parte da produção intelectual humana.
Destaca-se o grande envolvimento da lógica na Ciência da Computação. O alicerce
que funda toda a estrutura da computação é a lógica. Por sua tenra idade, quando compa-
24 Capítulo 1. Introdução
rada com as demais ciências, com a Matemática e com a Filosofia1, a Ciência da Computação
agrega de maneira muito natural até mesmo os temas de estudos de escolas de lógicas radi-
cais, como os temas propostos pelo Grupo de Bourbaki sobre o construtivismo que gerou a
divisão da lógica em Clássica e Intuicionista. (MINTS, 2000)
Acontece que a influencia da lógica na computação passou a ser uma via de mão du-
pla. Conceitos muito empregados em computação também começaram a receber atenção
por parte de lógicos que atuam em Matemática e Filosofia. Podendo-se citar as pesquisas em
redução de prova lógica por meio do emprego de estrutura de grafos e mesmo a utilização
de sistemas computacionais, notadamente os provadores de teoremas, como auxiliares na
comprovação de conjecturas matemáticas que perduraram por muito tempo, como o caso
do problema das quatro cores.
Nos dias atuais, a proposta de Leibniz além de já estar consolidada recebeu mais
colaboradores, pesquisadores que caminham livremente pelo campo da lógica, da mate-
mática, da filosofia e da computação. Nomes como Allan Turing, Dag Pravitz, John Buss,
Jhonatan Seldin e Newton da Costa, devem sempre serem lembrados por suas contribuições
em todas essas áreas citadas, sendo que o último nome, mas não menos importante, é de um
brasileiro que contribui com estudos em lógica que atacam diretamente o problema NP=P.
O uso de provadores de teoremas, inicialmente propostos para auxiliar matemáticos
na prova de suas conjecturas, hoje são muito úteis em computação para verificar a corretude
de sistemas computacionais complexos e, mais recentemente, para verificar formalmente a
consistência de grandes bases de conhecimento armazenadas na rede para serem manipu-
ladas por agentes inteligentes de software.
Foi com a intenção de aprofundar os estudos em provadores de teoremas e suas apli-
cações que, em meadas de 2011, o autor foi contemplado com bolsa de inovação tecnológica
do Ministério da Educação via Programa Institucional de Bolsas de Inovação Tecnológica
(PIBIT). O projeto previa o estudo e construção de provadores para posterior acoplagem em
um raciocinador baseado em ontologias. Tal projeto ainda se encontra em andamento e
parte dele será apresentada nesta monografia.
Durante os estudos do projeto, era notório a falta de conhecimento de conceitos de
lógica elementar pelos alunos envolvidos. Conceitos presentes em livros texto de Lógica,
abordados na bibliográfica básica da disciplina de Lógica, lhes eram estranhos. Podendo
citar, o uso de Tableaux semântico, conceitos de Dedução Natural, corretude e completude
de sistemas dedutivos, diferença entre lógica Clássica e Intuiucionista e o uso de provadores
de teoremas em computação.
Devido a esta falha de conhecimento, grande parte dos estudos do projeto de inova-
ção tecnológica ficaram restritos ao estudo de bibliografia básica, necessário para a forma-
1Pois tanto a Matemática quanto a Filosofia não são consideradas ciências. Estando ambas num patamarsuperior as estas.
25
ção de conhecimentos mínimos para a produção dos objetos do projeto. Contudo, ao final
do primeiro ano do projeto, dois provadores de teoremas foram construídos, um baseado
em Tableaux e um segundo baseado em Cálculo de Sequentes.
Neste trabalho será apresentado o provador de teoremas baseado no sistema dedu-
tivo Cálculo de Sequentes proposto por Gentzen, denominado LISA.
Evidente que a mera apresentação de um provador de teoremas tornaria o traba-
lho muito elementar, pois muitos provadores já foram construídos e estão disponíveis para
uso. O diferencial deste trabalho está na condução da construção de LISA. Além de expor
o sistema dedutivo Cálculo de Sequentes, uma abordagem na estrutura de dados foi imple-
mentada para facilitar o uso de grafos em vez de árvores de provas, agregando assim o que
há de mais atual na pesquisa de redução de provas lógicas.
Procurou-se, também, construir um provador que servisse como auxiliar na produ-
ção de provas lógicas e que fosse didático no sentido de poder ser operado por alunos ini-
ciantes da disciplina de Lógica. Para tanto, buscou-se aprimorar a interface com o usuário
para torná-la intuitiva e a saída dos resultados foi pensada a facilitar a visualização e o ar-
mazenamento das provas geradas.
Com o uso de provadores em sala de aula, a visão de construção de cadeias de en-
tidades lógicas fica evidente ao aluno, bem como o emprego da relação "... segue de...".
Mostrando, claramente a visão tradicional da Lógica.
Ao se compreender a construção encadeada de entidades lógicas, os passos de prova
de um provador permitem ao aluno estender o encadeamento lógico de uma prova ao en-
cadeamento empregado nas construções/análises de sistemas, independente da linguagem
de programação empregada.
Para facilitar a compreensão do trabalho produzido, este foi dividido da seguinte ma-
neira: O primeiro capítulo contém conceitos de lógica proposicional e cálculo de sequentes,
no segundo capítulo é realizada a revisão bibliográfica, tratando dos provadores de teore-
mas mais conhecidos. Já no terceiro capítulo apresenta-se o provador LISA, dos requisitos
aos detalhes de implementação, no quarto capítulo é apresentado o manual de utilização
de LISA e algumas características do provador. Por fim, no quinto capítulo apresenta-se as
conclusões.
27
CA
PÍ
TU
LO 2
FUNDAMENTAÇÃO TEÓRICA
Neste capítulo será apresentada a Lógica Proposicional, de forma resumida.
A intenção com o presente capítulo é a de familiarizar o leitor com as notações que
serão amplamente utilizadas no decorrer do trabalho.
2.1 Lógica Proposicional
O estudo dessa lógica segue fundamentalmente três passos básicos (SILVA; FINGER;
MELO, 2006)
1. Especificação de uma linguagem, a partir da qual o conhecimento é representado.
Tal representação considera os conceitos de sintaxe e semântica associados a lingua-
gem;
2. Estudo de métodos que produzam ou verifiquem as fórmulas ou os argumentos váli-
dos.
A verificação do conceito semântico de validade, de expressões sintáticas e da lingua-
gem, é um exemplo desse estudo;
3. Definições de sistemas de dedução formal em que são consideradas as noções de
prova e consequência lógica.
A noção de prova estabelece formas para a derivação de conhecimento a partir da-
quele representado previamente, o que também define a noção de consequência ló-
gica;
28 Capítulo 2. Fundamentação Teórica
Nas seções seguintes serão apresentadas os itens descritos acima. Sendo a secão
2.1.1 destinada à especificação da linguagem empregada, a seção 2.1.2 destinada ao estudo
de métodos que produzam fórmulas válidas e a seção 2.1.3 destinada a apresentação de
sistemas dedutivos.
2.1.1 Alfabeto da Lógica Proposicional
O Alfabeto da linguagem da Lógica Proposicional é definido pelo conjunto de sím-
bolos descritos a seguir.
• Símbolos de pontuação:(,);
• Símbolos de verdade: true, false;
• Símbolos proposicionais: P,Q,R,S,P1,Q1,R1, . . .;
• Conectivos proposicionais: ¬, ∨, ∧, →, ↔;
O alfabeto da linguagem da Lógica Proposicional é constituído de um conjunto infi-
nito, enumerável, de símbolos. Os símbolos para pontuação e os símbolos de verdade são
palavras reservadas, consideradas apenas como símbolos (van DALEN, D., 2004). Os conecti-
vos proposicionais possuem as seguintes denominações.
O simbolo : ¬ é denominado por "não", ∨por "ou", ∧por "e", →por "se então"ou "implica"e
o símbolo ↔ é denominado por "se, e somente se", "sse"ou "bi-implicação".
2.1.2 Fórmulas da Lógica Proposicional
Não é qualquer concatenação de símbolos que é uma fórmula na Lógica. O conjunto
de fórmulas da Lógica Proposicional, que são formadas pela concatenação de símbolos do
alfabeto (van DALEN, D., 2004), é definido abaixo:
• Todo símbolo de verdade é uma fórmula;
• Todo símbolo proposicional é uma fórmula;
• Se H é uma fórmula, então (¬H), a negação de H , é uma fórmula;
• Se H e G são fórmulas, então a disjunção de H e G , dada por: (H ∨G), é uma fórmula;
• Se H e G são fórmulas, então a conjuncão de H e G , dada por: (H ∧G), é uma fórmula;
• Se H e G são fórmulas, então a implicação de H em G , dada por:(H → G), é uma fór-
mula, onde H é o antecedente e G o consequente.
2.1. Lógica Proposicional 29
• Se H e G são fórmulas, então a bi-implicação de H e G , dada por: (H ↔ G), é uma
fórmula, onde H é o lado esquerdo e G é o lado direito da fórmula;
Definição 1. Conjunto Completo de Conectivos
Seja Σ um conjunto de conectivos. Diz-se que Θ é um conjunto completo de conec-
tivos se as condições a seguir forem satisfeitas:
Dada uma fórmula H com conectivos emΣ é possível determinar uma outra fórmula
G equivalente a H de modo que G contenha apenas conectivos pertencentes a Θ e os sím-
bolos proposicionais presentes em H (SILVA; FINGER; MELO, 2006).
Exemplo 1. Dada uma fórmula H é possível determinar uma outra fórmula G equivalente
a H de modo que G contenha apenas conectivos (¬, ∨) e os símbolos proposicionais pre-
sentes em H . Neste caso, G é obtido a partir de H substituindo os conectivos (∧, →, ↔) por
conectivos (¬, ∨) conforme as regras predefinidas abaixo.
Equivalência entre → e (∨, ¬)
(P →Q) = (¬P ∨Q)
Equivalência entre ∧ e (∨, ¬)
(P ∧Q) = (¬(¬P ∨¬Q))
Equivalência entre ↔ e (∨, ¬)
(P ↔Q) equivale a ((P →Q)∧ (Q → P ))
((P →Q)∧ (Q → P )) equivale a ((¬P ∨Q))∧ (¬Q ∨P ))
((¬P ∨Q))∧ (¬Q ∨P )) equivale a (¬(¬(¬P ∨Q))∨ (¬(¬Q ∨P )))
2.1.3 Sistema Dedutivo
Um sistema dedutivo nos permite inferir, derivar ou deduzir as consequências lógi-
cas de um conjunto de fórmulas. Quando um sistema dedutivo infere uma fórmula H a par-
tir de um conjunto Γ de fórmulas, denotamos como sendo Γ` H . O objeto Γ` H é chamado
de sequente, no qual Γ é o antecedente (ou hipótese) e H é o consequente (ou conclusão)
(SILVA; FINGER; MELO, 2006).
Há vários procedimentos distintos que permitem realizar uma inferência, e cada pro-
cedimento dá origem a um sistema dedutivo distinto. Dentre os mais conhecidos são:
• Tabela Verdade;
• Tableaux Analíticos;
• Axiomatizações;
• Dedução Natural;
• Cálculo de Sequentes;
30 Capítulo 2. Fundamentação Teórica
Sendo este último, o sistema dedutivo utilizado no provador fruto deste trabalho, conforme
a seção 2.2.
2.2 Cálculo de Sequentes
Cálculo de sequentes dedutivo foi introduzido na década de 30 por Gerhard Gentzen,
sendo prático no sentido que:
• Possui apenas regras de introdução;
• Premissas e conclusões são tratadas da mesma forma e são construídas simultanea-
mente;
• Menos natural, mas tecnicamente mais simples: quando lida de baixo para cima, as
regras no cálculo de sequentes simplificam o processo de construção de provas.
2.2.1 Provas Formais e Conceitos Relacionados
Uma inferência é uma expressão da forma:
S1
Sou
S1 S2
S
Onde S1, S2 e S são sequentes. Com S1 e S2 chamados de sequentes superiores, e S
chamado de subsequente inferior da inferência. Intuitivamente, isto significa que quando
S1 (S1 e S2) é (são) afirmado(s), podemos inferir S a partir dele (deles). Limitam-se as infe-
rências obtidas a partir das seguintes regras estruturais (TAKEUTI, 1987).
Para cada instancia abaixo, há a possibilidade de tanto se aplicar regras do lado di-
reito ou esquerdo do sequente "`".
Axioma Inicial:
( Ini t i al )∆, A `∆, A
Enfraquecimento:
Esquerdo:Γ`∆
D,Γ`∆
Direito:Γ`∆Γ`∆,D
2.2. Cálculo de Sequentes 31
D é derivado a partir da regra de enfraquecimento.
Contração:
Esquerdo:D,D,Γ`∆
D,Γ`∆
Direito:Γ`∆,D,D
Γ`,D,∆
Faz-se a duplicação de um termo (D) existente na fórmula corrente.
Permutação:
Esquerdo:Γ,C ,D,π`∆Γ,D,C ,π`∆
Direito:Γ`∆,C ,D,ν
Γ`,∆,D,C ,ν
Faz-se modificações na estrutura da fórmula, no caso do exemplo acima houve uma
permutação entre C e D .
Corte:
Γ1 `∆1, A A,Γ2 `∆2
Γ1,Γ2 `∆1,∆2
Faz-se a extração de um fragmento de fórmula "C ", presente na fórmula original. A
escolha deste fragmento, pode ser hipótese ao acaso, ou com alguma base conceitual.
Negação:
Esquerda:Γ`∆,D
¬D,Γ`∆
Direita:D,Γ`∆Γ`∆,¬D
Aplica-se a regra de negação a fragmentos da fórmula envolvidos pelo conectivo "¬".
Caso seja usado a regra a direita o fragmento de fórmula será passado para o lado esquerdo
do sequente "`". A regra esquerda é idêntica a da direita com a exceção de que o fragmento
de fórmula será passado para o lado direito do sequente.
32 Capítulo 2. Fundamentação Teórica
Conjunção "E":
Esquerda: C ,Γ`∆C∧D,Γ`∆ and D,Γ`∆
C∧D,Γ`∆
Aplica-se a regra a um fragmento de fórmula (C ∧ D) descartando um membro deste, a sua
escolha.
Direita:Γ`∆,C Γ`∆,DΓ`∆,C∧D
Ao aplicar a regra "E"à direita, ocasionará dois novos ramos contendo fragmento de
fórmula da subfórmula derivada (C ∧ D).
Disjunção "OU":
Esquerda:C ,Γ`∆ D,Γ`∆C∨D,Γ`∆
Ao aplicar a regra "OU"a esquerda, ocasionará dois novos ramos contendo fragmento
de fórmula da subfórmula derivada (C ∨ D).
Direita: Γ`∆,CΓ`Γ,C∨D and Γ`∆,D
Γ`Γ,C∨D
Aplica-se a regra a um fragmento de fórmula (C ∨ D) descartando um membro deste,
a sua escolha.
Implicação:
Esquerda:Γ1`A,∆1 Γ2,B`∆2Γ1,Γ2,A→B`∆1,∆2
Ao aplicar esta regra, a derivação ocasionará dois novos ramos contendo fragmento
de fórmula da subfórmula derivada (A → B).
Direita: Γ,A`B ,∆Γ`A→B ,∆
Ao aplicar esta regra a um fragmento de fórmula (A → B). Fragmentos da mesma
"A"será passado para o lado esquerdo do sequente.
As 3 primeiras regras apresentas são consideradas inferências fracas, enquanto as
demais que se segue são consideradas inferências fortes (TAKEUTI, 1987). No intuito de aju-
dar aos leitores a entender como se usa as demais formas apresentadas acima, um esboço
abaixo mostra o processo de uso das regras na prática.
2.2. Cálculo de Sequentes 33
2.2.2 Exemplos de Provas em Cálculo de Sequentes
Algumas ponderações relacionado as fórmulas apresentadas abaixo são necessárias.
Entre parênteses fica situado as legendas das regras usadas e o lado(esquerdo ou direito) do
sequente que foi aplicada tais derivações.
Exemplo 1:
Ini t i alp ` p` p,¬p
( ¬R )` p, p ∨¬p( ∨R2 )` p ∨¬p, p ∨¬p
( ∨R1 )` p ∨¬p (Cont )
Exemplo 2:
Ini t i alp ` p
(¬R) ` p,¬p(∨R) ` p ∨q,¬p
Ini t i alq ` q
` q,¬q (¬R)` p ∨q,¬q (∨R)
` p ∨q,¬p ∧¬q (∧R)(¬(p ∨q)) ` (¬p ∧¬q) (¬L)
Exemplo 3:
Ini t i alp, q ` q, p
p ` q, (q → p) (→ R)` (p → q), (q → p) (→ R)
` (p → q), (p → q)∨ (q → p) (∨R)` (p → q)∨ (q → p), (p → q)∨ (q → p) (∨R)
` (p → q)∨ (q → p) (Cont)
Concluindo assim a terminologia presente no âmbito da área de Lógica matemática,
apresentando o sistema dedutivo Cálculo de sequentes, e o uso de suas técnicas em exemplos
de provas lógicas.
35
CA
PÍ
TU
LO 3
REVISÃO BIBLIOGRÁFICA
Neste capítulo será apresentado o conceito de provadores de teoremas. Para tanto,
além de apresentar um histórico de sua aplicação e as justificativas para seu uso, serão
apresentados os principais provadores em uso, definindo provadores automáticos e semi-
automáticos, expostos alguns usos consagrados de provadores e destacadas vantagens em
se fazer uso desta ferramenta.
3.1 Provador de Teoremas
Provadores de Teoremas são poderosas ferramentas de métodos formais que podem
ser utilizadas em validação de sistemas e em raciocinadores automáticos. Dependendo da
lógica aplicada ao problema, decidir a validade de um teorema pode variar de trivial ao im-
possível (SANTOS, 2010). Para o caso frequente da lógica proposicional, o problema de va-
lidade é dicidível, mas NP-completo (DASGUPTA; PAPADIMITRIOU; VAZIRANI., 2009), e apenas
algoritmos de tempo exponencial são conhecidos para resolvê-lo. Para a lógica de primeira
ordem, tal problema é recursivamente enumerável. Com recursos ilimitados, qualquer con-
jectura válida pode ser provada. Por este motivo observa-se que a aplicabilidade de prova-
dores totalmente automáticos fica restringida. Por outro lado, aumenta-se a necessidade da
intervenção humana na condução das provas, nos chamados provadores interativos de teo-
remas ou assistentes de provas. Isto é, o especialista do domínio do problema interage com
o software na construção de provas.
Um provador deve utilizar estratégia de prova com regras de inferência compostas
por conjuntos de regras fundamentais do sistema dedutivo, e estabelecer uma ordem de
prioridade para quais destas regras terão preferência para serem aplicadas. Como são reali-
zadas essas escolhas varia de sistema dedutivo.
36 Capítulo 3. Revisão Bibliográfica
Neste trabalho, seguiu-se o usual em se tratando de cálculo de sequentes (TAKEUTI,
1987), no que envolve precedência de conectivos, isto é, as regras de maior precedência são
Negação(esquerda, direita) e OR(direita) e a regra OR(esquerdo) fica com menor prioridade.
Neste caso a escolha foi feita pelo fato de caso o provador venha a finalizar a prova usando
apenas as regras de maior prioridade, a construção da prova será da ordem polinomial, o
que é um fato relevante ao se construir um provador.
3.2 Interesse por Provadores
Pode-se dizer que a história da prova automática de teoremas começou em 1957,
com a publicação do artigo The Logic Theory Machine (MCCORDUCK, 2004), por Newell, Shaw
e Simon. Esse artigo descreve os resultados obtidos com o Logic Theorist, um programa es-
crito entre 1955 e 1956 que tentava simular os processos de dedução humana para provar
teoremas de lógica proposicional. O Logic Theorist foi capaz de provar 38 teoremas do Prin-
cipia Mathematica (WHITEHEAD; RUSSELL, 1997) e introduziu diversos conceitos básicos rela-
cionados a provadores automáticos e técnicas de inteligência artificial. Ele foi apresentado
em uma conferência em 1956, que inaugurou o termo inteligência artificial , despertando
o interesse de outros na área. Em 1960 o matemático Hao Wang desenvolveu programas
capazes de provar todos os teoremas de lógica proposicional do Principia Mathematica em
poucos minutos, e também a maior parte dos teoremas de lógica de predicados(van DALEN,
D., 2004). Usando o tipo de análise lógica iniciado por Herbrand e Gentzen, Wang avançou
substancialmente os trabalhos de Newell, Shaw, e Simon. Entre 1956 e 1959, Herbert Gelern-
ter e Nathaniel Rochester desenvolveram o Geometry Theorem-proving Machine (GTM), que
usava encadeamento reverso (backward chaining), partindo da conclusão em direção às pre-
missas, criando metas secundárias cuja validade implica a conclusão final. Onde era capaz
de provar a maior parte dos problemas de exame de ensino médio dentro de seu domínio,
levando cerca de 20 minutos para resolver os problemas mais difíceis (SANTOS, 2010). Nesse
meio tempo, Paul Gilmore trabalhava em métodos não-heurísticos, derivados dos procedi-
mentos de prova da lógica clássica. Gilmore inspirou-se na técnica do tableau semântico
(SILVA; FINGER; MELO, 2006) de Evert Willem Beth; o procedimento utilizado era rudimentar,
mas foi provavelmente o primeiro procedimento de prova mecanizado para o cálculo de
predicados (van DALEN, D., 2004), capaz de provar teoremas de dificuldade moderada.
Entre 1963 e 1967, desenvolveu-se o projeto Semi Automated Mathematics (SAM),
em que foi criada uma série de sistemas mais interativos do que os provadores automáticos
até então apresentados (SANTOS, 2010). Esses sistemas possuíam uma boa interface com o
usuário, e uma linguagem com grande poder de expressão. O primeiro dos sistemas SAM era
primariamente um verificador de provas, mas a capacidade de prova de teoremas aumen-
tou nas versões posteriores. No começo dos anos 70, a resolução recebeu críticas e outros
métodos de manipulação de fórmulas foram propostas. Woody Bledsoe questionou a ca-
3.3. Provadores mais conhecidos 37
pacidade de sistemas lógicos uniformes de manipular a matemática da teoria de conjuntos
(CASTRUCCI, 1967) e apontou que determinados problemas poderiam ser resolvidos de ma-
neira muito mais simples pelo método de encadeamento reverso do que pelo princípio da
resolução. Arthur Nevins desenvolveu paralelamente dois provadores capazes de processar
teoremas que a maior parte dos provadores por resolução não eram capazes de manipular.
Knuth e Bendix publicaram um artigo focando no potencial das regras de reescrita (rewrite
rules) (MÉTIVIER, 1983). Em 1975 e 1976 surgiu interesse em procedimentos de prova seme-
lhantes à resolução que utilizam grafos como representação. No final dos anos 70, Peter
Andrews desenvolveu o TPS, um provador de teoremas para a teoria de tipos (HONSELL; MI-
CULAN; SCAGNETTO, 2001). Embora esteja fundado nas técnicas lógicas (não heurísticas), o
TPS também apresenta traços da abordagem de simulação humana. Ele foi capaz de provar
vários teoremas de primeira ordem (MORTARI, 2001). Em 1976, Kenneth Appel e Wolfgang
Haken provaram o teorema das quatro cores , que diz que qualquer divisão de um plano em
regiões contíguas pode ser colorida com apenas quatro cores, sem que nenhuma região que
faça fronteira com outra possua a mesma cor. A validade do teorema havia sido estudada
desde 1852 e permanecia uma questão aberta até então. Esse foi o primeiro teorema im-
portante provado por um sistema de provas automáticas, ainda que boa parte do problema
tenha sido resolvida manualmente. Em 1997, uma prova mais simples foi publicada por Ro-
bertson, Sanders, Seymour e Thomas (FRITSCH; FRITSCH, 1998), utilizando outro sistema de
provas automáticas, para dissipar as dúvidas que ainda existiam quanto à prova original.
A partir dos anos 80, os provadores automáticos de teoremas começaram a ser usa-
dos comercialmente, principalmente para verificação de hardware, e no campo de enge-
nharia de software. Predominaram provadores interativos, embora tenha havido avanços
significativos com relação a provadores totalmente automatizados. O caso mais famoso de
bug em hardware aconteceu em 1994, no sistema de divisão em ponto flutuante no proces-
sador Pentium. Ficou conhecido como bug Pentium FDIV (FDIV era a instruções de divisão
de números com ponto flutuante, que potencialmente gerava resultados incorretos). A pos-
sibilidade do erro ocorrer era muito rara, mas a Intel foi forçada a fazer recall do produto
devido a grande número de reclamações de usuários e pressão dos distribuidores. Desde
então, tanto AMD quando Intel tem utilizado provadores automáticos de teoremas para sua
verificação e desenho de seus circuitos integrados.
3.3 Provadores mais conhecidos
A lista de provadores existentes é extensa, nesta seção serão descrito os mais conhe-
cidos no âmbito acadêmico.
38 Capítulo 3. Revisão Bibliográfica
3.3.1 E
É um provador de teoremas para a lógica de primeira ordem com igualdade plena
(SMULLYAN et al., 2009). Aceita uma especificação do problema, geralmente constituídos por
uma série de cláusulas de primeira ordem ou fórmulas, e uma conjectura, tanto em forma
clausal ou completa de primeira ordem. Caso a prova seja encontrada, o sistema pode for-
necer uma lista detalhada das etapas de prova podendo ser verificadas individualmente.
O desenvolvimento do provador E começou como parte do projeto E-SETHEO na
TUM 1. O primeiro lançamento público aconteceu em 1998, desde então o sistema tem sido
continuamente melhorado. É um dos sistemas de raciocínio mais poderosos e amigáveis
para lógica de primeira ordem, participando com sucesso em muitas competições 2.
3.3.2 Vampire
Vampire é um provador para lógica clássica de primeira ordem desenvolvido no De-
partamento de Ciência da Computação da Universidade de Manchester. Este provador ven-
ceu a copa do mundo de provadores automáticos ( CADE ATP System Competition) na di-
visão mais prestigiada por dez anos(1999, 2001-2009).Caracteriza-se por possuir eficientes
técnicas de indexação na implementação de operações em conjuntos de termos e cláusulas.
Além disso, uma especialização no tempo de execução de seus algoritmos é usada para ace-
lerar operações complexas como a checagem da ordem de condições que a solução de um
problema de otimização deve satisfazer 3.
O kernel deste sistema trabalha apenas com formas em cláusulas normais, o Vam-
pire aceita um problema na sintaxe completa da lógica de primeira ordem, pois seu proces-
sador de componentes executa muitas transformações úteis antes de analisar as cláusulas
em seu kernel. Quando um teorema é provado, o Vampire produz uma prova verificável, o
que valida tanto a fase de transformação em cláusulas como a refutação de sua forma nor-
mal conjuntiva.
3.3.3 PVS
PVS é um ambiente mecanizado para especificação e verificação formal4. Baseia
mais de 25 anos de experiência no desenvolvimento e uso de ferramentas para apoiar mé-
todos formais. Consiste de uma linguagem de especificação de ordem superior, uma série
de teorias pré-definidas, um verificador de tipo, um provador de teoremas interativo que
suporta o uso de vários processos de decisão, um verificador de modelo simbólico, diversos
utilitários, incluindo um gerador de código aleatório e o validador de documentação, biblio-
1http://www.in.tum.de/2http://www4.informatik.tu-muenchen.de/~schulz/E/Awards.html3http://www.voronkov.com/vampire.cgi4http://pvs.csl.sri.com
3.3. Provadores mais conhecidos 39
tecas, formalizadas, e os exemplos que ilustram métodos diferentes de utilização do sistema,
em várias áreas de aplicação.
Ao explorar a sinergia entre uma linguagem de especificação altamente expressiva de
dedução automática poderosa, o PVS serve como um ambiente produtivo para a construção
e manutenção de grandes formalizações de provas.
3.3.4 Isabelle
Isabelle também é uma ferramenta interativa na prova de teoremas. Escrito em Stan-
dard ML, baseado numa lógica simples e pequena mas que garante a correção do sistema. O
método de prova principal do Isabelle é uma versão de alta ordem do método de resolução
(TROELSTRA; SCHWICHTENBERG, 2000). Ainda que seja um sistema interativo, Isabelle também
propõe ferramentas eficientes de resolução automática, tais como um sistema de reescrita
de termos e um provador Tableaux, além de muitos procedimentos de decisão.
Um dos principais uso de Isabelle faz-se na formalização de muitos teoremas na área
da matemática e ciência da computação, sendo alguns deles: Teorema da completude de Gö-
del 5, teorema de Gödel sobre a consistência do axioma de escolha, teoremas sobre núme-
ros primos, correção de protocolos de segurança e propriedades da semântica de liguagem
de programação. Ainda no seu uso, pode-se destacar sua aplicação pela empresa Hewlett-
Packard (HP) para o desing do servidor de linha da Runway bus HP 9000, onde o sistema
constatou inúmeras inconsistências anteriormente não mostradas por testes e simulações6. Outra área importante do uso do Isabelle é na verificação de implementação de softwares.
3.3.5 Provadores automáticos x semi-automáticos
Há dois tipos de provadores de teoremas, aqueles em que o usuário interfere no pro-
cesso, ditos semi-automáticos, e aqueles sem tal interferência, ditos automáticos, nos quais
todo os passos são determinasticamente feitos pelo sistema computacional. Escolher um
tipo de provador em detrimento do outro envolve especificidades de aplicabilidade e o per-
fil do usuário do sistema. Empregar um provador automático, que, além de realizar a prova,
a apresenta graficamente ao usuário, tem sua utilidade didática, pois permite a um usuário
com pouca familiaridade com lógica entender os passos envolvidos no processo de prova.
Já para usuários mais tarimbados, a intervenção no processo de prova pode ser muito útil
para evitar o longo tempo de processamento7.
5http://www.im.ufrj.br/~risk/diversos/godel.html6http://www2.joinville.udesc.br/.../MFO-Aula14-Isabelle.pdf7Pois, como dito o problema de provas em NP completo.
41
CA
PÍ
TU
LO 4
PROVADOR LISA
Neste capítulo são apresentados os requisitos do provador Lisa, sua arquitetura, a
estrutura de dados empregada com níveis de especificação e os detalhes de implementação
do sistema dedutivo 2.2.
4.1 Requisitos de Sistema
O termo requisitos de sistema será usado para definir os requisitos do protótipo, já
que o plano estabelecido não envolve a construção de um software e sim de um protótipo.
A escolha de se definir os requisitos tem intuito de detalhar as funções, os serviços do protó-
tipo e o que será implementado.
Para o processo de identificação dos requisitos foi usado uma abordagem baseada
em formulários. Neste caso as seguintes informações foram incluídas (SOMMERVILLE, 2011):
1. Descrição da função ou da entidade que está sendo especificada.
2. Descrição de suas entradas e de onde elas são provenientes.
3. Descrição de suas saídas e para onde elas prosseguirão.
4. Indicações de quais outras entidades são usadas (a parte ’requer’).
5. Descrição da ação a ser tomada.
6. Se uma abordagem funcional for usada, uma precondição que estabeleça o que deve
ser verdadeiro antes da chamada da função, e uma pós-condição que especifique o
que é verdadeiro aós a chamada da função.
42 Capítulo 4. Provador Lisa
7. Descrição dos efeitos colaterais da operação (se existirem).
4.1.1 Especificação de requisitos do sistema com utilização de um formulário-
padrão
Quadro 1 – Requisito Validar Entrada
Função: Validar a entrada do usuário.Descrição: A partir da entrada do usuário verificar a sintaxe, afim de eliminar
problemas em etapas posteriores.Entrada: Lisa recebe como entrada uma string contendo conectivos e símbolos
pertencente ao alfabeto proposicional.Origem: Entrada de dados através do campo de captura do formulário.Saída: Informa ao usuário se é necessário corrigir a entrada, caso esteja cor-
reto a entrada o ok por parte do sistema para continuarAção: Processar a entrada do usuário afim de detectar inconsistência na fór-
mula de entrada.Requer: Tratar a entrada, verificando a consistência afim de encontrar erros
sintáticos.Precondição: A entrada do usuário.Pós-condição: Após o nucléo retornar uma resposta o usuário assume o controle.Efeitos colaterais: Nenhum.
Quadro 2 – Requisito Processar fórmula
Função: Processamento da fórmula fornecida pelo usuário.
Descrição: A partir da entrada do usuário o nucléo irá realizar o processamento
aplicando as regras cabíveis.
Entrada: A entrada validada em uma fase anterior.
Origem: Entrada de dados através do campo de captura do formulário.
Saída: Informa ao usuário se o sequente é valido ou não.
Ação: Processar a entrada do usuário e retornar um parecer.
Requer: Ter passado pela fase de validação da entrada.
Precondição: A entrada do usuário.
Pós-condição: Um parecer sobre o sequente ser válido ou não.
Efeitos colaterais: Pode demorar a retornar uma resposta pois lisa lida com problemas
de complexidade temporal na ordem exponencial.
4.1. Requisitos de Sistema 43
Quadro 3 – Requisito Visualizar Fórmula
Função: Usuário tem acesso a sua entrada.
Descrição: Como Lisa trabalha com conjunto completo de conectivos, a entrada
do usuário pode sofre alterações, nesse caso o usuário pode visualizar
como iria ficar após a transformação.
Entrada: A entrada validada em uma fase anterior.
Origem: Entrada de dados através do campo de captura do formulário.
Saída: Visualização da fórmula do usuário podendo ter sofrido mudanças.
Ação: Visualização.
Requer: Ter passado pela fase de validação da entrada.
Precondição: A entrada do usuário.
Pós-condição: O usuário tem acesso ao sistema para realizar outras requisições caso
queira.
Efeitos colaterais: Nenhum.
Quadro 4 – Requisito Rastro da Prova
Função: Usuário tem acesso ao rastro da prova.
Descrição: Após o processamento o usuário pode ter acesso a uma visualização
de como ficou o rastro produzido, através de uma interface gráfica no
formato de um grafo.
Entrada: O rastro produzido pelo processamento da entrada do usuário.
Origem: O rastro produzido na fase de processamento de fórmula.
Saída: Uma interface gráfica no formato de um grafo não direcionado.
Ação: Visualização.
Requer: Ter passado pela fase de validação da entrada, e processamento da
fórmula.
Precondição: O rasto da prova.
Pós-condição: O usuário tem acesso ao sistema para realizar outras requisições caso
queira.
Efeitos colaterais: Nenhum.
44 Capítulo 4. Provador Lisa
Quadro 5 – Requisito Armazenamento do Rastro da Prova
Função: Usuário ter um arquivo contendo rastro da prova.
Descrição: Após o processamento o usuário pode salvar o rastro da prova no for-
mato .tex para produzir o pdf do rastro da prova.
Entrada: O rastro produzido pelo processamento da entrada do usuário.
Origem: O rastro produzido na fase de processamento de fórmula.
Saída: Arquivo .tex.
Ação: Geração de arquivo.
Requer: Ter passado pela fase de validação da entrada, e processamento da
fórmula.
Precondição: O rasto da prova.
Pós-condição: O usuário tem acesso ao sistema para realizar outras requisições caso
queira.
Efeitos colaterais: Nenhum.
4.1.2 Projeto de Arquitetura
O projeto de arquitetura está preocupado com a compreensão de como um sistema
deve ser organizado e com a estrutura geral do sistema (protótipo), sendo o elo crítico entre
o projeto e a engenharia de requisitos (SOMMERVILLE, 2011).
4.1.3 Padrão de arquitetura MVC(Modelo-Visão-Controlador)
Separa a apresentação e a interação dos dados do sistema. O sistema é estruturado
em três componentes lógicos que interagem entre si. O componente Modelo gerencia o
sistema de dados e as operações associadas a esses dados. O componente Visão define e
gerencia como os dados são apresentados ao usuário. O componente Controlador gerencia
a interação do usuário e passa essas interações para Visão e o Modelo (SOMMERVILLE, 2011).
Este padrão é indicado quando existem várias maneiras de se visualizar e interagir com da-
dos, e quando são desconhecidos os futuro requisitos de interação e apresentação de dados,
sendo os dois últimos casos irrelevantes para o prótótipo que está em pauta.
O modelo da arquitetura do protótipo Lisa seguindo as recomendações do padrão
MVC ficou organizada da forma como segue a figura 5.
4.2. Linguagem de Programação Utilizada 45
Figura 1 – Modelo MVC do protótipo
4.2 Linguagem de Programação Utilizada
Ao escolher uma linguagem nativa, uma pesquisa com os pontos forte de cada uma
foi realizado:
• Recursos necessários tais como: boa documentação, fóruns para esclarecer dúvidas e
etc.
• Experiência com a linguagem.
• Interface gráfica de fácil manuseio, e frameworks de ambientes gráficos.
Com os requisitos mencionados acima, duas linguagens se sobressaíram Java (DEI-
TEL; DEITEL, 2010) e Python (BORGES, 2010). A partir de identificar as linguagens, e usufruir
de que cada uma oferecia, Java se mostrava mais convidativa, pois oferecia frameworks que
lidam muito bem com interfaces gráficas com nível de complexidade baixo. Com as qualida-
des apresentadas pela linguagem Java casando com os requisitos exigidos, Java ficou como
a linguagem padrão usada na implementação do provador.
46 Capítulo 4. Provador Lisa
4.3 Framework para Visualização de Grafos
Para apresentação do rastro das provas foi escolhido uma abordagem com interface
gráfica, fazendo uso de um framework denominado Prefuse1. Prefuse é extensível e serve
para ajudar desenvolvedores de software a criarem aplicações de visualizações de informa-
ções interativas usando a linguagem de programação Java, oferece recursos de visualização
para árvores e grafos podendo variar de acordo com a criatividade do desenvolvedor. Em
geral quando o Prefuse é utilizado, quatro aspectos precisam ser tratados:
1- Importar dados para as estruturas de dados internas
Dados podem ser importados a partir de arquivos xml através da web ou diretamente
de banco de dados.
2- Mapear os dados para uma abstração visual
Inclui características do layout, cor, forma, tamanho, elementos de dados, sendo que
cada um destes pode ser modificado.
3- Gerar uma abstração visual
A visão pode ser ampliada para mostrar apenas um subconjunto dos dados na abs-
tração visual. Múltiplas visões podem ser geradas para mostrar a mesma abstração visual de
diferentes perspectivas.
4- Adicionar recursos de interação do usuário
Tais como zoom, selecionar um objeto para alterar a abstração visual e adicionar
recursos de filtragem.
Para o armazenamento dos dados produzidos usa-se um arquivo xml que tem como
entrada um grafo, que traz consigo o rastro da prova.
A escolha de xml, em detrimento de outra linguagem de marcação, se deveu mais ao
conhecimento prévio que o autor possuía da mesma e pela ampla documentação disponí-
vel.
O uso do Prefuse para visualizações rápidas se mostrou muito produtivo, porém
quando o rastro da prova cresce o usuário pode encontrar dificuldades em visualizá-la. Para
resolver esse problema foi usado o pacote Qtree do LATEX(citar aqui) que é indicado para im-
pressões de árvores e grafos.
Com o uso do Qtree o ambiente de visualização ficou mais organizado. Contudo, ras-
tros de provas grandes ainda eram problemáticos, pois o plano da folha não tinha dimensões
suficientes para agrupar toda prova. A solução encontrada para tal problema foi renomear
as subfórmulas da fórmula a ser provada e criar legendas para o usuário identificar quais
subfórmulas foram renomeadas.
1http://prefuse.org/
4.4. Estrutura de Dados 47
Outro ponto a ser destacado refere-se às fórmulas não válidas. No ramo de prova se
insere uma marcação indicando o local em que a prova falha.
4.4 Estrutura de Dados
A preocupação para que um protótipo ou software não apresente problemas em eta-
pas posteriores, depende muito das escolhas em baixos níveis, nos primórdios da arquite-
tura do provador Lisa a estrutura de armazenamento teve uma atenção especial, e um estudo
minucioso foi feito afim de descartar inconsistência que pudesse gerar problemas futuros.
4.4.1 Escolha da estrututra de dados
Escolher entre o uso de árvore ou grafo como estrutura de dados para armazena-
mento e manipulação de valores, seguiu o proposto em (GORDEEV; HAEUSLER; COSTA, 2009).
Nestes trabalhos, os autores mostram que o uso de grafos acíclicos direcionados em vez de
a representação em árvore reduz o tamanho de provas de algumas tautologias.
Resumidamente, o uso de grafos acíclicos permite a reutilização de trechos de prova,
evitando-se assim a replicação de sub-árvores de prova durante a construção da mesma.
4.4.2 A adaptação de um grafo híbrido
Mesmo sabendo que o problema de redução de provas ser NP-completo, uma pre-
ocupação em qualquer provador de teoremas é o de tentar diminuir o tempo de proces-
samento, o projeto do provador Lisa não fugiu a esta preocupação, buscando, sempre que
possível construir provas com tempo de processamento polinomial no tamanho da entrada.
Com essa filosofia de trabalho estabelecida, a implementação de um grafo (GOO-
DRICH; TAMASSIA, 2007) que conjugasse características de grafo dinâmico com as de grafo
estático apresentou uma economia de tempo superior, quando comparado com um que
não conjugasse as caracterísitcas. Outra vantagem está na facilidade em se implementar as
estruturas.
Observação 1. No restante da monografia, o termo grafo híbrido será empregado para refe-
renciar um grafo que possui características estáticas e dinâmicas conjugadas.
De fato, a implementação híbrida carrega um arranjo de tamanho n estático que
armazenaria listas dinâmicas que representam as ligações ou arestas de um nó aos demais.
Considerando o grafo exposto na figura 2. Este seria representado hibridamente conforme
exposto na figura 3.
O pseudo-código para uma inserção no grafo é apresentado no algoritmo 1.
48 Capítulo 4. Provador Lisa
Figura 2 – Exemplo de um grafo
Figura 3 – Exemplo de um grafo híbrido
Algoritmo 1 – Algoritmo para inserção no grafo
Entrada: Primeiro argumento apontado, Segundo apontador (nova, apont a)1: aux . aux será uma lista auxiliar2: t amanho ← t amanho +13: se t amanho > t amanho_do_g r a f o −1 então4: aumenta() . aumenta a estrutura estática5: fim se6: i ndi ce ← busca_i ndi ce(apont ador ) . busca o indice dentro da estrutura vertices7: aux ← contei ner [i ndi ce].Li st a8: aux ← adi ci ona(apont ado, t amanho) . adicionando novo item a lista9: contei ner [i ndi ce] ← Atual i sa_l i st a(aux)
. conteiner é o apontador para cada lista representando as ligações símbolicas10: ver t i ces ← adi ci ona(apont ado, t amanho)
. vertices é global e faz referência ao indice de cada no inserido para facilitar abusca
11: contei ner [t amanho] ← novono_g r a f o. criando um apontador para o novo nó inserido no grafo
12: contei ner [t amanho] ← Atual i za_el emento_g r a f o(apont ado). Atualiza o conteiner agregando o novo elemento
4.5. Especificação das Regras a Nível de Programador 49
Com os detalhes sobre a estrutura de armazenamento, o próximo passo é descrever
os demais módulos que compõem o protótipo.
4.5 Especificação das Regras a Nível de Programador
Construir um provador que empregasse todas os conectivos da lógica proposicional
demandaria um esforço demasiado por parte do programador. Contudo, considerando o
exposto na seção 2.1.2 sobre Conjunto Completo de conectivos, construir um provador que
utilize apenas os conectivos ¬ e ∨, além de simplificar o trabalho, garante a possibilidade de
se provar qualquer fórmulas válidas do cálculo proposicional.
Ao entrar em detalhes de codificação sobre as regras usadas no provador Lisa, uma
rotina de suma importância para as demais regras deve ser abordada. A subrotina trans-
forma quebra cada fórmula corrente em subfórmulas que possam ser derivadas de acordo
com a semântica original. Sua estratégia leva em conta que a fórmula corrente tem a quanti-
dade de parênteses balanceada (isso é verificado por Lisa). Partindo da direita para esquerda
(do fim para o início), subfórmulas são formadas baseando-se nos parênteses e identificando-
se o conectivo principal.
O código em Java que faz a quebra de fórmulas pode ser visualizado no apêndice A.
4.5.1 Adaptando a Entrada do Usuário
Apesar de Lisa trabalhar apenas com o conjunto completo de conectivos (¬,∨), o
usuário pode inserir fórmulas que possuam todos conectivos do cálculo proposicional. Lisa
realiza a transformação da entrada do usuário antes de realizar o processo de prova da fór-
mula. Para fazer a transformação da fórmula de entrada, em tempo de execução, foram uti-
lizadas as conversões apresentadas na seção 2.1.2 para todos os demais conectivos ∧,→,↔.
Tais conversões estão representadas nos códigos 1, 2 e 3, todos em Java.
Código 1 – Transformando o conectivo ∧:
1 public String and( String a, String b){2 if(a. length () >2||b. length () >2){3 String aa="(-("+"-"+a+")v(-"+b+"))";4 return aa;5 }6 else{7 String aa="(-("+"-"+a+"v-"+b+"))";8 return aa;9 }
10 }
50 Capítulo 4. Provador Lisa
Código 2 – Transformando o conectivo →:
1
2 public String implica ( String a ,String b){3 String s="(-"+a+"v"+b+")";4 return s;5 }
Código 3 – Transformando o conectivo ↔:
1 public String bi_implica ( String a, String b){2 String recebe ="", p1="", p2="";3 p1=this. implica (a, b);4 p2=this. implica (b, a);5 recebe += this.and(p1 , p2);6 return recebe ;7 }
Ao implementar as transformações, definir como será identificado cada subfórmula
na entrada original do usuário é um requisito crítico (de maior precedência).
Para esta identificação, usou-se a seguinte abordagem:
• Usa-se uma pilha para armazenar todos os caracteres pertencentes a entrada do usuá-
rio.
• Procura-se pelas subfórmulas presentes na fórmula de entrada. Esta busca se baseia
na abertura e fechamento de parênteses da fórmula. Daí a importância de se escrever a
fórmula corretamente, pois o fechamento errôneo de um parêntese compromete toda
a leitura da fórmula. Cabe ressaltar, que Lisa possui um verificado de fórmula bem
formada.
• Enquanto não se localiza uma subformula, uma variável armazena os caracteres.
• Encontrou um abre parênteses, existe três opções, se na cabeça da lista existir um sím-
bolo ¬ aplica a regra de negação, se existir mais de três itens na lista aplica uma das
demais regra ↔,→,∧, e em última instância adiciona na lista.
• Ao aplicar uma das regras de transformações, adiciona a subfórmula gerada na lista.
• Ao final restará apenas um item na lista, que é a fórmula do usuário contendo apenas
conectivos ¬,∨.
4.5. Especificação das Regras a Nível de Programador 51
4.5.2 Regras da disjunção ∨As regras para o conectivo ∨ podem ser aplicadas tanto do lado esquerdo quanto do
direito do sequente (`), afim de realizar as derivações necessárias.
4.5.2.1 ∨-esquerda
Conforme seção 2.2, aplicar a regra ∨-esquerda no sequente gera dois novos sequen-
tes no ramo da prova, conforme exemplo a seguir:
C ,Γ`∆ D,Γ`∆C ∨D,Γ`∆
O procedimento de particionamento da fórmula corrente adota duas estratégias, que
são:
1. Copiar o lado esquerdo do sequente em uma variável e o lado direito em outra.
2. Encontrar na variável que armazena o lado esquerdo do sequente uma fórmula com
conectivo ∨ e derivá-la.
Após a derivação realizada, a concatenação com a parte direita do sequente, e a de-
volução dos dois novos ramos para posteriores derivações.
O código em Java da regra do ∨-esquerda do sequente está presente no apêndice B.
A rotina or_esquerdo faz a quebra da fórmula de entrada em subfórmulas que são
enviadas ao complemento_Or_esquerdo, onde através de requisições a rotina transforma
são gerados fragmentos de fórmula que passam pelas heurísticas de derivações.
O código em Java do complemento da regra do ∨-esquerda se encontra no apêndice C.
4.5.2.2 Regras ∨-direita
A regra ∨-direita sofreu alterações na sua estrutura original, com o intuito de dimi-
nuir ao máximo o tempo de processamento. Em vez de se escolher um fragmento da fórmula
e excluí-lo, como é feito nas regras originalmente propostas, a nova regra faz uma derivação
sem excluir nenhum fragmento. Com esta abordagem, se evita retrocedor na ramo de prova.
Pois não são excluídos fragmentos da fórmula original.
Regras Originais:
∨R1:Γ`∆,C
Γ` Γ,C ∨De ∨R2:
Γ`∆,D
Γ` Γ,C ∨D
52 Capítulo 4. Provador Lisa
Regra Otimizada:
∨R:Γ`∆,C ,D
Γ` Γ,C ∨D
A regra otimizada segue como consequência da aplicação das regras ∨R1 e ∨R2, con-
forme prova a seguir:
Γ`∆,C ,D( ∨R2 )
Γ`∆,C , (C ∨D)( ∨R1 )
Γ`∆, (C ∨D), (C ∨D)( Cont )
Γ`∆, (C ∨D)
Ao se analisar a parte de codificação da regra ∨-direita (cf. Apêndice D), tem-se que
a parte de quebra de fórmulas com o mesma esquema da regra do ∨-esquerda faz uso de
tabelas Hash.
O uso de Hash foi preferido, por facilitar as constantes verificações ao nó corrente na
busca por argumentos que confirmasse a existência de uma consequência lógica. Notada-
mente, tabelas Hash são ótimas para este tipo de consulta recorrente (CORMEN et al., 2002).
O algoritmo de geração de índices para a Hash usa os próprios literais como chave
para o armazenamento, usando o valor inteiro de cada literal que, diga-se de passagem,
é único, sendo este valor fornecido pela linguagem sem precisar do programador ter que
desenvolver algum tipo de algoritmo.
Γ`∆, (P ∨¬P )
Em um dado momento de derivação fazendo uso da regra a direta do OR tem-se um P ar-
mazenado na estrutura aqui chamada de E1(litarais sem negação) e um ¬P armazenado na
E2(litarais negado).
Figura 4 – Array E1 que armazena literais não negativos
Figura 5 – Array E2 que armazena literais negativos
4.5. Especificação das Regras a Nível de Programador 53
Ao se fazer uma pesquisa será constatado que tem-se uma consequência lógica, a
partir deste ponto Lisa tentará achar um novo ramo que possa ser processado, nessas tenta-
tivas, caso não encontre nenhum outro ramo, o nó inicial será atingido e Lisa retornará um
parecer ao usuário informando que sua entrada é uma consequência lógica . O código em
Java da regra ∨-direita do sequente pode ser visualizado no apêndice D.
A rotina or_direito também faz uso de uma rotina auxiliar (complemento_or_direito )
que e bem semelhante com a complemento_Or_esquerdo. Apenas um complemento foi feito
afim de adquirir uma melhor perfomance. Verificando se é possível derivar a subformula
corrente usando a regra de negação à direita (cf. seção 4.5.3.1).
O código em Java do complemento da regra ∨-direita do sequente pode ser visuali-
zado no apêndice E.
4.5.3 Regras de Negação (¬)
A implementação destas regras não se mostrou tão complexa quanto a das regras do
∨.
Há a possibilidade de trabalhar com derivações tanto do lado esquerdo como a di-
reita do sequente, sendo que essa regra não produz derivações que levem a duplicação da
fórmula, como acontece com a regra ∨-esquerda do sequente.
4.5.3.1 ¬-direita
Como dito acima a simplicidade de implementar essa regra está no fato de não se ter
muitos passos a seguir. O primeiro passo a ser realizado é pegar o fragmento de fórmula do
lado direito do sequente, em seguida começasse a fase de procura pelo conectivo de negação
(¬).
O próximo passo é analisar se o fragmento de fórmula está apto a ser derivado, já
que fragmentos do tipo ¬p, (¬q∨p) não podem ser derivados. Essa é a fase mais longa, com
vários testes condicionais a se realizar afim de identificar quando cabe o uso da regra.
O último passo consiste em transferir o fragmento de fórmula que pode ser derivado
para o lado esquerdo do sequente retirando o conectivo principal ( ¬). Um fato a ser fri-
sado é a necessidade de a fórmula de entrada ser bem formada com parênteses marcando
todas as subformula existentes, pois todos os procedimentos empregados são baseados nos
parênteses como fator primordial para indentificar subformulas derivaveis.
O código em Java da regra ¬-direita do sequente pode ser visualizado no apêndice F.
54 Capítulo 4. Provador Lisa
4.5.3.2 ¬-esquerda
A regra que se aplica ao lado esquerdo do sequente é muito semelhante com a regra
da direita. As mínimas diferenças encontradas são:
• Recupera-se o lado esquerdo do sequente em vez do direito.
• Ao derivar uma subformula, esta é transferida para o lado direito do sequente, em vez
do esquerdo.
Os demais processos para verificação de busca do conectivo principal, quebra de
subformulas e concatenação são idênticos aos da regra do lado direito.
O código em Java da regra neg -esquerda do sequente pode ser visualizado no apên-
dice G.
4.5.4 Gerenciando as Regras
Após expor as regras de cálculo de sequentes a nível de implementação, o último
passo é descrever como intercalar tais regra afim de verificar a validade das fórmulas. Para
isso foi proposto um modelo a ser seguido.
Ao iniciar: Valida a fórmula de entrada do usuário, ao encontrar um problema o
usuário recebe um alerta, caso contrário o processamento é iniciado.
Utilizar enquanto possível as regras que não produzem bifurcação: As regras de ¬-
(esquerda e direita) e∨-direita não produzem bifurcações. Derivando as fórmulas usando-se
tais regras diminui o tempo consumido na prova. O tempo da prova depende da quantidade
de aplicações das regras ∨-esquerda. Evitando seu uso ao máximo pretende-se reduzir o
tempo de prova. Contudo, uma vez que trata de problema NP-completo, nem sempre se
conseguirá um prova curta.
Retroceder no grafo: Ao aplicar uma regra de derivação faz-se a verificação no ramo,
localizou uma consequência lógica faz se o retrocesso no grafo afim de localizar um novo
ramo que ainda não foi verificado, ao utilizar o retrocesso há duas opções: encontrar um
novo ramo apto a ser derivado ou chegar ao nó inicial onde se encerra a prova e um parecer
é dado ao usuário.
Verificações recorrentes antes de se finalizar a prova: Ao aplicar uma regra de deri-
vação, verifica-se a fórmula afim de encontrar argumentos para se finalizar a prova. Em não
se encontrando, deve-se percorrer os ramos abertos na prova, aplicando as regras a estes
ramos, recorrentemente.
Finalizar a prova: Após derivar um nó uma ou mais vezes as subformulas propicias
podem se esgotar, neste caso Lisa verifica se a fórmula é válida. Caso contrário o processo é
4.5. Especificação das Regras a Nível de Programador 55
interrompido e o usuário é avisado de que a fórmula de entrada é válida.
O código em Java do gerenciador das regras pode ser visualizado no apêndice H.
57
CA
PÍ
TU
LO 5
UTILIZAÇÃO DO PROTÓTIPO
Será apresentado neste capítulo o protótipo e como utilizá-lo. Para tanto será feita
uma apresentação das funcionalidades e suas especificações associando os conceitos abor-
dados nas seções anteriores.
5.1 Interface do Provador
Procurou-se construir uma interface intuitiva para o provador Lisa. Uma caracterís-
tica que comprova esta iniciativa, é a não necessidade de acesso a outras telas para utilizar
a ferramenta, as mensagens dos botões são bem intuitivas no que diz respeito a ação reali-
zada por cada um, tudo para que usuário encontre o mínimo de dificuldades possíveis. Sua
interface pode ser visualizada na figura 6.
A tela inicial é composta de:
• Um campo para receber a fórmulas.
• O botão validar fórmula verifica se a fórmula está sintaticamente correta.
• O botão processar fórmula como o próprio nome indica realiza o processamento
baseando-se nas regras explicadas na seção 2.2.
• O botão visualizar fórmula, caso a entrada do usuário necessite sofrer transforma-
ções (usando os procedimentos de conectivos completos) o usuário terá uma noção
de como a entrada estará.
• O botão visualizar Prova apresenta o rastro da prova usando o framework Prefuse.
• O botão Créditos apresenta o título do projeto, e os dados do orientador e orientando.
58 Capítulo 5. Utilização do Protótipo
Figura 6 – Interface do Provador Lisa
Fonte: O autor
• O botão gerar tex abre uma janela onde o usuário pode escolher o diretório que deseja
salvar o arquivo.tex.
• O botão Help explica de forma abstata o funcionamento e o modelo de entrada aceita
por Lisa.
• O botão Sair finaliza a execução.
5.2 Utiilizando o protótipo
Como exemplo do uso do provador, será usada a fórmula:(p → q), (p → (q → r )), (q →(r → s)), (r → (s → t )) ` (p → t ) como entrada.
5.2. Utiilizando o protótipo 59
O primeiro passo é validar a entrada do usuário, ao clicar no botão validar fórmula,
será emitida uma mensagem informando se a fórmula está sintaticamente correta, con-
forme a figura 7. Enquanto não for apresentada uma entrada válida, Lisa não efetuará ne-
nhum outro passo.
Figura 7 – Validando a entrada do usuário
Fonte: O autor
Uma vez que Lisa trabalha apenas com conectivos ∨ e ¬, uma reformulação da fór-
mula do usuário, usando as técnicas de tranformação de conectivos (conjunto completo de
conectivos) será realizada. Ao clicar no botão visualizar fórmula o usuário pode ver como
ficou sua entrada original usando apenas os conectivos ¬, ∨, conforme a figura 8
Ao clicar no botão processar fórmula será iniciado o processamento, ao final o usuá-
rio terá um parecer da fórmula de entrada, quanto a sua validade ou não, conforme apresen-
tado na figura 9
A usuário poderá visualizar a prova ao clicar no botão visualizar prova conforme a
60 Capítulo 5. Utilização do Protótipo
Figura 8 – Visualizando a entrada modificada do usuário
Fonte: O autor
figura 10
O botão gerar tex ativa a janela para o usuário salvar o documento em um diretório
de sua escolha e produzir um documento contendo o código em LATEX do rastro da prova
conforme a figura 11.
O código em latex após compilado, irá produzir um arquivo pdf contendo o rastro da
prova no formato da figura 12.
5.2. Utiilizando o protótipo 61
Figura 9 – Informando o usúario
Fonte: O autor
62 Capítulo 5. Utilização do Protótipo
Figura 10 – Visualizando Prova
Fonte: O autor
5.2. Utiilizando o protótipo 63
Figura 11 – Código em latex da Prova
Fonte: O autor
64 Capítulo 5. Utilização do Protótipo
Figura 12 – PDF da prova
Fonte: O autor
65
CA
PÍ
TU
LO 6
CONCLUSÃO
Neste trabalho foi apresentado um protótipo de provador de teoremas, denominado
LISA. Para o protótipo de provador tornar um sistema totalmente funcional ainda são neces-
sários testes.
Bem mais que apresentar o provador, foi também explicado como construir um pro-
vador para a lógica proposicional que tenha como sistema dedutivo o Cálculo de Sequentes.
Se por um lado o mero uso do provador por um iniciante em lógica já apresenta um
ganho na absorção de conhecimentos do assunto, pretendia-se também que o texto da mo-
nografia servisse de material motivador para a compreensão de alguns conceitos de lógica.
Evidente que não se teve a pretensão de construir um livro didático de lógica, muitos existem
que cumprem bem este papel, alguns sendo amplamente consultados durante a confecção
deste texto. A intenção maior era despertar o interesse dos possíveis leitores sobre uma dis-
ciplina que constitui os alicerces da computação.
Cabe ressaltar que a construção do provador foi rápida quando comparada com a
tempo necessário para se absorver os conceitos para a sua construção. Os livros textos que
tratam do assunto são escassos e não há uma padronização nas notações empregadas. Não
sendo incomum o encontro de erros em alguns obras didáticas.
Não obstante, foi produzido um material que ainda pode ser ampliado para aplica-
ções mais ambiciosas. O que aqui foi apresentado é apenas o começo dos estudos realizados
durante o tempo em que o autor foi bolsistas do PIBIT. O objetivo final do projeto é se cons-
truir frameworks para trabalhar com representação/explicação do conhecimento.
Em suma, representação do conhecimento é uma parte da área de Inteligência Arti-
ficial que se preocupa em como um agente usa o que é conhecido para decidir o que fazer.
Isto é, representação do conhecimento pode ser visto como o estudo do pensamento como
66 Capítulo 6. Conclusão
um processo computacional ((BRACHMAN; LEVESQUE, 2004)).
Já explicações constituem assunto de pesquisa de diversas disciplinas, incluindo, por
exemplo, Filosofia da Ciência, Matemática, Lingüística e Inteligência Artificial. Esta diversi-
dade aponta para a existência de diferentes visões sobre o que exatamente vem a ser uma
explicação. No projeto final do PIBIT foi proposto um assistente de formalismo para aju-
dar o usuário a extrair a semântica de uma ação em um domínio específico. Neste sentido
é proposta uma aplicação que extrai e representa semânticas (i.e., significados de senten-
ças e textos em linguagem natural). O significado de uma ação no domínio tratado deve
ser convertido para uma forma lógica e armazenado em uma ontologia, que dependerá do
domínio.
Precisa-se acrescentar regras do cálculo de predicados no protótipo construído para
poder acoplá-lo num ambiente de representação de conhecimento. Apenas após estas eta-
pas, poderá se passar para verificação de consistência e extração de conhecimento em do-
mínios específicos.
67
REFERÊNCIAS
BORGES, L. E. Python para Desenvolvedores. 2. ed. Rio de Janeiro: Pearson Prentice Hall,2010. Citado na página 45.
BRACHMAN, R.; LEVESQUE, H. Knowledge Representation and Reasoning. Oxford: Else-vier Science, 2004. 381 p. (The Morgan Kaufmann Series in Artificial Intelligence). ISBN9781558609327. Citado na página 66.
CASTRUCCI, B. Elementos de teoria dos conjuntos. 3. ed. São Paulo: Grupo de Estudos doEnsino da Matemática, GEEM, 1967. 128 p. Citado na página 37.
CORMEN, T. H. et al. Algoritmos: Teoria e pratica. 2. ed. Rio de janeiro: Elsevier, 2002. Citadona página 52.
DASGUPTA, S.; PAPADIMITRIOU, C.; VAZIRANI., U. Algoritmos. São Paulo: Mc Graw Hill,2009. Citado na página 35.
DEITEL, P.; DEITEL, H. Java Como Programar. 8. ed. São Paulo: Pearson Prentice Hall, 2010.Citado na página 45.
ENDERTON, H. B. A Mathematical Introduction to Logic. 2. ed. San Diego: Harcourt/Acade-mic Press, 2001. ISBN 9780080496467. Citado na página 23.
FRITSCH, R.; FRITSCH, G. The Four Color Theorem: History, Topological Foundations,and Idea of Proof. Germany: Springer Verlag, 1998. 260 p. (Springer finance). ISBN9780387984971. Citado na página 37.
GABBAY, D. M.; WOODS, J. Handbook of the history of logic: The rise of modern logic : fromLeibniz to Frege. Michigan: North Holland, 2004. 770 p. (Handbook of the History of Logic,v. 3). ISBN 9780444516114. Citado na página 23.
GOODRICH, M. T.; TAMASSIA, R. Estrutura de Dados e Algoritmos em Java. 4. ed. Porto Ale-gre: Bookman, 2007. Citado na página 47.
GORDEEV, L.; HAEUSLER, E.; COSTA, V. Proof compressions with circuit-structured substi-tutions. Journal of Mathematical Sciences, 2009. Springer US, v. 158, p. 645–658, 2009. ISSN1072-3374. Disponível em: <http://dx.doi.org/10.1007/s10958-009-9405-3>. Citado na pá-gina 47.
HONSELL, F.; MICULAN, M.; SCAGNETTO, I. π-calculus in (co) inductive-type theory. The-oretical computer science, 2001. Elsevier, v. 253, n. 2, p. 239–285, 2001. Citado na página37.
68 Referências
MCCORDUCK, P. Machines who think: a personal inquiry into the history and prospects of ar-tificial intelligence. Universidade de Michican, Michigan: A.K. Peters, 2004. 565 p. (Ak PetersSeries). ISBN 9781568812052. Citado na página 36.
MÉTIVIER, Y. About the rewriting systems produced by the Knuth-Bendix completion algo-rithm. Information Processing Letters, 1983. Elsevier, v. 16, n. 1, p. 31–34, 1983. Citado napágina 37.
MINTS, G. A Short Introduction to Intuitionistic Logic. New York: Springer, 2000. 131 p. (Uni-versity Series in Mathematics). ISBN 9780306463945. Citado na página 24.
MORTARI, C. A. Introdução à lógica. São Paulo: Editora UNESP, 2001. ISBN 85.7139.337-0.Citado na página 37.
SANTOS, J. de B. Infraestrutura para Provadores Interativos de Teoremas na Web. Dissertação(Mestrado) — Pontífica Universidade Católica do Rio de Janeiro, Rio de Janeiro, 2010. Citado2 vezes nas páginas 35 e 36.
SILVA, F. S. C. da; FINGER, M.; MELO, A. C. V. de. Lógica Para Computação. São Paulo: Thom-son, 2006. Citado 3 vezes nas páginas 27, 29 e 36.
SMULLYAN, R. M. et al. Lógica de Primeira Ordem. SÃO PAULO: Editora UNESP, 2009. 188 p.Citado na página 38.
SOMMERVILLE, I. Engenharia De Software. 9. ed. São Paulo: Pearson Prentice Hall, 2011.Citado 2 vezes nas páginas 41 e 44.
TAKEUTI, G. Studies In Logic And The Foundations Of Mathematics. 2. ed. Amsterdam , NewYork, Oxford , Tokyo: Elsevier Science Publisher, 1987. Citado 3 vezes nas páginas 30, 32 e 36.
TROELSTRA, A. S.; SCHWICHTENBERG, H. Basic Proof Theory. 2. ed. Cambridge, England:Cambridge University Press, 2000. 417 p. Citado na página 39.
van DALEN, D. Logic and Structure. New York, NY: Springer, 2004. 217 p. (Uni-versitext (1979)). ISBN 9783540208792. Disponível em: <http://books.google.com.br-/books?id=4u9gQ6pctuIC>. Citado 3 vezes nas páginas 23, 28 e 36.
WHITEHEAD, A. N.; RUSSELL, B. Principia Mathematica to *56. Cambridge: Cambridge Uni-versity Press, 1997. 410 p. (Cambridge Mathematical Library). ISBN 9780521626064. Dispo-nível em: <http://books.google.com.br/books?id=ke9yGmFy24sC>. Citado na página 36.
69
AP
ÊN
DI
CE
AQUEBRA A FÓRMULA DE ORIGEM EM
SUBFÓRMULAS
1 public String [] transforma ( String s) {2 tranformacao p = new tranformacao (s);// transforma a
entrada do usuario em uma formula contendo apenasconectivos completos
3 Pilha pilha = p. empilha2 (); Lista list = new Lista ();String elemento = "";int sentinela = 0;
4 while (! pilha.vazia ()) {5 elemento = pilha.pop ();6 if ( elemento . equals ("(")) {7 if (list. cabeca (). equals ("-")) {8 if (list. tamanho () >= 2) {9 String a = list. remove (); String b = list
. remove ();list. adiciona ("(" + a + b + ")");
10 }11 }// fim nao12 else {// caso ou and13 if (( list. tamanho () >= 3 && pilha. tamano () >
0)) {14 sentinela ++; String a = list. remove ();15 String conectivo = list. remove (); String
b = list. remove ();16 if ( conectivo . equals ("v")) {17 String recebe = p.or(a, b); list.
70 APÊNDICE A. Quebra a fórmula de origem em subfórmulas
adiciona ( recebe );18 }19 }// fim do length320 }// fim else21 }// fim if22 else {23 if (!( elemento . equals ("(") || elemento . equals (")"
))) {24 list. adiciona ( elemento );25 }26 }27 }// fim while28 if (list. tamanho () == 1) {29 String vetor [] = new String [2]; vetor [0] = " continua "
;vetor [1] = list. cabeca (); return vetor;30 }31 if (list. tamanho () == 3) {32 String vetor [] = new String [list. tamanho ()]; vetor
[0] = list. cabeca (); list. remove ();33 vetor [1] = list. cabeca (); list. remove ();vetor [2] =
list. cabeca ();list. remove ();34 return vetor;35 } else {36 String vetor [] = new String [list. tamanho ()]; int c =
0;37 while (list. tamanho () > 0) {38 vetor[c] = list. cabeca (); list. remove ();39 c++;40 }41 return vetor;42 }43
44 }
71
AP
ÊN
DI
CE
BREGRA OU A ESQUERDA DO SEQUENTE
1 public String [] or_esquerdo ( String s) {2 String antes = "",String armazem = "",depois = "";3 String vet [] = new String [2]; String retornar [] = new
String [2];4 boolean sentinela = false; int i = 0, recupera_seguente =
-1;5 for (i = 0; i < s. length (); i++) {6 if (s. charAt (i) == ’|’) {7 recupera_seguente = i; sentinela = true;8 } else if ( sentinela == true) {9 depois += s. charAt (i);
10 }11 if ( sentinela == false && s. charAt (i) == ’,’ || (
sentinela == true && s. charAt (i) == ’|’ && (! antes.equals ("")))) {
12 vet = this. complemento_Or_esquerdo (antes);13 if (vet == null) {// caso nao seja possivel ou a
subformula seja um atomo14 if ( armazem . equals ("")) {15 armazem += antes ;}16 else { armazem += "," + antes ;}17 antes = "";18 } else {// foi possivel aplicar a regra19 break ;}20 }// fim do else21 else if ( sentinela == false) {
72 APÊNDICE B. Regra OU a esquerda do Sequente
22 antes += s. charAt (i);23 }24 }// fim do for // pega o restante da formula caso tenha
encerrado antes de se chegar ao final da formula25 depois = "";26 if (i < s. length ()) {27 for (int j = i; j < s. length (); j++) { depois += s.
charAt (j);}28 }29 if (vet != null) {// caso a formula nao tenha separação
por virgula30 if ( armazem . equals ("")) {31 retornar [0] = armazem + vet [0] + depois ; retornar
[1] = armazem + vet [1] + depois ;32 } else {// caso tenha separação por virgula33 retornar [0] = armazem + "," + vet [0] + depois ;
retornar [1] = armazem + "," + vet [1] + depois ;34 }35 return retornar ;36 } //se chegar aqui , não foi p o s s à v e l aplicar a regra37 return null;38 }
73
AP
ÊN
DI
CE
CCOMPLEMENTO DA REGRA OU A ESQUERDA
DO SEQUENTE
1 public String [] complemento_Or_esquerdo ( String s) {2 // so usa duas posicoes , a primeira posicao traz a
subformula derivada e a segunda o indice onde aconteceu3 String retorno [] = new String [2];4 //ja foi usada no processo de derivacao5 if (s. length () == 1 || s. length () == 2) {6 return null;7 }8 String p1 = ""; String p2 = ""; String antiga = "";9 // faz a separacao em subformulas válidas
10 String vet [] = this. transforma (s);11 if (vet [0]. equals (" continua ")) { vet = this. transforma (
vet [1]) ;}12 //eh uma negacao13 if (vet. length == 1 && vet [0]. length () > 2) { return null
;}14 int i = 0, t = 0;15 for (; i < vet. length ; i++) {16 if (i == 0 && !vet[i]. equals ("v")) {17 p1 += vet[i];18 t = 1;19 // retorno = this. ajuda_or_esquerdo (vet[i]);20 } else if (i != t) {p2 += vet[i];}21 }
74 APÊNDICE C. Complemento da regra OU a esquerda do Sequente
22 // isso acontece quando a formula ja foi toda trabalhada23 if (!( p1. equals ("") && p2. equals (""))) {24 vet [0] = p1; vet [1] = p2; return vet;25 }26 return null;27 }
75
AP
ÊN
DI
CE
DREGRA DO OU A DIREITA DO SEQUENTE
1 public No_grafo Or_direita ( No_grafo s1) {2 String s = s1. getelemento_grafo (); boolean sentinela =
false;3 String esquerdo = "", direito = "";4 No_grafo novo = new No_grafo ();5 novo. carrega_literais (s1. getliterais ());6 novo. carrega_not_literais (s1. getliterais_negado ());7 for (int i = 0; i < s. length (); i++) {8 if (s. charAt (i) == ’|’) {9 sentinela = true;
10 } else if ( sentinela == false) {11 esquerdo += s. charAt (i);12 }// fim do else13 else if ( sentinela == true) {14 direito += s. charAt (i);15 }// fim do else16 }// fim do for17 String devolve = "";// ira ser o retorno do metodo18 if ( direito . length () > 0) {19 int contador = 0;// vai servir pra dizer quando parar
de fazer a quebra20 String recebe = "";21 for (int j = 0; j < direito . length (); j++) {22 if ( direito . charAt (j) == ’,’) {23 String vet [] = this. complemento_or_direito (
recebe );
76 APÊNDICE D. Regra do OU a direita do Sequente
24 if (vet == null) {// calcular hash25 if ( recebe . length () == 1) {26 novo. setliterais (recebe , this.Hash(
recebe . charAt (0)));27 } else {28 novo. setliterais_negado (recebe , this.
Hash( recebe . charAt (1)));29 }30 if ( devolve . equals ("")) {31 devolve += recebe ;32 } else {33 devolve += "," + recebe ;34 }35 recebe = "";36 }// caso base37 // caso em q uma negacao foi encontrada38 else if (vet [1]. equals ("*")) {39 if ( devolve . equals ("")) {40 devolve += vet [0];41 recebe = "";42 } else {43 devolve += "," + vet [0];44 recebe = "";45 }46 }// fim do if47 else if (vet [0] != null && vet [1] != null) {48 if ( devolve . equals ("")) {49 for (int i = 0; i < vet. length ; i++)
{50 devolve += vet[i];51 }52 recebe = "";53 }// fim do if54 else {55 devolve += ",";56 for (int i = 0; i < vet. length ; i++)
{57 devolve += vet[i];58 }// fim do for59 recebe = "";60 }// fim do else61 // isso quer dizer que e um literal
77
62 if (vet [0]. length () <= 2) {63 if (vet [0]. length () == 1) {64 novo. setliterais (vet [0], this.
Hash(vet [0]. charAt (0)));65
66 } else {67 novo. setliterais_negado (vet [0],
this.Hash(vet [0]. charAt (1)));68 }69 }// fim do if q trata da hash dos literais70 if (vet [2]. length () <= 2) {71 if (vet [2]. length () == 1) {72 novo. setliterais (vet [2], this.
Hash(vet [2]. charAt (0)));73 } else {74 novo. setliterais_negado (vet [2],
this.Hash(vet [2]. charAt (1)));75 }76 }// fim do if q trata da hash dos literais77 }// fim do else if78 }// fim do else principal79 else {80 recebe += direito . charAt (j);81 }82
83 }// fim do for84 if (! recebe . equals ("")) {85 String vet [] = this. complemento_or_direito ( recebe
);86 // significa que é um literal87 if (vet == null) {// calcular hash88
89 if ( recebe . length () == 1) {90
91 novo. setliterais (recebe , this.Hash( recebe. charAt (0)));
92 } else {93 novo. setliterais_negado (recebe , this.Hash
( recebe . charAt (1)));94 }95 if ( devolve . equals ("")) {96 devolve += recebe ;
78 APÊNDICE D. Regra do OU a direita do Sequente
97 } else {98 devolve += "," + recebe ;99 }
100 recebe = "";101 }// caso base102 // caso em q uma negacao foi encontrada103 else if (vet [1]. equals ("*")) {104
105 if ( devolve . equals ("")) {106 devolve += vet [0];107 recebe = "";108 } else {109 devolve += "," + vet [0];110 recebe = "";111 }112
113 }// fim do if114 else if (vet [0] != null && vet [1] != null) {115 if (vet [0]. length () <= 2) {116 if (vet [0]. length () == 1) {117 novo. setliterais (vet [0], this.Hash(
vet [0]. charAt (0)));118 } else {119 novo. setliterais_negado (vet [0], this.
Hash(vet [0]. charAt (1)));120 }121 if (vet [2]. length () <= 2) {122 if (vet [2]. length () == 1) {123 novo. setliterais (vet [2], this.
Hash(vet [2]. charAt (0)));124 } else {125 novo. setliterais_negado (vet [2],
this.Hash(vet [2]. charAt (1)));126 }127
128 }// fim do if q trata da hash dos literais129 }// fim do if q tratá da hash dos literais130 if ( devolve . equals ("")) {131 for (int i = 0; i < vet. length ; i++) {132 devolve += vet[i];133 }134
79
135 recebe = "";136 }// fim do if137 else {138 devolve += ",";139 for (int i = 0; i < vet. length ; i++) {140 devolve += vet[i];141
142 }// fim do for143 recebe = "";144 }// fim do else145 }// fim do else if146
147 String a[] = novo. getliterais ();148 String b[] = novo. getliterais_negado ();149
150
151 }// fim do if152 }// fim do if153 if (! esquerdo . equals ("")) {154 novo. setelemento_grafo ( esquerdo + "|" + devolve );155 } else {156 novo. setelemento_grafo ("|" + devolve );157 }158 return novo;159 }
81
AP
ÊN
DI
CE
ECOMPLEMENTO DA REGRA DO OR A DIREITA
DO SEQUENTE
1 public String [] complemento_or_direito ( String s) {2 // caso em que for um literal3 if (s. length () == 1 || s. length () == 2) {4 return null;5 } else {6 String vetor [] = new String [2];7 // caso seja possivel usar a formula da negacao8 String beta = this. direita_negacao (s);9 if (beta != null) {
10 vetor [0] = s;11 vetor [1] = "*";// informa q foi derivado usando a
regra de negacao12 return vetor;13 }// fim do if q indica q existia uma negacao14 else {15 String vet [] = this. transforma (s);16 for (int i = 0; i < vet. length ; i++) {17 if (vet[i]. equals ("v")) {18 vet[i] = ",";19 }20 }21 return vet;22 }23 }// fim do metodo complemento -or - direito
82 APÊNDICE E. Complemento da regra do OR a direita do Sequente
24 }
83
AP
ÊN
DI
CE
FREGRA NEGAÇÃO A DIREITA DO SEQUENTE
1 public String direita_negacao ( String a) {2 String direito = "",squerdo = "",absolute = ""aux = "",
aux2 = "";3 boolean achei = false , entrei = true;int cont = 0;4 for (int i = 0; i < a. length (); i++) {5 if (a. charAt (i) == ’|’) {6 achei = true;7 } else if (achei == true) {8 direito += a. charAt (i);9 } else if (achei == false) {
10 esquerdo += a. charAt (i);11 }12 }// fim do for13 achei = false;14 if ( direito . equals ("")) {15 return null;16 }17 for (int i = 0; i < direito . length (); i++) {18 if ( direito . charAt (i) == ’-’ && entrei == true) {19 // passo base formulas do tipo (-( pvq))20 if (i < direito . length () - 2) {21 if ( direito . charAt (i + 1) == ’(’) {22 if (i - 1 == 0) {23 achei = true; entrei = false;24 i++; aux = "";25 } else if (i - 1 == 0) {
84 APÊNDICE F. Regra negação a direita do Sequente
26 achei = true; entrei = false;27 i++; aux = "";28 } else if (i - 2 >= 0) {29 if ( direito . charAt (i - 2) == ’,’) {30 achei = true; entrei = false;31 i++; aux = "";32 }33 }34 }35 }36 }// fim do if37 if (achei == true) {38 if ( direito . charAt (i) != ’,’) {39 if ( direito . length () > 3) {40 if (i == direito . length () - 1 && direito .
charAt (i) == ’)’)41 ; else if (i < direito . length () - 1 &&
direito . charAt (i) == ’)’ && direito .charAt (i + 1) == ’,’) {
42 ;43 } else {44 aux2 += direito . charAt (i);45 }46 } else {47 aux2 += direito . charAt (i);48 }49 } else {50 achei = false;51 }52 } else {53
54 if ( direito . charAt (i) == ’,’) {55 if ( absolute . equals ("")) {56 absolute += aux;57 } else {58 absolute += "," + aux;59 }60 aux = "";61 } else {62 aux += direito . charAt (i);63 }64 }
85
65 }// fim do for66 if (! aux. equals ("")) {67 if ( absolute . equals ("")) {68 absolute += aux;69 } else {70 absolute += "," + aux;71 }72 aux = absolute ;73 } else {74 aux = absolute ;75 }76 if ( entrei == true) return null;77 if (! esquerdo . equals ("")) {78 return esquerdo + "," + aux2 + "|" + aux;79 } else {80 return aux2 + "|" + aux;81 }82 }
87
AP
ÊN
DI
CE
GREGRA A ESQUERDA DA NEGAÇÃO
1 public String esquerda_Negacao ( String a) {2 int cont = 0; String direito = "", esquerdo = "",aux = ""
,aux2 = "",absolute = "";3 boolean achei = false , entrei = true;4 for (int i = 0; i < a. length (); i++) {5 if (a. charAt (i) == ’|’) {6 achei = true;7 } else if (achei == true) {8 direito += a. charAt (i);9 } else if (achei == false) {
10 esquerdo += a. charAt (i);11 }12 }// fim do fro13 achei = false;14 if ( esquerdo . equals ("")) {15 return null;16 }17 for (int i = 0; i < esquerdo . length (); i++) {18 if ( esquerdo . charAt (i) == ’-’ && entrei == true) {19 // passo base formulas do tipo (-( pvq))20 if (i < esquerdo . length () - 2) {21 if ( esquerdo . charAt (i + 1) == ’(’) {22 if (i - 1 == 0) {23 achei = true; entrei = false;24 i++; aux = "";25 } else if (i - 1 == 0) {
88 APÊNDICE G. Regra a esquerda da negação
26 achei = true; entrei = false;27 i++; aux = "";28 } else if (i - 2 != 0 && i - 2 >= 0) {29 if ( esquerdo . charAt (i - 2) == ’,’) {30 achei = true; entrei = false;31 i++; aux = "";32 }33 }34 }35 }// fim do if36 }// fim do if37 if (achei == true) {38 if ( esquerdo . charAt (i) != ’,’) {39 if ( esquerdo . length () > 3) {40 if (i == esquerdo . length () - 1 &&
esquerdo . charAt (i) == ’)’)41 ; else if (i < esquerdo . length () - 1 &&
esquerdo . charAt (i) == ’)’ && esquerdo .charAt (i + 1) == ’,’) {
42 ;43 } else {44 aux2 += esquerdo . charAt (i);45 }46
47 } else {48 aux2 += esquerdo . charAt (i);49 }50 } else {51 achei = false;52 }53 } else {54 if ( esquerdo . charAt (i) == ’,’) {55 if ( absolute . equals ("")) {56 absolute += aux;57 } else {58 absolute += "," + aux;59 }60 aux = "";61 } else {62 aux += esquerdo . charAt (i);63 }64 }
89
65 }// fim do for66 if (! aux. equals ("")) {67 aux += "," + absolute ;68 } else {69 aux += absolute ;70 }71 //if entrei isso indica q nao existia subformulas
negativas72 if ( entrei == true) {73 return null;74 }75 if (! aux. equals ("")) {76 if (aux. charAt (aux. length () - 1) == ’,’) {77 aux = this.copia(aux);78 }79 }// fim do if80 aux = this.corta(aux);81 if (! direito . equals ("")) {82 return aux + "|" + aux2 + "," + direito ;83 } else {84 return aux + "|" + aux2;85 }86 }
91
AP
ÊN
DI
CE
HGERENCIADOR DE REGRAS
1 public boolean executa () {2 // contador universal marca o no corrente que esta
trabalhando3 // verifica a formula4 if (this. valida_formula ( entrada )) {5 grafo. cria_raiz ( converte ());// converte a formula do
usuario para os padroes dos conectivos completos6 grafo. setanterior (0, -1);// vai ser util para minha
condicao de parada7 contador_universal ++;8 }// fim do if raiz9 else {// formula com erro
10 return false;11 }12 String recebe = grafo. imprime_raiz ();// pega a raiz13 while ( regras . esquerda_Negacao ( recebe ) != null) {14 String aux = regras . esquerda_Negacao ( recebe );15 grafo. armazena (aux , recebe );// guarda a antiga no nodo16 recebe = aux;// string atualizada17 int recupera = contador_universal ;18 contador_universal ++;19 grafo. setanterior ( contador_universal , recupera );// vai
ajudar para caso de retroceder afim de verificarse existe bifurcacao
20 }// fim do while21 // return false;
92 APÊNDICE H. Gerenciador de regras
22 while ( regras . direita_negacao ( recebe ) != null) {23 String aux = regras . direita_negacao ( recebe );24 grafo. armazena (aux , recebe );// insercao no grafo25 recebe = aux;26 int recupera = contador_universal ;27 contador_universal ++;28 grafo. setanterior ( contador_universal , recupera );29 }// fim do while30 // regras a direita31 if (grafo. posicao ( contador_universal ). getelemento_grafo ()
. charAt (grafo. posicao ( contador_universal ).getelemento_grafo (). length () - 1) != ’|’ &&verifica_usar_regra_or_direita (grafo. posicao (contador_universal ). getelemento_grafo ())) {
32 this. armazem_regra_or_direita ();33 }// fim do if%34 // olha se a prova esta completa , neste caso como nao ha
bifurcacao ja pode afirmar q ha uma consequencia logica35 if ( provou (grafo. posicao ( contador_universal ))) {36 return true;37 }// fim do if38 // exaustao afim de esgotar o lado direito39 String nega_direita = regras . direita_negacao (grafo.
posicao ( contador_universal ). getelemento_grafo ());40 String nega_esquerda = regras . esquerda_Negacao (grafo.
posicao ( contador_universal ). getelemento_grafo ());41 boolean or = verifica_usar_regra_or_direita (grafo. posicao
( contador_universal ). getelemento_grafo ());42 // enquanto tiver apto a realizar a derivacao43 while ( nega_direita != null || nega_esquerda != null ||
or) {44 this. dois_passos (grafo. posicao ( contador_universal ).
getelemento_grafo ());45 if (or) {46 this. armazem_regra_or_direita ();// armazena a
regra a direita no grafo47 }48
49 nega_direita = regras . direita_negacao (grafo. posicao (contador_universal ). getelemento_grafo ());
50 nega_esquerda = regras . esquerda_Negacao (grafo. posicao( contador_universal ). getelemento_grafo ());
93
51 or = verifica_usar_regra_or_direita (grafo. posicao (contador_universal ). getelemento_grafo ());
52
53 if ( provou (grafo. posicao ( contador_universal ))) {54 return true;55 }// fim do if56 }// isso while fará57
58 // ********** segunda parte trabalhando com o ladoesquerdo ******************
59 //o metodo ou a esquerda retorna um vetor de 3 posicoesonde a ultima posicao equivale a formula passada
60 int sentinela = -1;61
62 // **************************** atencao especial*********************************
63 while ( contador_universal != -1) {//se contador universalchegar em -1 chegou ao fim
64 if ( contador_universal == sentinela ) {65 break;66 }67 sentinela = contador_universal ;// sentinela e usado
para comparar se continua no mesmo no , isso evitade entrar em loop infinito
68
69 // tentar repetir os passos de70 if ( finaliza == 1) {71 nega_direita = regras . direita_negacao (grafo.
posicao ( contador_universal ). getelemento_grafo ());
72 nega_esquerda = regras . esquerda_Negacao (grafo.posicao ( contador_universal ). getelemento_grafo ());
73 or = verifica_usar_regra_or_direita (grafo. posicao( contador_universal ). getelemento_grafo ());
74
75 // enquanto tiver apto a realizar a derivacao76 while ( nega_direita != null || nega_esquerda !=
null || or) {77 if ( provou_lado_esquerdo (grafo. posicao (
contador_universal ))) {78 //se ele retornar true e pq chegou ao no
94 APÊNDICE H. Gerenciador de regras
inicial79 if (this. calcula_proximo (grafo. posicao (
contador_universal ))) {80 return true;81 }82 if ( contador_universal == -1) {// esta no
no inicial83 return true;84 }85 while (this. provou_lado_esquerdo (grafo.
posicao ( contador_universal ))) {86 if (this. calcula_proximo (grafo.
posicao ( contador_universal ))) {//tecnica de retrocesso
87 return true;88 }89 if ( contador_universal == -1) {90 return true;91 }92 }// fim do while93 }// fim do if94
95 this. dois_passos (grafo. posicao (contador_universal ). getelemento_grafo ());
96 if (or) {97 this. armazem_regra_or_direita ();98 }99 nega_direita = regras . direita_negacao (grafo.
posicao ( contador_universal ).getelemento_grafo ());
100 nega_esquerda = regras . esquerda_Negacao (grafo. posicao ( contador_universal ).getelemento_grafo ());
101 or = verifica_usar_regra_or_direita (grafo.posicao ( contador_universal ).getelemento_grafo ());
102 }// isso while fará103 }// fim do if do finaliza104 // estou usando regras aplicadas ao lado esquerdo105 while ( verificar_usar_or_esquerdo (grafo. posicao (
contador_universal ). getelemento_grafo ())) {106 finaliza = 1;
95
107 grafo. posicao ( contador_universal ). setabriu (true);108
109 this. regra_ou_esquerdo (grafo. posicao (contador_universal ));
110
111 // tentar fazer todos os passos novamente112 nega_direita = regras . direita_negacao (grafo.
posicao ( contador_universal ). getelemento_grafo ());
113 nega_esquerda = regras . esquerda_Negacao (grafo.posicao ( contador_universal ). getelemento_grafo ());
114 or = verifica_usar_regra_or_direita (grafo. posicao( contador_universal ). getelemento_grafo ());
115
116 while ( nega_direita != null || nega_esquerda !=null || or) {
117 this. dois_passos (grafo. posicao (contador_universal ). getelemento_grafo ());
118
119 // isso verifica se pode usar o direita120 if (or) {121 this. armazem_regra_or_direita ();122 }123 nega_direita = regras . direita_negacao (grafo.
posicao ( contador_universal ).getelemento_grafo ());
124 nega_esquerda = regras . esquerda_Negacao (grafo. posicao ( contador_universal ).getelemento_grafo ());
125 or = verifica_usar_regra_or_direita (grafo.posicao ( contador_universal ).getelemento_grafo ());
126 if ( provou (grafo. posicao ( contador_universal ))) {
127 //se entrar aqui chegou no no inicial128 if (this. calcula_proximo (grafo. posicao (
contador_universal ))) {129 return true;130 }131
132 if ( contador_universal == -1) {
96 APÊNDICE H. Gerenciador de regras
133
134 return true;135 }136
137 while (this. provou_lado_esquerdo (grafo.posicao ( contador_universal ))) {
138
139
140 if (this. calcula_proximo (grafo.posicao ( contador_universal ))) {
141 return true;142 }143
144 if ( contador_universal == -1) {145
146 return true;147 }148
149 }// fim do if150 break;151 }// fim do if152 }// isso while fará153
154 }// fim do while155 if (this. provou_lado_esquerdo (grafo. posicao (
contador_universal ))) {156 if (this. calcula_proximo (grafo. posicao (
contador_universal ))) {157 return true;158 }159 if ( contador_universal == -1) {160
161 return true;162 }163 while (this. provou_lado_esquerdo (grafo. posicao (
contador_universal ))) {164 if (this. calcula_proximo (grafo. posicao (
contador_universal ))) {165 return true;166 }167 if ( contador_universal == -1) {168 return true;
97
169 }170 }// fim do if171 }// fim do if172
173 }// fim do while174
175 grafo. conteiner [ contador_universal ]. setprovado (’*’);176
177 return false;178
179 }// fim do metodo
Top Related