Introdução à Linguagem Prolog Prof. Fabrício Enembreck PPGIA – Programa de Pós Graduação em Informática Aplicada Predicados Dinâmicos e Alocação de Memória • Visualizando cláusulas na memória ?- listing(p/2). (mostra todas as declarações referentes ao predicado p/2) • Adicionando programas da memória :- dynamic p/2. (declara um predicado como dinâmico) :- multifile p/2. (permite que cláusulas de um ou mais predicados sejam declaradas em arquivos diferentes) ?- assert(p(a,a)). (insere como último fato) ?- asserta(p(b,b)). (insere como primeiro fato) Predicados Dinâmicos e Alocação de Memória (cont.) • Removendo programas da memória ?- abolish(p/2). (remove todas as declarações relativas ao predicado p/2) ?- abolish(p,2). ?- retract(p(_,_)). (remove a primeira cláusula – fato ou regra - que “casa” como o parâmetro fornecido) ?- retractall(p(_,_)). (remove todas as cláusulas – fatos ou regras - que “casam” como o parâmetro fornecido) Predicados Dinâmicos e Alocação de Memória (cont) • Consultando arquivos: ?- consult(‘c:\\temp\\arquivo.pl’). Exercícios 1) Utilizando os predicados assert, asserta, retract, etc, crie a seguinte base de fatos: venda(‘joao da silva’, data(15,1,2005), 3, bola, 12.50). venda(claudia, data(18,1,2005), 1, tenis, 89.45). venda(‘joao claudio’, data(22,1,2005), 4, sabao, 1.35). 2) Altere o segundo fato na memória para: venda(claudia, data(18,1,2005), 1, tenis, 109.45). 3) Crie arquivos que contém cláusulas de predicados venda/5 4) Escreva um predicado no seu código-fonte que carrega todos os fatos de todos os arquivos na memória 5) Escreva um predicado que soma o valor de todas as vendas (vc deve utilizar um predicado dinâmico cont/1) Exercícios 6) Escreva um predicado que recebe como entrada um determinado mês e calcula a soma realizada naquele mês Conteúdo do Curso • Introdução à Lógica e à Programação Lógica • Introdução ao Prolog e ao SWI-Prolog • Matching e Backtraking • Listas e predicados recursivos • Múltiplas soluções Listas e predicados recursivos • Listas são estruturas heterogêneas de dados • Exemplos de Listas – [a] – [o, homem, [gosta,pescar]] – [a,V1,b,[X,Y], b(c)] – [] Listas e predicados recursivos • “[ ]” : Lista vazia • Estrutura de uma Lista não vazia [X | Y] Cabeça (é um elemento) Corpo (é uma lista) Barra Vertical Matching com Listas • ?- [a,b,c] = [X|Y]. X=a Y = [b,c] • ?- [casa,carro,[corsa,golf]] = [X|Y]. X = casa Y = [carro,[corsa,golf]] • ?- [[a,b,c],e,f,g] = [X|Y]. X = [a,b,c] Y = [e, f, g] • ?- [[a,b,c],e,f,g] = [X,Y|Z]. X = [a,b,c] Y = e Z = [f,g] • ?- [[a,b,c],e,f,g] = [X,Y,Z|W]. X = [a,b,c] Y=e Z=f • ?- [[a,b,c],e,f,g] = [X]. no W =[g] Predicados Recursivos com Listas • Pertence – Construir um predicado “pertence” que verifica se um elemento existe dentro da lista • Ex.: ?- pertence(2,[a,5,f(a), 2,casa]). yes Existem duas situações: • O elemento desejado está na cabeça da lista pertence(X,[X|_]). • O elemento não está na cabeça da lista mas pode estar no corpo da lista pertence(X,[_|Y]) :pertence(X,Y). 3a. Chamada Solução Debugando o “pertence” • ?- pertence(c, [a,b,c]). pertence(X,[X|_]). pertence(X,[_|Y]) :pertence(X,Y). X= c Y = [c] 2a. Chamada Fail pertence(X,[X|_]). pertence(X,[_|Y]) :pertence(X,Y). X= c Y = [c] 1a. Chamada Fail pertence(X,[X|_]). pertence(X,[_|Y]) :pertence(X,Y). X= c Y = [b,c] Yes Pesquisando elementos de uma lista • Construa um predicado Prolog que encontre os elementos pares de uma lista de inteiros ?- pares([2,45,21,12,8], L). L = [2, 12, 8] Pesquisando elementos de uma lista • Um procedimento recursivo sempre tem um CRITÉRIO DE PARADA. Na maioria das vezes esse critério é o de lista vazia pares([], []). % Os pares de uma % lista vazia resulta em outra lista vazia pares([X|Y], [X|Z]) :- % se a cabeça é um elemento par(X), % par então o armazenamos e pares(Y,Z). % chamamos o pred. sobre o corpo pares([_|Y], Z) :pares(Y,Z). % se a cabeça não é um elemento % par então o ignoramos e % chamamos o pred. sobre o corpo Exercícios • Implemente os seguintes programas Prolog: • ?- potencia(Base, Expo, V) % calcula a potência • ?- n_elementos([a,b,c], X). % calcula o tamanho da lista X=3 • ?- n_esimo(2, [a,b,c], X). % encontra o n-ésimo elem. X=b • ?- merge([1, 4, 12, 28], [6,7,10], X). % faz o merge X = [1,4,6,7,10,12,28] • ?- insere(a, 2, [1,2,3], L). % insere um elemento na posição L = [1,a,2,3] Exercícios • ?- concatena([a,b,c],[1,2,3], L). % une duas listas L = [a,b,c,1,2,3] • ?- inverte([a,b,c], X). X = [c,b,a] • ?- ultimo([a,b,c],X). % inverte uma lista % encontra o último elem. da lista Encontrando Múltiplas Soluções • bagoff : retorna uma lista não ordenada de soluções. Se não houver solução então falha objeto(bola,azul). objeto(bola,amarela). objeto(carro,vermelho). ?- bagof(A,objeto(X,A),Lista). A=_, X = bola , Lista = [azul,amarela] ; A=_, X = carro , Lista = [vermelho] ; no ?- bagof(A,X^objeto(X,A),Lista). A=_, X=_, Lista = [azul,amarela,vermelho] Encontrando Múltiplas Soluções • setof : retorna uma lista ordenada de soluções. Se não houver solução então falha objeto(bola,azul). objeto(bola,amarela). objeto(carro,vermelho). ?- setof(A,objeto(X,A),Lista). A=_, X = bola , Lista = [amarela, azul] ; A=_, X = carro , Lista = [vermelho] ; no ?- bagof(A,X^objeto(X,A),Lista). A=_, X=_, Lista = [amarela, azul,vermelho] Encontrando Múltiplas Soluções • findall : retorna uma lista única não ordenada de soluções. Se não houver solução então retorna lista vazia. objeto(bola,azul). objeto(bola,amarela). objeto(carro,vermelho). ?- findall(A,objeto(X,A),Lista). A=_, X = bola , Lista = [azul, amarela, vermelho]