Você está na página 1de 15

Sintaxe e Semântica de Objetos em Prolog

Programas Prolog
Objetos
‰ Nesta aula será vista a sintaxe e (Termos)
semântica de conceitos básicos
em Prolog e introduz objetos de
dados estruturados
Objetos
‰ Os tópicos abordados são: Simples
Estruturas
ƒ Objetos simples (átomos,
números, variáveis)
ƒ Objetos estruturados
ƒ Unificação como operação Constantes
fundamental em objetos Variáveis
(Atômicos)
ƒ Operadores
ƒ Significado declarativo e
Inteligência Artificial procedural
Átomos Números
José Augusto Baranauskas E-mail: augusto@usp.br
Departamento de Física e Matemática – FFCLRP-USP URL: http://dfm.fmrp.usp.br/~augusto
2

Átomos Números
‰ São cadeias compostas pelos seguintes caracteres: ‰ Números usados em Prolog incluem
ƒ letras maiúsculas: A, B, ..., Z
ƒ letras minúsculas: a, b, ..., z números inteiros e números reais
ƒ dígitos: 0, 1, ..., 9
ƒ caracteres especiais: + - * / < > = : . & _ ~ Operadores Aritméticos Operadores Relacionais
‰ Podem ser construídos de três maneiras: adição + X>Y X é maior do que Y
ƒ cadeias de letras, dígitos e o caractere ‘_’, começando com uma subtração - X<Y X é menor do que Y
letra minúscula: anna, nil, x25, x_25, x_25AB, x_, x__y,
multiplicação * X >= Y X é maior ou igual a Y
tem_filhos, tem_um_filho
ƒ cadeias de caracteres especiais: <--->, =====>, ..., .:., ::= divisão / X =< Y X é menor ou igual a Y
ƒ cadeias de caracteres entre apóstrofos: ‘Abraão’, divisão inteira //
X =:= Y X é igual a Y
‘América_do_Sul’, ‘América_Latina’ resto divisão inteira mod
X=Y X unifica com Y
potência **
atribuição is X =\= Y X é diferente de Y

3 4

Números Variáveis
‰ O operador = tenta unificar apenas ‰ São cadeias de letras, dígitos e caracteres ‘_’,
ƒ ?- X = 1 + 2. sempre começando com letra maiúscula ou com
ƒ X = 1 + 2 o caractere ‘_’
‰ O operador is força a avaliação aritmética ƒ X, Resultado, Objeto3, Lista_Alunos, ListaCompras,
ƒ ?- X is 1 + 2. _x25, _32
ƒ X = 3 ‰ O escopo de uma variável é dentro de uma
‰ Se a variável à esquerda do operador is já estiver mesma regra ou dentro de uma pergunta
instanciada, Prolog apenas compara o valor da variável ‰ Isto significa que se a variável X ocorre em duas
com o resultado da expressão à direita de is regras/perguntas, então são duas variáveis
ƒ ?- X = 3, X is 1 + 2. distintas
ƒ X = 3
‰ Mas a ocorrência de X dentro de uma mesma
ƒ ?- X = 5, X is 1 + 2.
ƒ no regra/pergunta significa a mesma variável

5 6

1
Variáveis Variável Anônima
‰ Uma variável pode estar: ‰ Quando uma variável aparece em uma única
ƒ Instanciada: quando a variável já referencia cláusula, não é necessário utilizar um nome para
(está unificada a) algum objeto ela
ƒ Livre ou não-instanciada: quando a variável ‰ Utiliza-se a variável anônima, que é escrita com
não referencia (não está unificada a) um um simples caracter ‘_’. Por exemplo
objeto, ou seja, quando o objeto a que ela ƒ temfilho(X) :- progenitor(X,Y).
referencia ainda não é conhecido
‰ Para definir temfilho, não é necessário o nome
‰ Uma vez instanciada, somente Prolog pode do filho(a)
torná-la não-instanciada através de seu
‰ Assim, é o lugar ideal para a variável anônima:
mecanismo de inferência (nunca o
ƒ temfilho(X) :- progenitor(X,_).
programador)
7 8

Variável Anônima Estruturas


‰ Cada vez que um underscore ‘_’ aparece em uma ‰ Objetos estruturados (ou simplesmente
cláusula, ele representa uma nova variável anônima
estruturas) são objetos de dados que têm vários
‰ Por exemplo
ƒ alguém_tem_filho :- progenitor(_,_). componentes
equivale à: ‰ Cada componente, por sua vez, pode ser uma
ƒ alguém_tem_filho :- progenitor(X,Y). estrutura
que é bem diferente de:
‰ Por exemplo, uma data pode ser vista como uma
ƒ alguém_tem_filho :- progenitor(X,X).
‰ Quando utilizada em uma pergunta, seu valor não é
estrutura com três componentes: dia, mês, ano
mostrado. Por exemplo, se queremos saber quem tem ‰ Mesmo possuindo vários componentes,
filhos mas sem mostrar os nomes dos filhos, podemos
perguntar:
estruturas são tratadas como simples objetos
ƒ ?- progenitor(X,_).

9 10

Estruturas Estruturas

‰ De forma a combinar componentes em um ‰ Qualquer dia em maio pode ser representado


simples objeto, deve-se escolher um pela estrutura:
functor ƒ data(Dia,maio,2003)
‰ Note que Dia é uma variável que pode ser
‰ Um functor para o exemplo da data seria
instanciada a qualquer objeto em qualquer
data momento durante a execução
‰ Então a data de 4 de maio de 2003 pode ‰ Sintaticamente, todos objetos de dados em
ser escrita como: Prolog são termos
ƒ data(4,maio,2003) ‰ Por exemplo, são termos:
ƒ maio
ƒ data(4,maio,2003)
11 12

2
Estruturas Estruturas

‰ Todos os objetos estruturados podem ser ‰ Porexemplo, o triângulo pode ser


representados como árvores representado como
‰ A raiz da árvore é o functor e os filhos da ƒ triângulo(ponto(2,4),ponto(3,6),ponto(4,2))
raiz são os componentes
(3,6) triângulo
‰ Para a estrutura data(4,maio,2003):

data (2,4) ponto ponto ponto


(4,2)

4 maio 2003 2 4 3 6 4 2
13 14

