Você está na página 1de 70

MC336 - Paradigmas de programao Prolog

Joo Meidanis

c Copyright 2011 J. 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

Estruturas de dados e recurso


4.1 4.2 4.3 4.4 4.5 Estruturas como rvores Listas . . . . . . . . . . . . . . . . . . . . .

24
24 25 28 31 33

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Juntando listas . . . . . . . . . . . . . . . . . . . . . . . . . .

Acumuladores . . . . . . . . . . . . . . . . . . . . . . . . . . .

Backtracking
5.1 5.2 5.3

e o corte

36
37 39 39 40 41 42 42

Gerando mltiplas solues . . . . . . . . . . . . . . . . . . . . O corte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Usos do corte 5.3.1 5.3.2 5.3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . .

Conrmando a escolha certa . . . . . . . . . . . . . . . Combinao corte-falha . . . . . . . . . . . . . . . . . . Limitando buscas . . . . . . . . . . . . . . . . . . . . .

5.4

Cuidados com o corte . . . . . . . . . . . . . . . . . . . . . . .

Entrada e sada de dados


6.1 6.2 6.3 6.4 6.5 Leitura e escrita de termos . . . . . . . . . . . . . . . . . . . . Leitura e escrita de caracteres . . . . . . . . . . . . . . . . . .

46
46 48 49 50 50

Ler e escrever arquivos . . . . . . . . . . . . . . . . . . . . . . Carregando um banco de dados Operadores . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

Predicados pr-denidos
7.1 7.2 7.3 7.4 7.5 7.6 Verdadeiros . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53
53 53 54 54 54 55

Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Banco de dados . . . . . . . . . . . . . . . . . . . . . . . . . . Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Conjuntos (listas sem repeties)

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

deve ser feito, prescreve-se

como

isto deve ser

ming in Prolog

Program-

[1]. Basicamente, o material apresentado aqui a traduo

das partes deste livro selecionadas para a disciplina MC600.

1.1

Objetos e relaes

Prolog lida com

objetos

relaes

entre eles. A palavra objeto no tem o

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

que engloba todos os dados e tambm

os programas nesta linguagem.

1.2

Programao em Prolog

Um programa em Prolog composto de:

fatos sobre certos objetos regras de inferncia perguntas sobre os objetos

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

os tipos de sistemas operacionais.

1.3

Fatos

Eis alguns exemplos de como se informam fatos a Prolog:

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

Uma pergunta em Prolog tem a forma:

?- 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

humano(socrates). humano(aristoteles). ateniense(socrates).


e a pergunta:

?- 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, flores). gosta(maria, pedro). gosta(paulo, maria).


Se zermos a pergunta:

?- 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

inicialmente, unicam com qualquer termo.

Prolog examina

os fatos na ordem em que aparecem no banco de dados, e portanto o fato

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,

ento Prolog respondeu Se teclarmos

Neste ponto Prolog aguarda novas instrues.

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.

?- gosta(X, paulo). X = maria ; no

pergunta inicial primeira resposta no h mais respostas

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:

gosta(maria, chocolate). gosta(maria, vinho).


8

gosta(pedro, vinho). gosta(pedro, maria).


A pergunta

?- gosta(pedro, maria), gosta(maria, pedro).


signica Ser Pedro gosta de Maria

Maria gosta de Pedro?. A vrgula

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.

Prolog tentar satisfazer as metas uma a uma. No caso em

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:

?- gosta(maria, X), gosta(pedro, X).


Prolog tenta satisfazer a primeira meta; caso consiga, manter uma marca no banco de dados no ponto onde houve unicao e tenta a segunda meta. Se a segunda meta tambm satisfeita, Prolog coloca uma outra marca para a segunda meta. Observe que cada meta tem sua prpria marca no banco de dados. Se a segunda meta falhar, Prolog tentar ressatisfazer a meta anterior (neste caso, a primeira) a partir da marca desta meta. O caso em questo ilustrativo do que chamamos de backtracking pois os seguintes eventos ocorrem:

1. a primeira meta encontra o fato unicador A varivel

instanciada a

gosta(maria, chocolate). chocolate em todas as ocorrncias de X

na pergunta.

Prolog marca esta posio para a primeira meta e a

instanciao de

X. gosta(pedro, chocolate) devido instan-

2. a segunda meta, que virou ciao de

X, no unica com nada no banco de dados, e por isso a meta


