Você está na página 1de 55

3 ALGUNS ASPECTOS DE

PROGRAMAÇÃO EM
LÓGICA E PROLOG
3.1 - Introdução
A lógica, desde Aristóteles, sempre esteve ligada ao pensamento
científico. Ela constitui a base para deduzir conseqüências a partir de certas
premissas; para estudar a validade ou a falsidade de sentenças dada a
validade ou a falsidade de outras sentenças; para verificar a validade de
argumentações; e para estabelecer a consistência de um conjunto de
sentenças.
Já os computadores surgiram na história há muito pouco tempo, ao
compará-los com a lógica. Quase todos os computadores de hoje em dia são
baseados no modelo (ou máquina) de von Neumann que surgiu na década de
40. Esta máquina é uma concretização da máquina ideal de Alain Turing. A
máquina proposta por von Neumann é constituída por um "grande" conjunto
de células de memória e uma unidade de processamento com algumas células
de memória locais chamadas registradores.
A unidade de processamento pode copiar dados armazenados nas células
de memória para os registradores, realizar operações com esses dados nos
registradores e transferir os resultados de volta para as células de memória.
Um programa para a máquina de von Neumann deverá fornecer instruções
que realizem as operações descritas acima.
O desenvolvimento de computadores baseados na máquina de von
Neumann encontrou muitas limitações tecnológicas e de engenharia que
foram sendo resolvidas através dos anos. Porém, à medida que os problemas
relativos à construção de computadores eram resolvidos, os problemas
relativos a como utilizá-los apareciam. Em outras palavras, os computadores
eram capazes de realizar as instruções fornecidas pelo homem porém o
homem ainda não era plenamente apto a programar os computadores para
resolver problemas práticos que surgiam. A única linguagem disponível na
época era a linguagem específica de cada máquina através da qual o
programador fornecia instruções ao "estilo von Neumann".
A construção de programas escritos em linguagem de máquina era
complexa e tomava muito tempo. A partir daí, linguagens mais fáceis para a
compreensão humana começaram a aparecer: Fortran, Algol e Pascal mas
todas elas apresentavam características marcantes da máquina de von
Neumann subjacente. Notamos que apesar dessas linguagens serem mais
fáceis para a compreensão do homem, elas ainda eram orientadas à máquina,
isto é, o homem contruía programas nessas linguagens pensando em termos
de operações do computador.

3.2 - A proposta da programação em lógica


Seria muito interessante se, ao invés de termos linguagens orientadas
à máquina, tivéssemos linguagens "orientadas ao homem", ou seja,
linguagens que não fossem meras abstrações do modelo de von Neumann
mas que fossem derivadas de um modelo abstrato que não tivesse relação
direta ou dependência com nenhuma máquina.
Felizmente isso foi possível através da lógica. Até o início da década
de 70 utilizava-se a lógica apenas como uma ferramenta para projetar
computadores (mais especificamente para projetar circuitos) e para auxiliar na
construção de programas escritos em Algol ou Fortran . A partir do início da
década de 70, trabalhos de Robert Kowalski propunham a utilização da
lógica diretamente como uma linguagem de programação. A essa nova área da
ciência que nascia, deu-se o nome de programação em lógica. Os programas
contruídos utilizando a lógica diretamente como linguagem de programação
receberam o nome de programas lógicos.
Em termos gerais, a proposta da programação em lógica é a seguinte:
um programa lógico é constituído por um conjunto de axiomas e por um
conjunto de regras de inferência. De posse desse programa podemos fazer
"perguntas" a ele. Essas "perguntas" na verdade são fórmulas as quais
desejamos saber se podem ser deduzidas (ou não) a partir dos axiomas e
regras de inferência contidos no programa lógico. Observando a Figura 2,
temos:

1
O conceito de máquina de Turing apóia toda a Teoria da Computabilidade que contém
problemas em aberto que desafiam pesquisadores do mundo todo.
2
A citada linguagem específica de cada máquina na verdade é a linguagem do
microprocessador com o qual a máquina (o computador) foi construído.
Pergunta: Programa Lógico P
Sim!
A fórmula F pode ser
deduzida a partir dos Axiomas
axiomas e regras de e
inferência de P? Regras de Inferência

Não!

Figura 2: Funcionamento de
um programa lógico.
Em outras palavras, as "perguntas" nada mais são do que fórmulas as
quais desejamos saber se são teoremas na teoria formal fornecida pelo
programa lógico. Essa teoria formal seria constituída pelos axiomas e regras de
inferência do programa lógico.
Dizemos que as "perguntas", que na verdade são fórmulas, as quais
submetemos ao programa lógico constituem a entrada do programa lógico.
Dada uma entrada, dizemos que o processo de tentarmos demonstrar essa
entrada a partir dos axiomas e regras de inferência do programa lógico é a
execução do programa lógico. Esta noção se identifica com a noção de
computação da máquina de Turing.
Paralelamente aos trabalhos de Robert Kowalski, Alain Colmerauer e
seus colegas desenvolveram um programa que capturava a idéia do
mecanismo de tentar provar as "perguntas" (fórmulas) a partir de um conjunto
de axiomas e regras de inferência. Esse programa recebeu o nome PROLOG (do
francês "PROgramation et LOGique"). Mais adiante veremos um pouco sobre
o PROLOG mas antes disso veremos os principais conceitos e ferramentas da
programação em lógica. Para começar, teremos uma seção totalmente
dedicada às cláusulas de Horn pois é através delas que poderemos escrever os
programas lógicos. Depois, teremos uma seção dedicada a exemplos e mais
conceitos ligados aos programas lógicos.
4.3 - Cláusula de Horn
A linguagem que utilizamos para trabalhar com a programação em
lógica é um subconjunto da linguagem do cálculo de predicados vista no
capítulo 3 e recebe o nome de linguagem das cláusulas de Horn. Portanto,
trabalharemos com o cálculo de predicados restrito à linguagem das cláusulas
de Hom.
Esquematicamente, temos:

3 Algol e Fortran eram as linguagens mais famosas até essa época.


Fórmulas do cálculo de predicados

Figura 3: Cláusulas de Horn.

O objetivo desta seção é estudar as cláusulas de Horn de tal modo


que na próxima seção estaremos em condições de utilizá-las para escrever os
primeiros programas lógicos. Para isso, primeiramente destacaremos
algumas das regras que já utilizamos no cálculo proposicional e de
predicados bem como um pouco do jargão da programação em lógica. Depois,
estudaremos as cláusulas de programa e as cláusulas gol (que são os dois
tipos de cláusulas de Horn).
3.4 - Considerações preliminares
O objetivo desta sub-seção é fixar parte do jargão da lógica e de
programação em lógica que utilizaremos daqui em diante.
A toda hora utilizaremos predicados na construção de programas
lógicos. Por isso, apesar de termos definido que apenas letras tais como p, q
com ou sem índices denotam predicados, tomaremos a liberdade de utilizar,
por exemplo,
casados ( x, y)
para denotar que x é casado com y ao invés de
P6(x,Y)
que seria muito menos ilustrativo.
Dizemos que uma fórmula do cálculo do predicados é atômica
quando ela é do tipo
p(ti ,t2,...,t.)
na qual:
· p é um predicado n-ário;
· ti , t2 , ..., t. são termos.
Como exemplos de fórmulas atômicas, podemos escrever:

Exemplos:
1. p(x).
2. q2 (x,y).
0. mãe(y,x).
3. q3(x,y,z).
Podemos dizer que uma fórmula atômica é uma literal positiva. Portanto, os
exemplos dados acima, além de serem exemplos de fórmulas atômicas,
também são exemplos de literais positivas.
A negação de uma fórmula atômica é dita literal negativa. Como
exemplos de literais negativas, podemos citar:
Exemplos:
1. —,q4 (x,y).
2. —itio(y,x).
3. —,q5(x,y,z).
4. —iavó (x,y).
Em programação em lógica, podemos escrever uma implicação do
tipo:
A—>B
de maneira inversa, ou seja,
B <—A

O motivo disso é simplesmente destacar a conclusão da implicação.