Predicados para Verificação dos


Estruturas
Tipos de Termos
P1=ponto P2=ponto S=seg triângulo

Predicado É verdadeiro se:


ponto ponto ponto ponto ponto
1 1 2 3 var(X) X é uma variável não instanciada

nonvar(X) X não é uma variável ou X é uma variável instanciada


1 1 2 3 4 2 6 4 7 1
atom(X) X é um átomo
(6,4)
integer(X) X é um inteiro
P2=(2,3)
float(X) X é um número real

S T atomic(X) X é uma constante (átomo ou número)


(4,2)

compound(X) X é uma estrutura


(7,1)
P1=(1,1)

15 18

Predicados para Verificação dos


Unificação de Termos
Tipos de Termos
?- var(Z), Z = 2.
Z = 2 ‰ Dois termos unificam (matching) se:
?- Z = 2, var(Z).
no ƒ Eles são idênticos ou
?- integer(Z), Z = 2.
no ƒ As variáveis em ambos os termos podem ser
?- Z = 2, integer(Z), nonvar(Z). instanciadas a objetos de maneira que após a
Z = 2
?- atom(3.14). substituição das variáveis por esses objetos os
no termos se tornam idênticos
?- atomic(3.14).
yes ‰ Por exemplo, há unificação entre os termos
?- atom(==>).
yes
?- atom(p(1)).
ƒ data(D,M,2003) e data(D1,maio,A)
no ƒ instanciando D = D1, M = maio, A = 2003
?- compound(2+X).
yes
19 20

3
Unificação de Termos Unificação de Termos
?- data(D,M,2003) = data(D1,maio,A),
‰ Por outro lado, não há unificação entre os termos
data(D,M,2003) = data(15,maio,A1).
D = 15 ƒ data(D,M,2003) e data(D1,M1,1948)
M = maio ƒ data(X,Y,Z) e ponto(X,Y,Z)
D1 = 15
‰ A unificação é um processo que toma dois termos
A = 2003
A1 = 2003 e verifica se eles unificam
ƒ Se os termos não unificam, o processo falha (e as
?- triângulo = triângulo, ponto(1,1) = X, variáveis não se tornam instanciadas)
A = ponto(4,Y), ponto(2,3) = ponto(2,Z).
X = ponto(1,1)
ƒ Se os termos unificam, o processo tem sucesso e
A = ponto(4,_G652) também instancia as variáveis em ambos os termos
Y = _G652 para os valores que os tornam idênticos
Z = 3

21 22

Unificação de Termos Comparação de Termos


‰ As regras que regem se dois termos S e T Operadores Relacionais

unificam são: X unifica com Y que é verdadeiro quando dois termos são o
mesmo. Entretanto, se um dos termos é uma variável, o
X=Y
ƒ se S e T são constantes, então S e T unificam operador = causa a instanciação da variável porque o
operador causa unificação
somente se são o mesmo objeto X \= Y X não unifica com Y que é o complemento de X=Y
ƒ se S for uma variável e T for qualquer termo, X é literalmente igual a Y (igualdade literal), que é verdadeiro
se os termos X e Y são idênticos, ou seja, eles têm a mesma
então unificam e S é instanciado para T X == Y
estrutura e todos os componentes correspondentes são os
mesmos, incluindo o nome das variáveis
ƒ se S e T são estruturas, elas unificam somente X \== Y X não é literalmente igual a Y que é o complemento de X==Y
se X @< Y X precede Y
™ S e T têm o mesmo functor principal e X @> Y Y precede X
™ todos seus componentes correspondentes unificam X @=< Y X precede ou é igual a Y
X @>= Y Y precede ou é igual a X
23 24

Comparação de Termos Precedência de Termos


?- f(a,b) == f(a,b).
yes
‰ A precedência entre termos simples é
?- f(a,b) == f(a,X). determinado para ordem alfabética ou numérica
no
?- f(a,X) == f(a,Y). ‰ Variável livres @< números @< átomos @<
no estruturas
?- X == X.
yes ‰ Uma estrutura precede outra se o functor da
?- X == Y. primeira tem menor aridade que o da segunda
no
?- X \== Y. ƒ Se duas estruturas têm mesma aridade, a primeira
yes precede a segunda se seu functor é menor que o da
?- X \= Y. outra
no
?- g(X,f(a,Y)) == g(X,f(a,Y)).
ƒ Se duas estruturas têm mesma aridade e functores
yes iguais, então a precedência é definida (da esquerda
para a direita) pelos functores dos seus componentes

25 26

4
Precedência de Termos Unificação de Termos
?- X @< 10. ?- g(X) @< f(X,Y). ‰ Unificação em Prolog é diferente da unificação
yes yes em Lógica
?- X @< isaque. ?- f(Z,b) @< f(a,A). ‰ A unificação Lógica requer a verificação de
yes yes ocorrência de uma variável em um termo (occurs
?- X @< f(X,Y). ?- 12 @< 13. check), que, por razões de eficiência, não é
yes yes implementado em Prolog
?- 10 @< sara. ?- 12.5 @< 20. ‰ Mas de um ponto de vista prático, a aproximação
yes yes de Prolog é bem adequada
?- 10 @< f(X,Y). ?- g(X,f(a,Y)) @<
‰ Exemplo:
yes g(X,f(b,Y)).
ƒ ?- X = f(X).
?- isaque @< sara. yes ƒ X = f(f(f(f(f(f(f(f(f(f(...))))))))))
yes
27 28

Exemplo: Macaco & Banana Exemplo: Macaco & Banana


‰ Um macaco encontra-se próximo à porta de uma
sala. No meio da sala há uma banana pendurada
no teto. O macaco tem fome e quer comer a
banana mas ela está a uma altura fora de seu
alcance. Perto da janela da sala encontra-se uma
caixa que o macaco pode utilizar para alcançar a
banana. O macaco pode realizar as seguintes
ações:
ƒ caminhar no chão da sala;
ƒ subir na caixa (se estiver ao lado da caixa);
ƒ empurrar a caixa pelo chão da sala (se estiver ao lado
da caixa);
ƒ pegar a banana (se estiver parado sobre a caixa
diretamente embaixo da banana).
29 30

