Escolar Documentos
Profissional Documentos
Cultura Documentos
progenitor(tom,liz).
progenitor(bob,ann).
progenitor(bob,pat).
progenitor(pat,jim).
?- progenitor(Y,jim),
progenitor(X,Y).
progenitor de Y.
A DEFINIÇÃO DE UMA REGRA RECURSIVA
Vamos adicionar mais uma relação ao programa da
família: a relação ancestral.
Esta relação será definida em termos da relação
progenitor.
Com duas regras a tarefa estará cumprida:
A primeira regra definirá o ancestral direto (imediato), e
A segunda regra definirá o ancestral indireto.
Dizemos que algum X é um ancestral indireto de algum
Z se houver uma cadeia de parentesco entre Z e X.
A DEFINIÇÃO DE UMA REGRA RECURSIVA
A primeira regra é simples: Para todo
X e Z, X é um ancestral de Z se X é
um progenitor de Z.
A segunda regra é mais complicada:
qual o tamanho da cadeia de
parentesco que teremos que
implementar?
Para todo X e Z, X é um ancestral de Z
se Y2 é progenitor de Z e Y1 é um
progenitor de Y2 e X é progenitor de
Y1. ou ... ???
Quais os problemas dessa
implementação??
A DEFINIÇÃO DE UMA REGRA RECURSIVA
Há uma maneira mais elegante de
resolver o problema: a idéia chave
é definir a relação ancestral em
termos dela mesma.
Para todo X e Z, X é um ancestral
de Z se há um Y tal que (1) X é
progenitor de Y e (2) Y é ancestral
de Z.
ancestral(X,Z) :- progenitor(X,Y),
ancestral(Y,Z).
COMO PROLOG RESPONDE QUESTÕES
Uma questão em Prolog é sempre uma sequência
de uma ou mais metas.
Prolog tenta satisfazer todas as metas. Mas, o que
é satisfazer uma meta?
Satisfazer uma meta significa demonstrar que a meta
é verdadeira, assumindo que as relações no programa
são verdadeiras.
Satisfazer uma meta significa demonstrar que a meta
decorre logicamente dos fatos e regras do programa.
COMO PROLOG RESPONDE QUESTÕES
Prolog também tem que encontrar quais são os objetos particulares
(no lugar das variáveis) para os quais as metas são satisfeitas.
A instanciação particular de variáveis a esses objetos é mostrada
ao usuário.
Se o Prolog não pode demonstrar para alguma instanciação de
variáveis que as metas decorrem logicamente do programa, então o
Prolog responde “false”.
Em termos matemáticos: Prolog aceita fatos e regras como um
conjunto de axiomas, e a questão do usuário como um teorema
conjeturado; então tenta provar o teorema – isto é: demonstrar que
ele pode ser logicamente derivado dos axiomas.
COMO PROLOG RESPONDE QUESTÕES
E se o teorema a ser provado fosse:
?- ancestral(tom, pat).
Sabemos que progenitor(bob,pat) é um fato.
Usando esse fato e a regra pr1 podemos concluir
ancestral(bob,pat). Esse é um fato derivado, não pode ser
encontrado explicitamente no nosso programa.
Um passo de inferência como esse pode ser escrito de uma
forma mais compacta:
progenitor(bob,pat) ==> ancestral(bob,pat)
Isso pode ser lido: de progenitor(bob,pat) segue-se ancestral(bob,pat)
pela regra pr1.
COMO PROLOG RESPONDE QUESTÕES
Sabemos também que progenitor(tom,bob) é um fato.
Usando esse fato e o fato derivado ancestral(bob,pat)
podemos concluir ancestral(tom,pat) pela regra pr2.
Assim, demonstramos que nossa declaração meta
ancestral(tom,pat) é verdadeira.
O processo todo de inferência pode ser escrito como:
progenitor(bob,pat) ==> ancestral(bob,pat)
progenitor(tom,bob) e ancestral(bob,pat) ==>
ancestral(tom,pat)
Mas, como o Prolog realiza essa prova?
COMO PROLOG RESPONDE QUESTÕES
Prolog encontra a sequência de prova na ordem inversa da que nós
usamos.
Prolog começa com as metas e, utilizando as regras, substitui a meta
corrente por novas metas até que as novas metas se tornem fatos
simples.
Dado a questão: ?- ancestral(tom,pat). Prolog vai tentar satisfazer essa
meta.
Primeiro procura uma cláusula no programa da qual a meta acima
decorra imediatamente. As únicas cláusulas relevantes são pr1 e pr2.
Essas duas cláusulas representam dois caminhos alternativos para o
Prolog prosseguir. Dizemos que as cabeças dessas regras casam com a
meta.
COMO PROLOG RESPONDE QUESTÕES
Prolog tenta a primeira cláusula casada que encontra:
Ancestral(X,Z) :- progenitor(X,Z).
Uma vez que a meta é ancestral(tom,pat) as variáveis são instanciadas:
X = tom e Z = pat.
A meta original agora é substituída pela nova meta do corpo de pr1:
progenitor(tom,pat).
Não há clausula no programa cuja cabeça case com essa nova meta, que
ancestral(X,Y) :- progenitor(X,Y).
ancestral(X,Y) :- progenitor(X,Z),
ancestral(Z,Y).
SIGNIFICADOS DECLARATIVOS E PROCEDURAL DE
PROGRAMAS