Isto ficará mais claro quando estivermos utilizando a regra de resolução que
apresentaremos mais adiante. Ainda com respeito às implicações, diremos
que B é a cabeça e A é o corpo da implicação. Observemos os seguintes
exemplos:
Exemplos:
1. vx vy ( p(x,y) —> q(x,y) ).
Escrita de maneira inversa: vx vy ( q(x,y) <— p(x,y) ).
Cabeça: q(xty).
Corpo: p(x,y).
2. Vx VY Vz ( ( P2 (x,Y,z) A (15 (X,Z) A (11 (Z) ) -> ( (13 (Z) V C14 (X) ) ).
Esc ri t a de m anei ra i nvers a: <- -->x z ((q 3 (z) v
<—(1)2(xY,z)^(15(x,z)AP1(z»).
Cabeça: q3(z)v q4 (x).
Corpo: p2 (xy,z) A (15 (X,Z) A Pi (z).
3. vx vy vz ( ( namorados (x, y) A namorados (34 z)) —> triângulo (x, y, z) ).
Escrita de maneira inversa: vx vy vz ( triângulo (x, y, z) <— (
namorados (x, y) A namorados (34 z))).
Cabeça: triângulo (x, y, z).
Corpo: namorados (x, y) A namorados (y, z).
Observação:
Os predicados acima se referem a pessoas e são definidos da
seguinte maneira:
· namorados(x,y) "x e y namoram";
· triângulo(x,y,z) "x, y, z formam um triângulo amoroso".
4. vx ( ( perto-da-praia(x) A grande(x) )—> casa-boa(x)).
Escrita de maneira inversa:vx (casa-boa(x)<—(perto-da-praia(x) A
grande(x))).
Cabeça: casa-boa(x).
Corpo: perto-da-praia(x) A grande(x).
Observação:
Os predicados acima se referem a casas e são definidos da seguinte
maneira:
· perto-da-praia(x) "x é uma casa localizada perto da praia.";
· grande(x) "x é uma casa grande.";
· casa-boa(x) "x é uma boa casa para morar.".
5. vx vy vz ( ( pai(x,y) A irmãos(x,z) )—> tio(z,x) ).
Escrita de maneira inversa: vx vy vz (tio(z,x) <— ( pai(x,y) A
irmãos(x,z))).
Cabeça: tio(z,x).
Corpo: pai(x,y) A irmãos(x,z).
Observação:
Os predicados acima se referem a pessoas e são definidos da
seguinte maneira:
· pai(x,y) "x é pai de y.";
· irmãos(x,z) "x e z são irmãos.";
· tio(z,x) "z é tio de x".
No decorrer do texto, utilizaremos, basicamente, duas regras de
inferência que vimos no cálculo de predicados de primeira ordem. São elas a
regra de modus ponens e a regra de particularização. Além disso, em alguns
momentos, utilizaremos a contrapositiva de uma implicação confome vista
no cálculo proposicional e de predicados. Eis aqui alguns exemplos de
contrapositivas de implicações:
1. vx ( q(x) —> p(x) ) cuja contrapositiva é: vx ( —ip(x) —> —4(x) ).
Escrevendo a cláusula de maneira inversa, teríamos:
vx ( p(x) <— q(x) ) cuja contrapositiva é:
vx ( —,q(x) <— —ip(x) ).
2. 3x vyvz (( p4 (x,y,z) A q(x) ) —> ( q4 (x,y) v q3 (z))) cuja contrapositiva é:
3x vy vz (—i( q4(x,y) v q3 (z)) —> —,(p 4(x,y,z) A q(x) ) ).
Escrevendo a cláusula de maneira inversa, teríamos:
3x vy vz( (q4(x,y) v q3 (z)) ( p4 (x,y,z) A q(x) ) ) cuja contrapositiva é: 3x
vy vz p4 (x,y,z) A q(x) ) —,(q4 (x,y) v q3 (z))).

3.vx vy vz ( ( pai(x,y) A irmãos(x,z) )—> tio(z,x) ) cuja conft-apositiva é: vx


vy vz (—itio(z,x) —> (pai(x,y) A irmãos(x,z) ) ).
Escrevendo a cláusula de maneira inversa, temos:
vx vy vz (tio(z,x) ( pai(x,y) A irmãos(x,z) ) ) cuja contrapositiva é: vx
vy vz (pai(x,y) A irmãos(x,z) ) —itio(z,x) ).

3.5 - Cláusula
Uma cláusula é uma fórmula (do cálculo de predicados) do seguinte tipo:
vxi , , vxk ( Li v v Lm ) (1)
na qual Li é uma literal positiva ou negativa e x1, xk são as variáveis que
ocorrem em Liv v Lm.
Exemplos: (Cláusulas)
1. v x v y v z ( p ( x ) v q(y,z) v (x,y,z)).
0. vx 1)5 (x).
1. VY Vz —,1)6(Y) v (13(z) ).
2. vx vy ( tio (x) v pai (y) ).
0. vx vz ( maior(x,z) v menor(x,z) v igual(x,z) ).
3. vx ( solteiro(x) v easado(x) v viúvo(x) v divorciado(x) ).
Diremos que a cláusula, tal como escrita em (1) , está no formato
original de disjunção. Porém, para escrevermos os programas lógicos, é
conveniente escrever (1), na notação clausal. Escrever uma cláusula na
notação clausal é reescrevê-la utilizando-se o conectivo de implicação ("<—").
Para entendermos melhor, vamos reescrever a cláusula (1) na notação clausal,
explicitando cada passo:
Passo 1 : Separação das literais positivas e negativas: já que temos a lei
comutativa e associativa para o conectivo de disjunção, podemos escrever
primeiro as literais negativas seguidas das positivas. Deste modo, podemos
reescrever (1) assim:
vxi , , vxk ( (—Bi v v ) v (Ai v v A )) (2)
s r

na qual — B ,
1 — B s são as literais negativas e Á , 1 A são as literais
r

positivas.
Passo 2 : Aplicação das leis de De Morgan: observemos que em (2) temos
uma disjunção de literais negativas, a saber, —B v v —B . Através das leis de
1 s

De Morgan, podemos escrever que:


( —B i v v — B ) 4 — > — , ( B . . . B s ).
s
Então, podemos escrever (2) da seguinte maneira: vxk
(—, (Bi A ... A B ) v (Ai v ... VÁ ) (3) Passo 3 :
s

Formato de implicação: Lembremos que:


(24—> B)<-> (—A v B)

e, portanto, podemos escrever (3) do seguinte modo:


vxi , ... , vxk ( (Bi A ... A B )—> (A v ... v Ar ) ) (4)
s i

Passo 4 : Notação Clausal: Conforme vimos na sub-seção 4.3.1 podemos


escrever (4) de maneira inversa:
vxi , ..., vxk ( (Ai v ... v Ar) <— (Bi A ... A B )) (5)
s

Observação:
· Todas as variáveis que ocorrem nas literais componentes de (5) estão
quantificadas universalmente : então, se não escrevermos "vxi ,..., vx2"
não tem problema pois já saberemos que todas as variáveis que ocorrem em
(5) já estão quantificadas universalmente;
· O corpo de (5) é composta de uma conjunção de literais: então ao
invés de escrevermos o conectivo "A" poderemos escrever uma vírgula (",")
e não haverá perigo de confusão;
· A cabeça de (5) é composta de uma disjunção de literais: então ao
invés de escrevermos o conectivo "v" poderemos escrever uma vírgula (",")
e não haverá perigo de confusão.
Com isso em mente, podemos escrever (5) da seguinte maneira:
A i, . . . , A r< — B i, . . . , B s (6)
e dizemos que (6) está escrita na notação clausal.
Dizemos que uma cláusula tem corpo vazio se não possui literais
negativas no formato original de disjunção. Dizemos que uma cláusula tem
cabeça vazia se não possui literais positivas no formato original de disjunção.
Vamos fazer alguns exemplos de escrever cláusulas nesta notação
através dos passos vistos anteriormente?

Exemplos:
1. cláusula vx vy ( p(x) v q(x) v —42(x,y) ).
Passo 1: Separação de literais: vx vy ( —42 (x,y) v (p(x) v q(x)) ).
Passo 2 : Aplicação das leis de De Morgan: como só há uma literal negativa,
não precisamos aplicar.
Passo 3 : Formato de implicação: vx vy ( q2 (x,y) —> (p(x) v q(x)) ).
Passo 4 : Notação clausal: p(x), q(x) <— q2(x,y).

Vamos examinar mais um exemplo no qual ocorra mais literais


negativas para que possamos aplicar as leis de De Morgan.
2. cláusula xv y Vz V( P2 (x,Y) v —,q1(x) v p3 (x,y) v —,q3(z)).
Passo 1: Separação de literais: vx VY Vz ( (-41 (x) v —43 (z)) v (p2 (x,y) v p3
(x,z)) ).
Passo 2: Aplicação das leis de De Morgan: vx-v y vz(—,(qi (x) A q3(z)) v (P2 (x,
y)v p3(x,z))).
Passo 3: Formato de implicação: vx vy ( (qi (x) A q3(z))—> (p2(x,y) v p3 (x,z))
).
Passo 4: Notação clausal: p2 (x,y), p3(x,z)<— q1 (x), q3(z).

3. cláusula vxv yv z( —ipai(y,x) v —iirmão(y,z) v tio(z,x) ). Passo


1: Separação de literais: vx vy vz ( (—ipai(y,x) v —iirmão(y,z)) v tio(z,x) ).
Passo 2 : Aplicação das leis de De Morgan: vx v y vz (—i( pai(y,x) A irmão(y,z) )
v tio(z,x)) .
Passo 3 : Formato de implicação: vx vyv z ( (pai(y,.,,c) A irmão(y,z)) —>
tio(z,x)).
Passo 4 : Notação clausal: tio(z,x) <— pai(y,x), irmão(y,z).

Observação:
A notação clausal é compacta e muito conveniente. A seguir,
estudaremos alguns tipos especiais de cláusulas.

3.6 - Cláusula de Programa


Dizemos que uma cláusula é uma cláusula de programa se:

· Possuir apenas uma literal na cabeça: conseqüentemente, no formato


original de disjunção, a cláusula de programa possui apenas uma literal
positiva;
· O corpo pode ou não ser vazio.
O formato de uma cláusula de programa pode ser:
A <— B1, ... ,B (corpo não vazio)
OU

A <— (corpo vazio)

Vejamos alguns exemplos de cláusulas de programa:


Exemplos:
1. p(x)<—q(x), r(x);
2. r(y)<— ;
3. gripe(x) <— febre(x),mal-estar(x).
4. q(x)<—qi (x,y), q2(x,z);
5. q3(z)<— ;
6. festa-ruim(x)<— pessoal-chato(x),comida-ruim(x);
0. aprovado(x)<— media-maior-sete(x),presença-ok(x);
8. r1 (x,y,z) <— r2 (x,y),r3(y,z),r4 (z,w);
9. q3 (x,y,z,w)<— .

4.7 - Cláusula de Programa Condicional.


Dizemos que uma cláusula de programa é condicional se:
· O corpo da cláusula tiver pelo menos uma literal: conseqüentemente, no
formato original de disjunção, a cláusula de programa condicional contém
pelo menos uma literal negativa e
· A cabeça da cláusula tiver exatamente uma literal: conseqüentemente, no
formato original de disjunção, a cláusula de programa condicional contém
exatamente uma literal positiva.
O "jeitão" das cláusulas de programa condicionais é o seguinte:
il<—Bi,...,B..
Podemos interpretá-la do seguinte modo:

"Para toda atribuição de valores às variáveis que ocorrem na cláusula, seBi ,


B2, ... , B. são todas verdadeiras então A é verdadeira."
Vejamos alguns exemplos de cláusulas de programa condicionais:

Exemplos:
1.) Veja os exemplos 1, 3, 4, 6, 7 e 8 da definição 5.3.3;
2.) p2 (x)<—p3 (x), q2 (y): Podemos ler esta cláusula do seguinte modo: "Para
toda atribuição de valores às variáveis x e y, se p3 (x) e q2 (y) forem ambas
verdadeiras então p2 (x) também o será";
3. q1 (x)4—r2 (x,y), rs (y,z), p3 (x,y): Podemos ler esta cláusula do seguinte
modo: "Para toda atribuição de valores às variáveis x, y e z, se r2 (x,y), rs (y,z) e p3
(x,y) forem verdadeiras ao mesmo tempo, q1 (x) também o será";
0. p3 (x)<—q2 (x,y,z): Podemos ler esta cláusula do seguinte modo: "Para toda a
atribuição de valores às variáveis x, y e z, se q2 (x,y,z) for verdadeira então p3
(x) também o será.
1. tio(z,.,,c)<—pai(y,.,,c),irmão(y,z): Podemos ler esta cláusula do seguinte modo:
"Para toda a atribuição de valores às variáveis x, y e z, se pai(y,x) for verdadeiro
( "se y for pai de x") e irmão(y,z) também o for ("se y for irmão dez") então
tio(z,x) também o será ("z é tio de x").

Agora vejamos o caso em que as cláusulas tem o corpo vazio pois


ela recebem uma denominação especial.
4.8 - Cláusula de Programa Incondicional
Dizemos que uma cláusula de programa é incondicional se:
· O corpo dela for vazio: conseqüentemente, no formato original de
disjunção, a cláusula de programa incondicional não contém literais negativas
e
· A cabeça dela contiver exatamente uma literal: conseqüentemente, no
formato original de disjunção, a cláusula de programa incondicional contém
exatamente uma literal positiva.
O "jeitão" das cláusulas de programa incondicionais é o seguinte: Á
—.
Isso, na forma original de disjunção, é o seguinte:

xi,..., xicil (7)


na qual x1,...,xk são as variáveis que ocorrem na literal A. Podemos interpretar
(7) do seguinte modo :

"Para toda atribuição de valores às variáveis da cláusula, A é verdadeira."

As cláusulas de programa incondicionais são também chamadas de


cláusulas unidade ou cláusulas com antecedente vazio. Alguns exemplos
nos ajudarão a entender melhor a idéia das cláusulas de programa
incondicionais.
Observações:
1. exemplos 2,5 e 9 da definição 4.3.3;
0. q2 (x)<— e podemos ler esta cláusula do seguinte modo: "Para toda a
atribuição de valores à variável x, q2 (x) é verdadeira";
1. r2 (x,y,z)<— e podemos ler esta cláusula do seguinte modo: "Para toda a
atribuição de valores às variáveis x, y e z, r2 (x,y,z) é verdadeira";
0. p7(x,y,z,w)<— e podemos ler esta cláusula do seguinte modo: "Para toda
atribuição de valores às variáveis x, y, z e w, p7(x,y,z,w) é verdadeira";
1. p(x,y,z)<— e podemos ler esta cláusula do seguinte modo: "Para toda
atribuição de valores às variáveis x,y,z,p(x,y,z) é verdadeira";
0. respira(x)<— e podemos ler esta cláusula do seguinte modo: "Para toda
atribuição de valores à variável x, respira(x) é verdadeira" ( todo humano
respira! );
Notemos que cláusulas de programa (tanto as condicionais quanto as
incondicionais) podem ser encaradas como axiomas. Também notemos que
as regras apresentadas na sub-seção 4.3.1 podem ser encaradas como regras
de inferência.
Isso parece com algo que já vimos! Se tivermos axiomas e regras de
inferência, podemos falar em teorias formais axiomáticas e podemos deduzir
(pelo menos, tentar!) fatos dessa teoria. Dada uma teoria formal axiomática T,
formada por axiomas (cláusulas de programa) e por regras de inferência
(subseção 4.3.1) e dada uma fórmula F, podemos tentar demonstrar F em T.
A seguir, começaremos a ver como podemos tentar demonstrar uma
dada fórmula F a partir de T tal como descrita acima.

3.9 - Cláusula gol 4


Dizemos que uma cláusula de programa é uma cláusula gol se:
· A cabeça é vazia: conseqüentemente, no formato original de disjunção, a
cláusula gol não contém literais positivas e
· Contiver pelo menos uma literal no corpo: conseqüentemente, no formato
original de disjunção, a cláusula gol contém pelo menos uma literal negativa.
Uma cláusula gol, portanto, tem o seguinte formato: <
— Bi , B2 , ..., B.. (8)
Suponhamos que as variáveis que ocorrem em (8) são y1,
Podemos escrever (8) no formato original de disjunção do seguinte modo:
vyi , ..., vyr ( —Bi v ... v —B ) (9)
.

Pelas leis de De Morgan, sabemos que:


(—Bi v ... v —B .) <4 —,(Bi A ... A B .).
e podemos escrever (9) da seguinte maneira:
vyi , ..., vyr —, (Bi A ... A B.)
(10).
Sabemos que:
(vx —A) <4 (—, 3x A) (11)
e, então, podemos escrever (10) da seguinte maneira:
—, ( 3yi , ..., 3yr (B A ... A B )) (12).
1 .

Para entendermos melhor o que significa uma cláusula gol, vejamos os


seguintes exemplos:
Exemplos:
1. <— p(x) que é o mesmo que escrever : —, ( 3x p(x) );
2. <— p(x), q(y) que é o mesmo que escrever : —, ( 3x 3y p(x) A q(y) );
3. <— p1 (x), q2 (x,y), r3 (x,y,z) que é o mesmo que escrever: —, ( 3x 3y 3z p1 (x) A
q2(x,y) A r3 (x,y,z));

4
do inglês "goal clause" A palavra goal podde ser traduzida também como meta
porém preferimos a palavra gol por ser mais "familiar"
4. (x,y,z,w), r6 (x) que é o mesmo que escrever: ( 3x 3y 3z 3w
<— p2 (x,y,z), qs

qs (x,y,z,w) r6 (x)).
p 2 (x,y,z)

0. <— q3(x,y,z) que é o mesmo que escrever: ( 3x 3y 3z q3(x,y,z));


0. <— gripe(x) que é o mesmo que escrever: —ax gripe(x);
1. <— pai(x,y) que é o mesmo que escrever: —,(3x 3y pai(x,y) ). Surge, então, a

pergunta:

Será que o fato de cláusulas gol serem, no fundo, negações contribui para
alguma coisa???
A resposta é "Sim". Ainda bem!
Geralmente, quando temos uma teoria formal axiomática T e uma
fórmula F e desejamos saber se há uma demonstração para F em T, um dos
procedimentos a tomar é admitir como hipótese que —Fé verdadeira. A partir
daí, utilizando os axiomas e regras de inferência de T, tentamos obter alguma
fórmula que seja a negação de algum axioma de T. Se conseguirmos
demonstrar uma fórmula que seja a negação de algum axioma de T, isso quer
dizer que —F é falso e, portanto, F pode ser demonstrada em T. A esse tipo de
demostração damos o nome de demonstração por redução ao absurdo.