Exemplo: Macaco & Banana Exemplo: Macaco & Banana


‰ É conveniente combinar essas 4 peças de ‰ Possíveis valores para os argumentos da
informação em uma estrutura, cujo functor será
estado
estrutura estado
‰ Observe que o estado inicial é determinado pela
ƒ 1º argumento (posição horizontal do macaco):
posição dos objetos: na_porta, no_centro, na_janela
estado
ƒ 2º argumento (posição vertical do macaco):
no_chão, acima_caixa
na_porta no_piso na_janela não_tem
ƒ 3º argumento (posição da caixa): na_porta,
‰ O estado final é qualquer estado onde o último no_centro, na_janela
componente da estrutura é o átomo tem ƒ 4º argumento (macaco tem ou não tem
ƒ estado(_,_,_,tem) banana): tem, não_tem
31 32

5
Exemplo: Macaco & Banana Exemplo: Macaco & Banana
‰ Quais os movimentos permitidos que alteram o mundo de ‰ O movimento ‘pegar a banana’ com sua pré-condição no
um estado para outro? estado antes do movimento pode ser definido por:
ƒ Pegar a banana move(estado(no_centro,acima_caixa,no_centro,não_tem),
ƒ Subir na caixa pegar_banana,
estado(no_centro,acima_caixa,no_centro,tem) ).
ƒ Empurrar a caixa
ƒ Caminhar no chão da sala ƒ Este fato diz que após o movimento o macaco tem a banana e ele
permanece acima da caixa no meio da sala
‰ Nem todos os movimentos são possíveis em cada estado
do mundo ‰ Vamos expressar o fato que o macaco no chão pode
ƒ ‘pegar a banana’ somente é possível se o macaco está acima da caminhar de qualquer posição horizontal Pos1 para
caixa diretamente abaixo da banana e o macaco ainda não tem a qualquer posição Pos2
banana move(estado(Pos1,no_chão,Caixa,Banana),
‰ Vamos formalizar em Prolog usando a relação move caminhar(Pos1,Pos2),
ƒ move(Estado1,Movimento,Estado2) estado(Pos2,no_chão,Caixa,Banana) ).
onde Estado1 é o estado antes do movimento, Movimento é o ‰ De maneira similar, os movimentos ‘empurrar’ e ‘subir’
movimento executado e Estado2 é o estado após o movimento
podem ser especificados

33 34

Exemplo: Macaco & Banana Exemplo: Macaco & Banana


‰ A pergunta principal que nosso programa deve responder é: O move(estado(no_centro,acima_caixa,no_centro,não_tem), % antes de mover
pegar_banana, % pega banana
macaco consegue, a partir de um estado inicial Estado, pegar a estado(no_centro,acima_caixa,no_centro,tem) ). % depois de mover
banana? move(estado(P,no_chão,P,Banana),
‰ Isto pode ser formulado usando o predicado consegue/1 que pode ser subir, % subir na caixa
formulado baseado em duas observações: estado(P,acima_caixa,P,Banana) ).
move(estado(P1,no_chão,P1,Banana),
ƒ Para qualquer estado no qual o macaco já tem a banana, o predicado empurrar(P1,P2), % empurrar caixa de P1 para P2
consegue/1 certamente deve ser verdadeiro; nenhum movimento é estado(P2,no_chão,P2,Banana) ).
necessário move(estado(P1,no_chão,Caixa,Banana),
™ consegue(estado(_,_,_,tem)). caminhar(P1,P2), % caminhar de P1 para P2
ƒ Nos demais casos, um ou mais movimentos são necessários; o macaco estado(P2,no_chão,Caixa,Banana) ).
pode obter a banana em qualquer estado Estado1 se há algum
movimento de Estado1 para algum estado Estado2 tal que o macaco
consegue pegar a banana no Estado2 (em zero ou mais movimentos) consegue(estado(_,_,_,tem)). % macaco já tem banana
™ consegue(Estado1) :-
move(Estado1,Movimento,Estado2), consegue(Estado1) :- % movimentar e tentar conseguir
consegue(Estado2). move(Estado1,Movimento,Estado2), % a banana
consegue(Estado2).

35 36

Exemplo: Macaco & Banana Listas


?- consegue(estado(na_porta,no_chão,na_janela,não_tem)).
yes
‰ Listaé uma das estruturas mais simples
estado(na_porta,no_chão,na_janela,não_tem)
em Prolog, muito comum em programação
caminhar(na_porta,P2)
não numérica
estado(P2,no_chão,na_janela,não_tem)
empurrar(P2,P2’) ‰ Ela é uma seqüência ordenada de
subir
backtrack
P2=na_janela
elementos
estado(na_janela,acima_caixa,na_janela,não_tem)
‰ Uma lista pode ter qualquer comprimento
estado(P2’,no_chão,P2’,não_tem)

Nenhum movimento possível subir


‰ Por exemplo uma lista de elementos tais
estado(P2’,acima_caixa,P2’,não_tem)
como ana, tênis, pedro pode ser escrita
pegar_barana
P2’=no_centro em Prolog como:
estado(no_centro,acima_caixa,no_centro,tem) ƒ [ana, tênis, pedro]
37 38

6
Listas Listas
‰ O uso de colchetes é apenas uma melhoria da ‰ No exemplo [ana, tênis, pedro]
notação, pois internamente listas são ƒ ana é a Cabeça da lista
representadas como árvores, assim como todos ƒ [tênis, pedro] é a Cauda da lista
objetos estruturados em Prolog ‰ A cabeça de uma lista pode ser qualquer objeto

‰ Para entender a representação Prolog de listas, é


(inclusive uma lista); a cauda tem que ser uma
lista
necessário considerar dois casos
‰ A Cabeça e a Cauda são então combinadas em
ƒ A lista é vazia, escrita como [ ] em Prolog
uma estrutura pelo functor especial .
ƒ Uma lista (não vazia) consiste: ƒ .(Cabeça, Cauda)
™ no primeiro item, chamado cabeça (head) da lista
™ na parte restante da lista, chamada cauda (tail) ‰ Como a Cauda é uma lista, ela é vazia ou ela tem
sua própria cabeça e sua cauda

39 40

