2. Aventura em Prolog 2
Aventura em Prolog
Estruturas de Dados
Exercícios
3. Aventura em Prolog 3
Estruturas de Dados
Até agora, trabalhamos com fatos,
consultas e regras que usam estruturas
de dados simples
Os argumentos de nossos predicados têm
sido átomos ou inteiros, blocos básicos de
construção em Prolog
Ex.: maçã, escritório, lanterna, cobertor
Tipos de dados primitivos podem ser
combinados para formar tipos de dados
complexos, chamados estruturas
4. Aventura em Prolog 4
Estruturas de Dados
Uma estrutura é composta por um funtor e um
número fixo de argumentos
Da mesma forma que objetivos e fatos
funtor(arq1, arq2, ...)
Cada argumento de uma estrutura pode ser
um tipo de dado primitivo ou uma outra
estrutura
Ex.: os objetos do jogo são atualmente
representados usando átomos, como ‘escrivaninha’,
‘maçã’, mas podemos utilizar estruturas para criar
uma representação mais rica das coisas
5. Aventura em Prolog 5
Exemplos
As estruturas a seguir descrevem um objeto,
sua cor, tamanho e peso:
objeto(vela, vermelha, pequena, 0.1).
objeto(maçã, vermelha, pequena, 0.1).
objeto(maçã, verde, pequena, 0.1).
objeto(mesa, azul, grande, 50).
Estas estruturas podem ser utilizadas
diretamente no segundo argumento de
local/2, mas para experimentação, iremos
criar um novo predicado local_s/2
6. Aventura em Prolog 6
Consultas
Note que mesmo usando estruturas complexas
para descrever os objetos do jogo, local_s/2
continua apenas com dois argumentos:
local_s(objeto(vela, vermelha, pequena, 0.1), cozinha).
local_s(objeto(maçã, vermelha, pequena, 0.1), cozinha).
local_s(objeto(maçã, verde, pequena, 0.1), cozinha).
local_s(objeto(mesa, azul, grande, 50), cozinha).
Variáveis em Prolog são “sem tipo” e podem
casar facilmente tanto com estruturas como
com átomos
7. Aventura em Prolog 7
Átomo X Estrutura
De fato, um átomo é apenas uma
estrutura simples com um funtor e sem
argumentos
Exemplo:
?- local_s(X, cozinha).
X = objeto(vela, vermelha, pequena, 0.1) ;
X = objeto(maçã, vermelha, pequena, 0.1) ;
X = objeto(maçã, verde, pequena, 0.1) ;
X = objeto(mesa, azul, grande, 50) ;
No
8. Aventura em Prolog 8
Variáveis X Estruturas
Podemos também escolher parte da estrutura
com variáveis
Ex.: encontrar todos os objetos vermelhos que
estão na cozinha
?- local_s(objeto(X, vermelha, T, P), cozinha).
X = vela
T = pequena
P = 0.1 ;
X = maçã
T = pequena
P = 0.1 ;
No
9. Aventura em Prolog 9
Variável Anônima
Se nós não nos preocupamos com o
tamanho e o peso podemos substituir as
variáveis T e P pela variável anônima
(_)
?- local_s(objeto(X, vermelha, _, _), cozinha).
X = vela ;
X = maçã ;
No
10. Aventura em Prolog 10
Nani Search
Podemos usar estas estruturas para dar mais
realismo ao jogo
Por exemplo, podemos modificar o predicado
pode_pegar/1, de maneira que só possamos pegar
objetos pequenos
pode_pegar_s(Objeto):-
aqui(Lugar),
(local_s(objeto(Objeto, _, pequeno, _), Lugar);
local_s(objeto(Objeto, _, pequena, _), Lugar)).
Podemos também mudar as mensagens de erro
para refletir as duas razões porque um objeto não
pode ser carregado
11. Aventura em Prolog 11
Predicado Interno not/1
Para garantir que o backtracking não cause a
exibição das duas mensagens de erro, iremos
construir cada cláusula de maneira que uma
única condição seja encontrada
Para fazer isso, utilizaremos o predicado interno
not/1 – o seu argumento é um objetivo, e ele é bem
sucedido se o seu argumento falha e falha caso seu
argumento seja bem sucedido
?- not( sala(escritório) ).
No
?- not( local(repolho, ‘sala de jantar’) ).
Yes
12. Aventura em Prolog 12
Predicado Interno not/1
Semanticamente, not em Prolog
significa que o objetivo não pode ser
resolvido de maneira bem sucedida com
a base de dados lógica atual de fatos e
regras
Lembre-se da “hipótese do mundo fechado”
13. Aventura em Prolog 13
Nova versão de pode_pegar/1
pode_pegar_s(Objeto):-
aqui(Lugar),
local_s(objeto(Objeto, _, pequeno, _), Lugar).
pode_pegar_s(Objeto):-
aqui(Lugar),
local_s(objeto(Objeto, _, grande, _), Lugar),
write(‘O(a) ’), write(Objeto),
write(‘ é grande demais para ser carregado(a).’), nl, fail.
pode_pegar_s(Objeto):-
aqui(Lugar),
not( local_s(objeto(Objeto, _, _, _), Lugar) ),
write(‘Não há nenhum(a) ’), write(Objeto), write(‘ aqui.’),
nl, fail.
14. Aventura em Prolog 14
Nova versão de pode_pegar/1
Agora podemos tentar, assumindo que
estamos na cozinha:
?- pode_pegar_s(vela).
Yes
?- pode_pegar_s(mesa).
O(a) mesa é grande demais para ser carregado(a).
No
?- pode_pegar_s(escrivaninha).
Não há nenhum(a) escrivaninha aqui.
No
15. Aventura em Prolog 15
Nani Search
O predicado lista_objetos/1 pode ser
modificado para dar uma descrição dos
objeto na sala:
lista_objetos_s(Lugar):-
local_s(objeto(Objeto, Cor, Tamanho, Peso), Lugar),
write(‘Um(a) ’), write(Objeto), tab(1),
write(Cor), tab(1),
write(Tamanho), write(‘, pesando ’),
write(Peso), write(‘ kilo(s)’), nl, fail.
lista_objetos_s(_).
17. Aventura em Prolog 17
Aperfeiçoando...
Cansado do formato ‘0.1 kilo(s)’?
Podemos corrigir isso criando uma nova regra para
escrever o peso, a qual poderá substituir os write’s
diretos até agora utilizados...
write_peso(P):-
P < 2, write(P), write(‘ kilo’).
write_peso(P):-
P >= 2, write(P), write(‘ kilos’).
Testando...
?- write_peso(4). ?- write_peso(1).
4 kilos 1 kilo
Yes Yes
18. Aventura em Prolog 18
Estruturas de Dados
Estruturas podem ser arbitrariamente
complexas, se quisermos ser mais caprichosos
a respeito dos objetos do jogo, podemos
manter suas dimensões (comprimento,
largura, altura) em vez de seu tamanho, como
parte de sua descrição:
objeto(mesa, marrom, dimensao(6, 3, 3), 90).
Podemos também usar estruturas embarcadas
por motivo de clareza:
objeto(mesa, cor(marrom), tamanho(grande),
peso(90)).
19. Aventura em Prolog 19
Estruturas de Dados
Uma consulta utilizando estas estruturas
apresenta uma leitura mais fácil:
?- local_s(objeto(X, _, tamanho(grande), _),
escritório).
Note que a posição dos argumentos é
importante
Os locais onde colocamos variáveis
anônimas são essenciais para a obtenção de
resultados corretos
20. Aventura em Prolog 20
Exercícios (1)
Nani Search
Incorpore um novo local ao jogo
Note que devido a abstração de dados e
procedimentos, nós precisamos mudar
apenas os predicados de baixo nível que
lidam diretamente com localização
Os predicados de alto nível, como olhar/0 e
pegar/1 não são afetados pela mudança