3.10 - Cláusula vazia


A cláusula vazia, denotada por, Llé a cláusula de programa sem
corpo e sem cabeça (isso mesmo!). Deve ser interpretada como uma
contradição. Para entender melhor a cláusula vazia, consideremos o seguinte
exemplo do cálculo proposicional: se tivermos 241, 242, ..., A., B letras do
cálculo proposicional e considerar B a disjunção 24 1 v v A ., B assumirá
valor verdade 1 se algum dos A i assumir valor verdade 1. Em outras
palavras, basta que um Ai assuma valor verdade 1 para que B assuma valor
verdade 1. Agora imaginemos que não temos Ai algum para compor a
disjunção. Logo,
B sempre assumirá valor verdade O, ou seja, B será uma contradição.
A cláusula vazia ( ) nos ajudará a indicar quando conseguimos refutar a
negação de uma fórmula F numa teoria formal axiomática T fornecida por um
programa lógico.

3.11 - Cláusula de Horn


Uma cláusula de Horn é uma cláusula de programa ou é uma cláusula
gol.
A seguir, vejamos alguns exemplos de cláusulas de Horn:
Exemplos:
1. todos os exemplos da seção 4.3.3;
159
2. todos os exemplos da seção 4.3.4;
3. todos os exemplos da seção 4.3.5;
0. q(x)<— p(x), p2 (x,y,z), (x,z,y);
4. avô(z,x)<— pai(z,y), pai(y,x).

O que temos até agora.


Após examinarmos várias definições, chegou o momento de dar
uma pausa e examinarmos, sucintamente, as ferramentas que temos até agora.
Voltando à Figura 1, podemos detalhar o conjunto das cláusulas de
Hom da seguinte maneira:

Cláusul2s de Hom
Figura 4: Tipos (1? cláusulas de Hom.
Cláusulas de Programa
Podemos, ainda, delall-mi-
Cláusulas Gol

Cláusulas dc Horn
Cláusula
Figura dc Programa
5: Tipos Incondicionais
de cláusulas de Horn.

Na próxima seção, utilizaremos todos estes tipos de cláusulas de


Cláusulas Gol :láusula!•; de Programa Condicionais
Horn para construir alguns programas lógicos, porém antes disso, alguns
exercícios.

Exercícios
1) Escreva as seguintes implicações na notação clausal.
a) vx ( p(x) s(x) —> q(x) v r(x) ).
0) Vx VY (x,Y) A P2 (x,Y) —> P3 (x,Y) v P4 (x,Y) ).

160
í 9 í

.soo!N)I sumuffloid op ouSuindmoo


