Exemplos de Prolog Automática I
Exemplo 1 Regra: Todos que possuem livros podem emprestá-lo à maria Fato: João possui um livro. Questão: O João pode emprestar um livro à maria? empresta(X,maria,livro(P)):-dono(X,livro(P)). dono(joao,livro(exodo)). Questão: ?- empresta(joao,maria,livro(X)).
Solução vista pelo PROLOG -1 ?- empresta(joao,maria,livro(X)). empresta(X,maria,livro(P)):-dono(X,livro(P)). dono(joao,livro(exodo)). X = joao e P = exodo X da pergunta equivale ao P da regra empresta(joao,maria,livro(exodo)) X = exodo
Exemplo 2 Regra: Todos que respeitam a si mesmo são respeitados pelos outros Fato: Carol respeita a si mesma. Pergunta: Quem é respeitado(a) por José? respeitado_por(_,X):- respeita_a_si_mesmo(X). respeita_a_si_mesmo(carol). Questão: respeitado_por(jose,X).
Solução vista pelo PROLOG - 2 REGRAS: respeitado_por(_,X):- respeita_a_si_mesmo(X). respeita_a_si_mesmo(carol). Questão:?- respeitado_por(jose,X). _ = qualquer valor ; verifica então quem respeita_a_si_mesmo respeita_a_si_mesmo(carol). então respeitado_por(jose,carol):- respeita_a_si_mesmo(carol). Logo X = carol!
Exemplo 3 – Torre de Hanoi
Exemplo 3 – Torre de Hanoi (nl – new-line) (vírgula = and) mover(1,X,Y,_) :- escrever('Mova o disco do topo da '), escrever(X), escrever(' para a '), escrever(Y), nl. mover(N,X,Y,Z) :- N>1, M is N-1, mover(M,X,Z,Y), mover(1,X,Y,_), mover(M,Z,Y,X).
REGRAS: mover(1,X,Y,_) :- escrever('Mova o disco do topo da '), escrever(X), escrever(' para a '), escrever(Y), nl. mover(N,X,Y,Z) :- N>1, M is N-1, mover(M,X,Z,Y), mover(1,X,Y,_), mover(M,Z,Y,X). mover(3,1,2,3) Lembrar: nl = nova linha, “,” = and (operador e) _ = null (qqer parametro torna verdadeiro) SOLUÇÃO:
Exemplo 4 Como deletar um membro de uma lista? Resposta: del(X,L1,L2) somente tem sucesso se X é um membro de L1 e L2 é a lista original (L1) sem X. Se X é o cabeça de L1, então a lista correta é o resto de L1. Se X está no resto de L1, então a lista correta é a cabeça de L1 mais o resto sem o X. del(X,[X|R],R). del(X,[H|R1],[H|R2]):-del(X,R1,R2). Questão: ?- del(3,[1,2,3],X).
Solução : Regras: del(X,[X|R],R). del(X,[H|R1],[H|R2]):-del(X,R1,R2). Questão: ?- del(3,[1,2,3],X). X = [1,2] del(3, [1|[2,3],[1|R2]):-del(3,[2,3],R2). R2 = [2] del(3, [2] | [3], [2 | R2]):-del(3,[3],R2). R2 = [] del(3, [3 | [] ], []) -> R = []
Exemplo 5 Como concatenar duas listas? Resposta: concatena(X,Y,Z) é verdadeiro se a lista Z é o resultado da concatenação das listas X e Y. Se X é lista vazia ([]) então Z=Y. Se X não é lista vazia, então a cabeça de Z é a cabeça de X e o resto de Z é igual à concatenação do resto de X com a lista Y. concatena([],L2,L2). concatena([H1|T1],L2,[H1|T3]):-concatena(T1,L2,T3). Questão: ?- concatena([a,b,c],[d,e,f],L)
Solução Regras: concatena([],L2,L2). concatena([H1|T1],L2,[H1|T3]):-concatena(T1,L2,T3). Questão: Concatena([a,b,c] , [d,e,f],L) L = [a,b,c,d,e,f] concatena([a|[b,c]] , [d,e,f] , [a|T3]):-concatena([b,c],[d,e,f],T3) concatena([b|c] , [d,e,f] , [b|T3]):-concatena(c , [d,e,f] , T3) concatena([c|[]] , [d,e,f] , [c|T3]):-concatena([] , [d,e,f] , T3) concatena([] , [d,e,f] , T3) T3 = [d,e,f] T3 = [b,c,d,e,f] T3 = [c,d,e,f] T3 = [d,e,f]
Exemplo 6 Como inverter uma lista? Resposta: inverte(L1,L2) é verdadeiro se a lista L2 é o inverso de L1. A inversão de uma lista vazia é a própria lista vazia (saída da recursão). A iversão de uma lista não vazia é uma lista obtida da concatenação (exemplo 4) do reverso do resto com uma lista que é apenas a cabeça da lista original. inverte([],[]). inverte([H|T],L):-inverte(T,L0),concatena(L0,[H],L). Questão: ?- inverte([a,b,c],L).
Solução : Regras: Questão: inverte([],[]). inverte([H|T],L):-inverte(T,L0),concatena(L0,[H],L). Questão: ?- inverte([a,b,c],L). L = [c,b,a] inverte([a|[b,c]],L):-inverte([b,c],L0),concatena(L0,[a],L). L0= [a] L = [c,b,a] inverte([b|c],L):-inverte(c,L0),concatena(L0,[b],L). L0 = [c] L = [c,b] inverte([c|[]],L):-inverte([],L0),concatena(L0,[c],L). L0 = [] L = [c] inverte([],L0). L0 = []. !
Exemplo 7 Como calcular o tamanho de uma lista? Resposta: tamanho([_|R],Tam):-tamanho(R,TamResto),Tam is TamResto+1. Questão: ?- tamanho([1,r,t,5],T).
Solução: Regras: Questão: ?- tamanho([1,r,t,5],T). T = 4 tamanho([_|R],Tam):-tamanho(R,TamResto),Tam is TamResto+1. Questão: ?- tamanho([1,r,t,5],T). T = 4 tamanho([1|[r,t,5]],T):-tamanho([r,t,5],TamResto),Tam is TamResto+1. Tam = 4 tamanho([r|[t,5]],T):-tamanho([t,5],TamResto),Tam is TamResto+1 Tam = 3 tamanho([t|[5]],T):-tamanho([5],TamResto),Tam is TamResto+1 Tam = 2 tamanho([5|[]],T):-tamanho([],TamResto),Tam is TamResto+1 Tam = 1 tamanho([],TamResto). TamResto = 0
Cut (!) ! é chamado de cut e sempre obtém sucesso. Mas há um porém: as metas à direita do ! podem ser re-satisfeitas em um backtracking, mas as metas à esquerda não! Note também que cláusulas alternativas no mesmo banco de dados não serão mais consideradas se uma meta deste tipo for encontrada. É usado para: Informar ao sistema que a regra correta foi encontrada e nenhuma outra alternativa pode ser considerada; Usando !,fail: Informar ao sistema que a meta falhou e nenhuma outra pode ser tentada. Informar ao sistema para buscar apenas uma solução descartando soluções alternativas.
Exemplo 8 Somar os inteiros de 1 a n. soma(1,1):-!. soma(N,Res):-N0 is N-1,soma(N0,Res0),Res is Res0+N. Questão: ?- soma(3,X). X = 6 soma(3,X):-2 is 3-1,soma(2,Res0),Res is Res0+3. Res = 6 soma(2,Res0):-1 is 2-1,soma(1,Res0’),Res is Res0’+2. Res = 3 soma(1,Res0’):-!. Res0’ = 1
Exemplo 9 Calcular M elevado na N recursivamente. exp(0,1,1). exp(M,N,Res):-N>0,N0 is N-1,exp(M,N0,Res0),Res is Res0*M. Questão: ?- exp(3,4,Res). Res = 81 exp(3,4,Res):-4>0, 3 is 4-1,exp(3,3,Res0),Res is Res0*3 Res = 81 exp(3,3,Res):-3>0, 2 is 3-1,exp(3,2,Res0),Res is Res0*3 Res = 27 exp(3,2,Res):-2>0, 1 is 2-1,exp(3,1,Res0),Res is Res0*3 Res = 9 exp(3,2,Res):-2>0, 1 is 2-1,exp(3,0,Res0),Res is Res0*3 Res = 3 exp(0,1,1). Não dá! Acho que era pra ser : exp(_,0,1). exp(_,0,Res0). Daí Res0 = 1