9

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

uma armao geral sobre objetos e seus relacionamentos. Por

exemplo, suponha que queremos representar a seguinte dependncia entre

Pedro gosta de todo mundo que gosta de vinho,

o que pode ser reescrito como:

10

Pedro gosta de

se

gosta de vinho.

Em Prolog, regras consistem de uma

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) :- gosta(X, vinho).


Note que regras tambm terminam com ponto nal. A cabea desta regra que est sendo

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:

gosta(pedro, X) :- gosta(X, vinho), gosta(X, chocolate).


ou, em outras palavras, Pedro gosta de qualquer um que goste de vinho e de chocolate. Ou ento, supondo que Pedro gosta de mulheres que gostam de vinho:

gosta(pedro, X) :- mulher(X), gosta(X, vinho).


Note que a mesma varivel

escopo

de

ocorre trs vezes na regra.

Dizemos que o

a regra toda. Isto signica que quando

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

com trs argumentos

11

tal que

pais(X, Y, Z)
e

signica que os pais de

argumento a me e o terceiro o pai de

mulher

homem

X. Usaremos tambm os predicados

so

Z.

O segundo

para indicar o sexo das pessoas.

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,

tem os mesmos pais de

X.

Em Prolog, isto vira:

irma_de(X, Y) :mulher(X), pais(X, M, P), pais(Y, M, P).


Se perguntarmos:

?- 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

Tabela 1.1: Processamento da meta N 1 2 3 4 Meta

irma_de(alice, eduardo).
Marca Variveis

irma_de(alice,eduardo) mulher(alice) pais(alice,M1 ,P1 ) pais(eduardo,vitoria,alberto)

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

Alice irm. A pergunta adequada seria

?- 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

e portanto Prolog responde:

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

para nos referirmos a fatos e regras

coletivamente.

13

Tabela 1.2: Processamento da meta N 1 2 3 4 Meta

irma_de(alice, X).
Marca Variveis

irma_de(alice,X) mulher(alice) pais(alice,M1 ,P1 ) pais(Y1 ,vitoria,alberto)

irma_de,
regra 1

mulher,
fato 1

X1 = alice, Y1 = X
-

pais,
fato 2

pais,
fato 1

M1 = vitoria, P1 = alberto Y1 = eduardo

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-

Como consertar a regra, supondo que existe um que satisfeito quando

dif(X,Y)

so diferentes?

14

Captulo 2 Sintaxe e unicao

Em Prolog h apenas um tipo, chamado de detalhe este tipo e seus subtipos. Um termo pode ser uma

termo, que engloba todas as cons-

trues sintticas da linguagem. Neste captulo vamos estudar com algum

constante, uma varivel, ou uma estrutura.

2.1
As

Constantes
pode ser

constantes

tomos

ou

nmeros.

Quem conhece LISP notar

uma diferena aqui: os nmeros so considerados tomos em LISP, mas em Prolog nmeros no so tomos (embora ambos sejam constantes). Um

livro,

tomo

indica um objeto ou uma relao. Nomes de objetos como

maria,

etc. so tomos. Nomes de tomos sempre comeam com letra mi-

nscula. Nomes de predicados so sempre atmicos tambm. Os grupos de caracteres

?- (usado em perguntas) e :- (usado em regras) so tambm to-

mos. tomos de comprimento igual a um so os

caracteres,

que podem ser

lidos e impressos em Prolog, como veremos no captulo sobre entrada e sada. Em relao a

nmeros,

Prolog acompanha as outras linguagens, permitindo

inteiros positivos e negativos, nmeros em ponto utuante usando ponto

15

decimal e opcionalmente expoente de dez. vlidos:

Alguns exemplos de nmeros

0, 1, -17, 2.35, -0.27653, 10e10, 6.02e-23

2.2

Variveis

Sintaticamente, as

variveis

tm nomes cujo primeiro caractere uma le-

