Sintaxe e Semântica
do
PROLOG
Introdução à programação em Prolog
PROLOG = PROgramming in 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.
Lógica para Programação
Facto ou cláusula unitária
A é verdadeiro.
2
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)
Lógica para Programação
3
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).
Lógica para Programação
4
Sintaxe e Semântica dos Programas em Prolog
SINTAXE
termos
termos simples
constantes
átomos
Lógica para Programação
inteiros
termos compostos
variáveis
reais
5
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’).
Lógica para Programação
6
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,_).
Lógica para Programação
7
Outro Exemplo
Para qualquer X, X tem um filho se X é progenitor de Y.
has_child(X) : parent(X,Y)
pam
tom
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,_)
liz
bob
Para a árvore genealógica ao lado que resultados
obtemos para os objectivos que se seguem?
?  has_child(X).
ann
pat
?  parent(X,_).
Nota
O alcance de uma variável está restrito à claúsula onde
ocorre.
Lógica para Programação
jim
8
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.
Lógica para Programação
9
Termos Compostos
functor argumento
Exemplo
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).
Lógica para Programação
10
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).
Lógica para Programação
11
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).
Lógica para Programação
12
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).
pai(X, Y) :- filho(Y, X).
Lógica para Programação
predicado pai
13
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âncias
gosta(X1, Y1) :- gosta(X1, Z1), gosta(Z1, Y1).
gosta(X, X)
:- gosta(X, Z), gosta(Z, X).
gosta(ana,Y) :- gosta(ana, Z), gosta(Z, Y).
gosta(ministro(a), b) :gosta(ministro(a), W), gosta(W, b).
Lógica para Programação
Substituições
{ X/X1, Y/Y1, Z/Z1}
{ Y/X }
{ X/ana }
{X/ministro(a), Y/b, Z/W}
14
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 com gosta(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).
Lógica para Programação
15
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!
Lógica para Programação
16
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.
Lógica para Programação
17
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.
Lógica para Programação
18
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.
Lógica para Programação
19
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.
Lógica para Programação
20
Á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:
{X/maria }
{X/jorge,Y/fut}
Programa
{X/jorge,Y/cin}
gosta(jorge, fut).
gosta(jorge, cin).
gosta(maria,X) :- gosta(X, fut), gosta(X, cin).
Interrogação
?- gosta(X,Y) .
Lógica para Programação
gosta(Y,fut), gosta(Y,cin)
{Y/jorge}
gosta(jorge,cin)
{Y/maria }
gosta(fut,fut), gosta(fut,cin)
gosta(maria,cin)
21
Árvore de execução
Exemplo 2:
descende(X,Y) :- filho(X,Y).
descende(X,Y) :- descende(X, Z), filho(Z,Y).
?- descende(jorge,carlos)
filho(rui, carlos) .
filho(jorge,carlos)
filho(jorge, rui).
descende(jorge,Z), filho(Z, carlos)
filho(jorge,Z), filho(Z, carlos)
filho(rui, carlos)
descende(jorge,Z1), filho(Z1,Z), filho(Z, carlos)
filho(jorge,Z1), filho(Z1,Z), filho(Z, carlos)
filho(rui,Z), filho(Z, carlos)
filho(carlos, carlos)
Lógica para Programação
22
…
Exemplo 3
Árvore genealógica
família Smith
(parcial)
da
pam
tom
Objectos
pam, tom, bob, liz, ann, pat e jim
Relação
X é ascendente de Y (predicado
parent(X,Y))
ann
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)
Lógica para Programação
liz
bob
pat
jim
23
Exemplo 3 (objectivos)
pam
? – parent(bob,pat). (“O bob é ascendente de pat?”)
tom
yes
? – parent(liz,pat). (“A liz é ascendente de pat?”)
no
liz
? – parent(tom,ben). (“O tom é ascendente de pam?”)
bob
no
? – parent(X,liz). (“Quem são os ascendentes de liz?”)
X = tom;
ann
pat
no
? – parent(bob,X). (“Quem são os descendentes de bob?”)
jim
X = ann;
X=jim;
X= pat;
no
? – parent(X,Y). (“Quem é descendente de quem?”)
? – parent(tom,X),parent(X,Y).
X = pam
(“Quem são os filhos e os netos de tom”)
Y = bob;
X = bob
? – parent(X,ann),parent(X,pat)
Y = ann;
(“Quem é ascendente de ann e pat?”)
X = bob
X = bob;
Y = jim;
no
…
Lógica para Programação
24

Download

SintaxeSemânticaProlog