Escolar Documentos
Profissional Documentos
Cultura Documentos
Joo Meidanis
Contedo
Introduo
1.1 1.2 1.3 1.4 1.5 1.6 1.7 Objetos e relaes . . . . . . . . . . . . . . . . . . . . . . . . . Programao em Prolog . . . . . . . . . . . . . . . . . . . . .
4
4 5 5 6 7 8 10
Fatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Perguntas . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conjunes . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Regras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sintaxe e unicao
2.1 2.2 2.3 2.4 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Estruturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Igualdade e unicao . . . . . . . . . . . . . . . . . . . . . .
15
15 16 16 18
Aritmtica
20
24
24 25 28 31 33
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Acumuladores . . . . . . . . . . . . . . . . . . . . . . . . . . .
Backtracking
5.1 5.2 5.3
e o corte
36
37 39 39 40 41 42 42
5.4
46
46 48 49 50 50
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
Predicados pr-denidos
7.1 7.2 7.3 7.4 7.5 7.6 Verdadeiros . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
53 53 54 54 54 55
Outros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Estilo e depurao
8.1 Depurao . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
58
Gramticas
9.1 9.2 9.3 9.4 O problema da anlise lxica . . . . . . . . . . . . . . . . . . . Anlise lxica em Prolog . . . . . . . . . . . . . . . . . . . . . Notao para regras gramaticais . . . . . . . . . . . . . . . . . Argumentos adicionais . . . . . . . . . . . . . . . . . . . . . .
60
60 62 66 67
Bibliograa
70
Captulo 1 Introduo
Prolog ao mesmo tempo uma linguagem descritiva e prescritiva. Ao mesmo tempo que descreve-se feito. As presentes notas esto baseadas no livro de Clocksin e Mellish,
o que
como
ming in Prolog
Program-
1.1
Objetos e relaes
objetos
relaes
mesmo sentido que em orientao a objetos, pois os objetos Prolog no tm mtodos e no h herana. Em Prolog, objetos so apenas coisas sobre as quais queremos raciocinar. Prolog tem um tipo chamado
termo
1.2
Programao em Prolog
Dizemos a Prolog certos fatos e regras, e depois fazemos perguntas sobre estes fatos e regras. Por exemplo, podemos informar Prolog sobre irms e depois perguntar se Maria e Joana so irms. Prolog responder sim ou no em funo do que lhe dissemos. Prolog na verdade faz muito mais do que responder sim ou no: a linguagem permite usar o computador como um aracbouo de fatos e regras, e proporciona meios de fazer inferncias, indo de um fato a outro, e achando os valores das variveis que podem levar a concluses lgicas. Prolog geralmente usada como uma linguagem interpretada. Neste curso vamos usar o interpretador SWI-Prolog, uma implementao disponibilizada gratuitamente. Onde pegar:
http://www.swi-prolog.org.
H para todos
1.3
Fatos
gosta(pedro, maria). gosta(maria, pedro). valioso(ouro). mulher(jane). possui(jane, ouro). pai(pedro, maria). entrega(romeu, livro, maria).
5
Pedro gosta de Maria Maria gosta de Pedro Ouro valioso Jane mulher Jane possui ouro Pedro pai de Maria Romeu entrega o livro a Maria
Observe que:
nomes de relaes e objetos iniciam-se com letra minscula o nome da relao vem primeiro, depois vem a lista de objetos separados por vrgula e envolta em parnteses o ponto nal obrigatrio ao nal do fato.
Terminologia: relaes so
predicados e os objetos a que se referem so seus argumentos. Chamaremos de banco de dados coleo de fatos e regras que
damos a Prolog para resolver um certo problema.
1.4
Perguntas
?- possui(maria, livro).
Estamos perguntando se Maria possui o livro. Prolog tenta
unicar
o fato
da pergunta com os fatos do banco de dados. Dois fatos se unicam se tm o mesmo predicado e os mesmos argumentos na mesma ordem. Se Prolog achar um fato que unica com a pergunta, vai responder sim. responder no. Perceba que a resposta no em Prolog no signica necessariamente que o fato no verdadeiro, mas simplesmente que Prolog no consegue o fato a partir de seu banco de dados. Considere o banco de dados: Conra isto no seguinte exemplo. Caso contrrio,
provar
?- ateniense(aristoteles).
Embora seja verdade que Aristteles tenha sido ateniense, no se pode provar isto a partir dos fatos dados.
1.5
Variveis
As variveis em Prolog servem para responder questes mais elaboradas, por exemplo Do que Maria gosta? ou ento Quem mora em Atenas?. Variveis distingem-se dos objetos por terem nomes iniciados com letra maiscula. Considere o seguinte banco de dados:
?- gosta(maria, X).
estaremos perguntando Do que Maria gosta?. Prolog responde:
X = flores
e ca esperando por mais instrues, das quais falaremos em breve. Novamente, Prolog busca fatos que uniquem com o fato da pergunta. A diferena que uma varivel est presente agora. Variveis no instanciadas, como o caso de
Prolog examina
gosta(maria, flores) encontrado primeiro. A varivel X unica com flores e a partir deste momento passa a estar instanciada com o termo flores. Prolog tambm marca a posio no banco de dados onde a unicao foi feita.
Quando Prolog encontra um fato que unica com uma pergunta, Prolog mostra os objetos que as variveis guardam. No caso em questo, s h uma varivel, que foi unicada com o objeto
X = flores.
flores,
ENTER, isto ser interpretado como signicando que estamos satisfeitos com a resposta dada e Prolog interrompe a busca. Se em lugar disto teclarmos um
do ponto onde tinha parado, tentando encontrar uma outra resposta pergunta.
ponto-e-vrgula (;) seguindo de ENTER, Prolog vai continuar sua busca Quando Prolog comea a busca a partir de uma posio previamente mercada ao invs de comear do incio do banco de dados, dizemos que est tentando
ressatisfazer
a pergunta.
Suponha que peamos a Prolog continuar a busca teclando ; e ENTER, ou seja, queremos ver a pergunta satisfeita de outra forma, com outro valor para
X. Isto signica que Prolog deve agora esquecer que X vale flores e continuar a busca com X voltando a estar no instanciada. A busca prossegue do ponto marcado no banco de dados. O prximo fato unicante gosta(maria, pedro). A varivel X agora instanciada a pedro e Prolog move a marca para o fato gosta(maria, pedro), respondendo X = pedro e aguardando
mais instrues. Se pedirmos continuao com ; e ENTER, no h neste caso mais respostas possveis, e por isso Prolog respoder no. Vejamos rapidamente um outro exemplo sobre o mesmo banco de dados.
1.6
Conjunes
Questes mais complexas como Ser que Pedro gosta de Maria e Maria gosta de Pedro? podem ser feitas com conjunes. Este problema consiste de duas metas separadas que Prolog deve tentar satisfazer, e existe uma notao para isto na linguagem. Considere o banco de dados:
pronunciada e e serve para separar um nmero qualquer de metas diferentes que devem ser satisfeitas para responder a uma pergunta, o que se chama de
conjuno.
questo, a resposta ser no, pois, embora a primeira meta seja um fato, a segunda no pode ser provada. Conjunes combinadas com variveis podem responder a perguntas bastante interessantes, por exemplo: H algo de que ambos Maria e Pedro gostam?. Isto seria escrito da seguinte forma:
instanciada a
na pergunta.
instanciao de
falha. Prolog ento tentar ressatistazer a meta anterior do ponto onde esta parou no banco de dados, desfazendo instanciaes associadas. 3. Na ressatisfao da primeira meta, o prximo fato unicador
gosta(maria, vinho).
Prolog move a marca para a nova posio e instancia 4. Prolog tenta a prxima meta, que agora
vinho.
Esta
gosta(pedro, vinho).
no uma ressatisfao, mas sim uma meta inteiramente nova, e portanto a busca comea do incio do banco de dados. Esta nova meta satisfeita e Prolog coloca a marca desta meta no fato unicador. 5. Todas as metas da pergunta esto satisfeitas agora. Prolog imprime as instanciaes de variveis:
X = vinho
e aguarda instrues.
Resumindo, cada meta tem seu prprio marcador no banco de dados, que usado caso a meta precise ser ressatisfeita. Junto com uma unicao cam guardadas instanciaes de variveis dela resultantes, que sero desfeitas em caso de necessidade de ressatisfao. A este processo se d o nome de
backtracking.
1.7
Uma fatos:
Regras
regra
10
Pedro gosta de
se
gosta de vinho.
so conectados pelo smbolo :- formado por dois pontos e hfen. O :- procuncia-se se. A dependncia acima seria escrito como:
cabea
e um
corpo.
A cabea e o corpo
gosta(pedro, X). A cabea de uma regra descreve o denido. O corpo, no caso gosta(X, vinho), uma conjun-
o de metas que devem ser satisfeitas para que a cabea seja considerada verdadeira. Por exemplo, podemos tornar Pedro mais exigente sobre o que ele gosta adicionando mais metas ao corpo da regra:
escopo
de
Dizemos que o
for instanciada, as
trs ocorrncias tero o mesmo valor. A maneira como as regras funcionam em relao satisfao de metas a seguinte. da regra. Uma meta unica com uma regra se ela unica com a cabea Agora, para vericar a veracidade da regra, o corpo usado.
Diferentemente dos fatos, onde basta haver unicao para que a meta seja sarisfeita, no caso de uma regra a unicao na verdade transfere a vericao da satisfao para a conjuno de metas que formam o corpo da regra. Vamos ilustrar este procedimento com nosso prximo exemplo, que envolve a famlia da rainha Vitria. Usaremos o predicado
pais
11
tal que
pais(X, Y, Z)
e
mulher
homem
so
Z.
O segundo
homem(alberto). homem(eduardo). mulher(alice). mulher(vitoria). pais(eduardo, vitoria, alberto). pais(alice, vitoria, alberto).
Deniremos agora o predicado quando
for irm de
irma_de tal que irma_de(X, Y) seja satisfeito Y. Dizemos que X irm de Y quando:
X X Y
mulher tem me
e pai
P,
X.
?- irma_de(alice, eduardo).
as seguintes metas sero tentadas e os resultados podem ser vistos na Tabela 1.1, onde numeramos as variveis com ndices de acordo com a meta,
12
irma_de(alice, eduardo).
Marca Variveis
irma_de,
regra 1
mulher,
fato 1
X1 = alice, Y1 = eduardo
-
pais,
fato 2
pais,
fato 1
M1 = vitoria, P1 = alberto
-
pois, embora a mesma letra signique a mesma varivel dentro de uma regra, em metas diferentes a mesma letra signica variveis diferentes. Note que, ao unicar com a cabea da regra, a meta 1 deu origem a trs outras metas, denotadas pelos nmeros 2, 3, e 4, que vieram do corpo da regra. Ao nal, Prolog consegue satisfazer a meta principal e responde: agora que queiramos saber
de quem
sim.
Suponha
?- irma_de(alice, X).
O que ocorre ento est na Tabela 1.2, onde da pergunta. Observe que
X sem ndice
indicar a varivel
X = Y1 = eduardo
X = eduardo
e ca aguardando novas instrues. O que acontecer se pedirmos respostas alternativas? Veja o exerccio a seguir. Em geral, um mesmo precicado denido atravs de alguns fatos e algumas regras. Usaremos a palavra
clusula
coletivamente.
13
irma_de(alice, X).
Marca Variveis
irma_de,
regra 1
mulher,
fato 1
X1 = alice, Y1 = X
-
pais,
fato 2
pais,
fato 1
Exerccios
1. Descreva o que acontece se forem pedidas respostas alternativas no exemplo envolvendo o predicado tamento esperado? predicado
irma_de
acima.
Este o compor-
dif(X,Y)
so diferentes?
14
Em Prolog h apenas um tipo, chamado de detalhe este tipo e seus subtipos. Um termo pode ser uma
2.1
As
Constantes
pode ser
constantes
tomos
ou
nmeros.
uma diferena aqui: os nmeros so considerados tomos em LISP, mas em Prolog nmeros no so tomos (embora ambos sejam constantes). Um
livro,
tomo
maria,
caracteres,
lidos e impressos em Prolog, como veremos no captulo sobre entrada e sada. Em relao a
nmeros,
15
2.2
Variveis
Sintaticamente, as
variveis
annimas.
underscore ) _.
Estas ltimas so
Variveis com o mesmo nome aparecendo numa mesma clusula so a mesma varivel, ou seja, se uma ganha um valor, este valor passa imediatamente para as outras ocorrncias, exceto para variveis annimas. As variveis annimas so diferentes das outras nos seguintes aspectos: (1) cada ocorrncia delas indica uma varivel diferente, mesmo dentro de uma mesma clusula, e (2) ao serem usadas numa pergunta, seus valores no so impressos nas respostas. Variveis annimas so usadas quando queremos que uniquem com qualquer termo mas no nos interessa com qual valor sero instanciadas.
2.3
As
Estruturas
seguido de Por exem-
estruturas so termos mais complexos formados por um funtor componentes separadas por vrgula e colocadas entre parnteses.
abaixo:
plo, para indicar um livro com seu ttulo e autor podemos usar a estrutura
livro(incidente_em_antares, verissimo)
Observe que os fatos de um banco de dados em Prolog so estruturas seguidas de um ponto nal.
16
livros, colocando nome e sobrenome do autor para poder diferenciar entre vrios autores com o mesmo sobrenome, podemos usar:
aridade.
Funtores de aridade
Quando no h argumentos, a
operador.
Um operador tem na verdade trs propriedades que devem ser especicadas: sua posio, sua precedncia e sua associatividade. A posio pode ser prexa, inxa ou posxa. A precedncia um nmero; quanto menor for, mais prioridade o operador ter nos clculos. A associatividade pode ser esquerda ou direita, e indica como devem ser agrupadas subexpresses consistindo apenas deste operador. Por exemplo, os operadores aritmticos inxa.
+, -, *, /
tm geralmente posio e
-.
maior que de
e e
8/(2/2). 2 + 3
8/2/2
(8/2)/2
Note que Prolog diferente das outras linguagens no aspecto aritmtico, pois uma expresso como simplesmente um fato como qualquer outro. Para a realizao de clculos aritmticos sempre necessrio usar o predicado
is
17
2.4
Igualdade e unicao
para a igualdade, mas em geral seu uso pode ser substitudo pelo
uso de variveis de mesmo nome. Se no existisse, o predicado denido por apenas um fato:
poderia ser
X = X.
Uma outra caracterstica da igualdade em Prolog, j que ela signica unicao, que ela pode causar a instanciao de algumas variveis, como temos visto nos exemplos introdutrios. Em geral, dada uma meta da forma
quer, a deciso sobre sua igualdade feita de acordo com a Tabela 2.1. Nesta tabela so tratados os casos onde cada termo pode ser uma constante, varivel, ou estrutura. Note que quando dizemos varivel estamos na verdade nos referindo a variveis no instanciadas, pois para variveis instanciadas deve se usar o valor a que esto associadas para consultar a Tabela 2.1.
T2
constante constante varivel s se for a mesma sempre; nunca causa instanciao estrutura varivel sempre; causa instanciao tornam-se ligadas sempre; causa instanciao sempre; mesmo de causa funtor, instanciao mesmo nmero componentes e cada componente igual estrutura nunca
T1
Tabela 2.1: Condies para que dois termos se uniquem, segundo seus subtipos. O subtipo varivel signica varivel no instanciada. O subtipo estrutura signica estruturas com aridade maior ou igual a um.
18
Exerccios
1. Decida se as unicaes abaixo acontecem, e quais so as instanciaes de variveis em caso haja unicao.
pilotos(A, londres) = pilotos(londres, paris) pilotos(londres, A) = pilotos(londres, paris) pilotos(A, londres) = pilotos(paris, londres) ponto(X, Y, Z) = ponto(X1, Y1, Z1) letra(C) = palavra(letra) letra(C) = letra(palavra) nome(alfa) = alfa f(X, X) = f(a,b) f(X, a(b,c)) = f(Z, a(Z,c))
2. Como se pode denir o predicado abaixo sem usar igualdade?
19
Captulo 3 Aritmtica
Prolog tem uma srie de predicados pr-denidos para artimtica, que podem ser divididos entre comparao e clculo. Vamos comear pelos de comparao. Os predicados de comparao so inxos e comparam apenas nmeros ou variveis instanciadas a nmeros. So eles:
=<,
e no
<=
como na
uma seta, para outros usos pelo programador. Os predicados pr-denidos no pode ser redenidos nem podem ter fatos ou regras adicionados a eles, por exemplo, tentar acrescentar um fato como seja verdadeiro. Para exemplicar o uso dos comparadores, considere o seguinte banco de dados contendo os prncipes de Gales nos sculos 9 e 10, e os anos em que reinaram. Os nomes esto em gals.
2 < 3.
20
reinou(rhodri, 844, 878). reinou(anarawd, 878, 916). reinou(hywel_dda, 916, 950). reinou(iago_ap_idwal, 950, 979). reinou(hywal_ap_ieuaf, 979, 985). reinou(cadwallon, 985, 986). reinou(maredudd, 986, 999).
Quem foi o prncipe em um ano dado? A seguinte regra tenciona responder isto.
?- principe(cadwallon, 986). yes ?- principe(X, 900). X = anarawd yes ?- principe(X, 979). X = iago_ap_idwal ; X = hywel_ap_ieuaf ; no
Para clculos aritmticos, o predicado especial pr-denido no resultado desta expresso. O operado
is
deve sempre aparecer uma expresso aritmtica envolvendo apenas nmeros ou varveis instanciadas com nmeros. Do lado esquerdo pode aparecer uma varivel no instanciada, que ser ento instanciada com o resultado da expresso, ou pode tambm aparecer um nmero ou varivel instanciada a um
21
assim como operador de igualdade numrica. O predicado aritmticas. Para exemplicar, considere o seguinte banco de dados sobre a populao e a rea de diversos pases em 1976. O predicado
pop
representar a populao
area
informar a rea de
pop(eua, 203). pop(india, 548). pop(china, 800). pop(brasil, 108). area(eua, 8). area(india, 3). area(china, 10). area(brasil, 8).
Para calcular a densidade populacional de um pas, escrevemos a seguinte regra, que divide a populao pela rea:
+ * / // mod
Exerccios
soma(2 + 3)
Com quais dos fatos esta meta unica? Quais so as instanciaes de variveis em cada caso? 2. Quais so os resultados das perguntas abaixo?
?????-
X X 6 X Y
is 2 is Y is 2 = 5, is X
+ 3. + Z. * 4. Y is X // 2. // 2, X = 5.
23
As estruturas de Prolog so muito versteis para represetar estruturas de dados nos programas. Neste captulo veremos alguns exemplos.
4.1
As estruturas podem ser desenhadas como rvores, onde o funtor ca na raiz e os componentes so seus lhos, como na Figura 4.1.
carlos
bete
felipe
Figura 4.1: Estruturas como rvores. Frases da lngua portuguesa podem ter suas sintaxes representadas por estruturas em Prolog. Um tipo de sentena muito simples, consisitindo de sujeito e predicado (no confundir com predicado Prolog!), poderia ser:
24
sentenca
sentenca
sujeito
predicado
sujeito
predicado
verbo
objeto
pedro
verbo
objeto
Z
Figura 4.2: Sintaxe de sentenas.
ama
maria
A representao de estruturas pode tambm dar uma descrio picttica das variveis, mostrando ocorrncias de uma mesma varivel. estrutura Por exemplo, a
4.2
Listas
As listas so estruturas de dados importantes em Prolog. Existem diversos predicados pr-denidos para lidar com listas em Prolog. Existem tambm predicados para transformar estruturas em listas e vice-versa.
25
ou uma
cauda.
O funtor (binrio) usado para representar a estrutura de lista o ponto .. Para quem conhece LISP, este funtor lembra o par-com-ponto. Na Figura 4.4 vemos uma lista que seria escrita como
(c .
()))).
. . .
[]
A exemplo de LISP, Prolog tambm tem uma maneira alternativa, mais prtica, de denotar listas, que no usa o funtor . explicitamente. Basta colocar
26
[a, b, c].
Qualquer
termo pode ser componente de uma lista, por exemplo, variveis ou outras
Lista
Cabea
Cauda
[a, b, c] a [b, c] [ ] no tem no tem [[o, gato], sentou] [o, gato] [sentou] [o, [gato, sentou]] o [[gato, sentou]] [o, [gato, sentou], ali] o [[gato, sentou], ali] [X + Y, x + y] X + Y [x + y]
Para combinar com a notao simplicada para listas, Prolog tambm tem uma notao especial, mais intuitiva, para indicar vertical |:
[X|Y].
.(X, Y)
usando a barra
em cabea e cauda, como no exemplo abaixo, onde aparecem um banco de dados e algumas perguntas:
p([1, 2, 3]). p([o, gato, sentou, [no, capacho]]). ?- p([X|Y]). X = 1 , Y = [2, 3] ; X = o, Y = [gato, sentou, [no, capacho]] ; no ?- p([_,_,_,[_|X]]). X = [capacho]
27
Uma ltima observao: possvel criar estruturas que parecem listas mas no so, por exemplo,
[cavalo|branco],
Exerccios
1. Decida se as unicaes abaixo acontecem, e quais so as instanciaes de variveis em cada caso positivo.
[X, Y, Z] = [pedro, adora, peixe] [gato] = [X|Y] [X, Y|Z] = [maria, aprecia, vinho] [[a, X]|Z] = [[X, lebre], [veio, aqui]] [anos|T] = [anos, dourados] [vale, tudo] = [tudo, X] [cavalo|Q] = [P|branco] [ ] = [X|Y]
4.3
Recurso
cauda agora.
relao
Escreve-
remos um predicado
member
member(X, Y)
verdadeiro quando o
28
termo
um elemento da lista
Y.
Em pri-
membro de
se
Y,
member(X, Y) :- Y = [X|_].
ou, simplicando,
member(X, [X|_]).
Note o uso da varivel annima. Neste fato, no nos interessa o que a cauda de
Y.
X membro de Y se X membro da cauda de Y. Aqui entrar recurso para vericar se X est na cauda. Veja como ca: member(X, Y) :- Y = [_|Z], member(X, Z).
ou, simplicando,
ressa o que est na cabea da lista, que foi tratada na primeira clusula do
member.
por
Y,
j que
sumiu na
simplicao. O que escrevemos foi basicamente uma denio do predicado ser usada computacionalmente. Exemplos:
member, porm
a maneira de processar perguntas de Prolog faz com que esta deniao possa
parada
caso recursivo.
No caso de
member,
condies de
h na verdade duas
condies de parada: ou achamos o objeto na lista, ou chegamos ao m dela sem ach-lo. A primeira condio tratada pela primeira clusula, que far a busca parar se o primeiro argumento de
member
segundo argumento. A segunda condio de parada ocorre quando o segundo argumento a lista vazia, que no unica com nenhuma das clusulas e faz o predicado falhar. Em relao ao caso recursivo, note que a regra escrita de tal forma que a chamada recursiva ocorre sobre uma lista encontremos o objeto antes. Certos cuidados devem ser tomados ao fazer denies recursivas. Um deles evitar circularidade, por exemplo:
menor
temos certeza de acabaremos por encontrar a lista vazia, a menos claro que
loop
innito.
Outro cuidado com a ordem das clusulas na denio de um predicado. Considere a seguinte denio:
?- homem(X).
Prolog estrar em
loop at esgotar a memria. O predicado homem est denido usando recurso esquerda, ou seja, a chamada recursiva a meta mais
esquerda no corpo, gerando uma meta equivalente meta original, o que se repetir eternamente at acabar a memria. Para consertar o predicado, basta trocar a ordem das clusulas:
30
?- lista(X).
Prolog entrar em ver o problema.
loop.
4.4
Juntando listas
append
usado para juntar duas listas formando uma terceira.
O predicado
Este predicado pode ser usado para criar uma lista que a concatenao de duas outras:
1. O primeiro elemento da primeira lista ser tambm o primeiro elemento da terceira lista. 2. Concatenando a cauda da primeira lista com a segunda lista resulta na cauda da terceira lista. 3. Temos que usar o prprio acima. 4. Conforme aplicamos a segunda clusula, o primeiro argumento vai diminuindo, at ser a lista vazia; logo, a recurso termina.
32
4.5
Acumuladores
Freqentemente, precisamos percorrer uma estrutura em Prolog e calcular resultados que dependem do que j foi encontrado at o momento. A tcnica de acumuladores consiste em utilizar um ou mais argumentos do predicado para representar a resposta at o momento durante este percurso. argumentos recebem o nome de Estes
acumuladores.
No prximo exemplo mostraremos uma denio para o predicado sem acumulador e depois com acumulador. A meta feita quando o comprimento da lista pr-denido
length
lenacc que uma generalizao de listlen. A lenacc(L, A, N) satisfeita quando o comprimento de L adicionado ao nmero A resulta em N. Para obter o comprimento da lista, basta chamar lenacc com o segundo argumento igual a zero. Eis as denies: lenacc([ ], A, A). lenacc([H|T], A, N) :- A1 is A + 1, lenacc(T, A1, N). listlenacc(L, N) :- lenacc(L, 0, N).
Acompanhe a seqncia de submetas criadas para calcular o comprimento de
das regras denidas. Esta ltima meta unica com a condio de parada (a primeira clusula de
listlen
rev,
reverse):
rev(L1, L3) :- revacc(L1, [ ], L3). revacc([ ], L3, L3). revacc([H|L1], L2, L3) :- revacc(L1, [H|L2], L3). revacc serve como acumulador. Observe a seqncia de metas usadas para responder pergunta ?- rev([a, b, c, d], L3).:
O segundo argumento de
rev([a, b, c, d], L3) revacc([a, b, c, d], [ ], L3) revacc([b, c, d], [a], L3) revacc([c, d], [b, a], L3) revacc([d], [c, b, a], L3) revacc([ ], [d, c, b, a], L3)
Nestas metas todas as variveis vo saindo de
L1
e entrando
entram pela frente nas listas, combinando com as operaes de lista em Prolog que s permitem manipular diretamente a cabea. parada instancia
L3
reversa.
nicado
sig-
34
revacc: a meta revacc(L1, L2, L3) lista L1 concatenada com a lista L2 resulta
satisfeita em
L3.
De
Exerccios
last(L, X) que satisfeito quando o termo X lista L. efface(L1, X, L2) delete(L1, X, L2)
que satisfeito quando
2. Escreva um predicado
X X
em
L1. L1.
L2 L2
35
Captulo 5
Backtracking e o corte
Resumindo o que vimos sobre a operao de Prolog at agora: 1. uma pergunta a conjuno de vrias metas, que chamaremos de 1, 2, 3, . . . ,
n.
de dados, a partir do incio, por uma clusula unicante. Se no houver tal clusula, a meta falha. Se houver clusula unicante, marca-se o ponto no banco de dados onde ela ocorre, e instanciam-se e ligam-se as variveis conforme necessrio. Dizemos neste caso que a meta
casou.
Se a clusula unicante for um fato, a meta satisfeita. Se for a cabea de uma regra, a meta d origem a um novo nvel de submetas, criadas a partir da cauda da regra, que chamaremos de de
A satisfao
3. quando uma meta satisfeita, passa-se para a prxima meta. Se no houver prxima, Prolog pra e informa o resultado (positivo), juntamente com os valores das variveis da pergunta. 4. quando uma meta falha, a meta anterior sofre tentativa de ressatisfao. Chamamos esta ao de
backtracking
36
5. a tentativa de ressatisfao de uma meta semelhante de satisfao, com as seguintes ressalvas: (a) desfazem-se as instanciaes e ligaes causadas pela ltima unicao desta meta. (b) a busca continua do ponto marcado no banco de dados ao invs de comear do nicio;
backtracking
backtracking
em
com uma regra interessante para saber quem a meta-me de cada meta gerada, o que vai ser importante no nosso estudo do corte. Porm, em certas situaes, podemos preferir simplesmente usar uma numerao sequencial para as metas, como fazem alguns depuradores de sistemas Prolog.
5.1
pai(X) :- pai(_,X).
H dois predicados
pai:
pai, nesta ordem, e um unrio, que baseado no outro, e diferencia pais de no-pais. A pergunta
?- pai(X).
37
X = X = X = X = no
Note que Jorge apareceu duas vezes, pois h dois fatos onde ele aparece como pai de algum. Talvez quisssemos que cada pai aparecesse uma vez s, mas a operao padro de Prolog causar o resultado acima. Uma situao semelhante ocorre com o predicado
member
visto anterior-
?- inteiro(N).
causar a gerao de todos os inteiros a partir do zero, em ordem crescente. Isto pode ser usado em parceria com outro predicado que seleciona alguns entre estes inteiros para uma determinada aplicao.
38
5.2
O corte
O corte um mecanismo especial em Prolog que instrui o sistema a no reconsiderar certas alternativas ao fazer
backtracking.
tante para poupar memria e tempo de processamento. Em alguns casos, o corte pode signicar a diferena entre um programa que funciona e outro que no funciona. Sintaticamente, o corte um predicado denotado por !, com zero argumentos. Como meta, ele sempre satisfeito da primeira vez que enconAlm disso, trado, e sempre falha em qualquer tentativa de ressatisfao. chamada de sua
como efeito colateral ele impede a ressatisfao da meta que lhe deu origem,
meta me.
o
Se o corte a meta
backtracking
g :- a, b, c, !, d, e, f.
Prolog realiza o sucesso de
backtracking
a, b
e
at que o
processo de
backtracking
cause a satisfao do corte e Prolog passe para a meta acontece normalmente entre
d, e
f,
mas se
algum momento falhar, o que ocorre que a meta envolvendo com esta regra falha imediatamente tambm.
d. O d em
que casou
5.3
Usos do corte
indicar que a regra certa foi encontrada combinao corte-falha indicando negao limitar uma busca nita ou innita
39
[X|Y]
no
casar com a lista vazia. Outras vezes, como quando os predicados envolvem nmeros, isto no possvel. Nestes casos, o corte pode ajudar a fazer com que a meta s case com o caso destinado a ela. Considere a seguinte denio de um predicado fatorial de um nmero:
fat(N, F)
que calcula o
loop
innito
out of memory )
A denio de
fat
40
fail fail.
0 > 1
nonmember(X, L) que o contrrio de member(X, L), ou seja, satisfeito exatamente quando membar(X, L) falha, isto , quando X no membro de L. Eis a implementao de nonmember
Suponha que precisemos de um predicado usando corte e falha:
nonmember(X, L), Prolog vai tentar a member(X, L) for satisfeito, o corte ser processado e logo a seguir vem fail. Devido ao corte, sabemos que esta tentativa de ressatisfao vai fazer a meta nonmember(X, L) falhar sem tentar a segunda
clusula, que exatamente o que queremos. No caso de
a segunda clusula, que devido s variveis annimas sempre satisfeita. Concluso: neste caso, queremos. Este mesmo mtodo pode ser usado para implementar a negao de qualquer predicado. O uso deste artifcio to comum que existe uma notao em Prolog para indicar esta forma de negao:
\+
41
//,
desta seo.
divide(Numerador, Denominador, Resultado) :inteiro(Resultado), Prod1 is Resultado * Denominador, Prod2 is Prod1 + Denominador, Prod1 =< Numerador, Prod2 > Numerador, !.
Esta denio usa o predicado
inteiro
para gerar candidatos a quociente inteiro, que so testados pelas metas subseqentes. Note que sem o corte teramos um ressatisfao.
loop
innito em tentativas de
5.4
Cortes tm um impacto signicativo no comportamento de qualquer predicado, e por isso necessrio ter clareza sobre exatamente que uso queremos fazer de um predicado ao considerar a incluso de cortes em sua denio. Para exemplicar esta questo, suponha que queiramos usar
member
apenas
para testar se elementos dados pertencem a listas dadas, sem nos importarmos com o nmero de vezes que aparecem. Neste caso, a denio
42
distinto da lista. Porm, perdemos a possibilidade de us-lo como gerador de mltiplas alternativas:
43
pois a meta no casa com a clusula especca para Eva, mas no h nada para impedir que a busca continue, e acabe casando com a clusula errada. Uma forma de arrumar isto a seguinte:
para o
Exerccios
1. Conserte o predicato das onde
en chama-
onde ambos
vm instanciados.
nonmember
no esto na lista
[a, b, c]
com a
44
member_com(X, [X|_]) :- !. member_com(X, [_|Y]) :- member_com(X, Y). member_sem(X, [X|_]). member_sem(X, [_|Y]) :- member_sem(X, Y).
45
Neste captulo veremos alguns dos mecanismos que Prolog oferece para a entrada e sada de dados. Dividiremos a apresentao em trs partes: leitura e escrita de termos; leitura e escrita de caracteres; leitura e escrita de arquivos. Alm disso, abordaremos a questo dos operadores, que inuenciam o modo como a leitura e a escrita ocorrem. A descrio baseia-se no SWI Prolog. Outros sistemas podem diferir desta implementao.
6.1
read(X)
satisfeita quando
dispositivo de entrada.
m do termo, sendo que este ponto nal no considerado parte do termo lido. Unicando ou no, o termo lido consumido, ou seja, a prxima leitura seguir da para a frente. O termo lido pode conter variveis, que sero tratadas como tal, mas seu escopo se restringe ao termo lido. Se o termo lido no tiver a sintaxe de um termo em Prolog, ocorre erro de leitura. Se o m do arquivo for encontrado,
46
especial
end_of_file.
Em caso de ressatisfao,
read
falha.
O seguinte predicado l um nmero do dispositivo de entrada e satisfeito quando o nmero lido menor que 50.
write,
que aceita um argumento e imprime no dispoditivo de sada o termo instanciado a este argumento. Se o argumento contm variveis no instanciadas, estas sero impressas com seus nomes internos, geralmente consistindo de um _ seguido de um cdigo interno alfanumrico. Alm de Prolog o predicado pr-denido linha na impresso (
newline ).
nl:
nl,
write,
existe em
read,
write,
nl
s so sa-
47
6.2
Como vimos, as constantes do tipo caractere em Prolog so denotadas usandose apstrofes, por exemplo, log oferece o predicado pr-denido
'e', '\n', etc. Para a leitura de caracteres, Proget_char(X), que satisfeito unicando
possvel que
em alguns sistemas a entrada s venha a Prolog linha a linha, o que signica que at que seja teclado um ENTER o interpretador no recebe nenhum caractere. Assim como acontece com pendentemente de especial
read, o caractere lido consumido indeget_char(X) ser satisfeito ou no. O predicado get_char
retornado.
end_of_file
A ttulo de exemplo, eis abaixo um predicado que l uma linha de caracteres e informa o nmero de caracteres na linha, exceto o
conta_linha(N) :- conta_aux(0, N). conta_aux(A, N) :- get_char('\n'), !, A = N. conta_aux(A, N) :- A1 is A + 1, conta_aux(A1, N). conta_aux(A, N) satisfeito quando o nmero de caracteres a serem lidos at o \n somado a A d N. Observe que no correto colocar um get_char na segunda clusula de conta_aux, pois um caractere foi consumido na chamada da primeira clusula independentemente de ter sido \n ou
O predicado no. Para escrever caracteres, h o predicado pr-denido Se
put_char(X),
onde
48
6.3
current_input(X)
em Prolog.
H um predicado
entrada de dados. Normalmente, este dispositivo o teclado, que indicado em Prolog pelo tomo especial
user_input.
H um predicado
corrente de sada
instancia
em Prolog.
current_output(X)
dispositivo
que Nor-
malmente, este dispositivo a tela do computador, que em Prolog indica-se pelo tomo especial
possvel trocar os dispositivos correntes de entrada e sada para arquivos, por exemplo. Para tanto, necessrio inicialmente abrir um arquivo atravs do predicado pr-denido
open.
arq.txt.
?- open('arq.saida', write, X). X a um dispositivo de sada que direciona os dados para o arquivo arq.saida. Note que o segundo argumento de open determina que tipo de
vai associar dispositivo est sendo criado. Aps abrir um arquivo, associando-o a um dispositivo (tambm chamado de
stream
dicados pr-denidos
set_input
set_output,
como argumento e tornam-no o dispositivo corrente de entrada ou sada, respectivamente. Assim, um programa em Prolog que pretenda usar um arquivo como entrada deve proceder da seguinte forma:
programa :49
Stream,
6.4
Ao escrevermos programas em Prolog, geralmente colocamos todas as clusulas dos predicados que queremos denir num arquivo, que depois carregamos no sistema Prolog. Para carregar arquivos existe um predicado pr-denido em Prolog chamado arquivo, a meta
consult. Quando X est instanciado ao nome de um consult(X) causa a leitura e armazenamento no banco de
dados de Prolog das clusulas contidas neste arquivo. Esta operao to comum que h uma abreviatura para ela: colocar vrios nomes de arquivos numa lista e us-la como pergunta para consult-los todos:
consult
6.5
Operadores
Como dissemos anteriormente, operadores conferem maior legibilidade, permitindo que certos funtores sejam lidos e escritos de forma prexa, inxa ou
50
prexa. Para tanto, necessrio tambm informar a precedncia e a associatividade destes operadores. Apenas funtores de aridade um ou dois podem ser operadores. Prolog oferece um predicado pr-denido nir novos operadores. O argumento
inteiro entre 1 e 1200. Quanto mais alto este nmero, maior a precedncia. O argumento
mentos.
Na primeira linha temos portanto especicaes para operadores Na segunda linha, especicaes para operadores unrios
binrios inxos.
x e y do informaes sobre a associatividade. Numa expresso sem x signica qualquer expresso contendo operadores de precedncia estritamente menor que a de f, enquanto y signica qualquer expresso contendo operadores de precedncia menor ou igual a de f. Assim, em particular yfx signica que o operador associa esquerda, e xfy signica que o operador associa direita. Se um operador declarado com xfx, ele no
As letras parnteses, associa. Para exemplicar, eis a denio de alguns dos operadores em Prolog vistos at agora.
???????-
op(1200, xfx, ':-'). op(1200, fx, '?-'). op(1000, xfy, ','). op(900, fy, '\+'). op(700, xfx, '='). op(700, xfx, '<'). op(700, xfx, '>').
51
????????-
xfx, 'is'). yfx, '+'). yfx, '-'). yfx, '*'). yfx, '//'). yfx, '/'). yfx, 'mod'). fy, '-').
Exerccios
estrelas(N) guess(N)
que imprime
caracteres * no
N,
e imprime Muito
N.
o caso, orientando o usurio na direo certa. 3. Escreva um predicado que l uma linha e imprime a mesma linha trocando todos os caracteres
'a'
por
'b'.
52
Neste captulo veremos alguns predicados pr-denidos importantes que no foram tratados at agora. Para organizar a exposio, vamos dividi-los em vrias partes: verdadeiros, tipos, banco de dados, listas e conjuntos, e outros.
7.1
true
Verdadeiros
satisfeito sempre, s uma vez. satisfeito sempre, inclusive em todas as ressatisfaes.
repeat
7.2
var(X)
Tipos
satisfeito quando
novar(X) atom(X)
satisfeito quando
contrrio de
var(X). X
satisfeito quando
number(X) atomic(X)
X X
53
7.3
Banco de dados
satisfeito uma vez, e lista todas as clusulas do banco de dados. satisfeito uma vez, e lista todas as clusulas do predicado
listing
listing(P)
P.
asserta(X), assertz(X) so satisfeitos uma vez, e adicionam a clusula X ao banco de dados. O predicado asserta adiciona a clusula nova antes das outras do mesmo predicado. O predicado assertz adiciona
a clusula nova
retract(X)
do banco de dados.
7.4
Listas
satisfeito quando
last(X, L)
L. M.
reverse(L, M)
L L.
a reversa da lista
delete(X, L, M)
o de todas as ocorrncias de
em
7.5
subset(X, Y)
elementos de
esto em
Y.
um subconjunto de
Y,
isto , todos os
lista
union(X, Y, Z) satisfeito quando a lista Z contm todos os elementos que esto em X ou em Y, e apenas estes.
54
7.6
Outros
satisfeito se
X =.. L
e os argumentos de
?- gosta(maria, pedro) =.. L. L = [gosta, maria, pedro] ?- X =.. [a, b, c, d]. X = a(b, c, d) random(N)
em SWI Prolog um operador que pode ser usado em uma expresso aritmtica direita de intervalo 0 a
N-1.
Exemplo:
aleatrio no
findall(X, M, L)
L a uma lista contendo todos os objetos X para os quais a meta M satisfeita. O argumento M um termo que ser usado como meta. A varivel X deve aparecer em M. Exemplo: findall(X, member(X,[a,b,c]), L) far com que L seja instanciada com a prpria lista [a,b,c].
instancia metas satisfeita. Em geral, pode ser substitudo por duas clusulas. Por exemplo,
um operador binrio que signica ou. satisfeito quando uma das duas
55
A melhor maneira de evitar ou minimizar erros programar com cuidado, seguindo as regras de estilo, consagradas ao longo de vrias dcadas pelos melhores programamdores. O provrbio melhor prevenir do que remediar aplica-se muito bem neste cenrio. Seguem-se algumas recomendaes de estilo ao escrever programas em Prolog.
Coloque em linhas consecutivas as clusulas de um mesmo predicado, e separe cada predicado do prximo com uma ou mais linhas em branco. Se uma clusula cabe toda dentro de uma linha (at cerca de 70 caracteres), deixe-a em uma linha. Caso contrrio, coloque apenas a cabea e o :- na primeira linha, e, nas linhas subseqentes, coloque as submetas do corpo, indentadas com TAB e terminadas por vrgula, exceto a ltima, que terminada com ponto nal.
Evite o uso de ;, substituindo-o por mais de uma clusula quando possvel. Use variveis annimas para variveis que ocorrem apenas uma vez numa clusula.
56
Ao lado destas recomendaes gerais, bom estar atento aos seguintes cuidados ao denir um predicado:
Verique se seu nome est digitado corretamente em todas as ocorrncias. Erros de digitao so comuns. Verique o nmero de argumentos e certique-se de que combina com o seu projeto para este predicado. Identique todos os operadores usados e determine sua precedncia, associatividade e argumentos para vericar se esto de acordo com o planejado. Em caso de dvidas, use parnteses.
Observe o escopo de cada varivel. Observe quais variveis vo compartilhar o mesmo valor quando uma delas car instanciada. Observe se todas as variveis da cabea de uma regra aparecem no corpo da regra.
Tente determinar quais argumentos devem vir instanciados ou no instanciados em cada clusula. Identique as clusulas que representam condies de parada. Verique se todas as condies de parada esto contempladas.
Fique atento tambm para certos erros comuns que costumam assolar os programas feitos s pressas:
No esquea o ponto nal ao temino de cada clusula. arquivo, certique-se de que haja um nal.
newline
No nal do
Verique o casamento dos parnteses e colchetes. Um bom editor (por exemplo, Emacs) pode ajudar nesta tarefa. Cuidado com erros tipogrcos nos nomes de predicados pr-denidos. Tenha sempre mo (ou Web) um manual completo da implementao de Prolog que voc est usando. Consulte-o para certicar-se do uso correto dos predicados pr-denidos em seu programa.
57
8.1
Depurao
Programas feitos com cuidado tendem a apresentar menos erros, mas difcil garantir que no haver erros. Caso seu programa no esteja funcionando, ou seja, provocando erros de execuo, dando a resposta errada ou simplesmente respondendo no, voc pode usar os potentes recursos de depurao de Prolog para localizar e corrigir os erros. H predicados pr-denidos para ajud-lo nesta tarefa. Nesta seo descreveremos os predicados de depurao existentes na implementao SWI Prolog. Outras implementaes podem ter predicados ligeiramente diferentes para depurao. O predicado
trace,
CALL quando ocorre uma tentativa de satisfao da meta EXIT quando a meta satisfeita REDO quando ocorre uma tentativa de ressatisfao da meta FAIL quando a meta falha
trace, h o predicado notrace. O predicado spy(P) P, ou seja, faz com que os eventos relacionados s metas do predicado P sejam acompanhados. Para cancelar este efeito, use nospy(P). O predicado debugging, sem arugmentos, indica o status da depurao e lista todos os
Para cancelar o efeito de espia predicados que esto sob espionagem. Quando o acompanhamento de metas est ligado, Prolog pra a execuo em cada evento relevante e nos mostra o evento e a meta que est sendo examinada. Neste ponto temos controle sobre como continuar o acompanhamento, com vrias opes. As opes so escolhidas por teclas, geralmente a primeira letra de um verbo em ingls que nos lembra a ao a realizar. A Tabela 8.1 contm algumas das opes disponveis.
58
Opo w c s l r f b a
Descrio imprime a meta segue para o prximo evento salta at o prximo evento desta meta salta at o prximo evento acompanhado volta primeira satisfao da meta causa a falha da meta inicia uma sesso recursiva do interpretador interrompe a depurao
59
Captulo 9 Gramticas
Um dos principais usos de Prolog em processamento de linguagens naturais. Seu emprego to intenso nesta rea que Prolog oferece mecanismos especcos para tratar este problema. mecanismos. Nesta seo conheceremos alguns destes
9.1
Para enteder uma frase numa lngua qualquer, o primeiro passo geralmente consiste em vericar se a frase segue as regras gramaticais da lngua. Computacionalmente, uma das maneiras mais simples de fazer esta vericao usando gramticas livres de contexto, como a que especicamos abaixo:
sentenca > sujeito, predicado. sujeito > artigo, substantivo. predicado > verbo. predicado > verbo, objeto. artigo > [o]. artigo > [a].
60
substantivo > [pera]. substantivo > [homem]. verbo > [come]. verbo > [canta]. objeto > artigo, substantivo.
A gramtica consiste em um certo nmero de regras, que dizem como os diversos tens da frase podem ser decompostos. Por exemplo, as regras acima denem que uma sentena vlida deve ser composta de um sujeito seguido de um predicado. Por sua vez, um sujeito formado por um artigo seguido de um substantivo. E assim por diante. Desta forma, para vericar se uma sentena vlida, devemos tentar encaixla na denio acima. Tome como exemplo a frase o homem come a pera. Ela pode ser encaixada na gramtica que demos da maneira indicada na Figura 9.1
sentenca
sujeito
predicado
homem
verbo
objeto
come
pera
61
Ao denir os diversos itens da frase, h sempre um que o principal, do qual emanam todos os demais. No nosso caso, este item sentenca, denido na primeira regra. E, ao denir cada item em funo de outros, fatalmente acabamos chegando aos itens chamados terminais, para os quais a denio dada em termos de exemplos concretos. Os itens verbo, artigo e susbtantivo so terminais na gramtica dada anteriormente. Observe que indicamos isto usando uma notao de lista para os exemplos. Pois bem, o problema da anlise lxica e dada uma frase qualquer, determinar se ela se encaixa numa descrio de gramtica cmo a que demos nesta seo, e construir uma rvore lxica para ela, nos moldes da Figura 9.1. Um programa que faa isto chamado de analisador lxico. A formalizao de regras sintticas que ilustramos nesta seo chamada de DCG, sigla do ingls
log fornecem mecanismos para lidar com estas gramticas e executar anlise lxica, complementada por vrias funcionalidades extras, como veremos no restante deste captulo.
9.2
Ao realizar anlise lxica em Prolog, usual representar palavras por tomos e frases por listas de tomos. Assim, a frase o homem come a pera seria representada pela lista
62
est agora sendo umada em dois sentidos diferentes. Um deles so os predicados em Prolog. O outro o predicado que um item, ou seja, uma parte, de uma frase vlida. Cuidado para no confundir estes dois usos! Continuando, seria interessante ter predicados (de Prolog) para validar os
sujeito(X) que satisfeito quando X representa um sujeito vlido, e predicado(X) que satisfeito quando X representa um predicado vlido. Com isto, poderamos escrever o predicado sentenca em funo de outros, como segue:
outros itens da frase, por exemplo, um predicado
append, que quebra a frase inicial de todas as formas possveis sentenca possa funcionar,
e testa, para cama uma delas, se os pedaos resultantes podem ser vistos como sujeitos e predicados. Para que o predicado algo como: preciso denir todos os outros dos quais depende. A denio nal caria
sentenca(X) :append(Y, Z, X), sujeito(Y), predicado(Z). sujeito(X) :append(Y, Z, X), artigo(Y), substantivo(Z). predicado(X) :- verbo(X). predicado(X) :append(Y, Z, X), verbo(Y), objeto(Z). artigo([o]). artigo([a]). substantivo([pera]). substantivo([homem]). verbo([come]). verbo([canta]).
63
append
em geral apenas uma ou duas delas sero corretas. O mesmo acontece nos pedaos de frases passados aos predicados de todos os intens tornando a busca ineciente. Mas, como melhorar a performance? cada item tenha no um mas A resposta est nos acumuladores,
que estudamos na Seo 4.5. Comeamos por fazer com que o predicado de
sujeito:
sujeito(X, Y)
satisfeito quando
X Y.
64
Para ajudar a entender o conceito, damos a seguir algumas perguntas que seriam respondidas armativamente com esta nova interpretao:
????-
homem, come, a pera], [come, a, pera]). pera, canta], [canta]). homem, come, a pera], X). pera, canta], X). X
ca instanciada com o que sobrar
Precisamos tambm modicar as denies dos predicados para acomodar o novo signicado. Por incrvel que parea, as denies cam mais simples, e evitam o uso de com:
append.
sujeito, camos
X deixando uma cauda igual a Y se X deixando uma cauda Z, e no incio desta cauda Z existe um substantivo, deixando uma cauda Y. A Figura 9.2 mostra o que seriam os pedaos X, Y e Z num caso prtico.
o homem come a pera
Y Z X
Figura 9.2: Valor dos parmetros
X, Y e Z numa anlise lxica para sujeito. sujeito lembra muito a segunda clu-
append.
65
sentenca(S0, S) :- sujeito(S0, S1), predicado(S1, S). sujeito(S0, S) :- artigo(S0, S1), substantivo(S1, S). predicado(S0, S) :- verbo(S0, S). predicado(S0, S) :- verbo(S0, S1), objeto(S1, S). artigo([o|S], S). artigo([a|S], S). substantivo([pera|S], S). substantivo([homem|S], S). verbo([come|S], S). verbo([canta|S], S). objeto(S0, S) :- artigo(S0, S1), substantivo(S1, S).
Observe como a nova denio se reete nos itens terminais. Eles tambm tm dois parmetros, sendo o primeiro a entrada e o segundo, o resto aps o terminal. No caso dos terminais, onde temos tomos concretos para o item, o segundo parmetro simplesmente a cauda do primeiro, aps consumido o tomo em questo. Estas novas denies tornam o programa mais eciente, mantendo-o correto. Porm, ainda d pra melhorar a forma, simplicando o trabalho do programador, como veremos na prxima seo.
9.3
SWI-Prolog, assim como vrias outras implementaes, oferece uma maneira mais conveniente de escever gramticas livres de contexto. Basicamente, tudo o que temos que fazer descrever a gramtica exatamente como foi feito no incio deste captulo, usando o funtor
66
explicada na Seo 9.2, gerando um predicado de dois parmteros para cada item. Para test-lo, pode-se usar perguntas como as seguintes:
?- sentenca([o, homem, come, a, pera], [ ]). yes ?- sujeito([o, homem, canta], X). X = [canta]
9.4
Argumentos adicionais
Alm dos dois argumentos que a notao para regras gramaticais automaticamente cria, possvel acrescentar argumentos adicionais para propsitos especcos. Vamos trabalhar um exemplo onde esta funcionalidade pode ser til. Trata-se da concordncia em nmero entre sujeito e verbo. Sentenas como os homens come a pera ou ento o homem comem a pera no so corretas, mas seriam aceitas pela extenso natural de nossa gramtica inicial ao incluir o artigo os, o substantivo homens e o verbo comem, ou seja, as formas plurais de itens terminais j presentes na gramtica. Para conseguir a concordncia em nmero entre o sujeito e o predicado, criaremos um argumento adicional para indicar se a frase est no singular ou no plural. Este argumento ser passado a todos os itens, e servir para garantir que sujeitos no singular combinem-se apenas com predicados no plural para constituir frases corretas. A gramtica modicada car assim:
sentenca > sentenca(X). sentenca(X) > sujeito(X), predicado(X). sujeito(X) > artigo(X), substantivo(X). predicado(X) > verbo(X). predicado(X) > verbo(X), objeto(_).
67
artigo(singular) > [o]. artigo(singular) > [a]. artigo(plural) > [os]. artigo(plural) > [as]. substantivo(singular) > [pera]. substantivo(singular) > [homem]. substantivo(plural) > [peras]. substantivo(plural) > [homens]. verbo(singular) > [come]. verbo(singular) > [canta]. verbo(plural) > [comem]. verbo(plural) > [cantam]. objeto(X) > artigo(X), substantivo(X).
Note que as regras continuam essencialmente as mesmas, apenas com o argumento adicional indicando se a frase est no singular ou no plural. Nos itens terminais, foi necessrio acrescentar fatos adicionais com as verses dos itens no prural. Agora nossas regras so capazes de vericar a concordncia em nmero:
?- sentenca(X, [os, homens, comem, as, peras], [ ]). X = plural ?- sentenca(X, [o, homens, come, as, pera], [ ]). no
Observe ainda que, na segunda clusula para predicado, a concordncia se d entre predicado e verbo, mas o objeto no precisa concordar com este verbo, visto que ele est ligado ao sujeito. Assim, frases como
68
Bibliograa
Programming in Prolog:
00678-8.
69