'e moo sopuuo!oujoi solpouoo salino sun4c somonpmso `soidmoxo
sosso s9dv Teuuojui ui!ouum umn op soo09I sumuffloid op soidmoxo sun4c
Jupmso somun oluommom! `oinui. und .somsom sop ouSuindmoo 'e und
sopoiám omoo moq so49I sumuffloid J!znpo.pui á ovos ulsop ted!ougd
()Ag° ko o .uo!N)I mo ouSumuffloidup suo!sug suluomu.uoj sup mim mompsuoo
onb moH op suinsnujo su sompinso ovos utmlin ut\I
·supoa a so31291 sutuu.i2o.id - zi.£
(iç`z)soyttu!`(x`z)lud —> (X`x)oqupclos
.(x)fr.i `((f`x)vb `(z`m.`x)vd —> C!
.—> (m.‘z`if`x)z.i (II
.(z‘m.‘x‘it)9b `(z`x)d -3( .
(z‘x)9b —> (x)9b `04.`9vb 04.`zx)zb (.
.(z`x)s `((f`x).1 —> (z`x)b Co
.(z`i(`x).1 '((t)b —> (x)d Cp
*—> Q9s Co .
(x‘41 ‘(z‘i)b `(x)d —> (•g
` r` r
O f —> J `Crig Cu
.io no s!uuo!o!puoom `s!uuo!o!puoo suinsnujo
os os -!1) mácimui .sup!monuo SiOAVinA SU M o z`iç`x onp!suop .ouSunfs!p op
juu! !.10 uuuoj uu su-unoioso 'moi{ op suinsnujo sowOos su supuG (17
.( (z`x)upu4sa <— ( (z`iç)upu4sa v (iç`x)upu4sa ) ) xA ffi
.( (x)uniotunaud <— ( (x)uAn43-uttu4 v (x)adp2 ) ) xA (j
.( ((f)s A (x)J A (z`x)b <— (z`x)d ) zAifAxA (o
.( (z'it» <— (z‘x)s v (x).1 ) ifAxA (p
.( (iftb A (z)9b <— (x)8d v (zx)Ld ) zAifAxA (o
A ((O% <— (x)i'd v (if`x)'d v (x)9d ) ifAxA (g
.( (x)9b A (x)lb <— (x)d v (x)zd v (x)Id ) xA(u
lusnujo ou_Suiou uu sogSumdm! sow!nos su unonsH (£

—>( .
(it'xfil (zx)zb —> (it'z'x)lb (j
.—> (zx)zb (o
.(z‘x)s `(z`x).1 —> (p
.(z`if`x)s `((f`x).1 —> (x)b (o
.—>(x)d (g
' 3 'ff —> f r
.sup!monuo SiOAVinA SU Z 'iç `X 0.10MSUOD 'ouSunfs-g) op
juu! !.10 uuuoj uu su-unoioso 'moi{ op suinsnujo sowOos su supuG (z
.( (x)odtuuJus <— ( (x)suffiattuaA-smpuutu v (x)a.maj ) ) xA (
.( (iç`z)gAu <— ( (x`z)md v (iç`x)md ) ) zA içA xA (j
.( (z`x)vd A (it)b <— (z`x)b v (z`i9.1 v (x)d ) ifAxA (o
A (x`z)zb <— (z`x)b v (z`x)d ) zA (CA xA (p
.( (z‘if‘x)9b <— (if`x)9b v (x) lb ) zA (CA xA (o
4.13 - Programa Lógico
Um programa lógico é um conjunto finito de cláusulas de programa.
Vejamos alguns exemplos de programas lógicos:
Exemplos:
1 .)- Programa Pl.
(1) p(a)<—.
(0) q(b) <—.
(1) q(x)<— p(x).

2.) - Programa P2.


(1) p(a,b)<—.
(2) q(a,b)<—.
(0) r(x ,y)<— p(x,y).
(3) s(xty)<— q(y,x).

3.) - Programa P3.


(1) p(a,b) 4—.
(2) q(b,c) 4—.
(0) r(x,z) <— p(x,y), q(y,z).

4.) - Programa P4.


(1) p(x)<— p(x).
(2) p(a) 4—.
(0) q(c) 4—.
(1) P(b)<—.
Daqui em diante, em nome da simplicidade, escreveremos
"programa" ao invés de "programa lógico".

Comentamos na seção anterior que um programa é constituído por


um conjunto finito de axiomas sobre os quais podemos aplicar modus ponens e
particularização (4.3.1) como regras de inferência. Observemos o programa Pi
do exemplo 1 acima.
Podemos dizer que:
· p(a) é axioma;
· q(b) é axioma;
· Para todo x, se —4(x) é verdadeiro então —ip(x) é verdadeiro.
Estranho! Ao invés de escrever "para todo x, se p(x) é verdadeiro
então q(x) é verdadeiro" conforme a linha (3) de P i, escrevemos a sua
contrapositiva. Bem, não há nenhum problema pois a cláusula de programa
escrita na linha (3) e a sua contrapositiva são logicamente equivalentes. O
motivo por havermos escrito a contrapositiva ficará mais claro adiante.

162
Juntamente com esses três axiomas, podemos considerar:
· A regra de modus ponens e
· A regra de particularizaçã o.
Notemos que com esses cinco itens, temos uma teoria formal
axiomática fornecida pelo programa Pi. Então, dado qualquer programa,
podemos construir uma teoria formal axiomática a partir dele de acordo com a
Figura 6 e dizemos que essa teoria formal axiomática foi fornecida pelo
programa.

Programa P

Cl. Prog. lncond. 1


Cl Prog. Incond. 2
Cl. Prog. lncond. 3

CI.Prog. !cond.
Cl. Prog.
Cond. 1
Cl. Prog. Cond.2
Cl. Prog. Cond3

CI. Prog. Cond.k

Figura 6: Construção de uma teoria formal axiomática a partir de um


programa.

Podemos demonstrar teoremas na teoria T acima. Dada uma fórmula


atômica F de T, por exemplo, podemos tentar demonstrar F em T. A fórmula F,
neste caso, é chamada de consulta ao programa P. Se F for teorema em T
dizemos que F foi deduzida a partir do programa P.

3.13 - Computação de gols


A computação de um gol consiste em tentarmos provar que uma
consulta a um programa é um teorema na teoria axiomática que o programa
fornece, tal como na Figura 6. No nosso texto, vamos só considerar as
consultas que são fórmulas atômicas ou fórmulas que são conjunções de
fórmulas atômicas. A seguir, descrevemos um método para computar gols
que utiliza a idéia da demonstração por absurdo. Dado um programa P e uma

163
consulta F, podemos executar os seguintes passos para verificar se F pode
ser deduzida a partir de P:
Método para computação de gols:
Passo 1: construção de T: construimos T conforme a Figura 6;
Passo 2 : construção do gol F': a partir de F, construimos o gol F' <— F.
Notemos que F' é a negação de F, conforme a seção 4.3.6;
Passo 3 : obtenção de contradição: assumimos F'como verdadeira em T e
tentamos demonstrar através dos axiomas e das regras de inferência de T que
a cláusula gol F' implica em uma contradição em T (computação de gols via
demonstração por absurdo).
Passo 4 : término da computação : se conseguirmos deduzir que F' implica
em uma contradição, conseguimos provar que F é um teorema em T que é o
mesmo que dizer que F foi deduzida a partir de P.
Caso contrário, se ao longo da tentativa de deduzir uma contradição
obtivermos uma fórmula F" tal que:
· F" não está na lista de axiomas ou
· Não podemos aplicar regras de inferência em F" e mais outro axioma
então dizemos que F não é um teorema de T e, portanto, F não pode ser
deduzida a partir de P.
Agora ficou mais claro porque chamamos de computação de gols o
método de tentar provar teoremas na teoria T fornecida pelo programa P:
simplesmente porque construímos uma cláusula gol com a consulta F
"candidata" à teorema em T. De acordo com o passo 2 do método acima, F' é a
negação de F. De acordo com o passo 3, tomaremos F' como verdadeira e
utilizaremos os axiomas e regras de inferência para tentar deduzir uma
contradição. Também dizemos que a computação do gol F' foi bem sucedida.
Sem mais discussões, vamos dar uma olhada nos exemplos da
subseção anterior. Tínhamos o programa P1 do exemplo 1 que
transcrevemos:
Exemplos:
Exemplo 1) - Programa Pl.
p(a) <—.
q(b) <—. q(x)<
— p(x).
Seguindo o passo 1 do método descrito acima, temos a seguinte
teoria fornecida por P1:
Teoria T1.
Axiomas:
(A1). p(a) <—
(A0).«h) <—
(A1).( —,q(x) —> —ip(x))
Regras de inferência:

164
• Modus ponens; •
Particularização.
Ok! Agora, consideremos algumas consultas a Pl. Para computar gols, vamos
utilizar o método descrito acima.
Consulta 1 - F p(a).
Passo 1: Teoria T1 já foi construída;
Passo 2: Podemos construir a cláusula gol F' 4—p(a). Lembremos que a
cláusula gol F' é a negação de F e, portanto, F' —, p(a);
Passo 3: Vamos assumir que F' é verdadeira em T1. Notemos que F' por si
mesma já contradiz (A1). Portanto, F' implica em uma contradição em T1;
Passo 4: Então F é teorema em T1 que é o mesmo que dizer que F foi deduzida a
partir de P1.

Consulta 2- F q(a).
Passo 1: Teoria T1 já foi construída;
Passo 2: Podemos construir a cláusula gol F' <— q(a) que significa —4(a);
Passo 3: Vamos assumir que F' é verdadeira em T 1. Observamos (A1) e (A2) e
não podemos utilizá-los para q(a) (o bom seria que ou (A 1) ou (A2) fosse um
axioma do tipo q(a) e aí já teríamos uma contradição!) porém podemos utilizar o
(A3) com particularização. Temos que:
—4(a) —> —, p(a).
Utilizando a regra de modus ponens, temos:
—,q(a).
—4(a) —> —, p(a).
—, p(a).
Notemos que —p(a) é o mesmo que <— p(a) que é uma nova cláusula
gol. De posse da nova cláusula gol, damos uma nova olhada nos axiomas.
Ao observamos os axiomas de T1, vemos que —p(a) contradiz o axioma (A2).
Portanto, F' implica em uma contradição em P1;
Passo 4: Então, F é teorema em T1 que é o mesmo que dizer que F foi deduzida a
partir de P1.

Consulta 3- F p(b).
Passo 1: Teoria T1 já foi construída;
Passo 2: Podemos construir a cláusula gol F' <— p(b) que significa —, p(b);
Passo 3: Vamos assumir que F' é verdadeira em T1. Olhando para os axiomas
(A1) e (A2) concluimos que não podemos utilizá-los para chegar a lugar
algum com —ip(b). Olhando para o axioma (A3) concluímos que também não

165
podemos utilizá-lo;
Passo 4: Concluimos que F não é um teorema de T1 e, portanto, F não pode
ser deduzida de P1.
Vamos dar uma olhada no programa P2 do Exemplo 2o qual transcreveremos:

Exemplo 2) - Programa P2.

p(a,b)<—.
q(a,b)<—.
r(x,y)<— p(x,y).
s(x,y)<— q(y,.,,c).
Construindo a teoria T2 associada ao Programa P2 (Passo 1), temos:
Teoria T2.
Axiomas:
(A1) p(a,b) <—
(A2) q(a,b) <—
(A3) vx vy (—ir(x,y) —> —ip(x,y) )
(A4).4-->x <-->y (—s(x,y) —> —4(y) )
Regras de inferência:
· Modus ponens;
· Particularização.
Consideremos algumas consultas a P2.

Consulta 1 - F r(a,b).
Passo 1: Teoria T2 já construída;
Passo 2: Considere a cláusula gol F' <— r(a,b) que significa —, r(a,b);
Passo 3: Vamos assumir que F' é verdadeira em T2. Ao olharmos para os
axiomas de T2 notemos que o único axioma que podemos utilizar é o (A3).
Utilizando particularização em (A3) podemos escrever:
—, r(a,b) —> —, p(a,b).
Utilizando a regra de modus ponens, temos:
—,r(a,b)
—,r(a,b) —> —ip(a,b)

—ip(a,b).
Notemos que —ip(a,b) é uma nova cláusula gol pois é o mesmo que <
— p(a,b). De posse da nova cláusula gol, damos uma nova olhada nos
axiomas. Podemos ver que a nova cláusula gol já contradiz o axioma (A1).
Portanto F' implica em uma contradição em T2;
Passo 4: Portanto, F é um teorema em T2 que é o mesmo que dizer que F foi

166
deduzida a partir de P2.

Consulta 2 - F s(a,b).
Passo 1: Teoria T2 já foi construída;
Passo 2: Considere a cláusula gol F' <— s(a,b) que significa —,s(a,b);
Passo 3: Vamos assumir que F' é verdadeira em T2. Olhando para os axiomas de
T2, não podemos utilizar nenhum deles bem como não podemos utilizar
nenhuma regra de inferência;
Passo 4: Portanto, concluímos que F não é teorema de T2 que é o mesmo que
dizer que F não pode ser deduzida a partir de P2.
Exemplo 3) - Examinemos o programa P4 o qual é o seguinte:
Programa P4.
(A1) p(x)<— p(x).
(A2) p(a) <—.
(A3) P(b) <—.
(A0) q(c) <—.
Construindo a teoria T4 associada ao P4 (através do Passo 1 do
Algoritmo 4.4.2.) ,temos:
Teoria T4.
Axiomas:
(A1) p(x)<—p(x)
(A0) p(a)<—.
(A1) q(c)<—.
(A2) P(b)<—.
Regras de inferência:
· Modus ponens;
· Particularização.
Consideremos algumas consultas a P4:

Consulta 1 - F p(a).
Passo 1: Teoria T4 já foi construída;
Passo 2: Consideremos a cláusula gol F' 4—p(a) que significa —ip(a);
Passo 3: Vamos assumir que F' é verdade em T4. Olhando para os axiomas,
podemos afirmar que —p(a) e o axioma (A2) já se contradizem em T4;
Passo 4: Portanto, F é teorema em T4 que é o mesmo que dizer que F pode ser
deduzida a partir de P4.
Vamos supor que, por algum motivo, não "tenhamos visto" o axioma
(A2) mas sim o axioma (A1): afinal, o axioma (A1) é o primeiro axioma da lista de
axiomas e podemos utilizá-lo. Aplicando particularização em (A1) para x =

167
a, temos:
—p(a) —> —p(a)
e aplicando modus ponens, temos:

Ah! Obtivemos —p(a) que é exatamente a cláusula gol inicial. Sem


problemas! Continuemos a tentar obter uma contradição: devemos dar uma
nova olhada nos axiomas e verificar se podemos utilizar algum deles.
Suponhamos que tenhamos escolhido o axioma (A1) novamente (nem vimos o
axioma (A2)!). Vamos obter —p(a) novamente! Notemos que se insistirmos em
utilizar (A1), não pararemos a computação.
Note que podemos adotar certas estratégias para efetuarmos
computação de gols. Vejamos que utilizar o primeiro axioma que aparece na
lista de axiomas pode ser um mau negócio como vimos no exemplo acima:
mesmo existindo o axioma (A,,) que já resolveria o problema, insistimos em
utilizar o axioma (A1) que nos levaria a uma computação sem término.
Em termos gerais, as computações de gol que fizemos aqui se
resumiram no seguinte (já supondo a teoria fornecida pelo programa):
1. começávamos com uma cláusula gol (que na verdade era uma negação
que assumíamos como verdade);
2. utilizávamos a regra de modus ponens;
3. utilizávamos a regra de particularização que no fundo era a substituição
da variável no axioma por uma constante da teoria fornecida pelo programa;
0. obtínhamos uma nova cláusula gol que geralmente era originária da
aplicação de modus ponens.
Com isso em mente, podemos dizer que para uma computação (finita
ou infinita):
· Temos uma seqüência CO3C1,... (finita ou infinita) dos axiomas da
teoria (fornecida pelo programa) que são usados. Notemos que um axioma
pode aparecer várias vezes nesta seqüência, porém, podem estar
particularizados para constantes distintas;
· Temos uma seqüência Go, G1,... (finita ou infmita) de cláusulas gol
que vão sendo obtidas a partir das regras de inferência;
· Temos uma seqüência So, (fmita ou infinita) de substituições
decorrentes das particularizações.
Na seção 4.6, apresentaremos um novo método de computação de
gols chamado SLD-derivação. Este método vai nos poupar o trabalho de
termos que escrever a teoria fornecida pelo programa e poderemos fazer
consultas a ele diretamente. Além disso, é um método mais rápido e prático. No
entanto, veremos que ao utilizarmos a SLD-derivação estaremos
implicitamente fazendo o mesmo serviço de demonstrar teoremas em uma

168
teoria fornecida por um programa. Antes disso, na seção 4.5 (a próxima
seção) veremos alguns conceitos bem importantes relacionados à SLD-
derivação.

Exemplo 4) Dado o programa abaixo e algumas consultas, escreva a teoria a


ele associada e faça a computação das cláusulas gol também dadas.
Programa P3.
p(a,b) <—.
q(b,c) <—.
r(x,z) <— p(x,y), q(y,z).

Construindo a teoria T3 associada a P3 (passo 1 do Algoritmo 4.4.2. acima),


temos:
Teoria T3

Axiomas:

(A1) p(a,b)<—.
(A2) q(b,c)<—.
(A0) X
VY Vz ( —,r(x,z) —> —, ( 1)(x ,Y) A (1(y,Z) ) )*

Regras de inferência:
· modus ponens;
· particularização.
Vamos fazer algumas consultas a P3.

Consulta 1 - F r(a,c).

Passo 1: Teoria T3 já foi construída;

Passo 2: Devemos construir a cláusula gol F' <—r(a,c). Lembremos, mais


uma vez, que podemos escrever a cláusula F' do seguinte modo: F' —,r(a,c);
Passo 3: Vamos assumir que F' é verdadeira em T3. Olhando para os axiomas,
notamos que podemos utilizar o axioma (A 3). Utilizando tês vezes, em seguida,
particularização, respectivamente, para x = a, y =b e z = c, temos:

—,r(a,c) —> —, (p(a,b) A q(b,c).

Note que a premissa da fórmula acima poderia ser vista como uma cláusula
gol <— ( p(a,b) A q(b,c) ).

Aplicando as leis de De Morgan, na fórmula acima, temos:

169
—,r(a,c) —> (—ip(a,b) v —,q(b,c) ).

Utilizando modus ponens, temos:

—,r(a,c).
—,r(a,c) —> (—ip(a,b) v —,q(b,c))
—ip(a,b) v —,q(b,c).

Notemos que —ip(a,b) e —,q(b,c) contradizem os axiomas (Ai) e (A2) de P3;

Passo 4: Portanto concluímos que F é teorema de T3 que é o mesmo que dizer


que F pode ser deduzida de P3.
Consulta 2- F r(c,a).

Passo 1: Teoria T3 já construída;

Passo 2: Considere a cláusula gol F' 4—r(c,a) que significa —,r(c,a);


Passo 3: Vamos assumir que F' é verdadeira em T3. Olhando para os axiomas ,
mais uma vez, utilizaremos o axioma (A3). Utilizando particularização três
vezes respectivamente para x = c, y = b, z = a, temos:
—,r(c,a) —> —,(p(c,b) A q(b,a) ).
Aplicando as leis de De Morgan na fórmula acima , temos:

—,r(c,a) —> (—ip(c,b) v —,q(b,a) ).

Utilizando modus ponens, temos:

—,r(c,a).
—,r(c,a) —> (—ip(c,b) v —,q(b,a) ).

—ip(c,b) v —,q(b,a).

Notemos agora que de posse de —ip(c,b) e de —,q(b,a) não


encontramos nenhum axioma que possamos utilizar: os axiomas (A 1) e (A2)
são fórmulas base bem como —ip(c,b) e —,q(b,a) e estas últimas duas fórmulas
não contradizem (A1) e (A2). Não podemos aplicar o axioma (A3) pelo mesmo
motivo: pelo fato de —ip(c,b) e —,q(b,a) serem fórmulas base. Não obtivemos
uma contradição e não podemos aplicar nem axiomas e nem regras de
inferência;
Passo 4: Portanto, F não é um teorema de T3 o que é o mesmo que dizer que F
não pode ser deduzida a partir de T3.

170
Exercícios
5) Cada item abaixo contém um programa lógico. Para cada um deles, escreva
a teoria finita associada e faça a computação das cláusulas gol dadas.
a) Programa:

p(x)<—q(x).
q(a)<—.

Consultas: p(a) , p(b) , p(c) , q(a) , q(b) , q(c).


b) Programa:
p(x)<—q(xty),q(y,x).
q(xty)<—r(x,y,z),r(x,z,y),q(y,z).
r(x,y,z)<—s(x,y).
r(xty,z)<—r(y,z),s(y,z).
q(a,a)<—.
q(b,b)<—.
s(a,b)<—.
P(b)<—.

Consultas: p(b) , s(b,a) , s(a,b) , r(a,b,c) , q(a,b) , r(b,a,c).

c) Programa:
p(x)<—p(y),q(xty).
q(xty)<—q(y,x).
q(a,b)<—.
p(a)<—.

Consultas: p(b) , p(a) , q(b,a) , q(a,b).

d) Programa:

p(x)<—p(x).
p(a)<—.
q(a)<—.
Consultas : p(a) , p(b) , q(a) , q(b).

e) Programa:

p(x,z)<—q(xty,z), q(y,x,z).
q(a,b,e)<—.
q(a,c,e)<—.
q(b,a,e)<—.
Consultas: p(a,c) , p(c,a) , q(a,b,e) , p(a,e) , p(e,a).

171
f) Aplicação de programas lógicos em diagnóstico médico:
mal-estar(Pedro)<—. temp-
maior-37(Maria)<—.
bolhinhas(Maria)<—. mal-
estar(Maria)<—. manchas-
verm(Pedro)<—. gland-
inflam(Pedro)<—. febre(x)<—
temp-maior-37(x).
gripe(x)<— mal-estar(x), febre(x).
sarampo(x)<— manchas-verm(x),febre(x).
caxumba(x)<— gland-inflam(x),febre(x).
catapora(x)<— bolhinhas(x),febre(x),mal-estar(x).
Consultas: catapora(Pedro), catapora(Maria), sarampo(Pedro).

3.14 - Substituições e unificadores


Nesta subseção, veremos os conceitos de substituição, unificador e
unificador mais geral. Terminaremos esta subseção apresentando o algoritmo
da unificação que será uma ferramenta importante para a próxima sub-seção
na qual veremos as SLD-derivações.
A idéia de utilizar os unificadores é bem intuitiva: quando
estávamos computando alguns gols na seção passada, nós tentávamos
achar um axioma tal que, particularizado convenientemente, poderíamos
usar modus ponens para esse axioma e para a cláusula gol.
Exemplo:
Se tínhamos uma cláusula gol
—p(a)
e tínhamos um axioma, vx
( —p(x) —> —4(x) )
nós particularizávamos este axioma com a constante a para podermos
aplicar modus ponens depois:
—p(a)
—p(a) —> —4(a) (axioma particularizado) —,q(a).
O que acabamos de fazer pode ser dito da seguinte maneira
utilizando unificadores: "a fórmula —p(a) foi unificada com a fórmula x (
p(x) —> q(x) )" .
O intuito do algoritmo de unificação é fornecer um método mecânico

172
para que alguém possa decidir se duas fórmulas podem ser unificadas ou
não. Além disso, se o algoritmo decidir que as duas fórmulas podem ser
unificadas ele também fornece o unificador mais geral, ou seja, a melhor
particularização possível para o axioma utilizado na computação.
3.15 - Substituição
Uma substituição a ?é um conjunto finito da forma
{ vIt, v21t2, vn/tn }
e
· cada vi é uma variável;
· cada t. é um termo distinto de v •
· as variáveis v1,•n • • ,v são distintas.

