Inteligência Artificial PROLOG – partes 1, 2 e 3 Rafael Rosario [email_address] [email_address]
PROLOG (I) Foi criada em meados de 1972 por Alain Colmerauer e Philippe Roussel, na  Universidade de Marselha. O nome PROLOG foi escolhido por Philippe Roussel como uma abreviação de “ PRO grammation en  LOG ique”. Propósito da criação: criar programas para tradução de linguagens faladas, como português ou inglês.
PROLOG (II) Fundamentada na  lógica simbólica ; É uma linguagem declarativa: em vez de o programa estipular a maneira de chegar à solução, passo a passo, limita-se a fornecer uma descrição do problema que se pretende computar.  Usa uma coleção de  fatos  e de relações lógicas ( regras ) que exprimem o domínio relacional do problema.
PROLOG(III) Outro fato que o difere das outras linguagens é o fato de não possuir estruturas de controle (if-else, do-while, for, switch). Para isso utilizamos métodos lógicos para declarar como o programa deverá atingir o seu objetivo.  Um programa em PROLOG pode rodar em um modo interativo: o usuário poderá formular queries utilizando fatos e regras para produzir a solução através do mecanismo de unificação.
Fato (I) Determina uma relação existente entre objetos conhecidos. Expressa uma verdade sobre um relacionamento: homem(jose). pai(jose,carina). homem / pai – Predicado ou Relação. jose / jose,carina – Argumento do Predicado ou  Objeto
Fato (II) Os nomes dos predicados e dos objetos devem começar com letra minúscula.  Os objetos são escritos dentro de parênteses. Todo fato é terminado com um ponto final. A ordem dos objetos é importante:  pai (jose, carina).    pai (carina, jose).
Fato (III) Com fatos, podemos montar uma base de conhecimento: pai(alfredo,moacyr). pai(alfredo,romeu). pai(moacyr,eduardo). pai(moacyr,rafael). pai(moacyr,vinicius). pai(romeu,cezar). pai(romeu,alfredinho).
Regra (I) Expressa um relacionamento entre fatos. Um relacionamento em uma regra é verdadeiro se os outros relacionamentos nessa regra também o são: luz(acesa) :- interruptor(ligado).  O ":-" significa "se"; ou seja, essa regra significa que luz(acesa) é verdadeiro se interruptor(ligado) é verdadeiro.
Regra (II) Regras podem também fazer uso de variáveis: avo(X,Z) :- pai(X,Y), pai(Y,Z). Isso significa "se X é pai de Y  e Y é pai de uma Z, então X é avô de Z“. X, Y e Z são variáveis. No PROLOG,uma variável não é um contêiner cujo valor pode ser atribuído. Seu comportamento é como de uma incógnita, cujo valor é desconhecido a princípio e, após descoberto, não sofre mais mudanças. Escritas sempre em Maiúsculo.
Consulta (I) Quando de uma consulta, a máquina PROLOG pesquisa a base de dados procurando cláusulas que se unifiquem com a consulta: ? – pai(moacyr, rafael). Responderá  true  se localizar um fato que se unifique com a consulta; se o fato consultado não existir na base de  dados, responderá  fail .
Consulta (II) Quando uma consulta contém variáveis, é  realizada uma pesquisa em todas as cláusulas, localizado os objetos que essas representam:  ?- avo(alfredo,N). N = eduardo ;  N = rafael ; N = vinicius ; N = cezar ; N  = alfredinho.
Regras Recursivas Um predicado definido por uma regra recursiva deve ter, no mínimo uma definição não recursiva. Se isto não acontecer, a definição é logicamente mal-formada e o programa ficaria em laço infinito.  ancestral(X,Y) :- mae(X,Y).  ancestral(X,Y) :- pai(X,Y).  ancestral(X,Y) :- mae(X,Z),ancestral(Z,Y).  ancestral(X,Y) :- pai(X,Z),ancestral(Z,Y).
Prática 1 Crie a árvore genealógica da sua família, utilizando os predicados pai e mae, e verifique o que retorna cada consulta: ancestral(fulano,ciclano). ancestral(X,ciclano). /*clique n a cada valor*/ ancestral(fulado,Y). /*clique n a cada valor*/ ancestral(fulado,_). /*clique n a cada valor*/ mae(X,_). /*clique n a cada valor*/ ancestral(X,_),pai(X,Y),pai(Y,_)
Prática 1 - exemplo mae(zilda,moacyr). mae(zilda,romeu). mae(maria,eduardo). mae(maria,rafael). mae(maria,vinicius). mae(norma,cezar). mae(norma,alfredinho). pai(alfredo,moacyr). pai(alfredo,romeu). pai(moacyr,rafael). pai(moacyr,eduardo). pai(moacyr,vinicius). pai(romeu,cezar). pai(romeu,alfredinho).
Outros conceitos (I) Conjunção : (“E” Lógico) é feita colocando-se uma vírgula entre os fatos:    avo(X,Z) :- pai(X,Y) ,  pai(Y,Z). Aridade : é usado para a quantidade de objetos que o argumento de um predicado possui.  gosta (maria, josé). /* aridade = 2 */ bebe (penélope, pinga, vodka, rum). /*4*/
Outros conceitos (II) Negação : uma consulta é avaliada como falsa no caso de não estar presente nenhuma regra positiva ou fato que dê suporte ao termo proposto.  Em outras palavras, se um fato não é conhecido ser verdadeiro (ou falso), assume-se que ele é falso. legal(X) :-  \+  ilegal(X). Diferente:  quando duas variáveis não podem ter o mesmo valor: vizinho(X,Y) :- rua(X,Z), rua(Y,Z), X  \==  Y.
Outros conceitos (II) Disjunção:  (OU lógico),   quando se declara mais de uma regra para determinar uma mesma relação: vizinho(X,Y) :- rua(X,Z), rua(Y,Z), X \== Y ;  rua(X,Z), rua (X,W), proximo(Z,W).
Prática 2 A partir da árvore genealógica da sua família, crie as funções para: irmão; meio-irmão; primo;
Resposta - Prática 2 (I) irmao(X,Y) :- pai(P,X), pai(P,Y),  mae(M,X),mae(M,Y),  X \== Y . meio-irmao(X,Y) :-  pai(P,X), pai(P,Y), X \== Y, \+ irmao(X,Y) ; mae(M,X),mae(M,Y), X \== Y, \+ irmao(X,Y).
Resposta - Prática 2 (II) genitor(X,Y) :- pai(X,Y); mae(X,Y). primo(X,Y) :- genitor(P,X), genitor(T,Y), P \== T,  genitor(V,P), genitor(V,T).
Aplicações (I) Lógica matemática, prova de teoremas e semântica; Solução de equações simbólicas; Bancos de dados relacionais; Linguagem Natural; Sistemas Especialistas;
Aplicações (II) Planejamento Automático de Atividades; Aplicações de “General Problem Solving”, como jogos (Xadrez, Damas, Jogo da Velha, etc.); Compiladores; Análise Bioquímica e projetos de novas drogas.
Revisando – 3 elementos Prolog (I) Fatos :  gosta(rafael,cachorro). valioso(ouro). pai(moacyr,rafael).
Revisando – 3 elementos Prolog (II) Regras : avo(X,Z) :- pai(X,Y), pai(Y,Z). filho(Y,X) :- pai(X,Y), homem(Y). aluno(X,ia) :- estuda(X,prolog).
Revisando – 3 elementos Prolog (III) Consultas (ou metas) : ? – avo (alfredo, rafael). ? – primo (cezar, X). ? – pai (moacyr,_). ? – pai (X, eduardo).
Operadores de Controle O Prolog utiliza de alguns operadores de controle para tratamento da recursividade: Backtracking; Cut; Fail.
Backtracking (I) Backtracking (ou retrocesso) : mecanismo usado pelo Prolog para encontrar fatos ou regras adicionais que satisfaçam um objetivo; Quando a questão possui muitas sub-metas, a falha em uma busca pode acontecer.  Neste momento, o Prolog precisa de uma maneira para “lembrar” os pontos de onde pode tentar procurar a solução, para encontrar uma resposta certa.
Backtracking (II) Considere a seguinte Base de Conhecimento: gosta (maria, pizza). gosta (maria, vinho). gosta (joão, vinho). gosta (joão, maria). É realizada a questão: ? - gosta (maria, X), gosta (joão, X).
Backtracking (III) ? - gosta (maria, X) X = pizza ? - gosta (joao, comida) – fail.. Neste ponto, o Prolog precisa ignorar esse valor para X e procurar de onde ele havia parado anteriormente: ? - gosta (maria, X). X = vinho. ? - gosta (joao, vinho) –  true
Cut (I) O corte (cut) é um usado para evitar o  backtracking. O corte pode tornar um programa mais rápido, pois evita que o Prolog explore alternativas que, sabe-se de antemão, não irão contribuir para a solução do problema, e ainda permite a economia de memória.
Cut (II) f(X,0) :- X < 3. f(X,2) :- X >= 3, X < 6. f(X,4) :- X >= 6.   Se infomar um valor > 3  -> retorna 0 Se informar um valor entre 3 e 6  -> retorna 2 Se informar um valor > ou igual a 6 ->retorna 4 Perguntamos:  ? -  f(1,Y).
Cut (II) O Prolog usando backtracking trata 2 regras que sabemos que irão falhar...  As 3 regras são mutuamente exclusivas: no momento em que uma funciona, não faz sentido tratar as outras 2.  Para isso usamos o Cut (!): f(X,0) :- X < 3, !. f(X,2) :- X >= 3, X < 6, !. f(X,4) :- X >= 6.  
Prática 3 Utilizando o Cut (!), escreva uma regra para validar se alguém tem um irmão, sem ter pesquisar toda a árvore: tem_irmao(X) :-  ???
Prática 3 - Resposta Utilizando o Cut (!), escreva uma regra para validar se alguém tem um irmão, sem ter pesquisar toda a árvore: tem_irmao(X) :- irmao(X,_), !.
Fail (I) Inversamente ao comando cut, o predicado pré-definido  fail  sempre falha.  O operador de corte (!) pode ser combinado com o predicado fail para produzir uma falha forçada: gosta(maria,X) :- rato(X), !, fail. gosta(maria,X) :- animal(X).
Prática 4 Podemos escrever a regra diferente de diversas formas: diferente1(X,Y) :- \+ X = Y. diferente2(X,Y) :- X\== Y. Escreva utilizando o cut (!)  e fail:
Prática 4 - Resposta Podemos escrever a regra diferente de diversas formas: diferente1(X,Y) :- \+ X = Y. diferente2(X,Y) :- X\== Y. Escreva utilizando o cut (!)  e fail: diferente1(X,X) :- !, fail. diferente1(X,Y).
Comando “Is” (I) Avalia a expressão e unifica o resultado. Exemplos: ? – X is 5 + 7 X = 12 ? 12.5 is 5 * 2.5. true
Comando “Is” (II) Também pode ser usada para criar funções matemáticas: divisao (X,Y,Z) :- Z is X  /  Y. ? divisao (10, 3, N). N = 3.33333
Fatorial Fatorial usando comando “is”: fatorial (0,1).  fatorial (N,F) :-  N1 is N - 1,     fatorial(N1,F1), F is N * F1.
fatorial(3,F)  – passo a passo (I) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. ------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =2; PILHA F 3 * F1
fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial(3,F)  – passo a passo (II) PILHA F 2 * F1 F 3 * F1
fatorial(3,F)  – passo a passo (III) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,F) => N=1, N1 =0; PILHA F 1 * F1 F 2 * F1 F 3 * F1
fatorial(3,F)  – passo a passo (IV) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1).  true fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,F) => N=1, N1 =0; fatorial(0,F) => F = 1 PILHA F 1 F 1 * F1 F 2 * F1 F 3 * F1
fatorial(3,F)  – passo a passo (V) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,1) => N=1, N1 =0; PILHA F = 1 1 * 1 F 2 * F1 F 3 * F1
fatorial(3,F)  – passo a passo (VI) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,F) => N=3, N1 =1; fatorial (2,2) => N=2, N1 =1; PILHA F = 2 2 * 1 F 3 * F1
fatorial(3,F)  – passo a passo (VII) fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,6) => N=3, N1 =1; F = 6 PILHA F = 6 3 * 2
Prática 5 Teste o fatorial para outros números: fatorial (0,1).  fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. ? – fatorial (7,F).  ? – fatorial (100,F). E se mudarmos a seqüência das regras? fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. fatorial (0,1).
Resposta - Prática 5 E se mudarmos a seqüência das regras? fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. fatorial (0,1).    ERROR: Unhandled exception: Out of local stack O Prolog entrou em loop e estourou a pilha (stack). Isso porque ele sempre executa as regras na ordem em que são colocadas.
Boas práticas (I) De uma forma geral, é uma boa idéia colocar fatos antes de regras sempre que possível: amigo(rafael,pedro). amigo(pedro,fernando). amigo(fernando,murilo). amigo(X,Y):-amigo(Y,X). O que acontece se colocarmos a última cláusula por primeiro, e fizermos uma consulta:  amigo (X,Y) ?
Boas práticas (II) Regras não recursivas normalmente devem ser colocadas antes de regras recursivas: ancestral(X,Y) :- mae(X,Y).  /*nao recursivo*/ ancestral(X,Y) :- pai(X,Y).  /*nao recursivo*/ ancestral(X,Y) :- mae(X,Z),ancestral(Z,Y).  ancestral(X,Y) :- pai(X,Z),ancestral(Z,Y).
Boas práticas (III) Quando possível, usar validações que façam com que a ordem das regras não cause loop: fatorial(N,F) :-  N > 0 ,  N1 is N - 1,   fatorial(N1,F1),  F is N * F1. fatorial(0,1).
Prática 6 1. Implemente:   max(X, Y, Max)  /*use max(4,5,Max) para testar*/ 2. A seguinte relação classifica números em três classes: positivo, nulo ou negativo. Defina este procedimento de forma mais eficiente usando cuts: classe(N, positivo) :- N > 0. classe(0, nulo). classe(N, negativo) :- N < 0.
Prática 6 - Respostas Implemente:   max(X, Y, Max)    max(X, Y, X) :- X >= Y.   max(X, Y, Y) :- X < Y.   max(X, Y, X) :- X >= Y, !.   max(X, Y, Y).
Prática 6 - Respostas classe(N, positivo) :- N > 0, !. classe(N, negativo) :- N < 0, !. classe(0, nulo).
Operadores infixos (I) E se eu quisessemos realizar consultas utilizando uma linguagem mais próxima da nossa? ? - Quem tem carro. ? joana faz Oque?
Operadores infixos (II) O programador Prolog pode definir seus próprios operadores, como no exemplo:  tem  e  faz . A definição de novos operadores é realizada pela inserção de um tipo especial de cláusula chamada  diretiva. As diretivas devem aparecer antes de qualquer expressão que contenha o operador criado.
Diretivas (I) Exemplo de diretiva: :- op (500, xfx, tem). Onde: 500  indica a prioridade do operador; xfx  indica que o operador (f) deve ser colocado entre dois argumentos (x); tem  indica o nome do operador.
Diretivas (II) Tendo a diretiva, criamos a base de conhecimento: pedro tem carro. joana tem dinheiro. joao tem problemas. joao tem dívidas. E fizemos as consultas: ?- Quem tem carro.   Quem = pedro.
Diretivas (III) Curiosidade : os “comandos” que usamos no Prolog, são diretivas pré-definidas na sua implementação: :- op (1200, xfx, ‘:-’); :- op (1200, fx [‘:-’, ‘?-]). :- op (1100, xfx, ‘;’) :- op (1000, xfx, ‘,’) /* etc...*/ Note que alguns operadores (ex.: ‘ :- ’), possuem definição infixa (xfx) e prefixa (fx).
Prática 7 Crie duas diretivas novas com operador infixo, e uma base de conhecimento usando estas diretivas. Em seguida crie consultas que se assemelhem a linguagem humana. Exemplos: ? - fulado conhece Quem. ? - ciclano mora Onde.
Operadores de Comparação Lista completa dos operadores de comparação: OPERADOR PRIORIDADE TIPO SIGNIFICADO > 700 xfx maior que < 700 xfx menor que >= 700 xfx maior ou igual a <= 700 xfx menor ou igual a =:= ou == 700 xfx valores iguais =\= ou \== 700 xfx valores diferentes
Base de dados relacional (I) Como criar uma base de dados relacional em Prolog? Como pesquisar resultados dentro dessa base? nasceu(pedroBarnack,joinville,1978). nasceu(muriloPereira,itajai,1980). nasceu(rafaelRosario,joinville,1980). nasceu(janineBoos,joinville,1985). nasceu(douglasSouza,curitiba, 1970).
Base de dados relacional (II) Como perguntamos:   Nome e ano de nascimento dos curitibanos?   ?- nasceu(Quem,curitiba,Ano). Quem nasceu em joinville a partir de 1980? ?- nasceu(Quem,joinville,Ano),Ano >= 1980. Nome e ano de nascimento de quem nasceu antes de 1980 (sem trazer a cidade)?   ?- nasceu(Quem,_,Ano), Ano  < 1980.
Prática 8 Crie um banco de dados que contenhas as seguintes informações: Nome do Professor e disciplina que leciona; Disciplina e horário (dia da semana, aula: primeiro ou segundo horário); Construa as consultas para responder: Qual o horário do professor X (disciplina, dia e aula)? Quais professores lecionam na terça-feira? Quais matérias o professor X leciona no primeiro horário?
Prática 8 - resposta horario_prof(P,D,S,A) :- leciona(P,D), horario(D,S,A). ? - horario_prof(rafael,Disc,DiaSemana,Aula) . 2. ?- leciona(X,Disciplina) , horario(Disciplina,3,Aula).  3. ?- leciona(eduardo,Disc), horario(Disc,_,aula1).*/ Base de dados: leciona(rafael,ia). leciona(eduardo,redes). horario(ia,2,aula1). horario(ia,5,aula1). horario(redes,3,aula1). horario(redes,4,aula2).
Prática 8 – resposta 2 (I) :- op(500, xfx,  leciona ). :- op(450, xfx,  eh_lecionada_na ). :- op(400, xfx,  no_horario ). :- op(300, fx,  qual_o_horario_do_professor ) qual_o_horario_do_professor(Prof , Materia, DiaSemana, SeqAula) :-  Prof  leciona   Materia, Materia  eh_lecionada_na  DiaSemana  no_horario  SeqAula.
Prática 8 – resposta 2 (II) Base de dados: rafael  leciona  ia. eduardo  leciona  redes. ia  eh_lecionada_na  segunda_feira  no_horario  primeira_aula. ia  eh_lecionada_na  quinta_feira  no_horario  primeira_aula. redes  eh_lecionada_na  terca_feira  no_horario  primeira_aula. redes  eh_lecionada_na  quarta_feira  no_horario  segunda_aula.
Prática 8 – resposta 2 (III) 1.  ? -  qual_o_horario_do_professor(eduardo , Materia, DiaSemana, SeqAula). ?- Professor  leciona  Materia, Materia  eh_lecionada_na  terca_feira  no_horario  Qualquer. ?- Professor  leciona  Materia, Materia  eh_lecionada_na  DiaSemana  no_horario  primeira_aula. /*ou _ no lugar de DiaSemana*/
Listas Listas podem ser definidas e transformadas em Prolog de diversas maneiras diferentes. Listas são representadas por []: [a,e,i,o,u]; [1,2,3,5,7,11];
Composição de Lista Listas são compostas por uma cabeça e uma cauda: [H,T]; Na lista [1,2,3,5,7], podemos dizer que: 1  é a cabeça da lista [2,3,5,7]  é a cauda da lista; De maneira similar,  2  e  [3,5,7]  são respectivamente a cabeça e a cauda da sub-lista  [2,3,5,7]  ;
Construindo uma Lista Um lista é construída a partir de seus elementos básicos - uma  cabeça  e um  corpo  (ou cauda): cons(X, Y, [X | Y]). ?-cons(a, b, Z). Z=[a | b]
Ocorrência de elementos na Lista (I) Para verificar se um elemento é membro de uma lista, precisamos construir uma regra. Podemos definir que tal regra gere os resultados abaixo: ? - membro( a , [a,b,c,d]).  true . ? - membro( c , [a,b,c,d]).  true . ? - membro ( j , [a,b,c,d]).  fail
Ocorrência de elementos na Lista (II) Ou seja, dada uma lista L, X é membro de L se: 1. X é a cabeça de L;   ? - membro(a, [a,b,c,d]). 2. Ou X é membro do corpo de L.   ? - membro(c, [a,b,c,d]).
Ocorrência de elementos na Lista (III) A regra membro (X,L) terá duas cláusulas: A primeira, um fato, estabelece a primeira condição: X é membro de L, se X é a cabeça de L.  A segunda, é uma chamada recursiva que diz que X ainda pode ser membro de L, desde que seja membro do corpo de L: membro(X, [X | C]). membro(X, [Y | C]) :- membro(X, C).
Prática 9  Dada a variante de implementação da regra membro: membro2(X, [H | T]) :- X == H. membro2(X, [H | T]) :- membro2(X, T).   Habilite o Debug gráfico (menu Debug -> Graphical Debugger). Use o comando trace. Em seguida, execute membro(d,[a,b,c,d]) e veja passo a passo. Execute membro(X,[a,b,c]) e membro2 (X,[a,b,c]). Qual das funções funciona? Por que?
Concatenação de listas (I) Para a concatenação de duas listas quaisquer, resultando em uma terceira, se definirá a relação: conc(L1, L3, L3). onde L1 e L2 são duas listas e L3 é a concatenação resultante. Por exemplo: ? - conc([a, b], [c, d], L3) L3 = [a, b, c, d].
Concatenação de listas (II) Novamente, dois casos devem ser considerados, dependendo do primeiro  argumento L1: Se o primeiro argumento é uma lista vazia, então o segundo e o terceiro argumentos devem ser a mesma lista.  Chamando tal lista de L, essa situação pode ser representada pelo seguinte fato  Prolog: conc([], L, L).
Concatenação de listas (III) Se o primeiro argumento for uma lista não-vazia, então é porque ela possui uma cabeça e um corpo, e pode ser denotada por [X|L1].  A concatenação de [X|L1] com uma segunda lista L2, produzirá uma terceira lista, com a mesma cabeça X da primeira e um corpo (L3) que é a concatenação do corpo da primeira lista (L1), com toda a segunda (L2). Isso se representa em Prolog por meio da regra: conc([X | L1], L2, [X | L3]) :-  conc(L1, L2, L3).
Concatenação de listas (IV) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3).   conc ([2],[3,4], L3).   conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). conc ([],[3,4], L3). conc([],L,L). conc([], [3,4], [3,4])
Concatenação de listas (V) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3).   conc ([2],[3,4], L3).   conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). conc ([],[3,4], L3).  L3 = [3,4] conc([],L,L).  L = [3,4] conc([], [3,4], [3,4])
Concatenação de listas (VI) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3). conc ([2],[3,4], L3).  conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). L3 = [3,4]  [X,L3] = [2,3,4]
Concatenação de listas (VII) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3] :- conc ([2],[3,4], L3).   conc ([2],[3,4], L3).  L3 = [2,3,4], [X,L3] = [1,2,3,4]
Prática 10 Utilize a regra conc/3 no sentido inverso ao que foi originalmente projetado, para decompor uma lista [a,b,c] em duas partes. Podemos também usar o programa para procurar por um determinado padrão em uma lista. Encontre os meses antes e depois de um determinado mês: ? - M=[jan, fev, mar, abr,  mai , jun, jul, ago, set, out, nov, dez], < cláusula usando conc/3 >. Antes=[jan,fev,mar,abr] Depois=[jun,jul,ago,set,out,nov, dez]
Remover da lista (I) A remoção de um elemento X de uma lista L pode ser programada através da relação: remover(X, L, L1). onde L1 é a mesma lista L com o elemento X removido.
Remover da lista (II) A relação remover/3 é definida de maneira similar à relação de ocorrência. São dois casos a estudar: Se X é a cabeça da lista L, então L1 será o seu corpo; Se X está no corpo de L, então L1 é obtida removendo X desse corpo. remover(X, [X | C], C). remover(X, [Y | C], [Y | D]) :- remover(X, C, D).
Remover da lista (III) Se há diversas ocorrências de X em L, a relação remove/3 é capaz de retirar cada uma delas através do mecanismo de backtracking do Prolog.  Em cada execução do programa remove/3 retiramos somente uma das ocorrências de X, por exemplo: ?-remover(a, [a, b, a, a], L). L=[b, a, a]; L=[a, b, a]; L=[a, b, a];
Prática 11 Utilize a regra remove/3 no sentido inverso, para  inserir  um novo item em qualquer lugar da lista. Crie uma nova cláusula para membro, utilizando a regra remover/3.
bagOf, setOf e findAll Podemos gerar, através de backtracking, todos os objetos, um a um, que satisfazem algum objetivo (next, next, next). Porém, algumas vezes, deseja-se dispor de todas as respostas juntas, por exemplo, dentro de uma lista. Os predicados  bagof/3, setof/3 e  findall/3  servem exatamente para tal propósito.
bagOf (I) bagof(X, P, L) Irá produzir uma lista L de todos os objetos X que satisfazem ao objetivo P.  Exemplo - dada a base de conhecimento abaixo: classe(a, vog). classe(b, con). classe(c, con). /* continua d, e, f… */
bagOf (II) Podemos obter a lista de todas as consoantes nessa especificação através do objetivo: ?-bagof(Letra, classe(Letra, con), Consoantes). Consoantes=[b, c, d, ..., z]
bagOf (III) Se a classe das letras não estivesse especificada, iríamos obter por meio de backtracking, duas listas, uma correspondendo às vogais e outra às consoantes: ?-bagof(Letra, classe(Letra, Classe), Letras). Classe=vog Letras=[a, e, i, o, u]; Classe=con Letras=[b, c, d, f, ..., z].
bagOf – Outro Exemplo Dada a base de conhecimento: leciona(rafael,progII).  leciona(rafael,ia). leciona(eduardo,redes). leciona(eduardo,progI). Qual seria o retorno da consulta: ?- bagof(Disc,leciona(rafael,Disc),Disciplinas). E  ?- bagof(Disc,leciona(Prof,Disc),Disciplinas).
setOf (I) setof(X, P, L) Irá novamente produzir uma lista L dos objetos X que satisfazem a P, só que desta vez a lista L estará ordenada e itens duplicados, se houver, serão eliminados.
setOf (II) Exemplo:  ?- setof(Disc,eh_lecionada(Disc,Prof),Disciplinas). Prof = rafael Disciplinas = [ia, progII] Prof = eduardo Disciplinas = [progI, redes]
setOf (III) Não há restrição quanto ao tipo de objeto a ser coletado. Assim podemos, por exemplo, construir uma lista de pares da forma Classe/Letra de forma que as constantes apareçam em primeiro lugar na lista  (&quot;con&quot; antecede alfabeticamente &quot;vog&quot;): ?-setof(Classe/Letra, classe(Letra, Classe), Letras). Letras=[con/b, con/c, ..., con/z, vog/a, ..., vog/u]
findall (I) Teste no Prolog e descubra o que faz o findall/3
What is next? Apostila completa: aluno@net Próxima aula - DIA 14/04 – AVALIAÇÃO EM DUPLAS
Referências http://pt.wikipedia.org/wiki/Prolog http://pt.wikipedia.org/wiki/Alain_Colmerauer http://www.linhadecodigo.com.br/Artigo.aspx?id=1697  http://en.wikipedia.org/wiki/Prolog  http://ccc.inaoep.mx/~emorales/Cursos/ProgSimb/node32.html  www.fei.edu.br/eletrica/r bianchi /ia/Apostila- Prolog .doc  http://www.swi-prolog.org/  http://www.sics.se/isl/sicstuswww/site/index.html  http://gersonc.anahy.org/graduacao/paradigmas/prologsan.pdf   http://ia.ucpel.tche.br/~lpalazzo/Aulas/PDEC/  http://gollem.science.uva.nl/SWI-Prolog/apps/view.html http://www.fdi.ucm.es/profesor/fernan/des/