Listas Listas
?- Lista1 = [a,b,c],
‰ Assim, para representar listas de qualquer Lista2 = .(a,.(b,.(c,[]))).
comprimento, nenhum princípio adicional é Lista1 = [a, b, c]
Lista2 = [a, b, c]
necessário
?- Hobbies1 = .(tênis, .(música,[])),
‰ O exemplo [ana, tênis, pedro] é . Hobbies2 = [esqui, comida],
representando como o termo: L = [ana,Hobbies1,pedro,Hobbies2].
Hobbies1 = [tênis,música]
ana .
ƒ .(ana, .(tênis, .(pedro, []) ) ) Hobbies2 = [esqui,comida]
L = [ana, [tênis,música], pedro, [esqui,comida]]
‰O programador pode escolher tênis .
ambas notações pedro []

41 42

Listas Unificação em Listas


‰ Em geral, é comum tratar a cauda como um Lista1 Lista2 Lista1 = Lista2
objeto simples [mesa] [X|Y] X=mesa
‰ Por exemplo, L = [a,b,c] pode ser escrito como Y=[ ]
ƒ Cauda = [b,c] [a,b,c,d] [X,Y|Z] X=a
ƒ L = .(a,Cauda) Y=b
‰ Para expressar isso, Prolog fornece uma notação Z=[c,d]
alternativa, a barra vertical, que separa a cabeça [[ana,Y]|Z] [[X,foi],[ao,cinema]] X=ana
da cauda Y=foi
ƒ L = [a | Cauda] Z=[[ao,cinema]]
[ano,bissexto] [X,Y|Z] X=ano
‰ A notação é geral por permitir qualquer número
Y=bissexto
de elementos seja seguido por | e o restante da
Z=[ ]
lista:
ƒ [a,b,c] = [a | [b,c]] = [a,b | [c]] = [a,b,c | [ ]] [ano,bissexto] [X,Y,Z] Não unifica

43 44

7
Operações em Listas Predicado de Pertinência
‰ Freqüentemente, é necessário realizar ‰ Inicialmente, é necessário definir o nome do predicado
que verifica se um elemento X pertence ou não a uma
operações em listas, por exemplo, buscar lista Y, por exemplo, pertence(X,Y)
um elemento que faz parte de uma lista ‰ A primeira condição especifica que um elemento X
‰ Para isso, a recursão é o recurso mais pertence à lista se ele está na cabeça dela. Isto é
indicado como:
amplamente empregado ƒ pertence(X,[X|Z]).
‰ Para verificar se um nome está na lista, é ‰ A segunda condição especifica que um elemento X
preciso verificar se ele está na cabeça ou pertence à lista se ele pertencer à sua cauda. Isto pode
ser indicado como:
se ele está na cauda da lista ƒ pertence(X,[W|Z]) :-
‰ Se o final da lista for atingido, o nome não pertence(X,Z).

está na lista
45 46

Predicado de Pertinência Predicado de Pertinência


‰ Sempre que um programa recursivo é ‰ ?- pertence(d,[a,b,c]).
no
definido, deve-se procurar pelas condições ‰ ?- pertence(X,[a,b,c]).
limites (ou condições de parada) e pelo X = a ;
X = b ;
caso(s) recursivo(s): X = c ;
ƒ pertence(Elemento,[Elemento|Cauda]). no
ƒ pertence(Elemento,[Cabeca|Cauda]) :- ‰ Entretanto, se as perguntas forem:
pertence(Elemento,Cauda). ƒ ?- pertence(a,X).
ƒ ?- pertence(X,Y).
‰ Após a definição do programa, é possível
‰ deve-se observar que cada uma delas tem
interrogá-lo. Por exemplo, infinitas respostas, pois existem infinitas listas
?- pertence(a,[a,b,c]). que validam essas perguntas para o programa
yes pertence/2
47 48

Modo de Chamada de Predicados Exercícios


‰ Para documentar como um predicado deve ser ‰ Definir predicado último que encontra o último elemento
chamado, utiliza-se a notação (como comentário de uma lista
no programa): ƒ O último elemento de uma lista que tenha somente um elemento é
o próprio elemento
ƒ + o argumento é de entrada (deve estar instanciado) ƒ O último elemento de uma lista que tenha mais de um elemento é
ƒ – o argumento é de saída (não deve estar instanciado) o ultimo elemento da cauda
ƒ ? o argumento é de entrada e saída (pode ou não ‰ Concatenar duas listas, formando uma terceira
estar instanciado) ƒ Se o primeiro argumento é a lista vazia, então o segundo e
terceiro argumentos devem ser o mesmo
‰ O predicado pertence/2 documentado com o ƒ Se o primeiro argumento é a lista não-vazia, então ela tem uma
modo de chamada é: cabeça e uma cauda da forma [X|L1]; concatenar [X|L1] com uma
% pertence(?Elemento, +Lista) segunda lista L2 resulta na lista [X|L3], onde L3 é a concatenação
pertence(E, [E|_]). de L1 e L2
pertence(E, [_|Cauda]) :- ‰ Defina uma nova versão do predicado último utilizando a
pertence(E,Cauda). concatenação de listas

49 50

8
Último Elemento de uma Lista Concatenar Listas
‰ O último elemento de uma lista que tenha ‰ Se o primeiro argumento é a lista vazia, então o segundo
e terceiro argumentos devem ser o mesmo
somente um elemento é o próprio elemento concatenar([ ],L,L).
ultimo(Elemento, [Elemento]). ‰ Se o primeiro argumento é a lista não-vazia, então ela
‰ O último elemento de uma lista que tenha mais tem uma cabeça e uma cauda da forma [X|L1];
de um elemento é o ultimo elemento da cauda concatenar [X|L1] com uma segunda lista L2 resulta na
lista [X|L3], onde L3 é a concatenação de L1 e L2
ultimo(Elemento, [Cabeca|Cauda]) :- concatenar([X|L1],L2,[X|L3]) :- [X | L1]
ultimo(Elemento,Cauda). concatenar(L1,L2,L3).

‰ Programa completo: ‰ Programa completo: X L1 L2

‰ % concatenar(?/+L1,?/?L2,+/?L)
% ultimo(?Elemento, +Lista) L3
‰ concatenar([ ],L,L).
ultimo(Elemento, [Elemento]).
‰ concatenar([X|L1],L2,[X|L3]) :- X L3
ultimo(Elemento, [Cabeca|Cauda]) :- concatenar(L1,L2,L3).
ultimo(Elemento,Cauda). [X | L3]