Cada elemento vi/ti é chamado de ligação. a

é chamada de :

· substituição base se ; são todos termos que não contêm


variáveis;
· substituição pura de variáveis se os termos ti são todos
variáveis;
· renomeação se os termos ti são todos variáveis distintas.
· substituição identidade quando o conjunto de ligações for
vazio.
Exemplos: (Substituições)
1.a1= { xi/a , x2/xi }
2. a2 = { x2/b , y/x2 , zlxi}
3. a3= { xly , zly}
4. a, = { x/a , y/b , zlx2}
5. a5 = { x3/x2 , x,/y2 , x5/x3 }
6. a6 = { }

4.16 - Instância de uma substituição.


Seja p = vn/tn} uma substituição e E uma expressão. Então a
instância de E por p representada por Ep é a expressão obtida de E
substituindo simultaneamente cada ocorrência da variável vi em E pelo termo
( i = 1,2,...,n). Se El3 não contiver variáveis, então El3 é chamada de instância
base de E.

Exemplos:
1. Considere a expressão Ei p(x ,y) e a substituição p = { x/a , y/b } Temos
que Eil3 p(a,b).
2. Considere a expressão E2 p(x,y) e a substituição 132 = x/a }

173
Temos que E2132 p(a,y).
3. Considere a expressão E3 q2(x,y,z) A q5(x,y) e a substituição p 3 = xly yl
z , z/x }
Temos que E3133 q2(y,z,x) A q5(y,z).
4. Considere a expressão E4 p(x,y) v p5(y,z,x,z2) e a substituição 134= { x/a ,
y/x , z/b , z2/y}
Temos que E4P4 p(a) v p5(x,b,a,y).
3.17 - Composição de substituições
Considere duas substituições a = {ui/si, ..., um/sm} e 13= {vi/ti,
vn/tn}. A composição aP de a eP éa substituição obtida pelo conjunto:
{ui/siP, um/smP, vit.}
de onde devemos retirar as eventuais ligações do tipo: •
ui/siP para as quais ui siP e
{• v./t.
JJ
para as quais v. E 111, ..., }.

Exemplos: (Composição de substituições)


1. Considere as substituições a 1 = { x/y , z/x 2 } e a 2 = { y/c , x 2 /d }
Temos que aia 2 = x/ya2 , z/x2a2 , y/c , x2/d } = { x/c , z/d , y/c , x2/d }

2. Considere as substituições a3 = { x2/z2 ,y2/y3 , z3/xi } e a4 = { y3/b , z2/x2 ,y3/


y
2}

Temos que a2?a, 3a4 = { x2/z2a4 , y2/y3a4 , z3/xia4 , y3/b , z2/x2 , y3/y2 } = =
{ x2/x2 , y2/b , z3/xi , y3/b , z2/x2 , y3/y2 } = = { y2/b
, z3/xi , y3/b , z2/x2 , y3/y2 } =
= { y2/b , z3/x1 , y3/b , z2/x2 }

3. Considere as substituições a5 = { x/y } e a6 = { y/b , z/d }


Temos que a3 asa6 = { x/ya6 ,y/b , z/d } = { x/b , y/b , z/d }

3.18 - Variante
Consideremos duas expressões E e F. Dizemos que E e F são
variantes se existirem substituições a e P tais que E F a e F Ep. Também
dizemos que E é variante de F ou F é variante de E.
Exemplos:
1. Considere as expressões E q(x,y,a) e F q(z,y2,a). E e F são variantes pois
dadas as substituições:
a= { z/x , y 2 /y } e 13?= { x/z , y/y 2 }

t em os q ue F E a e F p .

0. Considere as expressões E p(x 1,x2,x3,b) e F p(x3,x1,x2,b). E e F são


variantes pois dadas as substituições:

174
temos que F E y e E Fp, .

3. Considere as expressões E p 2(x) A q3(y) v q5(x,z) e F q3(x) A p 2(z) v q5(z,y). E


e F são variantes pois dadas as substituições:

a= { z/x ,x/y ,y/z } el3 = { x/z , y/x ,z/y}

temos que F E a e E FI3 .

3.19 - Proposição
Para quaisquer substituições a, 13 e y e uma expressão E, temos que:
(i ) (a13)Y aRy
( ii) (aR)y a(13y)
Demonstração : Exercício 11.4.

4.20 - Substituição mais geral

Considere duas substituições a e Í. Dizemos que a é mais geral que


p se existir uma substituição y tal que ay = I3y.
Como exemplos de substituições mais gerais utilizaremos os
exemplos dados no tópico 4.5.4. Observemos que:

1. a3 é mais geral que a2 poisexiste uma substituição a4 tal que a2a3=a4a3.


2. a5 é mais geral que a3 poisexiste uma substituição a6 tal que a3a5=a6a5.

3.21 - Unificador
Considere duas expressões A e B e uma substituição a. Se tivermos
que Act Ba então dizemos que a substituição a é um unificador de A e B.
Também podemos dizer que A e B são unificáveis.

Exemplos:
Considere as expressões E q(x,y,a) e F q(z,y 2,a) e a substituição a ={ x/d ,
y/e , z/d , y2/e } . Aplicando a substituição em E e F, temos:

Ecc, q(d,e,a) e Fa q(d,e,a).

Notemos que Ea Fa e, portanto, a é um unificador de E e F.

Considere as expressões E p(x,y) A q(y,z) e F p(z,w) A q(x 2 ,x 3 ) e a


substituição p = { x/z , y/w , x2/w , x3/z } . Aplicando a substituição em E e F,

175
temos:

EP p(x,w) A q(w,z) e F? p(z,w) A q(w,z).

Notemos que EP FP e, portanto, 13 é um unificador de E e F.

Considere as expressões E p 2(x,y,z) e F p2(x2,y2,z2) e a substituição a = {


x/x2 , y2/y , z/z2} . Aplicando a substituição em E e F, temos:
Eopt p2(x2,y,z2) e Fa p2(x2,y,z2).
Notemos que Ea Fa e, portanto, a é um unificador de E e F.

3.22 - Unificador mais geral- u.m.g.

Considere duas expressões A eB e um unificador a de A e B.


Dizemos que a é um unificador mais geral (umg) de A e B se for (uma
substituição) mais geral do que qualquer outro unificador de A e B.

Dadas duas expressões E e F, para efetivamente encontrarmos um


umg para elas (caso exista) devemos:
· achar uma substituição a tal que Ea Fa (unificador);
· provar que para qualquer outra substituição 13, a é mais geral que 13
(umg).

Dependendo da substituição, o segundo item pode proporcionar um


certo trabalho! Para evitar isso, o próximo tópico apresenta o algoritmo de
unificação : é um algoritmo determina se duas fórmulas atômicas têm um umg
ou não. Em caso afirmativo, o algoritmo também fornece o umg das duas
fórmulas atômicas. Este algoritmo não unifica expressões em geral uma vez
que o que nos importará é unificar apenas pares de fórmulas atômicas.

4.23 - Algoritmo de unificação


Aqui apresentamos um algoritmo que como entrada recebe um par de
fórmulas atômicas A eB e diz se A e B têm um unificador mais geral ou não. Se
ele disser que A e B têm um umg, o algoritmo também o fornece.
Algoritmo de unificação
Entrada: par de fórmulas atômicas (A , B) .
Saída: "não", se não for possível obter um umg para A e B.
"sim", se for possível obter um umg para A e B além do próprio umg
deA eB.

Passo O: se o símbolo de predicado de A for diferente do símbolo de

176
predicado de B então emitir "não" como saída e parar o algoritmo indicando
uma falha, senão criar uma coleção P constituído por pares de termos (t i, si) (i=
{ 1,2, ..., n } ) tais que C p(ti, t.) e D p(si,..., s.).
Passo 1: escolher aleatoriamente um par (C , D) de P;
Passo 2: se C f(si,...,s.) e D f(ti,...,t.) então remover o par (C , D) de P e
incluir os pares (si,ti), ..., (s., t.) em P e voltar ao Passo 1, senão
Passo 3 : se C f(si,...,s.) e D g(ti,...,tm) então emitir "não" como saída e
parar algoritmo indicando uma falha, senão
Passo 4 : se C D x (x variável) ou C D c ( c constante) então remover o
par (C , D) de P e voltar ao Passo 1, e se C c (constante) e D d (
constante) então emitir "não!" e parar o algoritmo indicando falha senão
Passo 5 : se C t (t termo que não é variável) e D x (x variável) remover o
par (C , D) de P e incluir o par (D , C) em P e voltar ao Passo 1, senão
Passo 6 : se C x (x variável) e D t ( t termo) ex t e x ocorre em algum
par de P
Além disso, se x ocorrer em t, emitir "não"como saída e parar o
algoritmo indicando uma falha, senão substituir cada x pelo termo t em todos os
outros pares de P e voltar ao Passo 1.
Passo 7: se nenhum passo anterior puder ser executado então emitir "sim" e
parar o algoritmo. O umg de A eB é dado pela substituição cujas ligações são
dadas pelos pares (C , D) que pertencem ao conjunto P.
Exemplos: (Utilização do algoritmo de unificação)
Considere Á p(x,y,z) eB q(x,y,z).
Passo O : o símbolo de predicado de A é diferente do símbolo de predicado de
B. Portanto, o algoritmo emite "não!" (pois não é possível unificar A e B) e
pára.
2. Considere Á p(x,y,z) eB q(x2,y2,z5).

Passo O : Os símbolos de predicado de A e de B são o mesmo. Portanto,


criamos a coleção P de pares:

P = { (x , x 2) ; (y , y2) ; (z , z 5) }
Passo 1: Escolhemos o primeiro par (x , x2).

Observemos que:

- não é possível aplicarmos o Passo 2 e o Passo 3 pois não há símbolo


funcional;
- não é possível aplicarmos o Passo 4 pois não temos que x x2;
- não é possível aplicarmos o Passo 5 pois x2 é variável;
- não é possível aplicarmos o Passo 6 pois x não ocorre em outros pares de
P.

177
Notemos que para o par ( x , x2 ) não pudemos fazer muita coisa.
Acontecerá o mesmo ao escolhermos o segundo ou o terceiro par. Notemos
que P permanecerá inalterado e aí teremos:
Passo 7: Portanto, o algoritmo de unificação emite "sim!" e fornece o umg
para A eB é a substituição cujas ligações são x/x2 , y/y2e z/z5.

3. Considere A p(x,g(a,y)) e B p(y,g (a,x)).

Passo O : Os símbolos de predicado de A e de B são o mesmo. Portanto,


criamos a coleção P de pares:

P = { (x,y) ; (g(a,y) , g(a,.,,c) ) } .


Passo 1: Escolhemos o primeiro par (x,y).

Notemos que:

- não é possível aplicarmos o Passo 2 e o Passo 3 pois não há símbolo


funcional;
- não é possível aplicarmos o Passo 4 pois não temos que x y;
- não é possível aplicarmos o Passo 5 pois os dois elementos do par são
variáveis;
Passo 6 : x é variável ey é termo (pois é uma variável). Devemos substituir x
por y em outros pares em que x ocorra. Então temos que:
P = { (x,y) ; (g(a,y) , g(a,y) ) } . e

voltamos ao Passo 1.

Passo 1: já que trabalhamos anteriormente com o par (x,y), vamos escolher o


par( g(a,y),g(a,y) ).

Passo 2: os dois elementos do par têm o mesmo símbolo funcional. Portanto P


fica:
P = { (x,y) ; (a,a) ; (y;y)}

e voltamos ao Passo 1.

Passo 1: escolhemos o par (a,a);

Notemos que não aplicamos o Passo 2 nem o Passo 3 pois não há símbolo
funcional.

Passo 4 : removemos o par (a,a) e P fica:

178
P = { (x,y) ; (y,y)}

e voltamos ao Passo 1.

Ao escolhermos o par (y,y) aplicaremos o Passo 4 novamente e


acabaremos por eliminar o par (y,y) de P. Portanto P fica:
P = { (x,y)} .

Assim, não poderemos mais aplicar nenhum dos 6 primeiros passos e


teremos o
Passo 7 : o algoritmo emite "sim!" e fornece o umg para A e B cuja única
ligação é x/y.

Exercícios Resolvidos.
10.1. Em cada item, dada a substituição ? e a expressão E, obtenha a instância
E??
a) E p(x,y,z2) e a = { x/y } .
b) E q(x,y) A r(x,z) A p(x,y,z) e a = { x/a ,y/b ,z/x } .
c) E q4(x,y,z2) e a = { x/c ,y/d } .
d) E p(x,y,z) e a = { } .
Resolução:
a) Temos que substituir todas as ocorrências de da variável x pela variável y e
teremos Ea p(yy,z2).
0) Substituindo todas as ocorrências da variável x pela constante a, todas as
ocorrências da variável y pela constante b e todas as ocorrências da variável z
pela variávely, teremos que: Ea q(a,b) A r(a,x) A p(a,b,x).
a) Substituindo todas as ocorrências da variável x pela constante c e todas as
ocorrências da variável y pela constante d termos: Ea q4 (c,d,z2).
b) Aqui temos que a não possui nenhuma ligação pois é a substituição
identidade. Temos que Ea p(x,y,z).
10.2. Em cada item serão dadas duas substituições a e Í. Obtenha a
composição de a e 13?
a) a = { x/a , y/b , z/x } e 13 = { ak};
0) a = { y/b , z/x } e 13 = { y/z};
b) a = {x/y,z/y} e 13 = { x/a , y/b} ;
a) a = { xi/z ,y/z } e 13 = { z/c } .
Resolução:
a) Temos que a composição al3= { x/aj3 , y/ bl3 , z/xl3 , ak 13 } = { x/c ,y/b , z/ c ,
a/c };
0) Temos que a composição al3 = { y/b z/x y/z } = { y/b , z/x , y/z } ;
b) Temos que a composição al3 = { x/y z/y x/a , y/b } = { x/b , z/b , y/b };

