Linguagens Lógicas mleal@inf.puc-rio.br 1 Introdução Em LPs imperativas um programa é composto por uma sequência de comandos que representam as atividades computacionais que serão executadas. O programador deve portanto especificar claramente como realizar o processamento desejado, ou seja, como é o algoritmo. Em LPs lógicas um programa consiste na definição de relações lógicas que devem ser satisfeitas pela solução procurada. A busca por uma solução acontece automaticamente através de regras de inferência. mleal@inf.puc-rio.br 2
Introdução Programar em uma LP lógica consiste em: Declarar fatos primitivos sobre um domínio; Definir regras que expressam relações entre os fatos de um domínio; Fazer perguntas sobre um domínio. O processo de dedução através do qual encontram-se respostas às perguntas é executado automaticamente pelo sistema. mleal@inf.puc-rio.br 3 1. Aves botam ovos. Exemplo 2. Mamíferos não botam ovos. 3. Baleias são mamíferos. 4. Baleias botam ovos? Não. 5. Quem bota ovos? Aves. mleal@inf.puc-rio.br 4
Fatos Uma forma de declarar um fato como uma baleia é um mamífero é: mamifero (baleia). Para representar o fato Bruno gosta de Ana podemos escrever: gostar(bruno, ana) Repare que este fato é diferente de Ana gosta de Bruno : gostar(ana, bruno) Nas expressões acima gostar é o predicado do fato, representando uma relação entre os argumentos. mleal@inf.puc-rio.br 5 Fatos Outros exemplos de fatos campeao(flamengo). vender(marcelo,carro,carlos). chuva. Esta sintaxe não corresponde a invocação de uma função!!! mleal@inf.puc-rio.br 6
Regras A declaração de regras (axiomas) em LPs lógicas segue um padrão conhecido como cláusulas de Horn: H A 1,A 2,..., A n se todos os A i são verdadeiros, então H é verdadeiro. Na expressão acima, H é denominado a cabeça da cláusula e A 1,A 2,..., A n é o seu corpo. Através de regras pode-se estabelecer relações entre fatos. mleal@inf.puc-rio.br 7 Resolução Para descobrir novas relações uma LP lógica utiliza um processo conhecido como resolução. O corpo de uma cláusula é equivalente a sua cabeça, e ambos podem ser substituídos livremente em outras cláusulas para formar novas regras. C A,B D C D A,B Através do processo de resolução uma LP lógica é capaz de provar a validade de proposições. mleal@inf.puc-rio.br 8
Banco de Dados O conjunto de fatos e relações contidos em um programa lógico é denominado banco de dados, e representa o conhecimento sobre um ou mais domínios. O objetivo de um programa lógico é inferir e validar novos fatos ou relações a partir do banco de dados. mleal@inf.puc-rio.br 9 Prolog Foi desenvolvida no início da década de 70 para ser usada na prova de teoremas. Ainda hoje é a mais popular e principal LP lógica. É bastante utilizada em sistemas especialistas. Em Prolog um programa é composto por fatos e regras. mleal@inf.puc-rio.br 10
Fatos em Prolog Fatos em Prolog são representados através de átomos ou estruturas. Átomos são strings que começam sempre com letra minúscula: esta_chovendo. dinheiro. joao. mleal@inf.puc-rio.br 11 Fatos em Prolog Estruturas são átomos seguidos de uma lista de argumentos entre parânteses: pred (arg1, arg2,..., argn). onde: pred - nome de um predicado arg1,... argn - argumentos N - número de argumentos (aridade). - final sintático de qualquer cláusula Prolog mleal@inf.puc-rio.br 12
Fatos em Prolog Os argumentos de uma estrutura podem ser átomos, estruturas, variáveis e números. Exemplos: caro(diamente). amigo(joana, patricia). arvore_bin(valor1, arvore_bin(valor2, valor3)). quantidade(24). Estruturas representam relações entre os argumentos, ou seus predicados. mleal@inf.puc-rio.br 13 Variáveis Em LPs imperativas variáveis são instanciadas através de operações explícitas de atribuição. Em LPs lógicas variáveis geralmente são instanciadas implicitamente pelo sistema durante o processo de resolução. São usadas basicamente para extrair informações do banco de dados, e para expressar relações entre fatos. Variáveis em Prolog são representadas por strings que começam com uma letra maiúscula. mleal@inf.puc-rio.br 14
Exemplos offroad(x):- carro(x),tracao4x4(x), suspensaoreforcada(x). frio(groelandia).?-frio(x). x=groelandia. mleal@inf.puc-rio.br 15 Questões Questões são representados por fatos precedidos por -?.?-gostar(bruno, ana). Informalmente: : Bruno gosta de Ana? Formalmente: : É possível provar a partir dos fatos conhecidos pelo programa que a relação gostar(bruno, ana) é verdadeira? mleal@inf.puc-rio.br 16
Exemplos animal (cachorro) animal (gato)?-animal(cachorro). yes?-animal(x) X = cachorro; X = gato; yes mleal@inf.puc-rio.br 17 Unificação Para tentar provar um fato Prolog precisa estabelecer a equivalência entre fatos. Dois fatos equivalentes são ditos unificáveis. Dois átomos são unificáveis apenas se são idênticos. Duas estruturas são unificáveis se o seu predicado é idêntico, e se seus argumentos são unificáveis. mleal@inf.puc-rio.br 18
Unificação Uma variável é unificável a qualquer coisa. Durante o processo de resolução, uma variável é instanciada com um valor que permite a sua unificação com um símbolo correspondente de um outro fato. O símbolo = em prolog representa unificação. mleal@inf.puc-rio.br 19 Exemplos fruta(manga).?-fruta(x). X = manga X foi unificada com manga gostar(bruno,ana).?-gostar(bruno,x). X = ana X foi unificada com ana?-x=sol. X=sol X foi unificada com sol?-sol=sol. yes sol foi unificado com sol mleal@inf.puc-rio.br 20
Regras em Prolog Regras são representadas como cláusulas de Horn seguindo a sintaxe: pred(x1,...,xn):- pred1(x1,...,xn),...,predn(x1,...,xn). se os predicados 1 a n são verdadeiros para as variáveis Xi, então o predicado pred é verdadeiro para as variáveis Xi. A variável representa portanto o símbolo para o qual a regra é verdadeira. mleal@inf.puc-rio.br 21 Exemplos pai(joao,joaquim). pai(joaquim,manuel). avo(x,y):-pai(z,y),pai(x,z).?-avo(joao,z). Z=manuel?-avo(joao,manuel). yes. mleal@inf.puc-rio.br 22
Conjunções Conjunções permitem a especificação de questões com múltiplas condições que devem ser satisfeitas simultaneamente. Conjunções são representadas por uma vígula (, ). Exemplo:?- localizacao(x,cozinha), comida(x), gostoso(x). Existe alguma comida gostosa na cozinha? mleal@inf.puc-rio.br 23 Disjunções Disjunções permitem a especificação de questões com múltiplas condições na qual ao menos uma delas deve ser satisfeita. Disjunções são representadas por um ponto-e- vírgula ( ; ). Exemplos:?-amigos(X,Y); parentes(x,y). inverno(x):- nevando(x); gelado(x). É inverno se está nevando ou está gelado. mleal@inf.puc-rio.br 24
Fluxo de Controle Prolog possui um fluxo de controle implícito através do qual busca responder uma questão. Este fluxo é determinístico, ou seja segue sempre uma mesma ordem: O banco de dados é percorrido sequencialmente na ordem em que os fatos\regras foram declarados. Para cada predicado correto encontrado, os argumentos são testados em ordem. Para cada regra,, as condições são testadas sempre da esquerda para a direita. mleal@inf.puc-rio.br 25 Exemplo tropical(caribe). (1) tropical(havai). praia(havai). praia(caribe). (2) bonito(havai). bonito(caribe). (3) paraiso_tropical(x):-tropical(x),praia(x), tropical(x),praia(x), bonito(x).?-paraiso_tropical(x). X=caribe; X is caribe true X is caribe true X is caribe tropical praia bonito true mleal@inf.puc-rio.br 26
Fluxo de Controle Variáveis são instanciadas implicitamente com valores que permitem a unificação da estrutura. Assim que uma associação válida for encontrada, os valores com os quais as variáveis foram instanciadas são impressos. Apenas a primeira associação válida é impressa. Para que todas as associações válidas possam ser encontradas basta digitar um ; após cada resultado apresentado por Prolog. mleal@inf.puc-rio.br 27 Fluxo de Controle Implícito Para provar questões mais complexas Prolog pode ser obrigado a testar várias vezes a mesma condicão, instanciando uma mesma variável com diferentes valores. A sequência com que os fatos e regras são testados portanto não é necessariamente linear, e segue um caminho semelhante a uma árvore. O processo de retornar para uma condicão e testá-la novamente é denominado backtracking. mleal@inf.puc-rio.br 28
Exemplos surf(vitor). surf(renan). surf(teco). skate(vitor). skate(teco). moto(renan). moto(teco). radical(x):-surf(x),skate(x),moto(x).?-radical(x). teco. mleal@inf.puc-rio.br 29 Exemplo radical(x):-surf(x),skate(x),moto(x). radical(x) surf(x) skate(x) moto(x) X is vitor X is renan X is teco X is vitor X is renan X is teco X is vitor x is teco surf true skate false skate true moto false moto true mleal@inf.puc-rio.br 30
Modificando o Fluxo de Execução Prolog oferece dois comandos que permitem alterar o fluxo natural de execução. cut:! fail Usado para impedir o backtracking. Ao ser ultrapassada, não permite retorno. Faz com que a busca sempre falhe, provocando backtracking. Usado em combinação com! para gerar um not. mleal@inf.puc-rio.br 31 Exemplos not(p):- call(p),!,fail;true. gosta(maria,x):- cobra(x),!, fail; animal(x). statement:- condition,!, then_part; else_part. filosofo(x) :-: intelectual(x),grego(x). intelectual(platao). intelectual(socrates). grego(platao). grego(socrates). listar_filosofos:- write( Filosofos: ), nl, filosofo(x),write(x),nl, fail. mleal@inf.puc-rio.br 32
Igualdade Em Prolog existem quatro operadores que representam igualdade: 1. X == Y Relação de identidade. É verdadeiro apenas se X e Y são idênticos (representam a mesma variável ou o mesmo símbolo). 2. X = Y - Unificação. É verdadeiro se X é unificável com Y. 3. X =:= Y Significa calcule X, calcule Y e teste sua igualdade. X e Y devem ser expressões aritméticas. 4. X is Y - Significa ``calcule Y e unifique X com Y''. Y deve ser uma expressão aritmética. mleal@inf.puc-rio.br 33 Aritmética O operador is é o mais utilizado em operações aritméticas, e força a instanciação de variáveis. Exemplos?- X is 1+2 X = 3?-1+2 is 4-14 no fib(0,1). fib(1,1). fib(x,r):- A is X-1, X B is X-2, X fib(a,r1), fib(b,r2), R is R1+R2. mleal@inf.puc-rio.br 34
Listas Prolog suporta uma notação especial para representar listas. Uma lista genérica tem a seguinte sintaxe: [elem1, elem2,..., elemn] Para manipular uma lista pode-se utilizar a notação [H T] onde H representa o primeiro elemento da lista e T os demais elementos. member(x, [X T]). member(x, [H T]):- member (X, T). last(x,[x]). last(x, [H T]):- last (X, T). mleal@inf.puc-rio.br 35 Predicados da Linguagem asserta(x) - adiciona a cláusula X no início do banco de dados. assertz(x) - adiciona a cláusula X no final do banco de dados. retract(x) - remove a cláusula X do banco de dados. call(x) tenta satisfazer a cláusula X. mleal@inf.puc-rio.br 36
I/O see(arq arq) redireciona o input para o arquivo arq. seeing(arq arq) unifica arq com o input corrente. seen - fecha o input corrente. tell(arq arq) redireciona o output para o arquivo arq. telling(arq arq) unifica arq com o output corrente. told - fecha o output corrente. mleal@inf.puc-rio.br 37 I/O read(term) lê o próximo termo (string) do arquivo corrente. Retorna end_of_file se eof. write(term) imprime Term no output corrente. get0(n) lê o próximo caracter do input corrente e unifica o seu código ASCII com N. Retorna 11 se eof. get(n) lê o próximo caracter não nulo do input corrente e unifica o seu código ASCII com N. Retorna 11 se eof. put(n) imprime o caracter correspondente ao ASCII N no output corrente. nl imprime um newline. tab(n) imprime N espaços. mleal@inf.puc-rio.br 38
Gramáticas de Cláusulas Definidas Gramáticas de Cláusulas Definidas (definite clause grammars - DCGs) estendem gramáticas livres de contexto permitindo o uso de argumentos ou procedimentos embutidos nas produções (cláusulas). Prolog suporta diretamente a definição de DCGs através de uma sintaxe especial. Através deste mecanismo é fácil construir parsers para qualquer gramática livre de contexto. mleal@inf.puc-rio.br 39 Exemplo Considera a seguinte gramática: <frase> ::= <sintagma nominal > <predicado>. <sintagma nominal > ::= <artigo> <substantivo> <predicado> ::= <verbo> <verbo> <sintagma nominal > <artigo> ::= a o <substantivo> ::= menino menina gato cachorro <verbo> ::= viu mordeu dormiu chamou mleal@inf.puc-rio.br 40
Exemplo A partir da frase o cachorro mordeu o gato. podemos criar o seguinte grafo: o cachorro mordeu o gato. 1 2 3 4 5 6 7 Para respresentar um sintagma nominal podemos usar a regra: sintagmanominal(k,l) :-: artigo(k,m), substantivo(m,l). sintagmanominal(1,3) :-: artigo(1,2), substantivo(2,3). onde os argumentos indicam os nós do grafo. mleal@inf.puc-rio.br 41 Exemplo frase(k,l) :-: sintagmanominal(k,m), predicado(m,n), period(n,l). sintagmanominal(k,l) :-: artigo(k,m), substantivo(m,l). predicado(k,l) :-: verbo(k,m), sintagmanominal(m,l). predicado(k,l) :-: verbo(k,l). artigo(k,l) :-: o(k,l). artigo(k,l) :-: a(k,l). substantivo(k,l) :-: menino(k,l). substantivo(k,l) :-: menina(k,l). substantivo(k,l) :-: gato(k,l). substantivo(k,l) :-: cachorro(k,l). verbo(k,l) :-: viu(k,l). verbo(k,l) :-: mordeu(k,l). verbo(k,l) :-: dormiu(k,l). verbo(k,l) :-: chamou(k,l). mleal@inf.puc-rio.br 42
Exemplo o(1,2). cachorro(2,3). mordeu(3,4). o(4,5). gato(5,6). ponto(6,7).?- frase(1,7). yes?- frase(x,y). X = 1 Y = 7 yes <frase> <predicado> <sintagma nominal > <sintagma nominal > o cachorro mordeu o gato. 1 2 3 4 5 6 7 mleal@inf.puc-rio.br 43 DCG Para representar uma DCG deve-se definir as cláusulas usando o operador -- -->. Os terminais são indicados entre colchetes ( [ ]). Terminais podem conter argumentos. Pode-se especificar rotinas a serem executadas durante a validação de uma cláusula através de chaves ({ }). mleal@inf.puc-rio.br 44
Exemplo frase --> > sintagmanominal, predicado, ['.']. ']. sintagmanominal --> > artigo, substantivo. predicado --> > verbo, sintagmanominal. predicado --> > verbo. artigo --> > [o]; [a]. substantivo --> > [menino] ; [menina] ; [cachorro] ; [gato]. verbo --> > [viu] ; [chamou] ; [dormiu] ; [mordeu]. mleal@inf.puc-rio.br 45 Exemplo frase(fr(n,p)) --> > sintagmanominal(n), predicado(p), ['.']. sintagmanominal(sintagn(d,n)) --> > artigo(d), substantivo(n). predicado(pred(v,n)) --> > verbo(v), sintagmanominal(n). predicado(pred(v)) --> > verbo(v). artigo(art(o)) --> > [o]. artigo(art(a)) --> > [a]. substantivo(sub (menino)) --> > [menino]. substantivo(sub (menina)) --> > [menina]. substantivo(sub (gato)) --> > [gato]. substantivo(sub (cachorro)) --> > [cachorro]. verbo(verb(viu)) --> > [viu]. verbo(verb(mordeu)) --> > [mordeu]. verbo(verb(dormiu)) --> > [dormiu]. verbo(verb(chamou)) --> > [chamou]. mleal@inf.puc-rio.br 46
Exemplo?- frase(f, [o,cachorro,mordeu,o,gato,'.'], []). F = fr(sintagn(art(o), sub (cachorro)), pred(verb(mordeu), sintagn(art(o), sub(gato)))) yes?- predicado(f, [mordeu,o,gato], []). F = pred(verbo(mordeu), sintagn(art(o), sub(gato))) yes mleal@inf.puc-rio.br 47 Scanner <num> ::= <digito> <digito><num>. <num> ::= <digito> <restnum>. <restnum> ::= ε <digito><num>. getnum(c,n) :-: digit(c), get0(d), restnum(d,lc), name(n,[c Lc]). restnum(c,[c Lc]) :-: digit(c), get0(d), restnum(d,lc). restnum(c,[]). mleal@inf.puc-rio.br 48
Scanner scan([t Lt]) :-: getch(c), gettoken(c, T, D), restprog(t, D, Lt),!. getch(c) :-: get0(c), (endline(c),nl; endfile(c), nl ; put(c)). restprog(eop, C, []). restprog(t, C, [U Lt]) :-: gettoken(c, U, D), restprog(u, D, Lt). mleal@inf.puc-rio.br 49 Invocando Rotinas scanp :-: nl, write('scan & Parse'), nl, nl, write('enter name of source file: '), nl, getfilename(filename), nl, see(filename), scan(tokens), seen, write('scan ok'), nl,!, write(tokens), nl, nl, parse(parsetree,tokens), write('parse ok'), nl,!, write(parsetree), nl, nl. getfilename(w) :-: get0(c), restfilename(c,cs), name(w,cs). restfilename(c,[c Cs]) :-: filechar(c), get0(d), restfilename(d,cs). restfilename(c,[]). mleal@inf.puc-rio.br 50