IA Prolog

  • 1.
    Inteligência Artificial PROLOG– partes 1, 2 e 3 Rafael Rosario [email_address] [email_address]
  • 2.
    PROLOG (I) Foicriada em meados de 1972 por Alain Colmerauer e Philippe Roussel, na Universidade de Marselha. O nome PROLOG foi escolhido por Philippe Roussel como uma abreviação de “ PRO grammation en LOG ique”. Propósito da criação: criar programas para tradução de linguagens faladas, como português ou inglês.
  • 3.
    PROLOG (II) Fundamentadana lógica simbólica ; É uma linguagem declarativa: em vez de o programa estipular a maneira de chegar à solução, passo a passo, limita-se a fornecer uma descrição do problema que se pretende computar. Usa uma coleção de fatos e de relações lógicas ( regras ) que exprimem o domínio relacional do problema.
  • 4.
    PROLOG(III) Outro fatoque o difere das outras linguagens é o fato de não possuir estruturas de controle (if-else, do-while, for, switch). Para isso utilizamos métodos lógicos para declarar como o programa deverá atingir o seu objetivo. Um programa em PROLOG pode rodar em um modo interativo: o usuário poderá formular queries utilizando fatos e regras para produzir a solução através do mecanismo de unificação.
  • 5.
    Fato (I) Determinauma relação existente entre objetos conhecidos. Expressa uma verdade sobre um relacionamento: homem(jose). pai(jose,carina). homem / pai – Predicado ou Relação. jose / jose,carina – Argumento do Predicado ou Objeto
  • 6.
    Fato (II) Osnomes dos predicados e dos objetos devem começar com letra minúscula. Os objetos são escritos dentro de parênteses. Todo fato é terminado com um ponto final. A ordem dos objetos é importante: pai (jose, carina).  pai (carina, jose).
  • 7.
    Fato (III) Comfatos, podemos montar uma base de conhecimento: pai(alfredo,moacyr). pai(alfredo,romeu). pai(moacyr,eduardo). pai(moacyr,rafael). pai(moacyr,vinicius). pai(romeu,cezar). pai(romeu,alfredinho).
  • 8.
    Regra (I) Expressaum relacionamento entre fatos. Um relacionamento em uma regra é verdadeiro se os outros relacionamentos nessa regra também o são: luz(acesa) :- interruptor(ligado). O &quot;:-&quot; significa &quot;se&quot;; ou seja, essa regra significa que luz(acesa) é verdadeiro se interruptor(ligado) é verdadeiro.
  • 9.
    Regra (II) Regraspodem também fazer uso de variáveis: avo(X,Z) :- pai(X,Y), pai(Y,Z). Isso significa &quot;se X é pai de Y e Y é pai de uma Z, então X é avô de Z“. X, Y e Z são variáveis. No PROLOG,uma variável não é um contêiner cujo valor pode ser atribuído. Seu comportamento é como de uma incógnita, cujo valor é desconhecido a princípio e, após descoberto, não sofre mais mudanças. Escritas sempre em Maiúsculo.
  • 10.
    Consulta (I) Quandode uma consulta, a máquina PROLOG pesquisa a base de dados procurando cláusulas que se unifiquem com a consulta: ? – pai(moacyr, rafael). Responderá true se localizar um fato que se unifique com a consulta; se o fato consultado não existir na base de dados, responderá fail .
  • 11.
    Consulta (II) Quandouma consulta contém variáveis, é realizada uma pesquisa em todas as cláusulas, localizado os objetos que essas representam: ?- avo(alfredo,N). N = eduardo ; N = rafael ; N = vinicius ; N = cezar ; N = alfredinho.
  • 12.
    Regras Recursivas Umpredicado definido por uma regra recursiva deve ter, no mínimo uma definição não recursiva. Se isto não acontecer, a definição é logicamente mal-formada e o programa ficaria em laço infinito. ancestral(X,Y) :- mae(X,Y). ancestral(X,Y) :- pai(X,Y). ancestral(X,Y) :- mae(X,Z),ancestral(Z,Y). ancestral(X,Y) :- pai(X,Z),ancestral(Z,Y).
  • 13.
    Prática 1 Criea árvore genealógica da sua família, utilizando os predicados pai e mae, e verifique o que retorna cada consulta: ancestral(fulano,ciclano). ancestral(X,ciclano). /*clique n a cada valor*/ ancestral(fulado,Y). /*clique n a cada valor*/ ancestral(fulado,_). /*clique n a cada valor*/ mae(X,_). /*clique n a cada valor*/ ancestral(X,_),pai(X,Y),pai(Y,_)
  • 14.
    Prática 1 -exemplo mae(zilda,moacyr). mae(zilda,romeu). mae(maria,eduardo). mae(maria,rafael). mae(maria,vinicius). mae(norma,cezar). mae(norma,alfredinho). pai(alfredo,moacyr). pai(alfredo,romeu). pai(moacyr,rafael). pai(moacyr,eduardo). pai(moacyr,vinicius). pai(romeu,cezar). pai(romeu,alfredinho).
  • 15.
    Outros conceitos (I)Conjunção : (“E” Lógico) é feita colocando-se uma vírgula entre os fatos: avo(X,Z) :- pai(X,Y) , pai(Y,Z). Aridade : é usado para a quantidade de objetos que o argumento de um predicado possui. gosta (maria, josé). /* aridade = 2 */ bebe (penélope, pinga, vodka, rum). /*4*/
  • 16.
    Outros conceitos (II)Negação : uma consulta é avaliada como falsa no caso de não estar presente nenhuma regra positiva ou fato que dê suporte ao termo proposto. Em outras palavras, se um fato não é conhecido ser verdadeiro (ou falso), assume-se que ele é falso. legal(X) :- \+ ilegal(X). Diferente: quando duas variáveis não podem ter o mesmo valor: vizinho(X,Y) :- rua(X,Z), rua(Y,Z), X \== Y.
  • 17.
    Outros conceitos (II)Disjunção: (OU lógico), quando se declara mais de uma regra para determinar uma mesma relação: vizinho(X,Y) :- rua(X,Z), rua(Y,Z), X \== Y ; rua(X,Z), rua (X,W), proximo(Z,W).
  • 18.
    Prática 2 Apartir da árvore genealógica da sua família, crie as funções para: irmão; meio-irmão; primo;
  • 19.
    Resposta - Prática2 (I) irmao(X,Y) :- pai(P,X), pai(P,Y), mae(M,X),mae(M,Y), X \== Y . meio-irmao(X,Y) :- pai(P,X), pai(P,Y), X \== Y, \+ irmao(X,Y) ; mae(M,X),mae(M,Y), X \== Y, \+ irmao(X,Y).
  • 20.
    Resposta - Prática2 (II) genitor(X,Y) :- pai(X,Y); mae(X,Y). primo(X,Y) :- genitor(P,X), genitor(T,Y), P \== T, genitor(V,P), genitor(V,T).
  • 21.
    Aplicações (I) Lógicamatemática, prova de teoremas e semântica; Solução de equações simbólicas; Bancos de dados relacionais; Linguagem Natural; Sistemas Especialistas;
  • 22.
    Aplicações (II) PlanejamentoAutomático de Atividades; Aplicações de “General Problem Solving”, como jogos (Xadrez, Damas, Jogo da Velha, etc.); Compiladores; Análise Bioquímica e projetos de novas drogas.
  • 23.
    Revisando – 3elementos Prolog (I) Fatos : gosta(rafael,cachorro). valioso(ouro). pai(moacyr,rafael).
  • 24.
    Revisando – 3elementos Prolog (II) Regras : avo(X,Z) :- pai(X,Y), pai(Y,Z). filho(Y,X) :- pai(X,Y), homem(Y). aluno(X,ia) :- estuda(X,prolog).
  • 25.
    Revisando – 3elementos Prolog (III) Consultas (ou metas) : ? – avo (alfredo, rafael). ? – primo (cezar, X). ? – pai (moacyr,_). ? – pai (X, eduardo).
  • 26.
    Operadores de ControleO Prolog utiliza de alguns operadores de controle para tratamento da recursividade: Backtracking; Cut; Fail.
  • 27.
    Backtracking (I) Backtracking(ou retrocesso) : mecanismo usado pelo Prolog para encontrar fatos ou regras adicionais que satisfaçam um objetivo; Quando a questão possui muitas sub-metas, a falha em uma busca pode acontecer. Neste momento, o Prolog precisa de uma maneira para “lembrar” os pontos de onde pode tentar procurar a solução, para encontrar uma resposta certa.
  • 28.
    Backtracking (II) Considerea seguinte Base de Conhecimento: gosta (maria, pizza). gosta (maria, vinho). gosta (joão, vinho). gosta (joão, maria). É realizada a questão: ? - gosta (maria, X), gosta (joão, X).
  • 29.
    Backtracking (III) ?- gosta (maria, X) X = pizza ? - gosta (joao, comida) – fail.. Neste ponto, o Prolog precisa ignorar esse valor para X e procurar de onde ele havia parado anteriormente: ? - gosta (maria, X). X = vinho. ? - gosta (joao, vinho) – true
  • 30.
    Cut (I) Ocorte (cut) é um usado para evitar o backtracking. O corte pode tornar um programa mais rápido, pois evita que o Prolog explore alternativas que, sabe-se de antemão, não irão contribuir para a solução do problema, e ainda permite a economia de memória.
  • 31.
    Cut (II) f(X,0):- X < 3. f(X,2) :- X >= 3, X < 6. f(X,4) :- X >= 6.   Se infomar um valor > 3 -> retorna 0 Se informar um valor entre 3 e 6 -> retorna 2 Se informar um valor > ou igual a 6 ->retorna 4 Perguntamos: ? - f(1,Y).
  • 32.
    Cut (II) OProlog usando backtracking trata 2 regras que sabemos que irão falhar... As 3 regras são mutuamente exclusivas: no momento em que uma funciona, não faz sentido tratar as outras 2. Para isso usamos o Cut (!): f(X,0) :- X < 3, !. f(X,2) :- X >= 3, X < 6, !. f(X,4) :- X >= 6.  
  • 33.
    Prática 3 Utilizandoo Cut (!), escreva uma regra para validar se alguém tem um irmão, sem ter pesquisar toda a árvore: tem_irmao(X) :- ???
  • 34.
    Prática 3 -Resposta Utilizando o Cut (!), escreva uma regra para validar se alguém tem um irmão, sem ter pesquisar toda a árvore: tem_irmao(X) :- irmao(X,_), !.
  • 35.
    Fail (I) Inversamenteao comando cut, o predicado pré-definido fail sempre falha. O operador de corte (!) pode ser combinado com o predicado fail para produzir uma falha forçada: gosta(maria,X) :- rato(X), !, fail. gosta(maria,X) :- animal(X).
  • 36.
    Prática 4 Podemosescrever a regra diferente de diversas formas: diferente1(X,Y) :- \+ X = Y. diferente2(X,Y) :- X\== Y. Escreva utilizando o cut (!) e fail:
  • 37.
    Prática 4 -Resposta Podemos escrever a regra diferente de diversas formas: diferente1(X,Y) :- \+ X = Y. diferente2(X,Y) :- X\== Y. Escreva utilizando o cut (!) e fail: diferente1(X,X) :- !, fail. diferente1(X,Y).
  • 38.
    Comando “Is” (I)Avalia a expressão e unifica o resultado. Exemplos: ? – X is 5 + 7 X = 12 ? 12.5 is 5 * 2.5. true
  • 39.
    Comando “Is” (II)Também pode ser usada para criar funções matemáticas: divisao (X,Y,Z) :- Z is X / Y. ? divisao (10, 3, N). N = 3.33333
  • 40.
    Fatorial Fatorial usandocomando “is”: fatorial (0,1). fatorial (N,F) :- N1 is N - 1, fatorial(N1,F1), F is N * F1.
  • 41.
    fatorial(3,F) –passo a passo (I) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. ------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =2; PILHA F 3 * F1
  • 42.
    fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial(3,F) – passo a passo (II) PILHA F 2 * F1 F 3 * F1
  • 43.
    fatorial(3,F) –passo a passo (III) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1). fail fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,F) => N=1, N1 =0; PILHA F 1 * F1 F 2 * F1 F 3 * F1
  • 44.
    fatorial(3,F) –passo a passo (IV) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial(0,1). true fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,F) => N=1, N1 =0; fatorial(0,F) => F = 1 PILHA F 1 F 1 * F1 F 2 * F1 F 3 * F1
  • 45.
    fatorial(3,F) –passo a passo (V) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,F) => N=3, N1 =1; fatorial (2,F) => N=2, N1 =1; fatorial (1,1) => N=1, N1 =0; PILHA F = 1 1 * 1 F 2 * F1 F 3 * F1
  • 46.
    fatorial(3,F) –passo a passo (VI) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,F) => N=3, N1 =1; fatorial (2,2) => N=2, N1 =1; PILHA F = 2 2 * 1 F 3 * F1
  • 47.
    fatorial(3,F) –passo a passo (VII) fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. --------------------------------------------------------- fatorial (3,6) => N=3, N1 =1; F = 6 PILHA F = 6 3 * 2
  • 48.
    Prática 5 Testeo fatorial para outros números: fatorial (0,1). fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. ? – fatorial (7,F). ? – fatorial (100,F). E se mudarmos a seqüência das regras? fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. fatorial (0,1).
  • 49.
    Resposta - Prática5 E se mudarmos a seqüência das regras? fatorial (N,F) :- N1 is N – 1, fatorial(N1,F1), F is N * F1. fatorial (0,1). ERROR: Unhandled exception: Out of local stack O Prolog entrou em loop e estourou a pilha (stack). Isso porque ele sempre executa as regras na ordem em que são colocadas.
  • 50.
    Boas práticas (I)De uma forma geral, é uma boa idéia colocar fatos antes de regras sempre que possível: amigo(rafael,pedro). amigo(pedro,fernando). amigo(fernando,murilo). amigo(X,Y):-amigo(Y,X). O que acontece se colocarmos a última cláusula por primeiro, e fizermos uma consulta: amigo (X,Y) ?
  • 51.
    Boas práticas (II)Regras não recursivas normalmente devem ser colocadas antes de regras recursivas: ancestral(X,Y) :- mae(X,Y). /*nao recursivo*/ ancestral(X,Y) :- pai(X,Y). /*nao recursivo*/ ancestral(X,Y) :- mae(X,Z),ancestral(Z,Y). ancestral(X,Y) :- pai(X,Z),ancestral(Z,Y).
  • 52.
    Boas práticas (III)Quando possível, usar validações que façam com que a ordem das regras não cause loop: fatorial(N,F) :- N > 0 , N1 is N - 1, fatorial(N1,F1), F is N * F1. fatorial(0,1).
  • 53.
    Prática 6 1.Implemente: max(X, Y, Max) /*use max(4,5,Max) para testar*/ 2. A seguinte relação classifica números em três classes: positivo, nulo ou negativo. Defina este procedimento de forma mais eficiente usando cuts: classe(N, positivo) :- N > 0. classe(0, nulo). classe(N, negativo) :- N < 0.
  • 54.
    Prática 6 -Respostas Implemente: max(X, Y, Max) max(X, Y, X) :- X >= Y. max(X, Y, Y) :- X < Y. max(X, Y, X) :- X >= Y, !. max(X, Y, Y).
  • 55.
    Prática 6 -Respostas classe(N, positivo) :- N > 0, !. classe(N, negativo) :- N < 0, !. classe(0, nulo).
  • 56.
    Operadores infixos (I)E se eu quisessemos realizar consultas utilizando uma linguagem mais próxima da nossa? ? - Quem tem carro. ? joana faz Oque?
  • 57.
    Operadores infixos (II)O programador Prolog pode definir seus próprios operadores, como no exemplo: tem e faz . A definição de novos operadores é realizada pela inserção de um tipo especial de cláusula chamada diretiva. As diretivas devem aparecer antes de qualquer expressão que contenha o operador criado.
  • 58.
    Diretivas (I) Exemplode diretiva: :- op (500, xfx, tem). Onde: 500 indica a prioridade do operador; xfx indica que o operador (f) deve ser colocado entre dois argumentos (x); tem indica o nome do operador.
  • 59.
    Diretivas (II) Tendoa diretiva, criamos a base de conhecimento: pedro tem carro. joana tem dinheiro. joao tem problemas. joao tem dívidas. E fizemos as consultas: ?- Quem tem carro. Quem = pedro.
  • 60.
    Diretivas (III) Curiosidade: os “comandos” que usamos no Prolog, são diretivas pré-definidas na sua implementação: :- op (1200, xfx, ‘:-’); :- op (1200, fx [‘:-’, ‘?-]). :- op (1100, xfx, ‘;’) :- op (1000, xfx, ‘,’) /* etc...*/ Note que alguns operadores (ex.: ‘ :- ’), possuem definição infixa (xfx) e prefixa (fx).
  • 61.
    Prática 7 Crieduas diretivas novas com operador infixo, e uma base de conhecimento usando estas diretivas. Em seguida crie consultas que se assemelhem a linguagem humana. Exemplos: ? - fulado conhece Quem. ? - ciclano mora Onde.
  • 62.
    Operadores de ComparaçãoLista completa dos operadores de comparação: OPERADOR PRIORIDADE TIPO SIGNIFICADO > 700 xfx maior que < 700 xfx menor que >= 700 xfx maior ou igual a <= 700 xfx menor ou igual a =:= ou == 700 xfx valores iguais =\= ou \== 700 xfx valores diferentes
  • 63.
    Base de dadosrelacional (I) Como criar uma base de dados relacional em Prolog? Como pesquisar resultados dentro dessa base? nasceu(pedroBarnack,joinville,1978). nasceu(muriloPereira,itajai,1980). nasceu(rafaelRosario,joinville,1980). nasceu(janineBoos,joinville,1985). nasceu(douglasSouza,curitiba, 1970).
  • 64.
    Base de dadosrelacional (II) Como perguntamos: Nome e ano de nascimento dos curitibanos? ?- nasceu(Quem,curitiba,Ano). Quem nasceu em joinville a partir de 1980? ?- nasceu(Quem,joinville,Ano),Ano >= 1980. Nome e ano de nascimento de quem nasceu antes de 1980 (sem trazer a cidade)? ?- nasceu(Quem,_,Ano), Ano < 1980.
  • 65.
    Prática 8 Crieum banco de dados que contenhas as seguintes informações: Nome do Professor e disciplina que leciona; Disciplina e horário (dia da semana, aula: primeiro ou segundo horário); Construa as consultas para responder: Qual o horário do professor X (disciplina, dia e aula)? Quais professores lecionam na terça-feira? Quais matérias o professor X leciona no primeiro horário?
  • 66.
    Prática 8 -resposta horario_prof(P,D,S,A) :- leciona(P,D), horario(D,S,A). ? - horario_prof(rafael,Disc,DiaSemana,Aula) . 2. ?- leciona(X,Disciplina) , horario(Disciplina,3,Aula). 3. ?- leciona(eduardo,Disc), horario(Disc,_,aula1).*/ Base de dados: leciona(rafael,ia). leciona(eduardo,redes). horario(ia,2,aula1). horario(ia,5,aula1). horario(redes,3,aula1). horario(redes,4,aula2).
  • 67.
    Prática 8 –resposta 2 (I) :- op(500, xfx, leciona ). :- op(450, xfx, eh_lecionada_na ). :- op(400, xfx, no_horario ). :- op(300, fx, qual_o_horario_do_professor ) qual_o_horario_do_professor(Prof , Materia, DiaSemana, SeqAula) :- Prof leciona Materia, Materia eh_lecionada_na DiaSemana no_horario SeqAula.
  • 68.
    Prática 8 –resposta 2 (II) Base de dados: rafael leciona ia. eduardo leciona redes. ia eh_lecionada_na segunda_feira no_horario primeira_aula. ia eh_lecionada_na quinta_feira no_horario primeira_aula. redes eh_lecionada_na terca_feira no_horario primeira_aula. redes eh_lecionada_na quarta_feira no_horario segunda_aula.
  • 69.
    Prática 8 –resposta 2 (III) 1. ? - qual_o_horario_do_professor(eduardo , Materia, DiaSemana, SeqAula). ?- Professor leciona Materia, Materia eh_lecionada_na terca_feira no_horario Qualquer. ?- Professor leciona Materia, Materia eh_lecionada_na DiaSemana no_horario primeira_aula. /*ou _ no lugar de DiaSemana*/
  • 70.
    Listas Listas podemser definidas e transformadas em Prolog de diversas maneiras diferentes. Listas são representadas por []: [a,e,i,o,u]; [1,2,3,5,7,11];
  • 71.
    Composição de ListaListas são compostas por uma cabeça e uma cauda: [H,T]; Na lista [1,2,3,5,7], podemos dizer que: 1 é a cabeça da lista [2,3,5,7] é a cauda da lista; De maneira similar, 2 e [3,5,7] são respectivamente a cabeça e a cauda da sub-lista [2,3,5,7] ;
  • 72.
    Construindo uma ListaUm lista é construída a partir de seus elementos básicos - uma cabeça e um corpo (ou cauda): cons(X, Y, [X | Y]). ?-cons(a, b, Z). Z=[a | b]
  • 73.
    Ocorrência de elementosna Lista (I) Para verificar se um elemento é membro de uma lista, precisamos construir uma regra. Podemos definir que tal regra gere os resultados abaixo: ? - membro( a , [a,b,c,d]). true . ? - membro( c , [a,b,c,d]). true . ? - membro ( j , [a,b,c,d]). fail
  • 74.
    Ocorrência de elementosna Lista (II) Ou seja, dada uma lista L, X é membro de L se: 1. X é a cabeça de L; ? - membro(a, [a,b,c,d]). 2. Ou X é membro do corpo de L. ? - membro(c, [a,b,c,d]).
  • 75.
    Ocorrência de elementosna Lista (III) A regra membro (X,L) terá duas cláusulas: A primeira, um fato, estabelece a primeira condição: X é membro de L, se X é a cabeça de L. A segunda, é uma chamada recursiva que diz que X ainda pode ser membro de L, desde que seja membro do corpo de L: membro(X, [X | C]). membro(X, [Y | C]) :- membro(X, C).
  • 76.
    Prática 9 Dada a variante de implementação da regra membro: membro2(X, [H | T]) :- X == H. membro2(X, [H | T]) :- membro2(X, T).   Habilite o Debug gráfico (menu Debug -> Graphical Debugger). Use o comando trace. Em seguida, execute membro(d,[a,b,c,d]) e veja passo a passo. Execute membro(X,[a,b,c]) e membro2 (X,[a,b,c]). Qual das funções funciona? Por que?
  • 77.
    Concatenação de listas(I) Para a concatenação de duas listas quaisquer, resultando em uma terceira, se definirá a relação: conc(L1, L3, L3). onde L1 e L2 são duas listas e L3 é a concatenação resultante. Por exemplo: ? - conc([a, b], [c, d], L3) L3 = [a, b, c, d].
  • 78.
    Concatenação de listas(II) Novamente, dois casos devem ser considerados, dependendo do primeiro argumento L1: Se o primeiro argumento é uma lista vazia, então o segundo e o terceiro argumentos devem ser a mesma lista. Chamando tal lista de L, essa situação pode ser representada pelo seguinte fato Prolog: conc([], L, L).
  • 79.
    Concatenação de listas(III) Se o primeiro argumento for uma lista não-vazia, então é porque ela possui uma cabeça e um corpo, e pode ser denotada por [X|L1]. A concatenação de [X|L1] com uma segunda lista L2, produzirá uma terceira lista, com a mesma cabeça X da primeira e um corpo (L3) que é a concatenação do corpo da primeira lista (L1), com toda a segunda (L2). Isso se representa em Prolog por meio da regra: conc([X | L1], L2, [X | L3]) :- conc(L1, L2, L3).
  • 80.
    Concatenação de listas(IV) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3). conc ([2],[3,4], L3). conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). conc ([],[3,4], L3). conc([],L,L). conc([], [3,4], [3,4])
  • 81.
    Concatenação de listas(V) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3). conc ([2],[3,4], L3). conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). conc ([],[3,4], L3). L3 = [3,4] conc([],L,L). L = [3,4] conc([], [3,4], [3,4])
  • 82.
    Concatenação de listas(VI) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3]) :- conc ([2],[3,4], L3). conc ([2],[3,4], L3). conc(2, [], [3,4], [2,L3]) :- conc ([],[3,4], L3). L3 = [3,4] [X,L3] = [2,3,4]
  • 83.
    Concatenação de listas(VII) conc([1,2],[3,4]). conc([X | L1], L2, [X |L3]) :- conc (L1,L2,L3) será: conc([1|[2]), [3,4], [1,L3] :- conc ([2],[3,4], L3). conc ([2],[3,4], L3). L3 = [2,3,4], [X,L3] = [1,2,3,4]
  • 84.
    Prática 10 Utilizea regra conc/3 no sentido inverso ao que foi originalmente projetado, para decompor uma lista [a,b,c] em duas partes. Podemos também usar o programa para procurar por um determinado padrão em uma lista. Encontre os meses antes e depois de um determinado mês: ? - M=[jan, fev, mar, abr, mai , jun, jul, ago, set, out, nov, dez], < cláusula usando conc/3 >. Antes=[jan,fev,mar,abr] Depois=[jun,jul,ago,set,out,nov, dez]
  • 85.
    Remover da lista(I) A remoção de um elemento X de uma lista L pode ser programada através da relação: remover(X, L, L1). onde L1 é a mesma lista L com o elemento X removido.
  • 86.
    Remover da lista(II) A relação remover/3 é definida de maneira similar à relação de ocorrência. São dois casos a estudar: Se X é a cabeça da lista L, então L1 será o seu corpo; Se X está no corpo de L, então L1 é obtida removendo X desse corpo. remover(X, [X | C], C). remover(X, [Y | C], [Y | D]) :- remover(X, C, D).
  • 87.
    Remover da lista(III) Se há diversas ocorrências de X em L, a relação remove/3 é capaz de retirar cada uma delas através do mecanismo de backtracking do Prolog. Em cada execução do programa remove/3 retiramos somente uma das ocorrências de X, por exemplo: ?-remover(a, [a, b, a, a], L). L=[b, a, a]; L=[a, b, a]; L=[a, b, a];
  • 88.
    Prática 11 Utilizea regra remove/3 no sentido inverso, para inserir um novo item em qualquer lugar da lista. Crie uma nova cláusula para membro, utilizando a regra remover/3.
  • 89.
    bagOf, setOf efindAll Podemos gerar, através de backtracking, todos os objetos, um a um, que satisfazem algum objetivo (next, next, next). Porém, algumas vezes, deseja-se dispor de todas as respostas juntas, por exemplo, dentro de uma lista. Os predicados bagof/3, setof/3 e findall/3 servem exatamente para tal propósito.
  • 90.
    bagOf (I) bagof(X,P, L) Irá produzir uma lista L de todos os objetos X que satisfazem ao objetivo P. Exemplo - dada a base de conhecimento abaixo: classe(a, vog). classe(b, con). classe(c, con). /* continua d, e, f… */
  • 91.
    bagOf (II) Podemosobter a lista de todas as consoantes nessa especificação através do objetivo: ?-bagof(Letra, classe(Letra, con), Consoantes). Consoantes=[b, c, d, ..., z]
  • 92.
    bagOf (III) Sea classe das letras não estivesse especificada, iríamos obter por meio de backtracking, duas listas, uma correspondendo às vogais e outra às consoantes: ?-bagof(Letra, classe(Letra, Classe), Letras). Classe=vog Letras=[a, e, i, o, u]; Classe=con Letras=[b, c, d, f, ..., z].
  • 93.
    bagOf – OutroExemplo Dada a base de conhecimento: leciona(rafael,progII). leciona(rafael,ia). leciona(eduardo,redes). leciona(eduardo,progI). Qual seria o retorno da consulta: ?- bagof(Disc,leciona(rafael,Disc),Disciplinas). E ?- bagof(Disc,leciona(Prof,Disc),Disciplinas).
  • 94.
    setOf (I) setof(X,P, L) Irá novamente produzir uma lista L dos objetos X que satisfazem a P, só que desta vez a lista L estará ordenada e itens duplicados, se houver, serão eliminados.
  • 95.
    setOf (II) Exemplo: ?- setof(Disc,eh_lecionada(Disc,Prof),Disciplinas). Prof = rafael Disciplinas = [ia, progII] Prof = eduardo Disciplinas = [progI, redes]
  • 96.
    setOf (III) Nãohá restrição quanto ao tipo de objeto a ser coletado. Assim podemos, por exemplo, construir uma lista de pares da forma Classe/Letra de forma que as constantes apareçam em primeiro lugar na lista (&quot;con&quot; antecede alfabeticamente &quot;vog&quot;): ?-setof(Classe/Letra, classe(Letra, Classe), Letras). Letras=[con/b, con/c, ..., con/z, vog/a, ..., vog/u]
  • 97.
    findall (I) Testeno Prolog e descubra o que faz o findall/3
  • 98.
    What is next?Apostila completa: aluno@net Próxima aula - DIA 14/04 – AVALIAÇÃO EM DUPLAS
  • 99.
    Referências http://pt.wikipedia.org/wiki/Prolog http://pt.wikipedia.org/wiki/Alain_Colmerauerhttp://www.linhadecodigo.com.br/Artigo.aspx?id=1697 http://en.wikipedia.org/wiki/Prolog http://ccc.inaoep.mx/~emorales/Cursos/ProgSimb/node32.html www.fei.edu.br/eletrica/r bianchi /ia/Apostila- Prolog .doc http://www.swi-prolog.org/ http://www.sics.se/isl/sicstuswww/site/index.html http://gersonc.anahy.org/graduacao/paradigmas/prologsan.pdf http://ia.ucpel.tche.br/~lpalazzo/Aulas/PDEC/ http://gollem.science.uva.nl/SWI-Prolog/apps/view.html http://www.fdi.ucm.es/profesor/fernan/des/