tra maiscula ou o sinal de sublinhado ( chamadas de 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

Estruturas podem ser aninhadas.

Se quisermos sosticar a indicao dos

livros, colocando nome e sobrenome do autor para poder diferenciar entre vrios autores com o mesmo sobrenome, podemos usar:

livro(incidente_em_antares, autor(erico, verissimo))


Estruturas podem ser argumentos de fatos no banco de dados:

pertence(pedro, livro(incidente_em_antares, verissimo)).


O nmero de componentes de um funtor a sua igual a zero so na verdade as constantes. estrutura escrita sem os parnteses. s vezes conveniente escrever certas estruturas na forma inxa ao invs de prexa. Quando isto acontece, dizemos que o funtor escrito como

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

O operador unrio de negao em geral prexo, e o operador de

fatorial (!) em geral posxo. A precedncia de

-.

maior que de

e e

A associatividade de todos os operadores aritmticos esquerda, o que

signica que uma expresso como no como

8/(2/2). 2 + 3

8/2/2

ser interpretada como

(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

que ser visto no captulo sobre aritmtica.

17

2.4

Igualdade e unicao

Em Prolog, igualdade signica unicao. Existe um predicado inxo prdenido

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

T 1 = T 2, onde T 1 e T 2 so termos quais-

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?

irmaos(X, Y) :pai(X, PX), pai(Y, PY), PX = PY.

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:

=:= =\= < > =< >=

igual diferente menor maior menor ou igual maior ou igual

Note que em Prolog o comparador menor ou igual

=<,

e no

maioria das linguagens. Isto foi feito para liberar o predicado

<=, que parece

<=

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.

ilegal, mesmo que

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(X, Y) :reinou(X, A, B), Y >= A, Y =< B.


Alguns usos:

?- 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 ser usado.

O seu papel transformar uma estrutura envolvendo operadores aritmticos

is

inxo, e de seu lado direito

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

nmero, caso em que

is testa se o lado esquerdo e direito so iguais, servindo

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

is o nico que tem o poder de calcular resultados de operaes

pop

representar a populao

de um pas em milhes de pessoas, e o predicado um pas em milhes de quilmetros quadrados:

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:

dens(X, Y) :pop(X, P), area(X, A), Y is P/A.


Alguns usos:

?- dens(china, X). X = 80 yes ?- dens(turquia, X). no


22

Os operadores para clculos aritmticos em Prolog incluem pelo menos os seguintes:

+ * / // mod
Exerccios

soma subtrao multiplicao diviso diviso inteira resto da diviso

1. Considere o seguinte banco de dados:

soma(5). soma(2). soma(2 + X). soma(X + Y).


e a meta

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

Captulo 4 Estruturas de dados e recurso

As estruturas de Prolog so muito versteis para represetar estruturas de dados nos programas. Neste captulo veremos alguns exemplos.

4.1

Estruturas como rvores

As estruturas podem ser desenhadas como rvores, onde o funtor ca na raiz e os componentes so seus lhos, como na Figura 4.1.

pais pais(carlos, bete, felipe)

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(sujeito(X), predicado(verbo(Y), objeto(Z)))


Tomando a sentena Pedro ama Maria e instanciando as variveis da estrutura com palavras da sentena, camos com o resultado mostrado na Figura 4.2.

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

f(X, g(X, a))

poderia ser representada como na Figura 4.3. A

gura no mais uma rvore, mas sim um grafo orientado acclico.

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

Figura 4.3: Diagrama mostrando ocorrncias da mesma varivel.

Em Prolog, Uma lista :

ou uma

lista vazia, escrita como [ ], cabea


e a

ou uma estrutura com dois componentes: a

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

em Prolog. Em LISP, esta mesma lista seria representada como

(c .

()))).
. . .

