240 likes | 386 Views
Sintaxe e Semântica do. PROLOG. Introdução à programação em Prolog. PROLOG = PRO gramming in LOG ic Linguagem baseada num subconjunto da lógica de predicados de 1ª ordem (cláusulas de Horn) programa = conjunto de cláusulas (axiomas)
E N D
Sintaxe e Semântica do PROLOG
Introdução à programação em Prolog PROLOG = PROgrammingin LOGic Linguagem baseada num subconjunto da lógica de predicados de 1ª ordem (cláusulas de Horn) programa = conjunto de cláusulas (axiomas) Cláusulas: A :- A1, ... , An. Regra ou cláusula não unitária A é verdadeiro se A1 e ... e An são verdadeiros. Uma forma de resolver A é resolver A1 e ... e An. A. Facto ou cláusula unitária A é verdadeiro.
Introdução à programação em Prolog Exemplo de programa P: gosta(jorge, futebol). gosta(jorge, cinema). gosta(maria,X) :- gosta(X, futebol), gosta(X, cinema). Interrogações ou perguntas (“queries”) sobre o programa P: ?- gosta(jorge, futebol). (gosta(jorge,futebol) prova-se a partir de P ?) yes. ?- gosta(jorge, maria). no. ?- gosta(jorge,X). (Existe algum valor para X tal que gosta(jorge,X) se prova a partir de P) X = futebol; (‘;’ indica “procure outra resposta”) X = cinema; no. (não há mais respostas)
Introdução à programação em Prolog • O Prolog é uma linguagem de programação para computação simbólica (não numérica), particularmente, adaptada à resolução de problemas que envolvam objectos e relações entre objectos, num determinado contexto. • Definir cada relação através de tuplos de objectos (lista dos argumentos da relação) que satisfazem (i.e. tornam verdadeira) essa relação. • Cada argumento da relação pode ser uma constante (objectos concretos num determinado contexto) ou uma variável que denotam um objecto arbitrário num determinado contexto. • Questionar o programa acerca das relações definidas, i.e. para cada questão, introduzir uma conjunção de objectivos que devem ser satisfeitos pelo programa. • As respostas às questões podem ser positivas (no caso do objectivo ser satisfeito, assim, diz-se que o objectivo é bem sucedido) ou negativas (no caso do objectivo não ser satisfeito, assim, diz-se que o objectivo falhou).
Sintaxe e Semântica dos Programas em Prolog • ÁTOMOS • Correspondem a nomes próprios em linguagem natural que representam relações, funções ou objectos. • Podem ter as seguintes formas • sequências de letras do alfabeto latino, dígitos ou ‘_’, iniciadas por uma letra minúscula (e.g. gosta, jorge, ana_maria, x, a1); • sequências de caracteres especiais (‘+’, ’-‘, ’*’, ’/’, ’\’, ’:’, ’=’, etc.) Ex: :-, >, >=, -->, $$ (Cuidado: algumas sequências têm significado pré-definido como, por exemplo, a sequência ‘:-‘); • sequências de caracteres entre plicas (e.g. ‘Bom dia’, ‘123’).
Sintaxe e Semântica dos Programas em Prolog INTEIROS E REAIS Exemplos 0, 999, -12, 1.0, -13.8e+8, A amplitude da representação dos inteiros e reais depende da implementação do Prolog. VARIÁVEIS Representam objectos definidos mas não identificados; variáveis no sentido matemático e não no sentido habitual atribuído nas linguagens de programação imperativa. • sequências de letras, dígitos ou ‘_’, iniciadas por uma letra maiúscula ou por ‘_’ Exemplos X, L, Lista, Valor, _3 • variáveis anónimas Se uma variável ocorre somente uma vez numa cláusula, não necessita ter um nome e, assim, pode ser nomeada (anonimamente) por ‘_’. Exemplo gosta(ana,X):- bonito(X),tem_carro_marca(X,_).
pam tom liz bob ann pat jim Outro Exemplo Para qualquer X, X tem um filho se X é progenitor de Y. has_child(X) : parent(X,Y) Como a variável Y ocorre apenas uma vez no corpo da cláusula, pode ser substituída por uma variável anónima. has_child(X) : parent(X,_) Para a árvore genealógica ao lado que resultados obtemos para os objectivos que se seguem? ? has_child(X). ? parent(X,_). Nota O alcance de uma variável está restrito à claúsula onde ocorre.
Termos Compostos Um termo composto é formado a partir de um functor que define um objecto estruturado (ou estrutura), i.e. um objecto constituído por componentes (termos simples ou compostos) • Exemplo A data pode ser representada por uma estrutura constituída por três componentes: dia, mês e ano. data(25,abril,1974) Representação de um functor Um functor é representado por um nome (na sintaxe associada aos átomos) concatenado com uma sequência de termos simples ou compostos, separados por vírgulas, e delimitados à esquerda pelo parêntesis esquerdo e à direita pelo parêntesis direito. O functor caracteriza-se pelo seu nome e a sua aridade.
Termos Compostos • Exemplo functor argumento maior( sucessor( N ) , N ) termo composto termo simples functor principal 1º argumento 2º argumento termo composto • Nota Podemos associar o mesmo nome a functores diferentes (a aridade distingue um functor) como, por exemplo, no caso de ponto(X,Y) e ponto(X,Y,Z).
Termos Compostos • functores como operadores É conveniente, por vezes, escrever alguns functores binários (com aridade 2) como operadores infixos e functores unários como operadores prefixos ou sufixos. • Exemplo X*Y, A>B+X, X+2*Y como representação alternativa de, respectivamente, *(X,Y), >(A,+(B+X)), +(X,*(2,Y)). • Nota A possibilidade de utilizar essa notação mais conveniente está dependente da declaração do functor como operador com determinado tipo e precedência (pré-definida para os operadores aritméticos usuais e alguns outros).
Termos Compostos • cláusulas como termos compostos Uma cláusula da forma: A :- A1, ..., An. é um termo composto constituído pelo functor especial ‘:-‘ aplicado ao termo A, designado por cabeça da claúsula, e à conjunção dos termos A1,...,An, designada por corpo da cláusula (a especificação de uma cláusula termina sempre com um ponto).
Objectivos e Predicados • Os termos principais que ocorrem numa cláusula (ou numa interrogação) são chamados objectivos. Assim, um objectivo é um termo que se distingue apenas pelo contexto em que ocorre. • A cabeça de uma cláusula é constituída por um único objectivo. • O corpo pode ser constituído por zero ou mais objectivos. • As claúsulas sem corpo (factos) e com cabeça A são escritas na forma: A. • O predicado (ou procedimento) para um dado functor, num programa, é o conjunto de claúsulas cuja cabeça tem esse functor como functor principal. Exemplo gosta(X, Y) :- irmão(X, Y). gosta(X, Y) :- pai(X,Y). predicado gosta gosta(ana, josé). pai(raul, maria). predicado pai pai(X, Y) :- filho(Y, X).
Instâncias de cláusulas • Uma instância de uma cláusula é obtida substituindo uniformemente uma variável por um novo termo, para zero ou mais das variáveis da cláusula. • Exemplo: cláusula: gosta(X, Y) :- gosta(X, Z), gosta(Z, Y). InstânciasSubstituições gosta(X1, Y1) :- gosta(X1, Z1), gosta(Z1, Y1). { X/X1, Y/Y1, Z/Z1} gosta(X, X) :- gosta(X, Z), gosta(Z, X). { Y/X } gosta(ana,Y) :- gosta(ana, Z), gosta(Z, Y). { X/ana } gosta(ministro(a), b) :- gosta(ministro(a), W), gosta(W, b). {X/ministro(a), Y/b, Z/W}
Unificação • Um objectivo O1 unifica com outro objectivo O2, se existe uma instância comum de O1 e de O2 (obtida por uma substituição s). gosta(X, jorge) unifica comgosta(ana,X) ? Não • Unificação de um objectivo O com a cabeça de uma cláusula C: gosta(X, jorge)unifica com a cabeça de gosta(ana,X) :- gosta(X,fut), gosta(X,cin).? • As variáveis de uma cláusula são variáveis locais dessa cláusula. • Podemos renomear as variáveis numa cláusula, de modo a que não tenha variáveis em comum com o objectivo dado, sem alterar o seu significado. gosta(ana,X1) :- gosta(X1,fut), gosta(X1,cin).
Unificação • Quando dizemos informalmente que um objectivo O unifica com a cabeça de uma cláusula C, pretendemos dizer que unifica com a cláusula, após renomear as suas variáveis de modo a não ter variáveis em comum com O. gosta(X, jorge)unifica com a cabeça de gosta(ana,X1) :- gosta(X1,fut), gosta(X1,cin).? Sim!
SEMÂNTICA DECLARATIVA DE UM PROGRAMA • Um objectivo é verdadeiro se unifica com a cabeça de uma claúsula C e se todos os objectivos no corpo da instância de C resultante da unificação são verdadeiros. • Definição recursiva • Não refere a ordem das cláusulas no programa nem a ordem dos objectivos no corpo das cláusulas • Exemplo programa P:significado declarativo de P: descende(X,Y) :- descende(X, Z), filho(Z,Y). X Y Z (descende(X, Z) filho(Z, Y) descende(X, Y) ) descende(X,Y) :- filho(X,Y). X Y ( filho(X, Y) descende(X, Y) ) filho(rui, carlos). filho(rui, carlos) filho(jorge, rui). filho(jorge, rui). Segundo a semântica declarativa de P, o objectivo descende(jorge, carlos) é verdadeiro.
SEMÂNTICA PROCEDIMENTAL/OPERACIONAL DE UM PROGRAMA • Define como é que o processador do Prolog executa (ou satisfaz) um objectivo/interrrogação sobre um programa P • A execução de um objectivo pode • terminar com sucesso(obtendo-se a resposta “yes” ou valores para as variáveis do objectivo) • ou terminar com insucesso ou falha (obtendo-se a resposta “no”) • ou não terminar. • A execução de um objectivo O com functor principal F é encarada como uma chamada do procedimento para F. Para executar O, o processador procura, sequencialmente nas cláusulas do procedimento F, a 1ª cláusula cuja cabeça unifica com O, e tenta executar o seu corpo. Se não tiver sucesso, continuará a procura a partir da cláusula seguinte de F. • A ordem das cláusulas no programa e a ordem dos objectivos no corpo das cláusulas são relevantes.
SEMÂNTICA PROCEDIMENTAL/OPERACIONAL DE UM PROGRAMA A execução de um objectivo O sobre um programa P, corresponde a: (1) Posicionar-se no início de P; (2) Procurar a próxima cláusula C cuja cabeça unifica com O, (seja CI a instância de C resultante dessa unificação) (2.1) Se existe e tem corpo vazio, termina com sucesso. (2.2) Se existe e tem corpo não vazio, então executar o corpo de CI (isto é, reduzir a execução de O à execução do corpo de CI); (2.1.1) Se a execução do corpo de CI for bem sucedida, então termina com sucesso (2.1.2) Se a execução do corpo de CI falhar, então voltar a (2). (retrocesso ou “backtracking”) (2.3) Se não existe, a execução falha. A execução de uma sequência de objectivos O1, ..., On, corresponde a executar O1, obtendo uma substituição de variáveis s1, e executar a sequência O2’,..., On’, onde O2’,...,On’ são as instâncias de O2,...,On, resultantes da aplicação de s1.
Interpretação declarativa vs procedimental • Interpretação Declarativa Incide sobre as relações definidas no programa e, assim, determina qual o output (i.e. a resposta) do programa para um dado input (i.e. para uma dada questão). • Interpretação Procedimental Incide sobre como o programa produz um output para um dado input, i.e. como as relações são valiadas pela implementação do Prolog. A abstracção dos detalhes envolvidos na interpretação procedimental dos programas é considerada uma vantagem visto que, assim, permite ao programador concentrar-se essencialmente nos aspectos declarativos da programação. Mas, em programas relativamente grandes, os aspectos procedimentais não podem ser total ignorados por razões de eficiência na execução dos programas.
Árvore de execução • Representação da sequência de estados da execução de um objectivo. • representa sucesso ; representa falha • Diferentes ramos terminados por representam diferentes soluções • ?- gosta(X,Y) • Exemplo 1: • Programa • gosta(jorge, fut). • gosta(jorge, cin). • gosta(maria,X) :- gosta(X, fut), gosta(X, cin). • Interrogação • ?- gosta(X,Y) . • {X/maria } • {X/jorge,Y/fut} • {X/jorge,Y/cin} gosta(Y,fut), gosta(Y,cin) {Y/jorge} • {Y/maria } gosta(jorge,cin) • gosta(fut,fut), gosta(fut,cin), • gosta(maria,cin)
Árvore de execução • Exemplo 2: descende(X,Y) :- filho(X,Y). descende(X,Y) :- descende(X, Z), filho(Z,Y). filho(rui, carlos) . filho(jorge, rui). ?- descende(jorge,carlos) descende(jorge,Z), filho(Z, carlos) filho(jorge,carlos) filho(jorge,Z), filho(Z, carlos) descende(jorge,Z1), filho(Z1,Z), filho(Z, carlos) filho(rui, carlos) filho(jorge,Z1), filho(Z1,Z), filho(Z, carlos) … filho(rui,Z), filho(Z, carlos) filho(carlos, carlos)
pam tom liz bob ann pat jim Exemplo 3 Árvore genealógica (parcial) da família Smith Objectos pam, tom, bob, liz, ann, pat e jim Relação X é ascendente de Y (predicado parent(X,Y)) Instâncias (da relação parent no contexto da família Smith) parent(pam,bob), parent(tom,bob), parent(tom,liz), parent(bob,ann), parent(bob,pat) e parent(bob,jim)
pam tom liz bob ann pat jim Exemplo 3 (objectivos) ? – parent(bob,pat). (“O bob é ascendente de pat?”) yes ? – parent(liz,pat). (“A liz é ascendente de pat?”) no ? – parent(tom,ben). (“O tom é ascendente de pam?”) no ? – parent(X,liz). (“Quem são os ascendentes de liz?”) X = tom; no ? – parent(bob,X). (“Quem são os descendentes de bob?”) X = ann; X=jim; X= pat; no ? – parent(tom,X),parent(X,Y). (“Quem são os filhos e os netos de tom”) X = bob Y = ann; X = bob Y = jim; … ? – parent(X,Y). (“Quem é descendente de quem?”) X = pam Y = bob; ? – parent(X,ann),parent(X,pat) (“Quem é ascendente de ann e pat?”) X = bob; no