Introdução a Prolog
Aula “teórico-prática”
O que é Prolog?
Linguagem mais divulgada do paradigma de Programação
em Lógica
Baseado em cláusulas de Horn
P1 P2 P3 ... Pn Q
Operacionalização simples, prática e eficiente da metáfora da
programação em lógica
Metáfora da programação em lógica
Programar = Declarar axiomas e regras
Teoria Lógica x Prolog
Axiomas: Fatos prolog
Regras: Regras prolog
Teoremas: Deduzidos a partir dos fatos e regras
Exemplo - Fatos
pam
tom
bob
ann
pat
jim
liz
parent(pam,
parent(tom,
parent(tom,
parent(bob,
parent(bob,
parent(pat,
bob).
bob).
liz).
ann).
pat).
jim).
female(pam).
female(ann).
female(pat).
female(liz).
male(bob).
male(tom).
male(jim).
Exemplo – Perguntas à base de
fatos
pam
tom
bob
ann
pat
jim
liz
Bob é filho de Jim?
- parent(jim, bob).
false
Bob é filho de quem?
- parent(X, bob).
X = pam ;
X = tom ;
Encontre X e Y tal que X é
“progenitor” de Y.
parent(X, Y).
X = pam
Y = bob ;
...
Exemplo – Regras
pam
tom
bob
ann
pat
jim
liz
Quem é o pai de bob?
- parent(X, bob),
male(X).
X = tom
Definindo uma regra para pai
father(X, Y) :- parent(X,
Y), male(X).
Isto é a sintaxe em prolog para
x, y parent(x, y) male(x)
father(x, y)
Agora podemos perguntar
- father(X, bob).
X = tom
Exercício 1
Defina as regras: (arquivo family.P)
mother(X,Y)
sister(X, Y)
grandparent(X, Y)
Defina a regra:
aunt(X, Y)
Dica: você pode usar a regra sister(X, Y) definida anteriormente
Exemplo – Regras recursivas
Quais são os ancestrais de jim?
Podemos expressar a relação
ancestor(X, Y) por uma regra
recursiva
ancestor(X, Y) :father(X, Y).
ancestor(X, Y) :father(X, Z),
ancestor(Z, Y).
pam
tom
bob
ann
pat
liz
Faça as perguntas
jim
Quem são os ancestrais de Jim?
Bob é ancestral de quem? E Jim?
Sintaxe de Prolog
fato -> fa. (abreviação para Formula Atômica)
regra -> fa0 :- fa1, ... , faN.
consulta -> fa1, ... , faN.
fa -> pred(termo1, ... , termoN) | preop termo1 termo2
| termo1 inop termo2 | termo1 termo2 postop
termo -> constante | variável | fa
constante -> átomos | números
pred -> átomo
Sintaxe de Prolog (2)
variável ex: C, Chico, Francisco_carvalho, Chico1, _fatc, _
átomo ex: c, fatc, =>, francisco_carvalho, chico1, ‘chico ia’
número ex: 23
termos, fatos, regras e consultas sem variáveis:
termos, fatos e regras com variáveis:
instanciados (ground)
ex.: person(bob,40,cs).
universais
ex.: father(adao,X).
father(X, Y) :- parent(X, Y), male(X).
consultas com variáveis:
existenciais
ex.: - father(F,P).
Intepretação de um programa
Prolog
P :- Q, R.
Interpretações declarativas
P é verdadeiro se Q e R forem verdadeiros.
Q e R implica P.
Interpretações procedurais
Para resolver o problema P:
Primeiro resolva o subproblema Q
Depois resolva o subproblema R
Para satisfazer P:
Primeiro satisfaça Q
E então satisfaça R
Interpretador Prolog: Controle e Busca
(funcionamento procedural)
Aplica regra de resolução:
com estratégia linear (sempre tenta unificar último fato a provar
com a conclusão de uma cláusula do programa),
na ordem escrita das cláusulas no programa,
com encadeamento de regras regressivo (backward-chaining),
busca em profundidade e
da esquerda para direita das premissas das cláusulas,
e com backtracking sistemático e linear quando a unificação
falha,
e sem occur-check na unificação.
Prolog e aritmética
Operadores aritméticos
+ adição
- subtração
* multiplicação
/ divisão
** potenciação
// divisão inteira
mod módulo (resto da divisão
inteira)
O atribuidor is
Variável is Expr. Aritmética
Exemplos
-
X
-
X
-
X
Y
Z
X = 1 + 2
= 1 + 2
X is 1 + 2
= 3
X is 5/2, Y is 5//2,
Z is 5 mod 2.
= 2.5
= 2
= 1
Prolog e aritmética (2)
Operadores de comparação
> maior que
< menor que
>= maior ou igual
=< menor ou igual
=:= teste de igualdade
aritmética
=\= teste de diferença
aritmética
Exemplos
1 + 2 =:= 2 + 1.
yes
1 + 2 = 2 + 1.
no
1 + A = B + 2.
A = 2
B = 1
-
Exemplo Aritmético - Fatorial
factorial(0, 1).
factorial(N, Fn) :N > 0,
M is N - 1,
factorial(M, Fm),
Fn is N * Fm.
(arquivo fac.P)
- factorial(10, X).
X = 362880
- factorial(10, 362880).
yes
- factorial(10, 10000).
no
Exercício 2
Defina uma regra fib(X, Y) que calcula o número de fibonacci
de X, atribuindo-o a Y.
A sequência de Fibonacci é definida matematicamente como
fib(1) = 1
fib(2) = 1
fib(n) = fib(n – 1) + fib(n – 2)
Use seu programa para calcular o fib(5).
O que acontece quando você calcula o fib(30)?
Adicionando e removendo
cláusulas dinamicamente
Um programa prolog pode ser visto como um banco de dados
Relações
Predicados built-in permitem a atualização do programa em
tempo de execução
Adicionar uma nova cláusula
assert, asserta, assertz
Remover uma cláusula
Explícitas: fatos
Implícitas: regras
retract
No XSB módulos com predicados dinâmicos devem ser
carregados com o comando load_dyn/1
Usando assert para tornar o
programa fib eficiente
fib(1, 1).
fib(2, 1).
fib(N, Fn) :N > 2,
M is N - 1,
fib(M, Fm),
O is N - 2,
fib(O, Fo),
Fn is Fm + Fo,
asserta(fib(N, Fn)).
Agora os resultados parciais
são armazenados, não
precisando serem
recalculados.
Teste fib(40, X).
Ferramentas de Debug
trace/0 : ativa o modo de rastreamento.
O sistema interage com o usuário cada vez que um predicado é:
Podem ser observados predicados específicos com o comando
spy(predicado/aridade).
Diferentes ações escolhidas na interação com o debugador:
ativado inicialmente (call)
retorna com sucesso (exit)
vai fazer backtracking (redo)
falhou completamente (fail)
Creep (step), Leap (continuar até próximo spy), Skip (desabilita trace
até o final desta execução), Abort (aborta a execução atual).
notrace/0, nospy/1.
Mais um Exemplo
Vamos definir a função
Se X < 3 então Y = 0
Se 3 X e X < 6 então Y = 2
Se 6 X então Y = 4
Y
4
2
3
6
X
(arquivo funct.P)
f(X, 0) :- X < 3.
f(X, 2) :- 3 =< X, X < 6.
f(X, 4) :- 6 =< X.
Execução do exemplo
Como prolog se comporta quando
fazemos uma consulta?
Vamos acompanhar a execução
de uma consulta ativando o
mecanismo de trace do xsb.
-
•
trace.
Agora façamos a consulta: f(1,
Y), 2 < Y.
f(X, 0) :- X < 3.
f(X, 2) :- 3 =< X, X < 6.
f(X, 4) :- 6 =< X.
(0)
(1)
(1)
(0)
(2)
(2)
(0)
(1)
(1)
(3)
(3)
(4)
(4)
(0)
Call:
Call:
Exit:
Exit:
Call:
Fail:
Redo:
Redo:
Fail:
Call:
Fail:
Call:
Fail:
Fail:
f(1,_h454) ? c
1 < 3 ? c
1 < 3 ? c
f(1,0) ? c
2 < 0 ? c
2 < 0 ? c
f(1,0) ? c
1 < 3 ? c
1 < 3 ? c
3 =< 1 ? c
3 =< 1 ? c
6 =< 1 ? c
6 =< 1 ? c
f(1,_h454) ? c
Diagrama da execução do
exemplo
f(1, Y)
2<Y
Regra 1
Y=0
1<3
2<0
CUT
Regra 3
Y=4
Regra 2
Y=2
3≤1
1<6
2<2
6≤1
2<4
no
no
2 < 0 no
f(X, 0) :- X < 3.
f(X, 2) :- 3 =< X, X < 6.
f(X, 4) :- 6 =< X.
Regras mutuamente
exclusivas
Evitar backtracking inútil: ! (o cut)
op built-in de pruning, logicamente sempre verificado
com efeito colateral de impedir backtracking:
na sua esquerda na cláusula que ocorre
em outras cláusulas com a mesma conclusão
ex: A :- B, C, D.
C :- M, N, !, P, Q.
C :- R.
impede backtracking P -> N
permite backtracking N -> M, Q -> P,
D -> (R xor Q), (P xor R) -> B
R tentado:
unicamente se M ou N falha
nunca se P ou Q falha
Cut: exemplo
Otimizando o exemplo anterior:
f(X, 0) :- X < 3, !.
f(X, 2) :- 3 =< X, X < 6, !.
f(X, 4) :- 6 =< X.
Nesse caso os cuts alteram apenas o comportamento
procedural do programa.
Se removermos os cuts o programa continuará produzindo os
mesmos resultados.
Green cuts
Cut: exemplo (2)
Podemos otimizar ainda mais
o programa, pensando-o da
seguinte forma:
if (X < 3) then Y = 0
else if (X < 6) then Y = 2
else Y = 4
Eliminamos assim 2
comparações desnecessárias.
Versão anterior:
f(X, 0) :- X < 3, !.
f(X, 2) :- 3 =< X,
X < 6, !.
f(X, 4) :- 6 =< X.
Reescrevemos para:
f(X, 0) :- X < 3, !.
f(X, 2) :- X < 6, !.
f(X, 4).
Cut: exemplo(3)
O que acontece agora se os cuts forem removidos?
f(X, 0) :- X < 3.
f(X, 2) :- X < 6.
f(X, 4).
f(1, Y).
Y = 0;
Y = 2;
Y = 4;
Neste caso os cuts afetam a semântica do programa
Red cuts
Hipótese do mundo fechado
Ao contrário da Lógica de 1a ordem, Prolog não permite nem
fatos, nem conclusões de regras negativos:
~animal_lover(geber).
~kill(X,Y) :- animal_lover(X), animal(Y).
Princípio de economia:
declarar e deduzir apenas o que é verdadeiro,
supor que tudo que não é mencionado nem dedutível é falso
(hipótese do mundo fechado)
Operador de negação por falha
Podemos usar o ! para implementar um operador de negação
por falha, tal que:
not p(X) verificado sse p(X) falha
Negação por falha
Uma maneira de definir a negação por falha:
not(P) :- P, !, fail
;
true.
fail é o objetivo que sempre falha, enquanto que true sempre
tem sucesso.
not já é pré-definido (built-in) no interpretador prolog, como
um operador pré-fixo.
- not true.
no
- not fail.
yes
Voltando ao exemplo da família...
Definimos a relação sister(X, Y) como:
sister(X, Y) :- female(X), parent(Z, X), parent(Z, Y).
Vimos que isso também deduz que uma mulher é irmã dela
mesma: logicamente correto pela definição acima.
Podemos usar a negação por falha para alcançar o resultado
desejado.
sister(X, Y) :- female(X), parent(Z, X), parent(Z, Y), not(X = Y).
Exemplo da família
pam
- sister(X, pat).
X = ann;
no
tom
bob
liz
Conforme o comportamento
esperado.
Experimento:
ann
pat
jim
Modifique a relação sister(X,
Y) para
sister(X, Y) :- not(X = Y),
female(X), parent(Z, X),
parent(Z, Y).
Agora consulte:
- sister(X, pat).
O que aconteceu?
Afinal de contas de acordo com a lógica:
a b c d e é equivalente a d a b c e
Negação por falha não tem a mesma semântica da negação
da lógica.
Vamos acompanhar o trace da consulta:
- trace.
- sister(X, pat).
(0) Call: sister(_h446,pat)
(1) Call: not _h446 = pat ?
(1) Fail: not _h446 = pat ?
(0) Fail: sister(_h446,pat)
? c
c
c
? c
O que aconteceu? (2)
Problema com objetivos não instanciados
Quantificação de variáveis diferente na negação por falha
not(X = pat) não é interpretado como “existe X tal que
not(X = pat)”
A quantificação na negação por falha é universal
Para todo X: not(X = pat)?
O que é claramente falso, pois X (não instanciado) unifica-se
perfeitamente com pat
Conclusão: cuidado ao usar cuts e negação por falha.
Prolog: listas
[ e ]: início e fim de lista
, separação entre elementos
|: separação entre 1° elemento (cabeça) e resto da lista (calda)
açúcar sintático para predicado .(Head,Tail)
ex.: [a,[b,c],d] açúcar sintático para .(a,.(.(b,.(c,[])),.(d,[])))
- [a,b,X,p(Y,C)] = [Head|Tail]
Head = a, Tail = [b,X,p(Y,C)]
- [[p(X),[a]],q([b,c])] = [[H|T1]|T2]
H = p(X), T1 = [[a]], T2 = [q([b,c])]
- member(X,[X|_]).
- member(X,[Y|Z]) :- member(X,Z).
- member(b,[a,b,c]) -> yes.
- member(X,[a,b,c]) -> X = a ; X = b ; X = c ; no.
Exemplo: Append
append(L1, L2, L3): L1 e L2 são duas listas e L3 é a sua
concatenação.
Append de uma lista vazia com uma segunda lista é a própria
segunda lista:
append([], L, L).
Append de uma lista [X|L1] com a lista L2 é uma lista [X|L3],
onde L3 é a concatenação da cauda da primeira (L1) com L2.
append([X|L1], L2, [X|L3]) :append(L1, L2, L3).
Exemplo: Append (2)
Exemplos do uso do append
Qual o resultado da concatenação das listas [a, b] e [c, d]?
- append([a,b], [c,d], X).
X = [a, b, c, d]
Que listas concatenadas resultam na lista [a, b, c, d]?
- append(X, Y, [a, b, c, d]).
X = []
Y = [a,b,c,d];
X = [a]
Y = [b,c,d];
…
Exercícios 3
Usando o append, escreva uma regra para apagar os três
últimos elementos de uma lista L, produzindo uma lista L1
(arquivo append.P)
Defina a relação last(Item, List) de forma que Item é o último
elemento de List de duas formas diferentes:
usando append
sem usar append
Prolog x prog. imperativa
Interativo:
compilação transparente integrada na interpretação
rodar programa = consultar um BD
Gerenciamento automático da memória
Mecanismo único de manipulação de dados -- unificação de
termos lógicos -- implementando:
atribuição de valor
passagem de parâmetros
alocação de estruturas
leitura e escrita em campos de estruturas
Prolog x prog. imperativa (2)
Estrutura de dados única: termo Prolog
variáveis lógicas sem tipo estático (tipos dinâmicos)
Controle implícito built-in na estratégia de resolução, ex: Em
programação imperativa
procedure c(E)
const e0:tipoE0;
var E:tipoE, S0:tipoS0, l1:tipo-I1, S1:tipoS1;
do if E = e0 then do S0 := call p0(e0); return S0; end;
else do I1 := call p1(E); S1 := call p2(E,l1); return S1; end;
end;
Em Prolog
c(e0,S0) :- p0(e0,S0).
c(E,S1) :- p1(E,I1), p2(E,I1,S1).
Prolog x prog. funcional
Matematicamente, predicado = relação:
não-determinismo:
bi-direcionalidade:
respostas múltiplas (disponíveis por backtracking),
unificação e busca built-in,
livra o programador da implementação do controle;
cada argumento pode ser entrada ou saída, dependendo do
contexto de chamada,
única definição para usos diferentes: verificador, instanciador,
resolvedor de restrições, enumerador.
integração imediata com BD relacional
Prolog x prog. funcional (2)
Append em Haskell:
append [] L = L
append H:T L = H : append T L
?- append([a,b],[c,d])
[a,b,c,d]
Append em Prolog:
append([],L,L).
append([H|T1],L,[H|T2]) :- append(T1,L,T2).
?- append([a,b],[c,d],R).
R = [a,b,c,d].
Append relacional codifica várias funções
Vários usos do mesmo predicado
verificador:
?- append([a,b],[c],[a,b,c]). -> yes.
?- append([a,b],[c],[a]). -> no.
instanciador:
?- append([a,b],[c],R). -> R = [a,b,c].
?- append(H,[c],[a,b,c]). -> H = [a,b].
resolvedor de restrições:
?- append(X,Y,[a,b,c]). -> X = [], Y = [a,b,c]
; -> X = [a], Y = [b,c] ...
enumerador:
?- append(X,Y,Z). -> X = [], Y =[], Z = []
; -> X = [_], Y = [], Z = [_] ...
Prolog x programação OO
Funcionalidades built-in:
+ unificação e busca
- tipos, herança e encapsulamento
Ontologicamente:
Entidade Atômica (EA): em OO, valor de tipo built-in
em Prolog, átomo (argumento ou predicado)
Entidade Composta (EC): em OO, objeto
em Prolog, fato
Relação simples entre EC e EA: em OO, atributo de tipo built-in
em Prolog, posição em um predicado
Relação simples entre ECs: em OO, atributo de tipo objeto
em Prolog, predicado
Relação complexa entre entidades: em OO, método
em Prolog, conjunto de regras
Prolog x programação OO:
exemplo
Em OO:
pt[subclass_of planobj;
attrs[X inst_of int, Y inst_of int];
mets[right(Pt inst_of pt) {return self.X >= Pt.X}]]
pt1[inst_of pt; attrs[X = 0, Y = 0]]
pt2[inst_of pt; attrs[X = 1, Y =1]]
?- pt1.right(pt2) -> no.
Em Prolog:
pt(0,0).
pt(1,1).
planobj(pt(_,_)).
right(pt(X1,_),pt(X2,_)) :- X1 >= X2.
?- right(pt(0,0),pt(1,1)). -> no.
Programação em Lógica: Disciplina
Eletiva de Graduação e Pós
Prolog aprofundado
Programação por resolução de restrições a base lógica
(Constraint Logic Programming)
extensão de Prolog com resoluções de inequações e equações
restrições quantitativas (N, Z, R, C)
ou qualitativas (tipos, ontologias)
Escalonamento, raciocínio espacial, otimização,
automação industrial, CAD/CAM, música computacional
Programação em lógica funcional
Programação em lógica orientada a objetos
Programação multiparadigma a base lógica:
lógica + restrições + funcional + OO
todo a IA e mais !
Programação em Lógica: Disciplina
Eletiva de Graduação e Pós
Programação em lógica para engenharia de software
Programação em lógica probabilista e bayesiana
raciocínio com incerteza
Programação em lógica indutiva
especificação formal prototipagem rápida
aceleração do modelo de desenvolvimento em espiral
aprendizagem de máquina, agentes adaptativos,
mineração de dados, descoberta de conhecimento em BD,
programação automática, bio-informática
Programação em lógica multiagentes
sistemas inteligentes distribuídos
comercio eletrônico
jogos, competição de futebol de robôs
Programação em Lógica: Disciplina
Eletiva de Graduação e Pós
Bancos de dados dedutivos:
Bancos de dados dedutivos orientada a objetos
Bancos de dados dedutivos temporais
Bancos de dados de restrições:
GIS, BD espaciais, BD espaço-temporais,
integração de dados e interoperabilidade
Bancos de dados de restrições orientada a objetos
descoberta de conhecimento em BD, sistemas especialistas de
grande porte, servidores de conhecimento ontológico
toda a IA de grande escala e mais !
Bancos de dados probabilistas:
BD de sensores, data warehousing, integração de dados com fontes
não confiáveis ou mutuamente inconsistentes,
Programação em Lógica: Disciplina
Eletiva de Graduação e Pós
Gramáticas lógicas:
Parser e gerador de linguagem built-in em Prolog
Basta desenvolver gramática (i.e., como com lex e yacc)
Mineração da web, extração de informação na Internet, compilação
tradução automática, geração automática de resumos, chatterbots
APIs Prolog/Java e Prolog/XML
sistemas de informação inteligentes distribuídos e heterogêneos a infraestrutura web
integração de dados, interoperabilidade entre sistemas, mediadores, data
warehousing
comercio eletrônico
agentes inteligentes de recuperação, classificação, extração e notificação
de informação na web, na Internet, em Intranet
inteligência na computação pervasiva
toda a IA embutida e mais !
Programação em Lógica:
Disciplina Eletiva de Graduação e
Pós-Graduação
Aplicação fio condutor para ilustração dos conceitos
“By the year 2050, develop a team of fully autonomous humanoid
robots that can win against the human world soccer champion team.”
http://www.robocup.org
Programação em Lógica: Disciplina
Eletiva de Graduação e Pós
Introdução a Prolog
FIM
Exercício 1 - Respostas
mother(X, Y) :- parent(X, Y), female(X).
sister(X, Y) :- female(X), parent(Z, X), parent(Z, Y).
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
aunt(X, Y) :- sister(X, Z), parent(Z, Y).
Quais são as respostas devolvidas para sister(X, pat). ?
Por que isso ocorre?
Como isso pode ser evitado?
Cenas dos próximos slides...
Exercício 2 - Resposta
fib(1, 1).
fib(2, 1).
fib(N, Fn) :N > 2,
M is N - 1,
fib(M, Fm),
O is N - 2,
fib(O, Fo),
Fn is Fm + Fo.
O programa tem
comportamento exponencial,
para cada passo calculamos
toda a seqüência de fibonacci.
Os mesmos valores são
calculados várias vezes...
Exercícios 3 - Resposta
del3(L, L1) :- append(L1, [_, _, _], L).
last(Item, List) :- append(_, [Item], List).
last2(Item, [Item]).
last2(Item, [_|XL]) :- last2(Item, XL).