.(a, .(b, .(c, [ ]))), (a . (b .

[]

Figura 4.4: Uma lista em Prolog.

A exemplo de LISP, Prolog tambm tem uma maneira alternativa, mais prtica, de denotar listas, que no usa o funtor  . explicitamente. Basta colocar

26

os elementos separados por vrgulas entre colchetes: listas:

[a, b, c].

Qualquer

termo pode ser componente de uma lista, por exemplo, variveis ou outras

[o, homem, [gosta, de, pescar]] [a, V1, b, [X, Y]]


Listas so processadas dividindo-as em cabea e cauda (exceto a lista vazia). Para quem conhece LISP, esta diviso anloga a tomar car e cdr de uma lista. Observe alguns exemplos:

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

Esta notao muito usada para decompor uma lista

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],

que no lista porque sua cauda

no uma lista nem a lista vazia.

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

Suponha que tenhamos uma lista de cores preferidas, por exemplo

[azul, verde, vermelho, amarelo]


e queiramos saber se uma determinada cor est nesta lista. A maneira de fazer isto em Prolog ver se a cor est na cabea da lista; se estiver, camos satisfeitos; se no estiver, procuramos na cauda da lista, ou seja, vericamos a cabea da inicial. Para implementar isto em Prolog, primeiramente estabelecemos que trata-se de denir uma

cauda agora.

E a cabea da cauda da cauda a seguir. Se chegarmos

ao m da lista, que ser a lista vazia, falhamos: a cor no estava na lista

relao

entre objetos e listas onde eles aparecem. tal que

Escreve-

remos um predicado

member

member(X, Y)

verdadeiro quando o

28

termo

um elemento da lista

meiro lugar, um fato que que pode ser escrito assim:

Y.

H duas condies a vericar.

Em pri-

membro de

se

for igual cabea de

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.

A segunda (e ltima) regra diz que

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,

member(X, [_|Y]) :- member(X, Y).


Observe novamente o uso da varivel annima. predicado Nesta regra, no nos inte-

ressa o que est na cabea da lista, que foi tratada na primeira clusula do

member.

Observe ainda que trocamos

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

?- member(d, [a, b, c, d, e, f, g]). yes ?- member(2, [3, a, d, 4]). no


29

parada

Para denir um predicado resursivo, preciso atentar para as e para o

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

unicar com a cabea do

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

que a lista dada. Assim

temos certeza de acabaremos por encontrar a lista vazia, a menos claro que

pai(X, Y) :- filho(Y, X). filho(X, Y) :- pai(Y, X).


Claramente, Prolog no conseguir inferir nada a partir destas denies, pois entrar num

loop

innito.

Outro cuidado com a ordem das clusulas na denio de um predicado. Considere a seguinte denio:

homem(X) :- homem(Y), filho(X, Y). homem(adao).


Ao tentar responder pergunta

?- 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

homem(adao). homem(X) :- homem(Y), filho(X, Y).


Em geral, aconselhvel colocar os fatos antes das regras. chamadas com variveis. Considere mais um exemplo: Os predicados

podem funcionar bem em chamadas com constantes, mas dar errado em

lista([A|B]) :- lista(B). lista([ ]).


a prpria denio de lista. Ela funciona bem com constantes:

?- lista([a, b, c, d]). yes ?- lista([ ]). yes ?- lista(f(1, 2, 3)). no


Mas, se perguntarmos

?- lista(X).
Prolog entrar em ver o problema.

loop.

Mais uma vez, inverter a ordem das clusulas resol-

4.4

Juntando listas
append
usado para juntar duas listas formando uma terceira.

O predicado

Por exemplo, verdade que

append([a, b, c], [1, 2, 3], [a, b, c, 1, 2, 3]).


31

Este predicado pode ser usado para criar uma lista que a concatenao de duas outras:

?- append([alfa, beta], [gama, delta], X). X = [alfa, beta, gama, delta]


Mas tambm pode ser usado de outras formas:

?- append(X, [b, c, d], [a, b, c, d]). X = [a]


A sua denio a seguinte:

append([ ], L, L). append([X|L1], L2, [X|L3]) :- append(L1, L2, L3).


A primeira clusula a condio de parada. A lista vazia concatenada com qualquer lista resulta na prpria lista. seguintes princpios: A segunda condio se apia nos

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.

append para obter a concatenao do item 2

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

L igual a N. Prolog possui o predicado

listlen listlen(L, N) satis-

para esta nalidade, mas vamos denir nossa prpria

verso. Eis a denio sem acumuladores:

listlen([ ], 0). listlen([H|T], N) :- listlen(T, N1), N is N1 + 1.


Observe que o primeiro argumento deve vir instanciado para que esta denio funcione. A denio com acumulador baseia-se no mesmo princpio recursivo, mas acumula a resposta a cada passo num argumento extra. Usamos um predicado auxiliar meta

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

[a, b, c, d, e]: listlenacc([a, b, c, d, e], N) lenacc([a, b, c, d, e], 0, N) lenacc([b, c, d, e], 1, N)


33

lenacc([c, d, e], 2, N) lenacc([d, e], 3, N) lenacc([e], 4, N) lenacc([ ], 5, N)


onde todos os

so variveis distintas mas ligadas entre si no procesamento

das regras denidas. Esta ltima meta unica com a condio de parada (a primeira clusula de

listlen

lenacc) e instancia N como 5, o que faz com que o N de

seja tambm igual a 5.

Acumuladores no precisam ser nmeros inteiros. Considere a seguinte denio do predicado

rev,

que inverte a ordem dos elementos de uma lista

(Prolog tem sua prpria verso chamada

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

L3 so distintas mas ligadas. Os elementos em L2 a cada chamada. Os elementos saem e


No nal, a clusula de

entram pela frente nas listas, combinando com as operaes de lista em Prolog que s permitem manipular diretamente a cabea. parada instancia

L3

reversa.

Ao lidar com acumuladores, muito importante no perder de vista o

nicado

sig-

dos predicados a denir.

Neste exemplo, essencial entender o

34

que signica o predicado quando a reversa da

revacc: a meta revacc(L1, L2, L3) lista L1 concatenada com a lista L2 resulta

satisfeita em

L3.

De

posse desta denio em palavras mais fcil chegar denio em Prolog.

Exerccios

1. Escreva um predicado o ltimo elemento da

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

a lista obtida pela remoo da primeira ocorrncia de 3. Escreva um predicado

X X

em

L1. L1.

L2 L2

que satisfeito quando em

a lista obtida pela remoo de todas as ocorrncias de

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.

Estas metas so processadas na ordem dada na tentativa de

satisfaz-las. 2. a tentativa de satisfao de uma meta

consiste numa busca no banco

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

k.1, k.2, etc.

A satisfao

agora depende da satisfao conjunta de todas as submetas.

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

(retrocesso). Se no existir meta

anterior, Prolog pra e informa o resultado (negativo) da busca.

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;

Neste captulo vamos examinar o processo de certas condies.

backtracking

com mais detalhe

e conhecer o corte, um mecanismo especial que inibe o

backtracking

em

A notao  k.m para indicar metas geradas por um casamento da meta

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

Gerando mltiplas solues

Considere o seguinte banco de dados.

pai(maria, pai(pedro, pai(sueli, pai(jorge,

jorge). jorge). haroldo). eduardo).

pai(X) :- pai(_,X).
H dois predicados

pai:

um binrio, cujos argumentos so uma pessoa e seu

pai, nesta ordem, e um unrio, que baseado no outro, e diferencia pais de no-pais. A pergunta

?- pai(X).
37

causar o seguinte resultado:

X = X = X = X = no

jorge ; jorge ; haroldo ; eduardo ;

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-

mente, quando a lista contm repeties. Uma meta do tipo

member(a, [a, b, c, a, c, a, d, a, b, r, a])


pode ser satisfeita vrias vezes antes de falhar (no caso ilustrado, cinco vezes). H situaes onde gostaramos que ela fosse satisfeita uma vez s. Podemos instruir Prolog a descartar escolhas desnecessrias com o uso do corte. As situaes mencionadas acima envolviam limitar um nmero nito de alternativas a uma s. H casos onde precisamos gerar um nmero innito de alternativas, no porque pretendemos consider-las todas, mas porque no sabemos de antemo quando vai aparecer a alternativa que nos interessa. Considere a seguinte denio de predicado:

inteiro(0). inteiro(N) :- inteiro(M), N is M + 1.


A pergunta

?- 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.

Isto pode ser impor-

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

k.l, sua meta me a meta

k . Numa tentativa k como um todo, e anterior a k .

de ressatisfao do corte, ele causa a falha da meta

backtracking

continua tentando ressatisfazer a meta

Vejamos um exemplo. Considere a regra

g :- a, b, c, !, d, e, f.
Prolog realiza o sucesso de

backtracking

normalmente entre as metas

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

H trs usos principais do corte:

indicar que a regra certa foi encontrada combinao corte-falha indicando negao limitar uma busca nita ou innita

39

5.3.1 Conrmando a escolha certa


Os predicados em Prolog tm em geral vrias clusulas. entrada. Em alguns predicados, diferentes clusulas so dirigidas a diferentes padres de dados de s vezes possvel selecionar qual regra apropriada para cada entrada s pela sintaxe da entrada, por exemplo, uma regra com

[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

fat(0, 1) :- !. fat(N, F) :- N1 is N - 1, fat(N1, F1), F is F1 * N.


O corte aqui serve para impedir que uma meta da forma corte. Com o corte:

fat(O, F) case com

a segunda clusula em caso de ressatisfao. Veja o que ocorre com e sem o

?- fat(5, F). F = 120 ; no


Sem o corte:

?- fat(5, F). F = 120 ;


(

loop

innito 

out of memory )

A denio de

fat

acima ainda no a melhor possvel. Veja na seo dos

exerccios o que precisa ser feito para melhor-la.

40

5.3.2 Combinao corte-falha


Existe em Prolog um predicado pr-denido sem argumentos chamado que sempre falha. mente falsa como por exemplo

fail fail.

Pode-se usar em seu lugar qualquer meta incodicional-

0 > 1

mas mais claro e elegante usar

Usado em combinao com o corte, ele pode implementar negao.

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) :- member(X, L), !, fail. nonmember(_, _).


Ao processar uma meta da forma primeira clusula. Se

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

member(X, L) falhar, o corte no ser processado e Prolog tentar nonmember(X, L)


satisfeito, que tambm o que

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:

\+

antecedendo uma meta

signica a negao dela. Por exemplo, podemos denir

nonmember(X, L) :- \+ member(X, L).


Contudo, em geral estas negaes s funcionam para metas onde os argumentos vm todos instanciados.

41

5.3.3 Limitando buscas


Muitas vezes em Prolog usamos um predicado para gerar vrias alternativas que sero testadas por um segundo predicado para escolher uma delas. Em alguns casos, o predicado gerador tem a capacidade de gerar innitas alternativas, e o corte pode ser til para limitar esta gerao. Considere o seguinte predicado para executar diviso inteira. rador Os sistemas

Prolog em geral tm este recurso pr-denido na linguagem, atravs do ope-

//,

mas usaremos esta verso mais ineciente para ilustrar o tema

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

denido anteriormente (pgina 38)

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

Cuidados com o corte

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

member(X, [X|_]) :- !. member(X, [_|Y]) :- member(X, Y).


apropriada. O predicado satisfeito uma nica vez para cada elemento

distinto da lista. Porm, perdemos a possibilidade de us-lo como gerador de mltiplas alternativas:

?- member(X, [b, c, a]). X = b ; no


O caso seguinte ilustrar como o corte pode impedir que o operador de igualdade  = seja substitudo pelo uso de variveis com o mesmo nome. Considere o predicado abaixo, que d o nmero de pais que uma pessoa tem:

pais(adao, 0). pais(eva, 0). pais(_, 2).


Isto , Ado e Eva tm zero pais e qualquer outra pessoa tem dois pais. Se usarmos este predicado para descobrir quantos pais uma pessoa tem, tudo vai bem:

?- pais(eva, N). N = 0 ?- pais(pedro, N). N = 2


Mas quando tentamos vericar uma armao algo inesperado acontece:

?- pais(eva, 2). yes

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:

pais(adao, N) :- !, N = 0. pais(eva, N) :- !, N = 0. pais(_, 2).


Agora as duas primeiras clusulas vo capturar as metas envolvendo Ado e Eva e travar ali com o corte, deixando a vericao do valor de corpo da regra. A concluso nal que ao introduzir cortes para que o predicado sirva a um certo tipo de metas, no h garantia que ele continuar funcionando a contento para outros tipos de metas.

para o

Exerccios
1. Conserte o predicato das onde

fat(N, F) para que no entre em loop

en chama-

um nmero negativo e nem em chamadas vericadoras,

onde ambos

vm instanciados.

2. Algum teve a idia de usar pergunta

nonmember

conforme denido no texto

para gerar todos os termos que

no esto na lista

[a, b, c]

com a

?- nonmember(X, [a, b, c]).


Vai funcionar? Por qu? 3. Suponha que algum queira listar os elementos comuns a duas listas usando a seguinte pergunta:

?- member1(X, [a, b, a, c, a]), member2(X, [c, a, c, a]).


Quais sero os resultados nas seguintes situaes:

44

(a) (b) (c) (d)

member1 member1 member1 member1

sem corte e sem corte e com corte e com corte e

member2 member2 member2 member2

sem corte? com corte? sem corte? com corte?

Relembrando as denies com e sem corte:

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

Captulo 6 Entrada e sada de dados

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

Leitura e escrita de termos


read
para a entrada de termos. A

Prolog oferece o predicado pr-denido meta

read(X)

satisfeita quando

unica com o prximo termo lido no

dispositivo de entrada.

preciso colocar um ponto nal para sinalizar o

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,

ser instanciada ao tomo

46

especial

end_of_file.

um erro tentar ler aps encontrar o m do arquivo.

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.

pequeno :- read(N), N < 50.


Exemplo:

?- pequeno. |: 40. yes


Observe o prompt '|:' usado por Prolog para indicar que est esperando um termo. Para escrever termos, Prolog disponibiliza o predicado pr-denido

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

sem arugmento, que causa mudana de

Assim, se quisermos dividir a sada em vrias

linhas, devemos usar

?- write(pedro), nl, write(ama), nl, write(maria). pedro ama maria yes


Assim como ocorre com tisfeitas na primeira vez.

read,

metas dos predicados

write,

nl

s so sa-

47

6.2

Leitura e escrita de caracteres

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

com o prximo caractere lido do dispositivo de entrada.

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.

falha em tentativas de ressatisfao. Se chegarmos ao m do arquivo, o tomo

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

newline, que indica o m

da linha. Usaremos um acumulador para contar os caracteres at o momento.

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

deve ser um caractere, ou um tomo cujo nome tem apenas um caractere.

estiver no instanciada ou for outro tipo de termo que no os descritos

acima, ocorre erro.

48

6.3

Ler e escrever arquivos

Os predicados de leitura que vimos at agora utilizam sempre o que chamamos de

current_input(X)

dispositivo corrente de entrada


que instancia

em Prolog.

H um predicado

ao dispositivo associado no momento

entrada de dados. Normalmente, este dispositivo o teclado, que indicado em Prolog pelo tomo especial

user_input.
H um predicado

De modo semelhante, a sada de dados feita sempre atravs do

corrente de sada
instancia

em Prolog.

X ao dispositivo associado sada de dados naquele momento. user_output.

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.

Por exemplo, a pergunta

?- open('arq.txt', read, X).


vai instanciar a varivel o arquivo

arq.txt.

X a um dispositivo de entrada que na verdade acessa

De forma semelhante, a pergunta

?- 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

em Prolog), pode-se us-lo como entrada ou sada atravs dos pre-

dicados pr-denidos

set_input

set_output,

que recebem um dispositivo

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

open('arq.txt', read, X), current_input(Stream), set_input(X), codigo_propriamente_dito, set_input(Stream), close(X).


Note que foi salvo o dispositivo anterior na varivel semelhante deve ser usada em relao sada.

Stream,

para ser reesAtitude

tabelecido como dispositivo de entrada ao trmino do programa.

6.4

Carregando um banco de dados

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:

?- [arq1, arq2, arq3].


O predicado

consult

remove as clusulas dos predicados consultados no

banco de dados antes de carregas as novas denies.

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

op(Prec, Espec, Nome) para dePrec indica a precedncia, que um

inteiro entre 1 e 1200. Quanto mais alto este nmero, maior a precedncia. O argumento

Espec serve para denir a aridade, a posio e a associatividade

do operador. Os seguintes tomos podem ser usados no segundo argumento:

xfx xfy yfx yfy fx fy xf yf


Aqui

indica a posio do operador (funtor) e

as posies dos argu-

mentos.

Na primeira linha temos portanto especicaes para operadores Na segunda linha, especicaes para operadores unrios

binrios inxos.

prexos e na ltima linha, para operadores unrios posxos.

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

????????-

op(700, op(500, op(500, op(400, op(400, op(400, op(400, op(200,

xfx, 'is'). yfx, '+'). yfx, '-'). yfx, '*'). yfx, '//'). yfx, '/'). yfx, 'mod'). fy, '-').

Exerccios

1. Escreva um predicado dispositivo de sada. 2. Escreva um predicado nmero

estrelas(N) guess(N)

que imprime

caracteres  * no

que incita o usurio a adivinhar o conforme

N,

e imprime  Muito

N.

O predicado repetidamente l um nmero, compara-o com

baixo!,  Acertou!,  Muito alto!,

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

Captulo 7 Predicados pr-denidos

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

uma varivel no instanciada.

novar(X) atom(X)

satisfeito quando

contrrio de

var(X). X

um termo ou uma varivel instanciada. O

satisfeito quando

um tomo (constante no numrica).

number(X) atomic(X)

satisfeito quando satisfeito quando

X X

um nmero. um tomo ou um nmero.

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

depois das outras do mesmo predicado.

retract(X)

satisfeito uma vez, e remove a clusula

do banco de dados.

7.4

Listas
satisfeito quando

last(X, L)

o ltimo elemento da lista

L. M.

reverse(L, M)

satisfeito quando a lista

L L.

a reversa da lista

delete(X, L, M)

satisfeito quando a lista

o de todas as ocorrncias de

M obtida da lista L pela remo-

em

7.5

Conjuntos (listas sem repeties)


satisfeito quando

subset(X, Y)

elementos de

esto em

Y.

um subconjunto de

Y,

isto , todos os

intersection(X, Y, Z) satisfeito quando a mentos comuns a X e a Y, e apenas estes.

lista

contm todos os ele-

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

X um termo e L uma lista onde aparecem o funtor X na ordem. Exemplos:

?- 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:

is, e produz um inteiro X is random(30000).

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

atomic(X) :- (atom(X) ; number(X)).


equivalente a

atomic(X) :- atom(X). atomic(X) :- number(X).

55

Captulo 8 Estilo e depurao

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 predicados com muitas regras. outros predicados.

Se um predicado tem mais de

cinco ou dez regras, considere a possibilidade de quebr-lo em vrios

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

aps o ltimo ponto

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,

sem argumentos, liga o mecanismo de acompanhamento

de metas. Cada meta impressa nos seguintes eventos:

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

Verbo write creep skip leap retry fail break abort

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

Tabela 8.1: Possveis aes numa parada de 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

O problema da anlise lxica

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

Figura 9.1: Anlise lxica da sentena o homem come a 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

Denite Clause Grammar.

Muitas implementaes Pro-

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

Anlise lxica em Prolog

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

[o, homem, come, a, pera]


Isto posto, natural implementar a anlise lxica como um predicado que ser satisfeito quando a frase dada (em forma de lista) segue as regras gramaticais indicadas, e falha caso contrrio. Assim, teremos um predicado que satisfeito quando vlida. Como testar isto? Bem, segundo as regras, uma sentena vlida deve ser

sentenca(X) X for uma lista de palavras que formam uma sentena

formada por um sujeito seguido de um predicado. Observe que a predicado

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

sentenca(X) :append(Y, Z, X), sujeito(Y), predicado(Z).


Note o uso de

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

objeto(X) :append(Y, Z, X), artigo(Y), substantivo(Z).


Observe que, para os itens terminais, as denies se transformam em fatos Prolog e no em regras Prolog. Note tambm que denies alternativas naturalmente se transformam em clusulas alternativas em Prolog. Agora o programa est completo, e ser capaz de vericar frases de acordo com a nossa gramtica. A pergunta

?- sentenca([o, homem, come, a, pera]). yes


respondida corretamente. Tambm frases gramaticalmente incorretas como

?- sentenca([homem, pera, come, a, o]). no


so classicadas como tais. Apesar de correto, o esquema acima no o mais eciente possvel, pois

append

experimenta todas as combinaes de quebra da frase, sendo que

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

dois parmetros, com o seguinte signicado,

exemplicado abaixo para o predicado

sujeito:

sujeito(X, Y)

satisfeito quando

existe um sujeito no incio da lista e o resto da lista aps o sujeito

X Y.

64

Para ajudar a entender o conceito, damos a seguir algumas perguntas que seriam respondidas armativamente com esta nova interpretao:

????-

sujeito([o, sujeito([a, sujeito([o, sujeito([a,

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

sendo que, nas duas ltimas, a varivel da lista aps um sujeito.

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.

Tomando como exemplo o caso de

sujeito, camos

sujeito(X, Y) :- artigo(X, Z), substantivo(Z, Y).


Ou seja, existe um sujeito no incio de existe um artigo no incio de

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-

Note, porm, que a nova denio de sula da denio de

append.

como se a tivessemos incorporado em cada

item. Vejamos como ca o programa inteiro.

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

Notao para regras gramaticais

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

> para indicar as regras gramaticais.

Prolog sabe traduzir esta notao em clusulas da maneira mais eciente

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

?- sentenca(X, [o, homem, come, as, peras], [ ]). X = singular


so tambm corretamente aceitas e classicadas.

68

Bibliograa
Programming in Prolog:

[1] William F. Clocksin and Christopher S. Mellish.

using the ISO standard.

Springer-Verlag, 5a. edition, 2003. ISBN 3-540-

00678-8.

69

Você também pode gostar