51 52

Exemplo: Macaco & Banana Operadores


move(estado(no_centro,acima_caixa,no_centro,não_tem),
pegar_banana,
% antes de mover
% pega banana
‰ Em várias situações é conveniente escrever functores
estado(no_centro,acima_caixa,no_centro,tem) ). % depois de mover como operadores
move(estado(P,no_chão,P,Banana), ‰ Esta é uma forma sintática que facilita a leitura de
subir,
estado(P,acima_caixa,P,Banana) ).
% subir na caixa
estruturas
move(estado(P1,no_chão,P1,Banana), ‰ Por exemplo, numa expressão aritmética como 2*a+b*c
empurrar(P1,P2),
estado(P2,no_chão,P2,Banana) ).
% empurrar caixa de P1 para P2 ƒ + e * são operadores
move(estado(P1,no_chão,Caixa,Banana), ƒ 2, a, b são argumentos
caminhar(P1,P2), % caminhar de P1 para P2 ‰ Esta expressão aritmética na sintaxe normal de estruturas
estado(P2,no_chão,Caixa,Banana) ).
(termos) é:
consegue(estado(_,_,_,tem),[]). % macaco já tem banana ƒ +( *(2,a), *(b,c) )
consegue(Estado1,[Movimento|Resto]) :- % movimentar e tentar conseguir ‰ Entretanto, é importante lembrar que os operadores não
move(Estado1,Movimento,Estado2),
consegue(Estado2,Resto).
% a banana
“realizam” nenhuma aritmética: o 3+4 não é a mesma
coisa que 7
?- consegue(estado(na_porta,no_chão,na_janela,não_tem),X). ƒ O termo 3+4 é representado como +(3,4), que é uma estrutura
X = [caminhar(na_porta,na_janela), empurrar(na_janela, no_centro), subir,
pegar_banana]
ƒ Assim, escrever 3+4 é equivalente a escrever +(3,4)
53 54

Operadores Operadores
‰ De forma que Prolog entenda apropriadamente ‰ A definição de um operador deve aparecer através de
expressões tais como a+b*c, Prolog deve conhecer que * uma diretiva antes da expressão contendo o operador
tem precedência sobre + ‰ No exemplo anterior, o operador tem pode ser definido
‰ Assim, a precedência de operadores decide qual é a através da diretiva
correta interpretação de expressões ƒ :- op(600,xfx,tem).
‰ Prolog permite a declaração de novos operadores, por ƒ Isso informa Prolog que desejamos usar tem como operador, cuja
exemplo, podemos definir os átomos tem e suporta como precedência é 600 e seu tipo é ‘xfx’, que é um tipo de operador
infixo
operadores e escrever no programa fatos tais como:
ƒ A forma ‘xfx’ sugere que o operador, denotado pela letra ‘f’ está
ƒ pedro tem informação. entre dois argumentos, denotados por ‘x’
ƒ chão suporta mesa.
‰ Novamente, a definição de operadores não especifica
‰ Estes fatos são equivalentes à: nenhuma operação ou ação e são usados apenas para
ƒ tem(pedro,informação). combinar objetos em estruturas
ƒ suporta(chão,mesa).

55 56

9
Operadores Operadores
‰ Os nomes dos operadores devem ser átomos ‰ Os especificadores são escolhidos para refletir a
estrutura da expressão, onde:
‰ A precedência varia em algum intervalo, ƒ f representa o operador
dependendo da implementação Prolog (1-1200) ƒ x representa um argumento cuja precedência é
‰ Há 3 grupos tipos de operadores, indicados pelos
estritamente menor que a do operador
ƒ y representa um argumento cuja precedência é menor
especificadores tal como xfx: ou igual à do operador
ƒ (1) Operadores infixos de três tipos: xfx, xfy, yfx ‰ A precedência de um argumento colocado entre
ƒ (2) Operadores pré-fixos de dois tipos: fx, fy parênteses ou de um objeto não estruturado é
ƒ (3) Operadores pós-fixos de dois tipos: xf, yf zero
‰ Se um argumento é uma estrutura, então sua
precedência é igual à precedência de seu functor
principal
57 58