179
d) Temos que a composição aP = { xi /z y/ z z/ c } = { xi /c , y/c , z/c }.
10.3. Em cada item será dado um par de expressões (E,F). Decida se E e F
são variantes. Se forem, exiba também substituições a e 13 tais que E Fa e
F Ep.
a) E p(x,y,z) e F p(y,z,x).
b) E q(x) e F p(y).
c) E p(x,y,z) A q(x,y) e F q(y,x,z) A q(z ,x).
d) E q(xi ,x2 ) v p(z,w) e F q(x,y) v p(w,z).

Resolução:
a) Temos que E e F são variantes pois tomando as substituições a = { x/y , y/ z ,
z/x } e P={ y/x , z/y , x/z } teremos que Ea FP.
0) Temos que E e F não são variantes pois não existem substituições a e P
tais que Ea FP. Na verdade, o que realmente impede que E e F sejam
variantes é que o símbolo de predicado de E é diferente do símbolo de
predicado de F.
a) Temos que E e F não são variantes pois não existem substituições a e P
tais que Ea FP. Além disso, temos o mesmo problema do item anterior.

b) Temos que E e F são variantes pois tomando as substituições a={ x1 /x, x2 /y


, z/w , w/z } e P = {x/x1 , y/x2 , w/z , z/w } teremos que Ea FP.

10.4. Em cada item serão dados: uma substituição a e duas expressões A e


B. Verifique se a é um unificador de A e B.
a) A p(x,y,z) , B (yi ,w,xi ) e a={ x/a ,y/b , z/w ,yi /a , w/b , xi /w};
0) A q(x,y,f(w)) , B p(w,y,f(w)) e a={ x/a ,y/c };
a) A tio(x,z) A pai(y,w) , B tio(w,zi ) A pai(y,w) e a={ x/b , z/c , y/x ,w/y ,w/ b ,
z1 /c , w/y} ;
Resolução:
a) Aa p(a,b,w) e Ba p(a,b,w). Portanto, Aa Ba e a é um unificador para A
e B;
b) Aa q(a,c,f(w)) e Ba p(w,c,f(w)). Portanto, a não é um unificador de A e
B;
c) Aa tio(b,c) A pai(x,y) e Ba tio(y,c) A pai(x,y). Portanto, Aa Ba e a é
um unificador para A e B;

Exercícios Propostos.
11.1. Em cada item, dada a substituição a e a expressão E, obtenha a
instância Ea.?
a) E p(x,y,z) A q(y,.,,c,z,w) v r(x,y) e a = { x/c, y/x };
0) E pi (x,y,z2) A —,q4(x,y) A r(x,y,z) e a = { z2/x ,y/c , x/y };

180
c) E tio(x,z) A mãe(x) v casados(x,w) e a= { x/z , w/y} ;
0) E casados(x,y) A irmãos(x,w) e a = { y/w , x/a };
d) E irmão(x,y) A irmão(y,z) —> irmão(x,z) e a = { x/y ,y/z , z/x}; O E
pai(x,y) A irmão(x,z) —> tio(z,y) e a = { x/a ,y/b , z/c };
g) E namorados(x,y) A namorados(x,z) —> problema(x,y,z) e a= {x/y
,z/x ,y/ z } ,
0) E p(x,y,z,w) A q(x) e a = { };
h) E q(x) A p(y) e a = { w/y , x2 /a };
i) E p(x,y,z) A q(x,y,z)v r(x,y) e a = { z/a } .
11.2. Em cada item serão dadas duas substituições a e p. Obtenha a
composição de a e 13:?
a) a = {x/a ,y/b , z/x,xi / z} el3 = {x/c,y/z};
b) a = { y/b , z/x , x/y} e 13 = { y/z, x/a} ;
c) a = {y/z,x/y ,z/y} e 13 = { w/c , x/a , y/b} ;
d) a = { x,/z , y/z , z/x , w/x} e 13 = {y/a , z/c };
e) a = { xly y/z , z/w } e13 = {y/w ,x/w ,z/y}; O a = { x2 /x , y2/y , z2 /z } e13 =
{};
g) a = { x/y , y/w} e 13 = { w/x };
h) a = { } e 13 = { };
0) a = { y/w , x/y } e 13= { y/a , z/c } ;
i) a = {wi/w , x2/ x} el3= {xi/ z};
11.3. Em cada item será dado um par de expressões (E,F). Decida se E e F
são variantes. Se forem, exiba também substituições a e 13 tais que E Fa
eFEI3.?
a) E p(x) A q(y) e F p(z) A q(w);
0) E q(x,y,z) e F p(x,y,z);
0) p(xi , x2 , z ) e F (y,z);
a) E pai(x,z) A pai(x,y) e F pai(w,y) A mãe (z,w);
b) E p(x,y,z,)v q(x,y) e F p(wi ,w2 ,w3) v q(xi ,x2);
O E pai(x,z) A irmãos(x,y) e F pai(wi , w) i'. irmãos(x,y);
g) E p(x,y,zi , z2) e F q(x,y,z,w);
h) E filho(x,y) A filho(z,y) e F filho (xi,yi ) A filho (z1 ,y1);
0) E q(y,x) e F q2(x,y,z);
a) E mãe(x,y) v pai(z,y) e F mãe(y,x) v pai(y,z).
11.4 Prove a Proposição 5.
11.5 Utilize o algoritmo de unificação para obter um umg para os seguintes
pares de fórmulas:
a) A p(x,y,z) e B p(f(y) ,w,x);
b)A q(x,y,z) e B p(w,y,z);
c) A q(x,g(y),z) e B q(w,g(y), x1);
d)A p6(x,y,g(x,y)) e B p 6 (w,z,h(w,z));
e) A p4( x,y,z,w) e B p4(x,y,g(x),w));
O A tio(x,y,g(x,y,z) ) e B tio (w1, w2 g ( w1,w2, w));
g) A colineares(x,g(x,y) ) e B colinéares(w,g(w,x) );

181
Programas lógicos e a SLD-derivação.
Nesta seção, apresentaremos o conceito de SLD-derivação.
Conforme já havíamos adiantado anteriormente, este conceito vem a ser um
método de computação de gois tal que não temos a necessidade de escrever a
teoria associada ao programa: as cláusulas gol podem ser diretamente
submetidas ao programa.
3.24 - Resolvente
Seja P um programa lógico e G <— Ai, ..., An uma cláusula gol.
Suponhamos que CÁ <— Bi,...,Bk é uma cláusula de programa de P. Se para
algum i, 1 i n, podemos unificar A e Ai através de um umg a então
chamamos:

G' <— ( ...,Ai-i, B1,..., Bk, Ai+i, ..., An) a

de resolvente de G e C.

Em resumo, o resolvente de G e C vem a ser o produto da unificação do


corpo da cláusula gol e da cabeça de uma cláusula de programa de P.
Podemos escrever um algoritmo para obter um resolvente de uma cláusula G e
de uma cláusula de programa C.
Algoritmo para obter resolventes.

Entrada : cláusula gol G e cláusula de programa C;


Saída : resolvente G' de G e C.
Passo 1: selecionar Ai em G (Ai está no corpo de G);
Passo 2: unificar (se possível) A e Ai através de um umg de A e Ai (podemos
utilizar o algoritmo de unificação). Notemos que A é a cabeça de C;
Passo 3: se tivermos sucesso no Passo 2 então substituir Ai por B 1,..., Bk em
G obtendo uma cláusula gol G";
Passo 4: aplicar o umg obtido no Passo 2 em G" obtendo uma cláusula G'
que é o resolvente de G e C.
Exemplos:
1. Lembra do Programa P1 da sub-seção 4.4.1?

Programa P1.
p(a) <—. (1)
q(b) <— . (2)
q(x) <— p(x) . (3)

e consideremos a cláusula gol G <— q(a).

Se tentarmos unificar q(a) de G com (1) ou (2), obteremos falha, ou

182
seja, q(a) não pode ser unificada nem com (1) (símbolo de predicado é
diferente) nem com (2) (símbolo de predicado é o mesmo mas o argumento que
é uma constante é diferente). A única cláusula de programa que poderá ser
unificada com q(a) é a (3).

Podemos considerar que:


· G <— p(a). e então temos que A1 p(a);
· C q(x) <— p(x) , A q(x) e 131 p(x);
·opt {x/a}.

Agora, aplicando o algoritmo acima para G e C, temos que:


Passo 1: selecionamos A1 p(a) (só temos ele!);
Passo 2 : podemos unificar A1 e A através de a { x/a } que é um umg para A1
e A;
Passo 3 : já que achamos um umg de A1 e A, podemos substituir A1 por B1
obtendo a cláusula gol

G" <— p(x);

Passo 4 : aplicar a em G" e obtemos:

G' <— p(a).

que é o resolvente de G 4—q(a) e de C q(x) <— p(x).

2. Ainda com base no Programa P1, vamos considerar a cláusula gol G <—
p(a). Observemos que G pode ser unificada com a cláusula de programa (1) de
P1.

Podemos escrever o seguinte:


· G <— p(a) e Ai p(a);
· CI p(a) <—, A p(a) e Bi pois o corpo de C é vazio;
· a= { } que é a substituição identidade.

Agora, aplicando o algoritmo para calcular resolventes, temos:


Passo 1: selecionamos A1 p(a) (aliás, só temos ele!);
Passo 2: podemos unificar A1 e A através de a que é um umg para A1 e A;
Passo 3 : já que achamos um umg de A1 e A, podemos substituir A1 por B1
obtendo a cláusula gol

Passo 4 : aplicar a em G" e obtemos:

G'.

183
que é o resolvente de G 4—p(a) e de C p(a) .

Depois de fazer alguns exemplos, podemos notar que obter


resolventes é um modo indireto de aplicar particularização e modus ponens
numa teoria fornecida por um programa sem ter que escrever a teoria
propriamente dita. As demonstrações de teoremas na teoria fornecida por um
programa são feitas indiretamente pelas sucessivas obtenções de resolventes.
Na verdade, a SLD-derivação é justamente isso: ela consiste, grosso modo,
de utilizarmos sucessivamente o algoritmo para obtenção de resolventes para
computar uma cláusula gol.

3.25 - SLD-derivação
Considere um programa P e uma cláusula gol G. Uma SLD-derivação
de P u {G} consiste de:
· uma seqüência (finita ou infinita) G=Go, G1, G2, ... de cláusulas gol;
· uma seqüência (finita ou infinita) Co, C1, C2, ... de cláusulas de
programa de P;
· uma seqüência (fmita ou infinita)?? ?i ?2 ??? de substituições

tais que para i = O, 1, 2, ...

· Gi+1 é um resolvente de G. e Ci;


· ?i é o umg mencionado no Passo 2 do algoritmo para obter
resolvente;
· C. não tem variáveis em comum com G.

Dizemos que uma SLD-derivação é finita quando as seqüências Gi, Ci


e ai são fmitas.Podemos representar através de um esquema gráfico o
processo de SLD-derivação:
Cio = (3 a,

Cn, (In

Figura 7: Esquema de uma SLD-derivaçã o.

184
Existe um jeito muito prático e útil de representar o esquema
acima. Ao efetuarmos um SLD-derivação, podemos representar os gols,
cláusulas de programa e unificadores mais gerais do seguinte modo:
GL, =G Cu

urriga.,
G1

devernos ler este 6 2

trao do seu.uinie látsula de prowdrna Cm- um2


apodo: "a partr escolhkla para unifieacão
Un-':IIn-i e com gol Gn-1
Ct.r_, temos
resolvente Gn.
L
Gri-1

C11-

unvA

cláusula 201 Gn Gn umg para Gn-1 en-1. é


oecsolvente de
Con-1 e Cn-1 pelo 1_______
Figura 8: Modo mais prático de representar uma SLD-derivaçã o.
LIME 01.).

Esse esquema nos permite escrever de uma maneira compacta


e clara a SLD-derivação que estamos construindo. Na primeira linha temos
que o gol Go (à esquerda) e a cláusula Co (à direita) são unificadas através do
umg ai ?ao lado direito na altura do traço)e obtemos o resolvente G i que
escrevemos na linha seguite (à esquerda). Podemos ver que uma SLD-
derivação é (como havíamos adiantado na sub-seção anterior) é a aplicação
sucessiva do algoritmo de obtenção de resolventes. Como na sub-seção 4.4, o
nosso objetivo na SLD-derivação é obter a cláusula vazia.
A seguir, veremos a SLD-refutação que, em poucas palavras, é a
computação bem sucedida de um gol.

