1 / 143

Universidade Federal de São Carlos Departamento de Computação

Universidade Federal de São Carlos Departamento de Computação. Programação Lógica. ProLog. Prof. Dr. Antonio Francisco do Prado e-mail: prado@dc.ufscar.br. Entrada e Saída. Manipulando Base de Dados. Operadores e Listas. Programação Lógica. Linguagem PROLOG. Exercícios.

stacie
Download Presentation

Universidade Federal de São Carlos Departamento de Computação

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Universidade Federal de São CarlosDepartamento de Computação Programação Lógica ProLog Prof. Dr. Antonio Francisco do Pradoe-mail: prado@dc.ufscar.br

  2. Entrada e Saída Manipulando Base de Dados Operadores e Listas Programação Lógica Linguagem PROLOG Exercícios Fatos, Regras e Controle de Corte Outros Exemplos Metodologia de Programação Lógica Fuzzy

  3. Programação Lógica Raízes • O uso da lógica na representação do raciocínio remonta os estudos de Boole (1815-1864) e de De Morgan (1806-1871) sobre a “Álgebra de Boole”; • Em 1879 surge a primeira versão do “Cálculo de Predicados” com o matemático alemão Göttlob Frege, onde era oferecida uma representação adequada para a formalização do raciocínio dedutivo; • Em 1930, em estudos simultâneos, o alemão Kurt Gödel e o francês Jacques Herbrand demonstraram que o mecanismo de prova do Cálculo de Predicados poderia oferecer uma prova formal de toda proposição logicamente verdadeira; • Ainda na década de 30 diversos estudos, entre eles os de Alan Turing e Alonzo Church, aproximaram muito o Cálculo de Predicado com a forma como hoje é conhecido; • Em 1939 toda fundamentação teórica básica da lógica computacional já estava pronta, faltava apenas uma meio prático para realizar o imenso volume de computações necessárias aos procedimentos de prova;

  4. Somente nos meados da década de 50 que o desenvolvimento dos computadores permitiu experiências mais significativas com o Cálculo de Predicados; • Em 1958 uma forma simplificada do Cálculo de Predicados denominada forma Clausal começou a despertar o interesse dos estudiosos. Nessa forma de cálculo era empregado um tipo muito simples de sentença lógica, a Cláusula; • Também nessa época (1960) Dag Prawitz propôs um novo tipo de operação sobre os objetos do Cálculo de Predicados, que foi mais tarde conhecido como Unificação; • Apesar de toda base teórica para a Programação Lógica estar pronta, ela somente se tornou possível a partir da pesquisa sobre prova matemática de teoremas, particularmente no desenvolvimento do Princípio da Resolução por J.A. Robinson (1965); • A expressão “Programação Lógica” (Logic Programming) surge com Robert Kowalski (1974) e designa o uso da lógica como uma linguagem de programação de computadores. OBS: muitos outros pesquisadores colaboraram para o aparecimento da Programação Lógica. No texto apenas foram relatados alguns deles.

  5. Conceitos da Programação Lógica • Uma das principais idéias em Programação Lógica é que um algoritmo é constituído por dois elementos disjuntos: • Lógica: corresponde à definição do que deve ser solucionado; • Controle: estabelece como a solução pode ser obtida; • A tarefa do programador é somente descrever (especificar) o componente lógico do algoritmo, deixando o controle da execução para ser exercido pelo sistema de programação em lógica utilizado; • Um Programa em Lógica é então a representação de determinado problema ou situação expressa através de um conjunto finito de um tipo especial de sentenças lógicas, denominadas cláusulas; • O paradigma fundamental da programação em lógica é o da Programação Declarativa, em oposição à Programação Procedimental típica das linguagens convencionais; • O ponto focal da Programação em Lógica consiste em identificar a noção de computação com a noção de dedução, onde a execução de programas se reduzem à pesquisa da refutação das sentenças do programa em conjunto com a negação da sentença que expressa a consulta, seguindo a regra: "uma refutação é a dedução de uma contradição".

  6. Os termos "programação em lógica" e "programação Prolog" tendem a ser empregados indistintamente. Deve-se, entretanto, destacar que a linguagem Prolog é apenas uma particular abordagem da Programação em Lógica; • Pode-se expressar conhecimento (programas e/ou dados) em Prolog por meio de cláusulas de dois tipos: • Fatos: denota uma verdade incondicional; • Regras: definem as condições que devem ser satisfeitas para que uma certa declaração seja considerada verdadeira. Características da Programação Lógica • Os sistemas de Programação em Lógica em geral e a linguagem Prolog em particular possuem as seguintes propriedades: • Funcionam simultaneamente como linguagem de programação e de especificação; • Possuem capacidade dedutiva; • Operam de forma não-determinística; • Permitem a representação de relações reversíveis; • Permitem interpretação declarativa, operacional e procedimental; • São naturalmente recursivas. 

  7. Aplicações da Programação Lógica • As principais aplicações da Programação em Lógica são: • Sistemas Baseados em Conhecimento (SBCs) • Sistemas de Bases de Dados (BDs); • Sistemas Especialistas (SEs); • Processamento da Linguagem Natural (PLN); • Educação; • Modelagem de Arquiteturas Não-Convencionais. Linguagens Convencionais x Lógicas

  8. Entrada e Saída Manipulando Base de Dados Operadores e Listas Programação Lógica Linguagem PROLOG Exercícios Fatos, Regras e Controle de Corte Outros Exemplos Metodologia de Programação Lógica Fuzzy

  9. Linguagem PROLOG Linguagens Funcionais x Lógicas Conclusão Tanto as linguagens Funcionais como Lógicas são importantes e empregadas principalmente em Sistemas Transformacionais, Inteligência Artificial (IA) e Robótica.

  10. Histórico • Criado por Alain Colmerauer por volta de 1970 na Universidade de Marselha, França. • Seu objetivo inicial era servir de apoio a sistemas de Linguagem Natural. Algol 60 Algol 68 Prolog Programação Prolog Para executar um programa em prolog, primeiro deve-se criar um arquivo com a extensão correspondente do interpretador ( .ari, .pl, etc). Depois, execute no interpretador correspondente. Em seu menu acione a opção File e Consult para carregar o programa no interpretador. Se houver algum erro no programa, este será mostrado na tela, senão o programa está pronto para ser executado (interpretado).

  11. A programação Prolog consiste fundamentalmente em: • Declarar fatos ou assertivas; • Estabelecer regras ou procedimentos; e • Fazer perguntas. • Os fatos e as regras são fornecidos e a linguagem usa dedução para obter respostas para as questões.

  12. Considerações sobre o aprendizado do aluno Temos observado que o estilo procedimental de programação, talvez por ser o primeiro a ser ensinado, interfere de certa forma, na correta aprendizagem de linguagens como Lisp ou Prolog por parte dos estudantes. Tentaremos minimizar essa interferência submetendo o aluno a resolução de conjuntos de problemas semelhantes, principalmente problemas envolvendo listas. É essencial que o aluno tente compreender a lógica de programação Prolog, entendendo mecanismos de unificação, backtracking entre outros. Também é importante que o aluno tente resolver os exercícios propostos no ultimo capítulo, para consolidar o seu aprendizado.

  13. Entrada e Saída Manipulando Base de Dados Operadores e Listas Programação Lógica Linguagem PROLOG Exercícios Fatos, Regras e Controle de Corte Outros Exemplos Metodologia de Programação Lógica Fuzzy

  14. Fatos, Regras e Controle de Corte Introdução • Um programa Prolog consiste de : • Definição de fatos arespeito de objetos de dados e suas relações; • Definição de regras a respeito de objetos de dados e suas relações; • Interrogação a respeito de objetos de dados e suas relações. Um objeto de dados em Prolog é definido de acordo com a seguinte árvore : objetos objetos simples estruturas variáveis constantes átomos números

  15. Átomo é a estrutura mais simples do Prolog, eles são construídos por cadeias de letras, dígitos e caracteres especiais( _, +, *). Todo átomo deve possuir a primeira letra minúscula. Exemplos de átomos : x_y, maria, copa2002. • Números em Prolog incluem números inteiros e números reais. A sintaxe é bem simples : 1, -20. • Variáveis são cadeias de letras, dígitos e caracteres sempre começando com letra maiúscula. • Estruturas são objetos de dados que têm vários componentes, podendo cada um deles, por sua vez, ser uma outra estrutura. • Por exemplo, uma data pode ser vista como um conjunto de dia, mês e ano. Embora composta por vários componentes, estruturas são tratadas no programa como objetos simples. A combinação dos componentes de um objeto simples é feita através de seu funtor. No caso de data, o funtor pode ser data e pode – se escrever 7 de setembro de 2002 da seguinte maneira : • data(7, setembro, 2002) • Note que os componentes 7, setembro e 2002 são todos constantes(2 inteiros e 1 átomo)

  16. Fatos, Regras e Controle de Corte tom pam liz bob pat ann jim Fatos Um Fato denota uma verdade incondicional. Uma relação pode ser especificada por um fato. Sintaxe: predicado(arg1[,arg2,...,arg n]). Argumentos (arg1...arg n) são objetos quaisquer e Predicado é a relação que une esses objetos.

  17. progenitor(pam,bob). %pam é um dos progenitores de bob progenitor(tom,bob). progenitor(tom,liz). %tom é um dos progenitores de liz progenitor(bob,ann). progenitor(bob,pat). progenitor(pat,jim). Em Prolog usam-se maiúsculas para variáveis e minúsculas para átomos. Questões: ?-progenitor(X,Y). X=pam , Y=bob ; X=tom , Y=bob ; X=tom , Y=liz ; X=bob , Y=ann ; X=bob , Y=pat ; X=pat , Y=jim ; variável átomo ?-progenitor(bob,pat). yes ?-progenitor(liz,pat). no ?-progenitor(X,liz). X=tom ; no ?-progenitor(bob,X). X=ann X=pat

  18. X Progenitor Avos Y Progenitor jim  Quem são os avós de Jim? (1) Quem é progenitor de Jim? (Por exemplo, Y) e (2) Quem é progenitor de Y? (Por exemplo, X). "Encontre X e Y tais que X é progenitor de Y e Y é progenitor de Jim". Questões: ?-progenitor(X, Y), progenitor(Y, jim). X=bob Y=pat ; • Quem é neto de Tom? Questões: • ?-progenitor(tom, X), progenitor(X, Y). • X=bob Y=ann; • X=bob Y=pat.

  19. Definição de uma extensão da base anterior • (característica do objeto): • mulher(pam). • homem(tom). • homem(bob). • mulher(liz). • mulher(pat). • mulher(ann). • homem(jim). Regras As regras definem as condições que devem ser satisfeitas para que uma certa declaração seja considerada verdadeira. Sintaxe: pred(arg/Var,arg/Var) :- pred(arg/Var,arg/Var). cabeça se corpo (conclusão) (condição) Onde o símbolo :- indica uma condição (se) e separa a regra em conclusão ou cabeça da regra e condição ou corpo da regra.

  20. Definir a relação filho. • Poderia ser definida como: • filho(bob,tom). • filho(bob,pam). • ... • Entretanto existe uma maneira mais elegante, que seguiria a seguinte declaração: • Para todo X e Y • Y é filho de X se • X é progenitor de Y. •  filho(Y, X) :- progenitor(X, Y). • "Para todo X e Y, se X é progenitor de Y, então Y é filho de X". • Questões: • ?-filho(jim,pat). yes filho(Y, X) :- progenitor(X, Y) cabeça  se  corpo (conclusão) (condição)

  21. Frases Compostas robo(peter). capaz_de_fazer(peter,armas). machuca(armas,pedro). homem(pedro). proibido_fazer(R,B):-robo(R),capaz_de_fazer(R,B), machuca(B,H),humano(H). Questão ? - proibido_fazer(R,B). R = peter , B = armas Significa: R está proibido de fazer um ato B se R for um robô e R for capaz de fazer B e B machuca H e H for humano. Para todo R e B proibido_fazer(R,B) se existe H tal que robo(R) e capaz_de_fazer(R,B) e machuca(B,H) e humano(H). humano(H):-homem(H). Hífen Usa-se o hífen para indicar irrelevância de um objeto Exemplo: aniversario(maria,data(25,janeiro,1979)). aniversario(joao,data(5,janeiro,1956)). signo(Pessoa,aquario):-aniversario(Pessoa,data(Dia,janeiro,_)), Dia >= 20. ? - signo(Pessoa,aquario). Pessoa = maria; no

  22. Conjunção e Disjunção Em prolog o operador de conjunção e ( , ) implica na necessidade de aceitação de todas as condições, enquanto o operador de disjunção ou ( ; ) permite a aceitação de uma ou outra condição. Estes operadores permitem a composição de fatos. Exemplos: amiga(X):-(X = maria; X = joana). disjunção ou • Definição de uma regra avos: • Usando-se a conjunção podemos definir o predicado avos seguindo a seguinte declaração: Para todo X e Z • X é progenitor de Y e • Y é progenitor de Z. • "Para todo X e Z, se X é progenitor de Y, e Y é progenitor de Z, então X é um dos avos de Z". • avos(X,Z):-progenitor(X,Y) , progenitor(Y,Z). conjunção e Questões: ?-avos(bob,jim). yes ?-avos(liz,jim). no ?-avos(pam,X). X=ann ; X=pat

  23. Z progenitor progenitor X Y mulher irmã • Definição de uma regra mãe: mae(X,Y):-progenitor(X,Y),mulher(X). Questões: ?-mae(pat,jim). yes ?-mae(bob,ann). no • Definição de uma regra irmã: irma(X,Y):-progenitor(Z,X),progenitor(Z,Y),mulher(X). Questões: ?-irma(ann,pat). yes ?-irma(X,pat). X=ann ; X=pat ; no • Definição de uma regra diferente: diferente(X,Y):-X\==Y. %X é diferente de Y

  24. bob Antepassados indiretos Antepassados diretos pat jim • Definição de uma regra irmã usando a regra diferente: irma(X,Y):-progenitor(Z,X),progenitor(Z,Y),diferente(X,Y). Questão: ?-irma(X,pat). X=ann ; no • Definição de uma regra tia: tia(X,Y):-progenitor(Z,Y),irma(X,Z). Questão: ?-tia(liz,X). X=ann ; X=pat ; no Recursão • Definição de uma regra antepassado • Necessita de duas regras: antepassados diretos e antepassados indiretos.

  25. Primeira regra bastante simples: • Para todo X e Z • X é antepassado de Z se • X é progenitor de Z. • antepassado(X, Z) :- progenitor(X, Z). • Segunda regra complicada. A cadeia de progenitores pode se estender indefinidamente: • antepassado(X, Z) :- progenitor(X, Y), • progenitor(Y, Z). •   antepassado(X, Z) :- progenitor(X, Y1), • progenitor(Y1, Y2), • progenitor(Y2, Z). • antepassado(X, Z) :- progenitor(X, Y1), • progenitor(Y1, Y2), • progenitor(Y2, Y3), • progenitor(Y3, Z). • ....

  26. X Progenitor Y Antepassado Antepassado Z • Solução: definir a regra recursivamente • Para todo X e Z • X é antepassado de Z se • existe um Y tal que • X é progenitor de Y e • Y é antepassado de Z. • A segunda regra fica: antepassado(X, Z) :- progenitor(X, Y), • antepassado(Y, Z). Questões: ?-antepassado(X,liz). X=tom ; no ?-antepassado(X,pat). X=bob ; X=pam ; X=tom ; no

  27. Controle de Corte Há ocasiões em que, por um ou outro motivo, desejamos controlar a execução do programa. Para isso, utilizamos o mecanismo de corte. Operador Cut • Algumas das principais aplicações do cut são as seguintes: • Unificação de padrões, de forma que quando um padrão é encontrado os outros padrões possíveis são descartados (quando uma determinada regra é a última a ser analisada e haveria problemas na continuidade da verificação das demais regras); • Para eliminar da árvore de pesquisa soluções alternativas quando uma só é suficiente; • Especificar regras mutuamente exclusivas, expressas na forma: Se P então Q senão R; • Como indicativo do caso limite ou para evitar que a pesquisa prossiga indefinidamente através do backtracking. • Simbolizado pela exclamação (“!”). • Seu uso deve ser considerado pelas seguintes razões: • Execução mais rápida do programa (não desperdiça tempo tentanto satisfazer objetivos que não contribuirão para a solucão desejada); • Economiza memória (corta a ávore de pesquisa).

  28. Exemplos: • Podemos simular a programação procedimental em Prolog. Aqui simularemos a estrutura if-then-else: • ifThenElse(X,Y,Z) • "Se X for verdadeiro, então execute Y, senão execute Z".   • ifThenElse(X, Y, _) :- X, !, Y. • ifThenElse(_, _, Z) :- Z. • Questão: • ?-ifThenElse(X, Y is Z+1, Y is 0). • OBS: este programa emprega meta-variáveis (variáveis que podem ser instanciadas com chamadas a predicados) • Exemplo do operador Cut: amigo(joana,ana). amigo(maria,ana). amigo(pedro,jose). amigo(pedro,ana). • um_unico_amigo(X,Y):-amigo(X,Y),!. Questões: ?- um_unico_amigo(X,ana). X = joana ?- um_unico_amigo(pedro,X). X = jose • Mínimo entre dois números: • minimo(X,Y,X):-X =< Y, !. • minimo(X,Y,Y):-X > Y, !. Questões: ?- minimo(10,3,Min). Min = 3 ?- minimo(12,56,Min). Min = 12

  29. Fail O predicado Fail, força um retrocesso, como se indicasse uma falha. Junto com o corte (Cut), acelera a avaliação de regras economizando memória. Exemplos: • Exemplo do operador Fail: cliente(ana,123,bradesco). cliente(jose,456,itau). executa :- cliente(Nome,Conta,Agencia), write(Nome),write(’ tem conta ’),write(Conta), write(’ na agencia ’),write(Agencia),nl,fail. • Neste caso fail força um backtracking e repete a a impressão. Questões: ?-executa. ana tem conta 123 na agencia bradesco jose tem conta 456 na agencia itau no Not (X) O operador unário not define uma forma particular de negação denominada "negação por falha”.

  30. Definição de uma regra para exemplificar o not: • estudante(jorge). • casado(jose). • estudante_solteiro(X):-not casado(X), estudante(X). Questões: ?-estudante_solteiro(jorge). yes ?-estudante_solteiro(jose). no Cuidados com o Cut e a Negação • O uso do cut pode levar a perda da correspondência entre o significado declarativo e a interpretação operacional do programa: • Se não houver cuts no programa pode-se trocar a ordem das cláusulas e objetivos que seu significado declarativo não será alterado (há apenas uma possível perda de performance); • Se houver cuts essa alteração pode afetar o significado declarativo levando a resultados inesperados. • O uso da negação também pode levar a resultados inesperados. Qual o problema do programa abaixo? Questões: r(a). q(b). p(X) :- not r(X). ?-p(X), q(X). no ?-q(X), p(X). X = b.

  31. Outros Exemplos de Regra • Definição das regras positivo e negativo: positivo(X):-X>=0. %X é maior ou igual a 0 negativo(X):-X<0. %X é menor que 0 Questões: ?-positivo(7). yes ?-negativo(10). no • Máximo entre 2 números: max(X,Y,X):-X>=Y. max(X,Y,Y):-X<Y. • Máximo entre 2 números usando corte: max(X,Y,X):-X>=Y,!. max(X,Y,Y). Questão: ?-max(10,3,Max). Max=10 • Definição das regras par e impar: par(X):-X mod 2 =:=0 % o mod de 2 é igual a 0 impar(X):-par(X),!,fail. impar(X). Questões: ?-par(6). yes ?-impar(6). no

  32. Y=f(X) • Definição de uma função f(X): • f(X, 0):- X < 3. • f(X, 2):- 3=< X, X < 6. • f(X, 4):- 6 =< X. • Definição de uma função f(X) com corte: • f(X, 0):- X < 3, ! . • f(X, 2):- 3 =< X, X < 6, ! . • f(X, 4). Questões: ?-f(1,Y),2<Y. no ?-f(7,Y). Y = 4 • Definição de uma regra para fatorial: • fatorial(0, 1):- !. • fatorial(N, F):- N1 is N - 1, %Atribuição • fatorial(N1, F1), • F is F1 * N. Questão: ?- fatorial(4, F). F = 24

  33. Exemplo de recursividade Para o exemplo anterior da regra do Fatorial recursivo, é mostrado a execução passo a passo, note que em todos os passos(com excessão do 5) há unificação com a segunda regra. (primeira regra é critério de parada). Questão: ?- fatorial(4, F). F = 24 Passo 1 : fatorial(4, F) { N = 4, N1 =3, F = F1 * 4, fatorial(N1, F1) } F = 6 Passo 2 : fatorial(3, F) { N = 3, N1 =2, F = F1 * 3, fatorial(N1, F1) } F = 2 Passo 3 : fatorial(2, F) { N = 2, N1 =1, F = F1 * 2, fatorial(N1, F1) } F = 1 Passo 4 : fatorial(1, F) { N = 1, N1 =0, F = F1 * 1, fatorial(N1, F1) } F = 1 Passo 5 : fatorial(0, F) {F = 1 }

  34. Definição de uma regra para fatorial com recursão de cauda: • fact(N,Fn):-fact(N,Fn,0,1). • fact(N,Fn,N,Fn):-!. • fact(N,Fn,I,P):-Novoi is I+1,Novop is P*Novoi, • fact(N,Fn,Novoi,Novop). Questão: ?- fact(6, F). F = 720 Recursão de cauda. A recursividade é a última. • Definição de uma regra para fibonacci: • fib(1, 1). • fib(2, 1). • fib(N, F):- N > 2, • N1 is N - 1, fib(N1, F1), • N2 is N - 2, fib(N2, F2), • F is F1 + F2. Questão: ?- fib(6, F). F = 8 ; no

  35. Entrada e Saída Manipulando Base de Dados Operadores e Listas Programação Lógica Linguagem PROLOG Exercícios Fatos, Regras e Controle de Corte Outros Exemplos Metodologia de Programação Lógica Fuzzy

  36. Operadores e Listas Operadores Aritméticos Exemplo: • Cálculo de um número elevado ao quadrado: • ao_quadrado(X,Y):-Y is X*X. Questão: ?- ao_quadrado(6,X). X=36

  37. Operadores de Comparação Exemplo: • Definição de uma regra intervalo aberto: • interv_aberto(K,X1,X2):-K > X1,K < X2. Questões: ?- interv_aberto(5,0,5). no ?- interv_aberto(2,0,5). yes

  38. Listas As listas são estruturas de dados dinâmicas com as quais é possível a construção de vetores e matrizes. Sintaxe: pred([elem,...],[],[elem[elem,...],...],arg,...). Onde elem pode ser qualquer tipo sintático. Listas são compostas por cabeça e cauda. A cabeça de uma lista pode ser qualquer objeto Prolog e a cauda deve ser uma lista. Como a cauda, por sua vez, é uma lista, ela á a lista vazia ou tem sua própria cabeça e cauda. Sintaxe para Listas A lista vazia é denotada por [] ; a lista que tem cabeça X e cauda Y é denotada por [X|Y] . Dentro das listas, os elementos são separados por vírgula. Exemplo : Lista Cabeça Cauda [gosto,de, vinho] gosto [de, vinho] [X,Y|Z] X [Y|Z] [[o,gato]] [o,gato] []

  39. Lista 1 Lista 2 Unificação [mesa] [X|Y] X / mesa Y / [ ] [a,b,c,d] [X,Y|Z] X / a Y / b Z / [c,d] [[ana, Y] | Z] [[X, foi], [ao, cinema]] X / ana Y / foi Z / [[ao, cinema]] [ano, bissexto] [X,Y|Z] X / ano Y/ bissexto Z / [ ] Unificação em listas Em Prolog, a mais importante operação envolvendo termos é chamada unificação. Dois termos T e S unificam se : 1. Se T e S são constantes, então unificam se e só se S e T são o mesmo objeto. 2. Se S for uma variável e T qualquer termo, então unificam, e S é instanciado com T ; vicer – versa, com a variável T instanciada com S. 3. Se S e T são estruturas, eles unificam se e só se S e T tem o mesmo funtor principal e todos os elemtentos correspondentes unificam. A seguir são mostrados vários exemplos de unificação em listas :

  40. Lista 1 Lista 2 Unificação [ano, bissexto] [X,Y,Z] não unifica (aridade diferente) [data(7,Z,W), hoje] [X,Y] X / data(7,Z,W) Y / hoje [data(7,W,1993), hoje] [data(7,X,Y), Z] X / W Y / 1993 Z / hoje Busca recursiva Freqüentemente é necessário procurar por algum termo Prolog ; isto resulta em uma busca recursiva. Para verificar se um elemento pertence à uma lista, usamos o seguinte predicado: pertence(X, [X | _]). % verifica se X esta na cabeça pertence(X, [_ | Y]):- pertence(X, Y). % verifica se X % esta na cauda Questões: ?- pertence(a, [h, a, b]). yes ?- pertence( a, [hoje, amanha]). no ?- pertence(X, [a, b, c]). X = a; X = b; X = c; no

  41. Goal ?- X = [1,2,3],pertence(a,X). no ?- pertence( a, X),X = [1,2,3]. X = [a |_] %pode ser o 1º elemento de X X = [_ , a | _] %pode ser o 2º elemento de X X = [_ , _ , a | _] %pode ser o 3º elemento de X . . . %computação infinita! Sequência de ligação -> da esquerda para a direita Conclusão Escolha o “subgoal” com o menor número de soluções como “goal” a adivinhar. No caso anterior o “goal” a adivinhar correto é X = [1,2,3], porque tem apenas uma solução e esta solução não satisfaz pertence(a,X), porque “a” não está na lista [1,2,3].

  42. Controle em Prolog 1. Iniciar pelo goal 2. Enquanto o goal corrente não é vazio faça 2.1. Comece pelo subgoal mais à esquerda 2.2. Se uma regra aplica ao subgoal então 2.2.1. Para esta regra, usando unificadores genéricos, volte para 2.1 Senão backtrack fim-se fim-enquanto Exemplo: anexa([ ],Y,Y ). anexa([H | X],Y,[H| Z]):- anexa(X, Y,Z). prefix(X,Z):-anexa(X,Y,Z). sufix(Y,Z):-anexa(X,Y,Z).

  43.  1º Subgoal ?- sufix ( [ a ] , L ) , prefix ( L , [ a , b , c ] ). L = [ a ] ; %sem backtraing X = [ ] Y = [ b , c ]  O fato sufix ( Y´ , Z´ ) :- anexa ( X´ , Y´ , Z´ ) aplica ao subgoal mais à esquerda sufix ( [ a ] , L )  A substituição Y´ -> [ a ] , Z´ -> L Unifica a cabeça da regra com o subgoal sufix ( [ a ] , L ) Tem-se então: sufix ( [ a ] , L ) if anexa ( _1 , [ a ] , L ) nome Prolog  Substituindo pela condição tem-se: anexa ( _1 , [ a ] , L ) , prefix ( L , [ a , b , c ] )  O fato anexa ( [ ] , Y´´ , Y´´ ) aplica ao novo subgoal mais á esquerda: [ ] -> _1 , Y´´ -> [ a ] , Y´´ -> L  Uma vez que o fato consiste de uma cabeça e nenhuma condição, o novo goal corrente torna-se: prefix ( [ a ] , [ a , b , c ] ) substituída -> L  Tem-se então: prefix ( [ a ] , [ a , b , c ] ) if anexa ( [ a ] , _2 , [ a , b , c ] ) . anexa ( [ a ] , _2 , [ a , b , c ] ) if anexa ( [ ] , _2 , [ b , c ] ). anexa ( [ ] , _2 , [ b , c ] ) 2 -> [ b , c ] anexa ( [ ] , [ b , c ] , [ b , c ] ) . L = [ a ] ;

  44. Modos de Chamada Usando o exemplo do pertence([arg1], [arg2]) mostrado anteriormente, o que aconteceria se as interrogações fossem : ?- pertence(a,X) % ou ?- pertence(X,Y) Pode – se observar que cada uma delas tem “infinitas” respostas, uma vez que existem infinitas listas que validam estas interrogações para o programa pertence. Portanto, é necessário definir se os argumentos devem estar ou não instanciados. Usaremos a seguinte notação para documentar as formas corretas de interrogação : modo(<arg – 1>, <arg – 2>, .....,<arg – n>) onde : <arg – i > = + se <arg – i > deve estar instanciado. <arg – i > = - se <arg – i > deve ser variável livre. <arg – i > = ? se <arg – i > puder ser qualquer um dos casos. Exemplo : o exemplo pertence ([arg1], [arg2]) tem o modo(? , +).

  45. Outros Exemplos de Lista • Verificação se um elemento de uma lista não pertence a outra lista, modo(+, +) : nao_pertence(X,Y):- \+ (pertence(Z,X),pertence(Z,Y)). Questões: ?- nao_pertence([a,b,c],[d,e,f]). • yes ?-nao_pertence([a,b],[b,c]). no • Soma dos elementos de uma lista, modo(+, ?) : • soma([ ], 0). • soma( [Elem | Cauda], S):- soma(Cauda, S1), • S is S1 + Elem. Questão: • ?- soma([1, 2, 3, 4, 5, 6], S). • S = 21 • Verificação se uma lista está ordenada, modo(+) : ordenada([ ]). • ordenada([X,Y | Resto]):-X=<Y,ordenada([Y | Resto]). Questões: • ?-ordenada([1,5,6,6,9,12]). • yes ?-ordenada([3,2,1]). no

  46. Verificação se um termo é uma lista, modo(+) : eh_lista([ ]). • eh_lista(X):- not var(X), • not atom(X). Onde os predicados: • var(X) - Verdadeiro se o termo X é uma variável  atom(X) - Verdadeiro se o termo X é um átomo Questões: ?- eh_lista([a, b, c, d, e, f]). • yes • ?- eh_lista([ ]). • yes ?- eh_lista( 2 ) no • Duplicação dos elementos de uma lista, modo(+,?) : duplica([ ], [ ]). • duplica( [X | L], [X, X | L1]):- duplica(L, L1). Questão: ?- duplica([1, 2, 3], L). • L = [1, 1, 2, 2, 3, 3]

  47. Concatenação de duas listas, modo(+,?,?) : concatena([ ], Lista, Lista). • concatena([ Elem | Lista1], Lista2, [Elem | Lista3]):- • concatena(Lista1, Lista2, Lista3). • Questão: ?- concatena([um, dois], [tres, quatro], L). • L = [um, dois, tres, quatro] • Também pode – se usar o modo modo(-,-,+) para decompor uma lista em duas sublistas. • Maior elemento de uma lista numérica, modo(+,?) : • max([X], X). % Maior elemento de uma lista com 1 • % elemento é o próprio elemento • max([X, Y | Cauda], Max):- X >= Y, ! , • max([X | Cauda], Max). • max([X, Y | Cauda], Max):- max([Y | Cauda], Max). Questão: • ?- max([1, 10, 100, -1, 20], M). • M = 100 ; • no • N_ésimo elemento de uma lista, modo(?,?,+) : • n_esimo(1, Elem, [Elem | _]). • n_esimo(N, Elem, [ _ | Cauda]):- n_esimo(M, Elem, Cauda), • N is M + 1. Questão: • ?- n_esimo(4, Elem, [a, b, c, d, e]). • Elem = d ; • no

  48. Inversão de uma lista, modo(+,?) : • inverter([ ],[ ]). • inverter([Elem | Lista1], Lista3):-inverter(Lista1,Lista2), • concatena(Lista2,[Elem], Lista3). Questões: • ?- inverter([a,b,c], L). ?-inverter([1,2,3,4,5,6],L). • L = [c,b,a] L = [6,5,4,3,2,1] • Número de elementos em uma lista, modo(+,?) : • tamanho([ ],0). • tamanho([_ | R], N):-tamanho(R, N1),N is N1+1. Questão: • ?- tamanho([a,b,c,d,e], N). • N = 5 • Seleção de determinados elementos de uma lista, em uma lista separada, identificados pela sua posição, modo(+,+,?) : seleciona([ ], _, [ ]). • seleciona([M | N], L, [X | Y]):-n_esimo(M, X, L), seleciona(N, L, Y). Questão: • ?- seleciona([2, 4], [a, b, c, d, e], L). • L = [b, d] ; • no

  49. Ultimo elemento de uma lista, modo(+,?) : ultimo([Elem], Elem). • ultimo([_|Cauda], Elem) :- ultimo(Cauda, Elem). Questões: • ?- ultimo([casa, bola, carro], X) • X = carro ; • no • Elementos consecutivos em uma lista, modo(?,?,+) : • consecutivos(E1,E2, [E1, E2|_]). • consecutivos(E1, E2, [_|Cauda]) :- • consecutivos(E1, E2, Cauda). Questões: • ?- consecutivos(a, b, [d, e, f, g, a, b]). • yes • ?- consecutivos(X, Y, [d, e, f, g]). • X = d • Y = e ; • X = e • Y = f ; • X = f • Y = g ; • no

  50. Inserção de um elemento na 1ª posição de uma lista, modo(?,?,?) : • inserir(Elem, Lista, [Elem | Lista]). Questão: • ?- inserir(a, [b, c, d], L). • L = [a, b, c, d] • Exclusão de um elemento de uma lista, modo(?,+,?) ou modo(+,?,+) : • del(X,[X | Corpo],Corpo). • del(X,[Y | Corpo], [Y | Corpo1]):-del(X,Corpo,Corpo1). Questão: • ?- del(b,[a,b,c], L). • L = [a,c] ; • no • Permutação de uma lista, modo(+,?) : • permuta([ ],[ ]). • permuta(L,[X | P]):-del(X,L,L1),permuta(L1,P). Questão: • ?- permuta([vermelho,azul,verde], L). • L = [vermelho,azul,verde] ; • L = [vermelho,verde,azul] ; • L = [azul,vermelho,verde] ; • L = [azul,verde,vermelho] ; • L = [verde,vermelho,azul] ; • L = [verde,azul,vermelho] ; • no

More Related