Operadores Operadores
‰ Exemplo de alguns operadores pré-definidos
‰ Por exemplo a-b-c é entendido como (a-b)-c e ƒ :-op(1200,xfx,[-->,:-]).
não como a-(b-c) ƒ :-op(1200,fx,[:-,?-]).
ƒ Assumindo que – tenha precedência 500 ƒ :-op(1100,xfy,[’;’,|]).
ƒ :-op(1050,xfy,->).
ƒ O operador – tem que ser definido como yfx ƒ :-op(1000,xfy,’,’).
Interpretação
ƒ :-op(954,xfy,\).
– – inválida porque a ƒ :-op(900,fy,[’\+’,not]).
precedência de b-c ƒ :-op(700,xfx,[is,<,=,=..,=@=,=:=,=<,==,=\=,
não é menor do que >,>=,@<, @=<,@>,@>=,\=,\==]).
– c a – a precedência de -
ƒ :-op(600,xfy,:).
prec. 0 prec. 0 ƒ :-op(500,yfx,[+,-]).
a b b c ƒ :-op(500,fx,[+,-]).
ƒ :-op(400,yfx,[*,/,//,mod]).
ƒ :-op(200,xfx,**).
precedência 500 precedência 500 ƒ :-op(200,xfy,^).
59 60

Exemplo Exemplo

‰ Assumindo as diretrizes ‰ ~(a e b) <===> ~a ou ~b é interpretado como


ƒ :-op(800,xfx,<===>). <===>(~(e(a, b)), ou(~(a), ~(b))
ƒ :-op(700,xfy,ou).
ƒ :-op(600,xfy,e). <===>

ƒ :-op(500,fy,~). ~ ou

‰ Como é interpretada a expressão


e ~ ~
~(a e b) <===> ~a ou ~b
a b a b

61 62

10
Predicados para (De)composição Predicados para (De)composição
Termos Termos
atom_chars(A,L): converte um átomo A em uma lista L
‰ Termo =.. L: é verdadeiro se L é uma lista
‰
composta pelos caracteres (e vice-versa)
ƒ ?- atom_chars(laranja,X). contendo o functor principal de Termo,
ƒ X = [l,a,r,a,n,j,a]
ƒ ?- atom_chars(Z,[m,a,c,a,c,o]). seguido pelos seus argumentos
ƒ Z = macaco
‰ number_chars(A,L): Similar ao predicado atom_chars,
ƒ =.. é lido como univ
mas para números ‰ functor(Termo,F,N): é verdadeiro se
ƒ ?- number_chars(123.5,X).
ƒ X = ['1', '2', '3', '.', '5'] Termo é uma estrutura com functor F e
ƒ ?- number_chars(X,['1', '2', '3']). aridade N
ƒ Z = 123
‰ Algumas implementações Prolog fornecem o predicado ‰ arg(N,Termo,A): é verdadeiro se o N-
name(A,L) que tem a mesma funcionalidade que
atom_chars(A,L) e number_chars(A,L) combinados ésimo argumento do Termo é A
63 64

Predicados para (De)composição Predicados para (De)composição


Termos Termos
?- f(a,b) =.. L. ?- functor(t(f(x),x,t),F,Aridade).
L = [f,a,b] F = t, Aridade = 3
?- T =.. [retângulo,3,5]. ?- functor(a+b,F,N).
T = retângulo(3,5)
F = +, N = 2
?- Z =.. [p,X,f(X,Y)].
?- functor(f(a,b,g(Z)),F,N).
Z = p(X,f(X,Y))
?- (a+b) =.. [F,X,Y].
Z = _G309, F = f, N = 3
F = +, X = a, Y = b ?- functor([a,b,c],F,N).
?- [a,b,c,d] =.. L. F = ., N = 2
L = [.,a,[b,c,d]] ?- functor(laranja,F,N).
?- [a,b,c,d] =.. [X|Y]. F = laranja, N = 0
X = ., Y = [a,[b,c,d]] ?- functor([a,b,c],’.’,3).
?- X =.. [a,b,c,d]. no
X = a(b,c,d) ?- functor([a,b,c],a,Z).
?- X =.. [concatenar,[a,b],[c],[a,b,c]].
no
X = concatenar([a,b],[c],[a,b,c])

65 66

Predicados para (De)composição Predicados para (De)composição


Termos Termos
?- arg(1,t(f(x),y,t),Arg). ‰ Termos construídos com o predicado =.., podem ser
Arg = f(x) usados como metas
?- arg(2,t(f(x),y,t),Arg). ‰ A vantagem é que o programa pode modificar-se a si
Arg = y próprio durante a execução, gerando e executando metas
?- arg(1,a+(b+c),Arg). de formas que não foram necessariamente previstas
Arg = a quando o programa foi escrito
?- arg(2,[a,b,c],X). ‰ O seguinte fragmento ilustra essa idéia
X = [b,c] ƒ obter(Functor),
calcular(ListaArgumentos),
?- arg(1,a+(b+c),b). Meta =.. [Functor | ListaArgumentos],
no Meta.
?- functor(D,data,3), arg(1,D,29), ƒ obter/1 e calcular/1 são predicados definidos pelo usuário para
arg(2,D,janeiro), arg(3,D,2004). obter os componentes da meta a ser construída; a meta é então
D = data(29,janeiro,2004) construída por =.. e disparada sua execução simplesmente
através de seu nome, Meta
67 68

11
Predicados para (De)composição
Semântica de Programas Prolog
Termos
‰ Algumas implementações Prolog exigem que ‰ Considere a cláusula onde P, Q e R são termos:
ƒ P :- Q, R.
todas as metas sejam átomos ou estruturas com
‰ Significado Declarativo:
um átomo como functor principal ƒ P é verdadeiro se Q e R são verdadeiros
‰ Assim, uma variável, mesmo que instanciada, ƒ P segue (conseqüência) de Q e R
não é sintaticamente aceita como uma meta ƒ De (a partir de) Q e R segue P
‰ Significado Procedural:
‰ O problema é solucionado através do predicado ƒ Para resolver o problema P, resolva primeiro sub-problema Q e
call/1, assim o fragmento anterior torna-se: então o sub-problema R
ƒ obter(Functor), ƒ Para satisfazer P, primeiro satisfaça Q e então R
calcular(ListaArgumentos), ‰ A diferença entre os significados declarativo e procedural
Meta =.. [Functor | ListaArgumentos], é que o último não apenas define as relações lógicas
entre a cabeça da cláusula e as condições no corpo, mas
call(Meta). também a ordem na qual as condições são executadas
69 70

Semântica de Programas Prolog Significado Declarativo


Em geral, uma meta em Prolog é uma lista de condições separadas
‰O significado declarativo determina quando ‰
por vírgulas que é verdadeira se todas as condições na lista são
verdadeiras para uma determinada instanciação de variáveis
uma dada condição é verdadeira e, se for, ‰ A vírgula denota conjunção (e): todas as condições devem ser
para quais valores das variáveis ela é verdadeiras:
ƒ X, Y neste exemplo X e Y devem ser ambos verdadeiros para X,Y ser
verdadeira ‰
verdadeiro
O ponto-e-vírgula denota disjunção (ou): qualquer uma das condições
em uma disjunção tem que ser verdadeira
‰ O significado procedural determina como ƒ X;Y neste exemplo basta que X (ou Y) seja verdadeiro para X;Y ser
Prolog responde perguntas ‰
verdadeiro
O operador \+ denota a negação (não): é verdadeiro se o que está
sendo negado não puder ser provado por Prolog
ƒ \+X é verdadeiro se X falha
ƒ Na sintaxe de Edinburgh o operador \+ é denotado por not
‰ O predicado true/0 sempre é verdadeiro
‰ O predicado fail/0 sempre falha

71 72

Significado Declarativo Significado Procedural


‰ A cláusula grande(urso). % Cláusula 1
ƒ P :- Q ; R. grande(elefante). % Cláusula 2
pequeno(gato). % Cláusula 3
‰ é lida como: P é verdade se Q é verdade ou R é verdade.
É equivalente às duas cláusulas: marrom(urso). % Cláusula 4
preto(gato). % Cláusula 5
ƒ P :- Q.
cinza(elefante). % Cláusula 6
ƒ P :- R.
escuro(Z) :- % Cláusula 7
‰ A conjunção (,) tem precedência sobre a disjunção (;), preto(Z).
assim a cláusula: escuro(Z) :- % Cláusula 8
ƒ P :- Q, R; S, T, U. marrom(Z).
‰ é interpretada como:
ƒ P :- (Q, R) ; (S, T, U). ?- escuro(X), grande(X).
‰ e tem o mesmo significado que:
ƒ P :- Q, R.
ƒ P :- S, T, U.

73 74

12
Significado Procedural Significado Procedural
grande(urso). % Cláusula 1 grande(urso). % Cláusula 1
grande(elefante). % Cláusula 2 grande(elefante). % Cláusula 2
pequeno(gato). % Cláusula 3 pequeno(gato). % Cláusula 3
marrom(urso). % Cláusula 4 marrom(urso). % Cláusula 4
preto(gato). % Cláusula 5 preto(gato). % Cláusula 5
cinza(elefante). % Cláusula 6 cinza(elefante). % Cláusula 6
escuro(Z) :- % Cláusula 7 escuro(Z) :- % Cláusula 7
preto(Z). preto(Z).
escuro(Z) :- % Cláusula 8 escuro(Z) :- % Cláusula 8 (Passo 2)
marrom(Z). marrom(Z). Procure de cima para baixo por
uma cláusula cuja cabeça
(Passo 1) unifique com a primeira
?- escuro(X), grande(X). Pergunta inicial: ?- escuro(X), grande(X). condição da pergunta
escuro(X), grande(X). escuro(X)

75 76

Significado Procedural Significado Procedural


grande(urso). % Cláusula 1 grande(urso). % Cláusula 1
grande(elefante). % Cláusula 2 grande(elefante). % Cláusula 2 (Passo 3)
(Passo 2)
pequeno(gato). % Cláusula 3 pequeno(gato). % Cláusula 3 Nova meta: preto(X), grande(X).
Procure de cima para baixo por
marrom(urso). % Cláusula 4 uma cláusula cuja cabeça marrom(urso). % Cláusula 4
preto(gato). % Cláusula 5 unifique com a primeira preto(gato). % Cláusula 5 Procure por uma cláusula que
cinza(elefante). % Cláusula 6 condição da pergunta cinza(elefante). % Cláusula 6 unifique com preto(X)
escuro(X). Cláusula 5 encontrada
escuro(Z) :- % Cláusula 7 Cláusula 7 encontrada escuro(Z) :- % Cláusula 7
preto(gato)
preto(Z). escuro(Z) :- preto(Z). preto(Z).
Esta cláusula não tem corpo,
escuro(Z) :- % Cláusula 8 Troque a primeira condição pelo escuro(Z) :- % Cláusula 8 assim a lista de condições
marrom(Z). corpo instanciado da cláusula marrom(Z). depois de instanciada torna-
7, obtendo a nova lista de se:
condições: grande(gato).
?- escuro(X), grande(X). preto(X), grande(X). ?- escuro(X), grande(X).
uma vez que já se provou
preto(gato)
X instancia com gato

77 78

Significado Procedural Significado Procedural


grande(urso). % Cláusula 1 grande(urso). % Cláusula 1
grande(elefante). % Cláusula 2 grande(elefante). % Cláusula 2
pequeno(gato). % Cláusula 3 pequeno(gato). % Cláusula 3 (Passo 4)
(Passo 4) meta: preto(X), grande(X).
marrom(urso). % Cláusula 4 Nova meta: grande(gato). marrom(urso). % Cláusula 4
preto(gato). % Cláusula 5 preto(gato). % Cláusula 5
Continue procurando após a
cinza(elefante). % Cláusula 6 Procure por uma cláusula que cinza(elefante). % Cláusula 6 Cláusula 5. Nenhuma cláusula é
escuro(Z) :- % Cláusula 7 unifique com grande(gato). escuro(Z) :- % Cláusula 7 encontrada. Volte (backtrack)
preto(Z). Nenhuma cláusula é encontrada. preto(Z). ao Passo 2 e continue
escuro(Z) :- % Cláusula 8 Volte (backtrack) para o Passo 3, escuro(Z) :- % Cláusula 8 procurando após a cláusula 7.
desfazendo a instanciação
marrom(Z). X=gato marrom(Z). Cláusula 8 encontrada:
Novamente a meta é escuro(Z) :- marrom(Z).
?- escuro(X), grande(X). preto(X), grande(X). ?- escuro(X), grande(X). Troque a primeira condição pelo
corpo instanciado da cláusula
8, obtendo a nova lista de
condições:
marrom(X), grande(X).

79 80

13
Significado Procedural Significado Procedural
grande(urso). % Cláusula 1 grande(urso). % Cláusula 1
grande(elefante). % Cláusula 2 (Passo 5) grande(elefante). % Cláusula 2 (Passo 6)
pequeno(gato). % Cláusula 3 meta: marrom(X), grande(X). pequeno(gato). % Cláusula 3 meta: grande(urso).
marrom(urso). % Cláusula 4 marrom(urso). % Cláusula 4
preto(gato). % Cláusula 5 Procure por uma cláusula que preto(gato). % Cláusula 5 Procure por uma cláusula que
cinza(elefante). % Cláusula 6 unifique com marrom(X) cinza(elefante). % Cláusula 6 unifique com grande(urso)
escuro(Z) :- % Cláusula 7 Cláusula 4 encontrada escuro(Z) :- % Cláusula 7 Cláusula 1 encontrada
marrom(urso) grande(urso)
preto(Z). preto(Z).
Esta cláusula não tem corpo, Esta cláusula não tem corpo,
escuro(Z) :- % Cláusula 8 escuro(Z) :- % Cláusula 8
assim a lista de condições assim a lista de condições
marrom(Z). depois de instanciada torna-se: marrom(Z). torna-se vazia.
grande(urso). Isto indica um término com
?- escuro(X), grande(X). uma vez que já se provou ?- escuro(X), grande(X). sucesso e a instanciação
marrom(urso) correspondente é
X instancia com urso X = urso

81 82

Ordem das Cláusulas Macaco & Banana (Original)


‰ No exemplo do “Macaco & Banana”, as cláusulas sobre a move(estado(no_centro,acima_caixa,no_centro,não_tem),
pegar_banana,
% antes de mover
% pega banana
relação move foram ordenadas como: pegar a banana, estado(no_centro,acima_caixa,no_centro,tem) ). % depois de mover
subir na caixa, empurrar a caixa e caminhar move(estado(P,no_chão,P,Banana),
subir, % subir na caixa
‰ Estas cláusulas dizem que pegar é possível, subir é estado(P,acima_caixa,P,Banana) ).
possível, etc move(estado(P1,no_chão,P1,Banana),
empurrar(P1,P2), % empurrar caixa de P1 para P2
‰ De acordo com o significado procedural de Prolog, a estado(P2,no_chão,P2,Banana) ).

ordem das cláusulas indica que o macaco prefere pegar a move(estado(P1,no_chão,Caixa,Banana),


caminhar(P1,P2), % caminhar de P1 para P2
subir, subir a empurrar, etc. estado(P2,no_chão,Caixa,Banana) ).

‰ Esta ordem, na realidade, ajuda o macaco a resolver o


problema consegue(estado(_,_,_,tem)). % macaco já tem banana

‰ Todavia, o que aconteceria se a ordem fosse diferente? consegue(Estado1) :- % movimentar e tentar conseguir
Por exemplo, vamos assumir que a cláusula sobre move(Estado1,Movimento,Estado2), % a banana
consegue(Estado2).
‘caminhar’ apareça em primeiro lugar

83 84

Macaco & Banana (Ordem Alterada) Ordem das Cláusulas


move(estado(P1,no_chão,Caixa,Banana), ‰ Vamos analisar a execução da versão com ordem alterada da pergunta
caminhar(P1,P2), % caminhar de P1 para P2 ?- consegue(estado(na_porta,no_chão,na_janela,não_tem)).
estado(P2,no_chão,Caixa,Banana) ). ‰ Que produz a seguinte execução (variáveis renomeadas apropriadamente):
move(estado(no_centro,acima_caixa,no_centro,não_tem), % antes de mover (1) consegue(estado(na_porta,no_chão,na_janela,não_tem))
pegar_banana, % pega banana ™ A segunda cláusula de consegue/1 é aplicada
estado(no_centro,acima_caixa,no_centro,tem) ). % depois de mover (2) move(estado(na_porta,no_chão,na_janela,não_tem),M’,S2’), consegue(S2’)
move(estado(P,no_chão,P,Banana), ™ Através do movimento caminhar(na_porta,P2’) temos:
subir, % subir na caixa (3) consegue(estado(P2’,no_chão,na_janela,não_tem))
estado(P,acima_caixa,P,Banana) ). ™ A segunda cláusula de consegue/1 é aplicada novamente
move(estado(P1,no_chão,P1,Banana), (4) move(estado(P2’,no_chão,na_janela,não_tem),M’’,S2’’), consegue(S2’’)
empurrar(P1,P2), % empurrar caixa de P1 para P2 ™ Agora ocorre a diferença: a primeira cláusula cuja cabeça unifica com a primeira meta
estado(P2,no_chão,P2,Banana) ). acima é caminhar (e não subir como antes). A instanciação é S2’’ =
estado(P2’’,no_chão,na_janela,não_tem), portanto a lista de metas se torna
(5) consegue(estado(P2’’,no_chão,na_janela,não_tem))
™ Novamente, a segunda cláusula de consegue/1 é aplicada
consegue(estado(_,_,_,tem)). % 1a cláusula de consegue/1
(6) move(estado(P2’’,no_chão,na_janela,não_tem),M’’’,S2’’’), consegue(S2’’’)
™ Novamente, caminhar é tentado primeiro, produzindo
consegue(Estado1) :- % 2a cláusula de consegue/1
(7) consegue(estado(P2’’’,no_chão,na_janela,não_tem))
move(Estado1,Movimento,Estado2),
consegue(Estado2).
‰ As metas (3), (5) e (7) são as mesmas, exceto por uma variável; e o sucesso
de uma meta não depende do nome particular das variáveis envolvidas
‰ Assim a partir da meta (3) a execução não mostra progresso algum
85 86

14
Ordem das Cláusulas Pontos Importantes
‰ Nota-se que a segunda cláusula de consegue/1 e ‰ Objetos simples em Prolog são átomos, números
cláusula caminhar de move/1 são usadas repetidamente
e variáveis
‰ O macaco caminha sem nunca tentar usar a caixa
‰ Como não há progresso, isso procede infinitamente: ‰ Objetos estruturados, ou estruturas, são
Prolog não percebe que não há sentido em continuar utilizados para representar objetos que possuem
utilizando esta linha de raciocínio vários componentes
‰ Este exemplo mostra Prolog tentando resolver um
‰ Estruturas são construídas através de functores;
problema de modo que a solução nunca é encontrada,
embora exista uma solução cada functor é definido por seu nome e aridade
‰ O programa está declarativamente correto, mas ‰ O escopo léxico de uma variável é uma cláusula;
proceduralmente incorreto no sentido que ele não é capaz
de produzir uma resposta à pergunta assim o mesmo nome de variável em duas
cláusulas significam duas variáveis diferentes

87 88

Pontos Importantes
Slides baseados em:
‰ Estruturas podem ser vistas como árvores; Prolog
pode ser vista como uma linguagem para Bratko, I.;
Prolog Programming for Artificial Intelligence,
processamento de árvores 3rd Edition, Pearson Education, 2001.
‰ A operação de unificação toma dois termos e Clocksin, W.F.; Mellish, C.S.;
tenta torná-los idênticos através da instanciação Programming in Prolog,
5th Edition, Springer-Verlag, 2003.
das variáveis em ambos os termos
Programas Prolog para o
‰ A ordem das cláusulas pode afetar a eficiência do Processamento de Listas e Aplicações,
programa; uma ordem indevida pode até mesmo Monard, M.C & Nicoletti, M.C., ICMC-USP, 1993

causar chamadas recursivas infinitas Material elaborado por


José Augusto Baranauskas
2004

89 90

15

Você também pode gostar