3.26 - SLD-refutação
Considere um programa P e uma cláusula gol G. Uma SLD-refutação de
P u {G} é uma SLD-derivação finita de P u {G} que tem a cláusula vazia como
última cláusula gol da derivação. Se Gn = ,dizemos que a SLD-refutação tem
tamanho n. Neste caso dizemos que o gol G foi refutado, ou que a
computação de G foi bem sucedida. Já que uma cláusula gol F' é a negação de
uma outra fórmula F, quando refutamos F', provamos F, ou seja, provamos
que F pode ser deduzida a partir do programa.

185
Na próxima sub-seção, veremos apenas exemplos de programas e
computaremos alguns gols a partir deles utilizando o novo conceito de SLD-
derivaç ão.
Exemplos.
1. O Programa P1 ataca novamente!

Programa P1.
p(a) <—. (1)
q(b) <—. (2)
q(x) <— p(x). (3)
Vamos considerar as mesmas cláusulas gol vistas na sub-seção
4.4.2:

1. <— p(a). De acordo com o algoritmo de obtenção de resolventes, o objetivo é


tentar unificar o corpo da cláusula gol com a cabeça de alguma cláusula de
programa de P1. Notemos que podemos unificar <— p(a) com p(a)<—. Podemos
representar isso através de um esquema parecido com a Figura 8:
<— p(a) p(a) Go <—p(a) e
C0 p(a)<—; umg a = {}

Gi

Notemos que o resolvente é a cláusula vazia pois a cláusula de


programa tem o corpo vazio. Notemos também que já que obtivemos a
cláusula vazia como resolvente e então obtivemos uma SLD-refutação para o
gol <—p(a) e isto significa que p(a) pode ser deduzida a partir de P1. A partir de
agora, quando obtivermos uma SLD-refutação para um gol G, diremos
apenas que refutamos o gol G.
0. <—q(a). O objetivo é tentarmos unificar o corpo da cláusula gol com a
cabeça de alguma cláusula de programa de P 1. Podemos unificar q(a) com
q(x) em (3). Então, representamos:
<— q(a) q(x) <— p(x) G Go <—q(a) e
Co q(x)<— p(x) umg ai ={ x/a}

Gi <— p(a).

E temos uma nova cláusula gol <— p(a). De posse da nova cláusula
gol, damos uma nova olhada nas cláusulas de programa de P 1 e tentamos
unificar o corpo da cláusula gol com a cabeça de alguma cláusula de programa de
P .
1 Escolhemos a cláusula de programa (2) e temos:

<— q(a) q(x) <— p(x) G Go 4 — q ( a ) e C C o

186
q(x) <— p(x)
umg ai ={ x/a}
<— p(a) p(a)<— G1 <— p(a) e C1
p(a) <—
umg a, ={}

Portanto, refutamos o gol 4—q(a).

3. <— p(b). O objetivo é tentar unificar o corpo da cláusula gol com a


cabeça de alguma cláusula de programa de P i. Notemos que não há cláusula
com a qual poderíamos unificar 4—p(b). Neste caso, como não conseguimos
unificar uma cláusula gol com cláusula de programa alguma, não podemos
deduzir p(b) a partir de P1 e portanto temos apenas que G Go 4—p(b) e não
conseguimos refutar G.
Agora, examinemos o não menos famoso Programa P3:
Programa P3.
p(a,b) <—. (1)
q(b,c) <—. (2)
r(x,z) <— p(x,y), q(y,z). (3)

Vamos considerar as mesmas cláusulas gol que estudamos em


4.4.2.

1. <— r(a,c). O objetivo é tentar unificar o corpo da cláusula com a


cabeça de alguma cláusula de programa de P3. Podemos escolher a
cláusula de programa (3) e temos:
<— r(a,c) r(x,z) <— p(x,y), q(y,z). G Go 4—r(a,c) e C Co
r(x,z)<—p(x,y),q(y,z)
ai={x/a, z./ c }
<— p(a,y), q(y,c) G1 4—p(a,y),q(y,c).

Agora temos que unificar p(a,y) e q(y,c) com duas cláusulas de P3.
Ao olharmos as cláusulas de programa de P3, podemos escrever:

<— r(a,c) r(x,z) <— p(x,y), q(y,z). G Go 4—r(a,c) e C Co


r(x,z)<—p(x,y),q(y,z)
ai={x/a, zk }
<— p(a,y), q(y,c) p(a,b) <— Gi 4—p(a,y),q(y,c) C1 p(a,b)<—.
a =
2 { Yib }
<— q(y,c) q(b,c) <— G2 4—q(y,c) C2 q(b,c)<—.
a3={ y/b }
G3.

187
Portanto, conseguimos refutar o gol 4—r(a,c).
2. <— r(c,a). O objetivo é tentar unificar o corpo da cláusula com a cabeça
de alguma cláusula de programa de P3. Podemos escolher a cláusula de
programa (3) e temos:
r(c,a) r(x,z) p(x,y), q(y,z). G Go 4—r(c,a) e C Co
r(x,z)<—p(x,y),q(y,z)
oci={x/a, z/c }
p(c,y), q(y,a) Gi 4—p(c,y),q(y,a).

Agora temos que unificar p(c,y) e q(y,a) com duas cláusulas de


P3.Ao olharmos as cláusulas de programa de P, observamos que não
podemos unificar nem p(c,y) nem q(y,a) com alguma cláusula de P3.
Portanto, não temos uma SLD-refutação para <—r(c,a).

Estudo de caso: relações de parentesco.


Para ilustrar toda essa teoria de programação em lógica, vamos
ver um estudo de caso onde poderemos ver uma das aplicações de
programas lógicos. Através de programas lógicos podemos armazenar
informações sobre as relações de parentesco de pessoas dentro de uma
família. Consideremos, por exemplo, a seguinte árvore de família:

José Maria
Fábio Eduardo Carlos T Mariana

Sônia

Marcos Fátima Adi-lano Cláudia


Mário Paula
Através dos predicados:

· homem(x) "x é do sexo masculino" e


· mulher(y) "y é do sexo feminino"

podemos escrever:

homem(José)<—. (1)
188
homem(Fábio)<—. (2)
(3) homem(Eduardo)<—.
4) homem(Carlos)<—.
(5) homem(Marcos)<—.
(0) homem(Adriano)<—.
(6) homem(Mário)<—.
e
(0) mulher(Maria)<—.
(1) mulher(Sônia)<—.
(0) mulher(Ana)<—.
(0) mulher(Mariana)<—.
(1) mulher(Fátima)<—.
(2) mulher(Cláudia)<—.
(1) mulher(Paula)<—.

Podemos definir os predicados:

pai(x,y) "x é pai de y"


mãe(z,w) "z é mãe de w"
e continuar a escrever:

(3) pai(José,Fábio)<—.
(4) pai(José,Ana)<—.
(5) pai(José,Carlos)<—.
(6) pai(Fábio,Marcos)<—
(7) pai(Fábio,Fátima)<—.

(8) pai(Eduardo,Adriano)<—.
(9) pai(Eduardo,Cláudia)<—.

22)pai(Carlos,Mário)<—.
(23)pai(Carlos,Paula)<—.

(24)mãe(Maria,Fábio)<—.
(25)mãe(Maria,Ana)<—.
(26)mãe(Maria,Carlos)<—.
(27) mãe(Sônia,Marcos)<—.
(28) mãe(Sônia,Fátima)<—.
(29) mãe(Ana,Adriano)<—
(30) mãe(Ana,Cláudia)<—.

(31) mãe(Mariana, Mário)<—.


(32) mãe(Mariana,Paula)<—.

189
Tendo essas relações de parentesco básicas estabelecidas, podemos
construir outros predicados baseados nesses mais básicos. Um exemplo seria
o predicado "irmão". Como poderíamos estabelecer que duas pessoas são
irmãs baseados nos predicados que temos até agora? Uma sugestão seria o
seguinte:
irmãos(x,y) 4—pai(z,x),pai(z,y). (33)

Para duas pessoas x e y serem irmãs, podemos ter que existe uma
pessoa z tal que z é pai de x ez é pai de y. Dizer isto é sufuciente? Considere o
programa P formado pelas cláusulas de (1) até (33). Façamos a seguinte
consulta: irmãos(Mário,Paula). Temos, então, o seguinte gol:
G <— irmãos(Mário,Paula) e

a seguinte SLD-derivação:

4—irmãos(Mário,Paula) irmãos(x,y)<—pai(z,x),pai(z,y)
umg = { x/Mário , y/Paula } 4
—pai(z,Mário), pai(z,Paula) pai(Carlos,Mário)<—
umg = { z/Carlos }

Como a cláusula G foi refutada (obtivemos uma SLD-refutação)


então irmãos(Mário,Paula) pode ser deduzida a partir de P. Portanto, Mário e
Paula são irmãos.
Poderíamos definir outro predicado como, por exemplo, filho(x,y) "x
é filho de y". Poderíamos definir este predicado do seguinte modo:

filho(x,y) <— pai(y,x),homem(x) (34)

que quer dizer : "para que x seja filho de y, y deve ser o pai de x e além disso x
deve ser do sexo masculino". Também poderíamos ter definido o predicado de
filho(x,y) por:
filho(x,y)<— mãe(y,x),homem(x) (35)

que significa : "para que x seja filho de y, y deve ser a mãe de x e além disso x
deve ser do sexo masculino". Notemos que, no nosso caso, como para cada
filho x temos uma cláusula do tipo pai(y,x) e uma cláusula do tipo mãe(z,x)
então qualquer uma das cláusulas (34) ou (35) serve. Vamos manter as duas
cláusulas. Ao colocarmos todas as possibilidades de definição de um
predicado, vamos obter informações de árvores de família que podem não
estar tão completas como no nosso exemplo.
Vamos considerar a cláusula gol G 4—filho(Marcos,José). Só dando

190
uma olhada na árvore, já podemos dizer que esta cláusula gol não poderá ser
refutada pois Marcos é, na verdade, neto de José. Vejamos:
<— filho(Marcos,José) filho(x,y) 4—pai(y,x),homem(x)
umg = { x/Marcos , y/José } 4
—pai(José,Marcos),homem(Marcos) homem(Marcos)<—.
umg = { }

4—pai(José,Marcos)

E aí não conseguimos mais continuar a SLD-derivação. Notemos


que não obtivemos uma SLD-refutação da cláusula gol G. Portanto, não
podemos deduzir filho(Marcos,José) a partir de P. Portanto, Marcos não é
filho de José.
Qual seria uma maneira de definir o predicado tio(x,y) "x é tio de y"
Uma das maneiras seria:

tio(x,y) <— pai(z,y),irmãos(x,z) (36).


Considerando a cláusula gol G —tio(Carlos,Marcos), vamos tentar
obter uma SLD-refutação. Pela árvore de família, sabemos que Carlos é tio de
Marcos.

<—tio(Carlos, Marcos) tio(x,y) <— pai(z,y),irmãos(x,z)


Carlos , y/Marcos} <— umg = { x/
pai(z,Marcos),irmãos(Carlos,z) pai(Fábio,Marcos)<—.
4—irmãos(Carlos,Fábio) <— umg = { z/F'ábio} irmãos(x,y)<—
pai(z,x),pai(z,y) umg = { x/Carlos ,
pai(z,Carlos),pai(z,Fábio) 4— y/Fábio } pai(José,Carlos)<—
umg = { z/José}
pai(José,Fabio) pai(José,Fábio)<—
umg = { }

E portanto o gol G pode ser deduzido a partir de P. Portanto, Carlos é


tio de Marcos.
Outro modo de definir o predicado tio(x,y) é o seguinte:

tio(x,y) <— mãe(z,y),irmãos(x,z).

Exercícios Propostos.
7.1. Considere o exercício proposto 4.4.4.1. Para cada item do exercício 4.4.4.1.
faça a computação das cláusulas gol dadas diretamente a partir do programa.

191
7.2. Consideremos o problema de relações de parentesco. Cada item é um
predicado a ser definido. Para cada predicado, escreva todas as maneiras
como podemos defini-lo:
a) tia(x,y) "x é tia de y";
0) sobrinho(x,y) "x é sobrinho de y" ;
0) sobrinha(x,y) "x é sobrinha de y" ;
0) avô(x,y) "x é avô de y" ;
b) avó(x,y) "x é avó de y" ;
a) neta(x,y) "x é neto de y" ;
a) neta(x,y) "x é neta de y";
b) primos(x,y) "x ey são primos".
7.3. Considere a árvore da sua própria família. Primeiramente, faça um esboço
desta árvore: incluindo seus pais, tios, avós, primos, cônjuge, filhos. Escreva
cláusulas incondicionais para relações de parentesco do tipo pai, mãe,etc.,
como fizemos na sub-seção 4.6.5 e depois inclua as cláusulas condicionais
que definem os predicados vistos até gora.

3.27 - Um pouco de PROLOG


O PROLOG, grosso modo, é o "concretizado?' dos programas lógicos:
Fornecemos a ele um programa lógico e depois podemos fazer várias consultas ao
programa. O PROLOG ao ler a consulta, a transforma num gol e tenta uma SLD-
refutação deste gol no programa lógico que ele tem dentro de si. Se
conseguir, ele responde "sim!" o que significa que ele conseguiu refutar o
gol que é o mesmo que dizer que a consulta pode ser deduzida a partir do
programa. Ele também pode responder "não!" quando um determinado gol Gi
da SLD-derivação não puder mais ser unificado com alguma das cláusulas do
programa. Além de "sim!" e "não!" o PROLOG pode "não responder nada".
Isso mesmo! Parece estranho mas é verdade!
Na sub-seção 7.1 vamos mostrar como escrever programas PROLOG.
Por exemplo, não poderemos utilizar a nossa tradicional "<—" para escrever
programas PROLOG. Na sub-seção 7.2 veremos um pouco mais o que
estávamos comentando no parágrafo anterior: a estratégia ingênua de
refutação do PROLOG.

4.28 - A notação do PROLOG


A única diferença ente um programa lógico e um programa PROLOG é
a notação. Vamos escrever o Programa P1 da sub-seção 4.4.1 na notação de
PROLOG.
Programa P1 (notação de programa lógico).

p(a)

192
q(b) <—. q(x) <
— p (x).
Escrevendo P1 na notação de PROLOG, temos:

Programa P1 (notação de PROLOG).

p (a).
(0).
q(X) :- p(X).
Observações:
· constantes são representadas por letras minúsculas e as variáveis,
por letras maiúsculas;
· todas as cláusulas de programa são finalizadas com "." (ponto
fmal);
· cláusulas de programa incondicionais não necessitam de "<—" no
fmal. Apenas devemos escrever a(s) fórmula(s) seguidas do ponto final;
· o conectivo de implicação "<—" das cláusulas de programa
condicionais é representado por ":-" (dois pontos seguidos de um hífen).
As consultas são representadas por ?-p(a) (por exemplo) ao invés
de <—p (a).

Escrevendo o Programa P3 da sub-seção 4.4.1 na notação de


PROLOG, temos:

P(a,b).
q(b,c).
r(X,Z) :- p(X,Y),q(Y,Z).

E o Programa P4, fica:

P(X) :- P(X).

p (a).
q(c). P()).

Conforme vimos na seção 4.4, o programa P4 tem uma peculiaridade: ao


considerarmos a consulta ?-p(a) ou seja, tentar refutar o gol <— p(a),
tínhamos dois caminhos: já podíamos unificar o gol 4—p(a) com a cláusula
p(a)<— diretamente e aí já obteríamos a cláusula vazia. Alternativamente,
poderíamos unificar o gol 4—p(a) com a primeira cláusula obtendo o mesmo
gol 4—p(a) e acabaríamos por ter uma computação sem término. Cabe a nós
escolher a cláusula de programa que nos leve mais facilmente à cláusula
vazia. Tendo isso em mente, não escolheríamos a primeira cláusula para o gol 4
—p(a) porém escolheríamos a segunda cláusula. Esse tipo de raciocínio que
fizemos se constituiu numa estratégia, ou seja, fizemos uma espécie de análise

193
antes de escolher uma cláusula de programa.

Comentamos a estratégia que nós, humanos, adotaríamos para tentar


refutar gols em um programa lógico. Vimos que o PROLOG faz esse serviço
para nós. Será que ele possui a sua própria estratégia??? A resposta está na
próxima sub-seção.

3.29 - A estratégia do PROLOG


Suponhamos que temos um programa P e as suas cláusulas de
programa são C1, C2, Ck onde Ci é a cláusula de programa de P que está
escrita na i-ésima linha do programa. Dado Ci, dizemos que i é o índice da
cláusula Ci. Suponhamos também que temos um gol G que desejamos refutar a
partir de P. Como já vimos, a idéia e achar um i tal que podemos unificar a
cabeça de Ci com o corpo de G.
Caso 1. pode ser que tais cláusulas não existam;
Caso 2. pode ser que exista apenas uma cláusula e
Caso 3. pode ser que existam várias cláusulas de programa de P cujas
cabeças podem ser unificadas com o corpo de G.
No Caso 1,o PROLOG (assim como nós) diremos que G não pode
ser refutado e paramos a computação. No Caso 2, suponhamos que a cláusula de
programa de P cuja cabeça é unificável como corpo de G é C. O PROLOG
(assim como nós) unificará G e Ci e obterá um resolvente. No Caso 3,
consideremos Q, o conjunto formado por mais de uma cláusula de programa de
P cuja cabeça é unificável com o corpo de G. Neste caso, nós, humanos,
vamos escolher, através de algum julgamento, a melhor cláusula de Q que
será unificada com G. Já o PROLOG sempre escolherá a cláusula de programa de
Q de índice mínimo

Este jeito de escolher a cláusula para unificação é muito importante:


pode haver uma diferença de resposta entre nós, humanos, e o PROLOG.
Lembra do Programa P4?
Programa P4.

P(X):-P(X). (1)
p(a). (2)
q(c). (3)
p(b). (4)
Se fizermos a consulta ?-p(a), nós, humanos, escolheríamos a
cláusula (2) para a unificação e já obteríamos a cláusula vazia, refutando o gol
<—p(a) correspondente à consulta ?-p(a). Porém, o PROLOG escolherá (1) e
obterá novamente o mesmo gol como resolvente, a saber , 4—p(a). De posse do
novo gol, o PROLOG lerá alista de axiomas de P4 e escolherá (1) novamente

194
para a unificação obtendo, como resolvente, o mesmo gol 4—p(a) e assim por
diante. Enquanto que nós, humanos já obtemos uma refutação para o gol 4—
p(a), o PROLOG prosseguirá a SLD-derivação sempre utilizando a cláusula (1) e
não parará a computação. Neste caso de computação sem término, o
PROLOG não emite resposta alguma.
Este modo através do qual o PROLOG escolhe as cláusulas para
unificação é um tipo de estratégia determinística que, grosso modo, é um
método precisamente definido de, no nosso caso, escolha de cláusulas. Já o
modo com nós, humanos, escolhemos uma cláusula a ser unificada é um tipo de
estratégia não-determinística, ou seja, não existe uma regra ou um método
precisamente defmido para a escolha de cláusulas de programa.

3.30 - Interpretador PROLOG


Para fazer com que o computador faça as SLD-derviações para nós, é
necessário ter um interpretador PROLOG. Um interpretador é um programa que
é capaz de ler programas lógicos e, ao ser perguntado, consegue fazer a SLD-
derivação da cláusula gol que foi perguntada. Um interpretador PROLOG
tradicional após ser chamado, exibirá o seguinte "prompt" :
9-

A partir desse "prompt" podemos pedir a ele que leia programas


lógicos e uma vez que já temos o programa carregado, podemos fazer
consultas. Por exemplo, suponhamos que já temos o Programa P 1 (aquele
mesmo!) carregado pelo interpretador PROLOG. Podemos fazer as seguintes
consultas:
?- p(a).
yes.

?-P(c).
no.

Como carregar programas e outros detalhes técnicos são coisas


específicas de cada interpretador PROLOG e deixamos o estudo destes
detalhes a cargo do leitor.

Estudo de caso: Alice, o Leão e o Unicórnio.


O problema que vamos estudar agora é uma passagem do livro "Alice no
país das maravilhas" de Lewis Carol. Poucas pessoas sabem que Lewis Carol
era um lógico. Se lermos o livro "Alice no país das maravilhas" mais
atentamente perceberemos um certo conteúdo de lógica por trás do texto.
A passagem do texto é a seguinte: Alice entra em uma floresta e perde a
noção dos dias da semana. O Leão e o Unicórnio eram duas das criaturas

195
que habitavam a floresta. Alice os encontra e deseja obter alguma informação
sobre o dia da semana. O problema é que o Leão mente em determinados dias
da semana e o mesmo acontece com o Unicórnio. Alice sabe que eles
mentem e sabe em que dia cada um mente. Naquela época o Leão mentia às
segundas, terças e quartas e falava a verdade nos outros dias da semana. O
Unicórnio mentia às quintas, sextas e sábados e falava a verdade nos outros
dias da semana.
Quando Alice os encontra o Leão diz:

Ontem foi um dos meus dias de mentir! e

o Unicórnio diz:
Ontem foi um dos meus dias de mentir!

A partir dessas informações, Alice descobriu o dia da semana. Qual


era?
A idéia é implementar um programa lógico que dadas as informações
sobre os dias que o Leão e o Unicórnio mentem, o programa determina em
que dia Alice, o Leão e o Unicórnio se encontraram. Inicialmente, devemos
criar o predicado ontem cuja a função é fornecer a seqüência dos dias da
semana para o programa. Este predicado tem o seguinte formato:
ontem (x,y) "x é dia da semana que vem depois do y".

Isto posto, podemos escrever:

ontem(domingo, sábado) .
ontem(segunda, domingo) .
ontem(terça, segunda) .
ontem(quarta, terça) .
ontem(quinta, quarta) .
ontem(sexta, quinta) .
ontem(sábado, sexta) .

Agora, precisamos criar um predicado que relacione o Leão e o


Unicórnio aos dias em que eles mentem. O predicado mentira faz este serviço:
mentira (x, y) "x mente no dia y"

e temos que x pode ser o Leão ou o Unicórnio. A variável y é um dos dias da


semana. Podemos, de acordo com o que foi fornecido sobre os dias em que os
dois mentem, escrever o seguinte:
mentira(leão, segunda).
mentira(leão, terça).

196
mentira(leão, sábado).
mentira(leão, domingo)
mentira(unicórnio, segunda).
mentira(unicórnio, quarta).
mentira(unicórnio, sexta).
mentira(unicórnio, domingo)

Temos que o programa completo é:


ontem(domingo, sábado) .
ontem(segunda, domingo) .
ontem(terça, segunda) .
ontem(quarta, terça) .
ontem(quinta, quarta) .
ontem(sexta, quinta) .
ontem(sábado, sexta) .
mentira(leão, segunda).
mentira(leão, terça).
mentira(leão, sábado).
mentira(leão, domingo)
mentira(unicórnio, segunda).
mentira(unicórnio, quarta).
mentira(unicórnio, sexta).
mentira(unicórnio, domingo)
Este programa é suficiente para Alice determinar o dia em que ela
conversou com o Leão e o Unicórnio porém devemos fazer as consultas
corretamente para obtermos alguma resposta. Quando o Leão (ou o Unicórnio)
diz que o dia anterior era um dos dias dele mentir ele pode estar mentindo.
Como temos o Leão e o Unicórnio, temos quatro possibilidades: os dois
podem estar mentindo no dia em que falam, um mentir, outro não e assim por
diante. Isto posto, podemos fazer as seguintes quatro consultas:
a) ontem(X,Y), mentira(leão,Y), verdade(leão,X) : o leão está
mentindo no dia
em que ele conversa com a Alice e diz a verdade no dia anterior. Se aplicarmos a
regra de resolução para esta consulta composta de três predicados,
obteremos que X = qui e Y = qua.
a) ontem(X,Y), mentira(unic,Y), verdade(unic,X) : mesma situação
acima só
que para o unicórnio. Se aplicarmos a regra de resolução, obteremos X =
dom e Y = sab;

197
a) ontem(X,Y), verdade(leão, Y), mentira(leão, X) : quando o leão
falou com
Alice ele disse a verdade sobre o dia anterior. Obtemos X = seg e Y = dom;
a) ontem(X,Y), verdade(unic, Y), mentira(unic, X) : mesma situação
acima para
o unicórnio. Obtemos X = qui e Y = qua.

Notemos que nas consultas a) e d) temos que X = qua e Y = qui e o dia


em que os três conversaram foi quinta-feira.

3.31 - Assuntos relacionados à programação em lógica


O que fizemos neste capítulo foi apenas dar uma pequena introdução à
programação em lógica e ao PROLOG. Na verdade, o PROLOG é apenas um
instrumento de concretização da teoria de programação em lógica.
A teoria de programação em lógica constitui a base para a construção de
sistemas especialistas. Estes sistemas especialistas são programas
construídos para armazenar informações sobre um determinado assunto e ser
capaz de "responder perguntas" (consultas) sobre esse assunto quando
perguntado. O programa de relações de parentesco é um pequeno exemplo de
sistema especialista.
A teoria de programação em lógica que apresentamos é a teoria de
programação em lógica clássica. Existem muitas lógicas não-clássicas, isto é,
lógicas cujos valores verdade não são apenas V ou F. Em alguns casos
também temos teorias de programação em lógicas não-clássicas.

Exercícios Propostos.
4.1. Refaça o exercício 4.6.7.2. só que desta vez utililize a notação do
PROLOG.
4.2. Refaça o exercício 4.6.7.3. utilizando a notação do PROLOG.

4.3. Refaça o exercício 4.6.7.3. e implemente o programa num interpretador


PROLOG. Para cada consulta, faça primeiro a SLD-derivação no papel e
depois submeta a consulta ao interpretador PROLOG.

4.4. Alice encontra o Leão e ele diz:

"Eu menti ontem e mentirei amanhã.".


Aproveitando a tabela de mentiras já colocada anteriormente, faça um
programa e construa consultas convenientes para Alice poder descobrir em
que dia ela encontrou o Leão.

198
3.5. Desta vez o Unicórnio encontra Alice e diz:

"Eu menti antes de ontem e mentirei depois de amanhã.".


Aproveitando a tabela de mentiras já colocada anteriormente, faça um
programa e construa consultas convenientes para Alice poder descobrir em
que dia ela encontrou o Leão.

199

Você também pode gostar