Inteligência Artificial  
Aula 08 Introdução ao Prolog  
Edirlei Soares de Lima  
<edirlei@iprj.uerj.br>  
Introdução  
O Prolog é uma linguagem de programação baseada  
em lógica de primeira ordem.  
Não é padronizada.  
Algumas implementações: SICStus Prolog, Borland  
Turbo Prolog, SWI-Prolog...  
Geralmente é interpretado, mas pode ser compilado.  
Prolog x Outras Linguagens  
Linguagens Procedimentais (C, Pascal, Basic...):  
Especifica-se como realizar determinada tarefa.  
Linguagens Orientadas a Objetos (C++, Java, C#...):  
Especifica-se objetos e seus métodos.  
Prolog: Especifica-se o quê se sabe sobre um  
problema e o quê deve ser feito. É mais direcionada  
ao conhecimento e menos direcionada a algoritmos.  
Programação em Prolog  
Programar em Prolog envolve:  
Declarar alguns fatos a respeito de objetos e seus  
relacionamentos.  
Definir algumas regras sobre os objetos e seus  
relacionamentos.  
Fazer perguntas sobre os objetos e seus  
relacionamentos.  
SWI-Prolog  
Open Source.  
Multiplataforma.  
Possui interface com as linguagens C e C++.  
www.swi-prolog.org  
SWI-Prolog - Interface  
Sentenças Prolog  
Nomes de constantes e predicados iniciam sempre com letra  
minúscula.  
O predicado (relação unária, n-ária ou função) é escrito  
primeiro e os objetos relacionados são escritos depois entre  
parênteses.  
Variáveis sempre começam por letra maiúscula.  
Toda sentença termina com ponto “.”  
Exemplo: gosta(maria, jose).  
Operadores Lógicos  
Símbolo  
Conectivo  
Operação Lógica  
:
-
IF  
Implicação  
Conjunção  
Disjunção  
Negação  
,
AND  
OR  
;
not  
NOT  
Operadores Relacionais  
Operador  
X = Y  
Significado  
Igual a  
X \= Y  
X < Y  
Não igual a  
Menor que  
Y > X  
Maior que  
Y =< X  
Y >= X  
Menor ou igual a  
Maior ou igual a  
Regras  
Regras são utilizadas para expressar dependência entre um  
fato e outro fato:  
criança(X) :- gosta(X,sorvete).  
criança(X) :- not odeia(X,sorvete).  
Ou grupo de fatos:  
avó(X,Z) :- (mãe(X,Y),mãe(Y,Z)); (mãe(X,Y),pai(Y,Z)).  
Podem conter listas:  
compra(ana, [roupa, comida, brinquedo])  
Definindo Relações por Fatos  
Exemplo de relações familiares:  
O fato que Abraão é um progenitor de  
Isaque pode ser escrito em Prolog como:  
progenitor(abraão, isaque).  
Neste caso definiu-se progenitor como o  
nome de uma relação; abraão e isaque  
são seus argumentos.  
Definindo Relações por Fatos  
Árvore familiar completa em Prolog:  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
Cada cláusula declara um fato sobre a  
relação progenitor.  
Definindo Relações por Fatos  
Quando o programa é interpretado,  
pode-se questionar o Prolog sobre a  
relação progenitor, por exemplo:  
Isaque é o pai de Jacó?  
?- progenitor(isaque,jacó).  
Como o Prolog encontra essa  
pergunta como um fato inserido em  
sua base, ele responde:  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
true  
Definindo Relações por Fatos  
Uma outra pergunta pode ser:  
?- progenitor(ismael,jacó).  
O Prolog responde:  
false  
O Prolog também pode responder a pergunta:  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
?
- progenitor(jacó,moisés).  
false  
Definindo Relações por Fatos  
Perguntas mais interessantes também podem  
ser efetuadas:  
Quem é o progenitor de Ismael?  
?- progenitor(X,ismael).  
Neste caso, o Prolog não vai responder  
apenas true ou false. O Prolog fornecerá o  
valor de X tal que a pergunta acima seja  
verdadeira‰. Assim a resposta é:  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
X = abraão  
Definindo Relações por Fatos  
A pergunta “Quais os filhos de Isaque?” pode  
ser escrita como:  
?
- progenitor(isaque,X).  
Neste caso, mais de uma resposta  
possível. O Prolog primeiro responde com  
uma solução:  
X = esaú  
Pode-se requisitar uma outra solução  
digitando ;) e o Prolog a encontra:  
(
X = jacó  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
Se mais soluções forem requisitadas, o Prolog  
ira responder “false”, pois todas as soluções  
foram retornadas (false = sem mais soluções).  
Definindo Relações por Fatos  
Perguntas mais complexas também podem ser  
efetuadas, tais como: Quem é o avô de José?  
Como o programa não conhece diretamente a  
relação avô, esta pergunta deve ser desmembrada  
em dois passos  
(1) Quem é o progenitor de José? Assuma que é um Y  
(2) Quem é o progenitor de Y? Assuma que é um X  
Esta pergunta composta pode ser escrita em  
Prolog como:  
?- progenitor(Y,josé), progenitor(X,Y).  
X = isaque  
Y = jacó  
Definindo Relações por Fatos  
De maneira similar, podemos perguntar:  
Quem são os netos de Abraão?  
?- progenitor(abraão,X), progenitor(X,Y).  
X = isaque  
Y = esaú  
X = isaque  
Y = jacó  
progenitor(sara,isaque).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
Definindo Relações por Fatos  
É possível expandir o programa sobre relações familiares de várias formas.  
Pode-se, por exemplo, adicionar a informação sobre o sexo das pessoas  
envolvidas.  
mulher(sara).  
homem(abraão).  
homem(isaque).  
homem(ismael).  
homem(esaú).  
homem(jacó).  
homem(josé).  
Definindo Relações por Regras  
Pode-se estender o programa utilizando  
regras. Por exemplo, criando a relação filho  
como o inverso da relação progenitor.  
É possível definir filho de maneira similar à  
relação progenitor, ou seja enumerando uma  
lista de fatos sobre a relação filho, mas esta  
não é a forma correta!  
filho(isaque,sara).  
progenitor(sara,isaque).  
filho(isaque,abraão).  
filho(ismael,abraão).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
.
..  
Definindo Relações por Regras  
A relação filho pode ser definida de modo  
mais elegante:  
Para todo X e Y, Y é um filho de X se X é um  
progenitor de Y.  
Em Prolog:  
filho(Y,X) :- progenitor(X,Y).  
Definindo Relações por Regras  
A cláusula Prolog filho(Y,X) :- progenitor(X,Y) é  
chamada de regra (rule).  
Há uma diferença importante entre fatos e regras:  
Um fato é sempre verdadeiro (verdade incondicional).  
Regras especificam coisas que são verdadeiras se alguma condição é  
satisfeita.  
Definindo Relações por Regras  
Após definir a regra filho, é possível perguntar ao Prolog se Ismael é filho  
de Abraão:  
?- filho(ismael, abraão).  
Como não existem fatos sobre a relação filho, a única forma do Prolog  
responder esta pergunta é aplicando a regra filho:  
filho(Y,X) :- progenitor(X,Y).  
A regra filho é aplicável a qualquer objeto X e Y; portanto ela pode  
também ser aplicada a objetos ismael e abraão.  
Definindo Relações por Regras  
Para aplicar a regra a ismael e abraão, Y tem que ser substituído por  
ismael e X por abraão. Ou seja, as variáveis X e Y estão instanciadas a:  
X = abraão e Y = ismael  
Depois da instanciação, obtêm-se um caso especial da regra:  
filho(ismael,abraão) :- progenitor(abraão,ismael).  
Se o Prolog provar que progenitor(abraão,ismael) é verdadeiro, então ele  
pode afirmar que filho(ismael,abraão) também é verdade.  
Definindo Relações por Regras  
É possível também incluir a especificação da relação mãe,  
com base no seguinte fundamento lógico:  
Para todo X e Y,  
X é a mãe de Y se  
X é um progenitor de Y e  
X é uma mulher.  
Traduzindo para Prolog:  
mãe(X,Y) :- progenitor(X,Y), mulher(X).  
Definindo Relações por Regras  
A relação irmão pode ser definida como:  
Para todo X e Y,  
X é irmão de Y se  
ambos X e Y têm um progenitor em comum.  
Em Prolog:  
irmão(X,Y) :- progenitor(Z,X), progenitor(Z,Y).  
Interpretação Prolog  
A interpretação do programa pode Prolog ser lógica ou procedimental.  
A interpretação procedimental corresponde a satisfazer cada subgoal  
mediante processos sucessivos de matching.  
Exemplo:  
pai(fred, marcos).  
pai(ricardo, pedro).  
pai(pedro, paulo).  
avo(X,Y) :- pai(X, Z), pai(Z, Y).  
---  
?- avo(X,paulo).  
Programas Prolog  
Programas Prolog podem ser estendidos simplesmente pela  
adição de novas cláusulas.  
Cláusulas Prolog são de três tipos: fatos, regras e perguntas.  
Fatos declaram coisas que são sempre (incondicionalmente)  
verdadeiras.  
Regras declaram coisas que são verdadeiras dependendo de  
determinadas condições.  
Através de perguntas, o usuário pode questionar o programa sobre  
quais coisas são verdadeiras.  
Regras Recursivas  
Para criar uma relação ancestral é necessária a criação de  
uma regra recursiva:  
ancestral(X,Z) :- progenitor(X,Z).  
ancestral(X,Z) :- progenitor(X,Y), ancestral(Y,Z).  
Quais os descendentes de Sara?  
?- ancestral(sara,X).  
X = isaque;  
X = esaú;  
X = jacó;  
X = josé  
Programa Exemplo  
progenitor(sara,isaque).  
filho(Y,X) :- progenitor(X,Y).  
progenitor(abraão,isaque).  
progenitor(abraão,ismael).  
progenitor(isaque,esaú).  
progenitor(isaque,jacó).  
progenitor(jacó,josé).  
mae(X,Y) :- progenitor(X,Y), mulher(X).  
avo(X,Z) :- progenitor(X,Y), progenitor(Y,Z).  
irmao(X,Y) :- progenitor(Z,X), progenitor(Z,Y).  
mulher(sara).  
homem(abraão).  
homem(isaque).  
homem(ismael).  
homem(esaú).  
homem(jacó).  
homem(josé).  
ancestral(X,Z) :- progenitor(X,Z).  
ancestral(X,Z) :- progenitor(X,Y), ancestral(Y,Z).  
Variáveis  
Variáveis são representadas através de cadeias de letras,  
números ou _ sempre começando com letra maiúscula:  
X, Resultado, Objeto3, Lista_Alunos, ListaCompras...  
O escopo de uma variável é valido dentro de uma mesma  
regra ou dentro de uma pergunta.  
Isto significa que se a variável X ocorre em duas regras/perguntas, então são  
duas variáveis distintas.  
A ocorrência de X dentro de uma mesma regra/pergunta significa a mesma  
variável.  
Variáveis  
Uma variável pode estar:  
Instanciada: Quando a variável referencia (está unificada a) algum  
objeto.  
Livre ou não-instanciada: Quando a variável não referencia (não está  
unificada a) um objeto.  
Uma vez instanciada, somente Prolog pode torná-la não-  
instanciada através de seu mecanismo de inferência (nunca o  
programador).  
Variável Anônima  
Variáveis anônimas podem ser utilizadas em sentenças cujo  
valor atribuído a variável não é importante. Por exemplo, a  
regra tem_filho:  
Tem_filho(X) :- progenitor(X,Y).  
Para relação “ter filhos” não é necessário saber o nomes dos  
filhos. Neste vaso utiliza-se uma variável anônima  
representada por “_”.  
Tem_filho(X) :- progenitor(X,_).  
Variável Anônima  
Cada vez que uma variável anônima aparece em uma  
cláusula, ele representa uma nova variável anônima. Por  
exemplo:  
alguém_tem_filho :- progenitor(_,_).  
É equivale à:  
alguém_tem_filho :- progenitor(X,Y).  
Estruturas  
Objetos estruturados são objetos de dados com vários  
componentes.  
Cada componente da estrutura pode ser outra estrutura.  
Por exemplo, uma data pode ser vista como uma estrutura  
com três componentes: dia, mês, ano.  
data(4,maio,2003)  
Estruturas  
Todos os objetos estruturados são representados como  
árvores.  
A raiz da árvore é o funtor e os filhos da raiz são os  
componentes.  
data(4,maio,2003):  
data  
4
maio 2003  
Estruturas  
Um triângulo pode ser representado da seguinte forma:  
triângulo(ponto(2,4), ponto(3,6), ponto(4,2))  
triângulo  
ponto  
2
ponto  
ponto  
4 3  
6 4  
2
Operadores  
Operadores Aritméticos  
Operadores Relacionais  
Adição  
+
X > Y  
X é maior do que Y  
X é menor do que Y  
X é maior ou igual a Y  
X é menor ou igual a Y  
X é igual a Y  
Subtração  
Multiplicação  
Divisão  
-
*
X < Y  
X >= Y  
X =< Y  
X == Y  
X = Y  
/
Divisão Inteira  
Resto da Divisão  
Potência  
//  
Mod  
**  
is  
X unifica com Y  
X \== Y  
X é diferente de Y  
Atribuição  
Operadores  
O operador “=” realiza apenas a unificação de termos:  
?- X = 1 + 2.  
X = 1 + 2  
O operador “isforça a avaliação aritmética:  
?- X is 1 + 2.  
X = 3  
Operadores  
Se a variável à esquerda do operador “is” já estiver  
instanciada, o Prolog apenas compara o valor da variável com  
o resultado da expressão à direita de “is”:  
?- X = 3, X is 1 + 2.  
X = 3  
?- X = 5, X is 1 + 2.  
false  
Unificação de Termos  
Dois termos se unificam (matching) se:  
Eles são idênticos ou‰as variáveis em ambos os termos  
podem ser instanciadas a objetos de maneira que após a  
substituição das variáveis os termos se tornam idênticos.  
Por exemplo, existe a unificação entre os termos‰  
data(D,M,2003) e data(D1,maio,A) instanciando D = D1, M =  
maio, A = 2003.  
Unificação de Termos  
data(D,M,2003) = data(D1,maio,A), data(D,M,2003) = data(15,maio,A1).  
D = 15  
M = maio  
D1 = 15  
A = 2003  
A1 = 2003  
Por outro lado, não existe unificação entre os  
termos:  
data(D,M,2003), data(D1,M1,1948)  
Unificação de Termos  
A unificação é um processo que toma dois termos e  
verifica se eles unificam:  
Se os termos não unificam, o processo falha (e as variáveis não se  
tornam instanciadas).  
Se os termos unificam, o processo tem sucesso e também instancia as  
variáveis em ambos os termos para os valores que os tornam  
idênticos.  
Unificação de Termos  
As regras que regem se dois termos S e T unificam são:  
Se S e T são constantes, então S e T unificam somente se são o mesmo  
objeto.  
Se S for uma variável e T for qualquer termo, então unificam e S é  
instanciado para T.  
Se S e T são estruturas, elas unificam somente se‰:  
S e T têm o mesmo funtor principal.  
Todos seus componentes correspondentes unificam.  
Comparação de Termos  
Operadores Relacionais  
X = Y  
X unifica com Y, é verdadeiro quando dois termos são o  
mesmo. Entretanto, se um dos termos é uma variável, o  
operador = causa a instanciação da variável.  
X \= Y  
X == Y  
X não unifica com Y  
X é literalmente igual a Y (igualdade literal), que é verdadeiro  
se os termos X e Y são idênticos, ou seja, eles têm a mesma  
estrutura e todos os componentes correspondentes são os  
mesmos, incluindo o nome das variáveis.  
X \== Y  
X não é literalmente igual a Y que é o complemento de X==Y  
Comparação de Termos  
?
- f(a,b) == f(a,b).  
true  
?
- f(a,b) == f(a,X).  
false  
?
- f(a,X) == f(a,Y).  
false  
- X == X.  
true  
?
?
- X == Y.  
false  
?
- X \== Y.  
true  
?
- g(X,f(a,Y)) == g(X,f(a,Y)).  
true  
Predicados para Verificação de Tipos de Termos  
Predicado  
var(X)  
Verdadeiro se:  
X é uma variável não instanciada  
X não é uma variável ou X é uma variável instanciada  
X é uma sentença atômica  
X é um inteiro  
nonvar(X)  
atom(X)  
integer(X)  
float(X)  
X é um número real  
atomic(X)  
compound(X)  
X é uma constante  
X é uma estrutura  
Predicados para Verificação de Tipos de Termos  
?
true  
?
true  
?
false  
?
true  
- atomic(3.14).  
?
- var(Z), Z = 2.  
Z = 2  
- Z = 2, var(Z).  
false  
- integer(Z), Z = 2.  
false  
- Z = 2, integer(Z), nonvar(Z).  
Z = 2  
- atom(3.14).  
false  
- atom(==>).  
?
- atom(p(1)).  
?
- compound(2+X).  
?
?
Exemplo: Macaco e as Bananas  
Um macaco encontra-se próximo à porta de uma sala. No meio da sala há  
uma banana pendurada no teto. O macaco tem fome e quer comer a  
banana mas ela está a uma altura fora de seu alcance. Perto da janela da  
sala encontra-se uma caixa que o macaco pode utilizar para alcançar a  
banana. O macaco pode realizar as seguintes ações:  
Caminhar no chão da sala;  
Subir na caixa (se estiver ao lado da caixa);  
Empurrar a caixa pelo chão da sala (se estiver ao lado da caixa);  
Pegar a banana (se estiver parado sobre a caixa diretamente embaixo da banana).  
Exemplo: Macaco e as Bananas  
É conveniente combinar essas 4 informações em uma estrutura de  
estado:  
estado  
na_porta  
no_piso  
na_janela  
não_tem  
O estado inicial é determinado pela posição dos objetos.  
O estado final é qualquer estado onde o último componente da  
estrutura é “tem”:  
estado(_,_,_,tem)  
Exemplo: Macaco e as Bananas  
Possíveis valores para os argumentos da estrutura estado:  
1º argumento (posição do macaco):  
na_porta, no_centro, na_janela  
2º argumento (posição vertical do macaco):  
no_chão, acima_caixa  
3º argumento (posição da caixa):  
na_porta, no_centro, na_janela  
4º argumento (macaco tem ou não tem banana): tem,  
não_tem  
Exemplo: Macaco e as Bananas  
Movimentos permitidos que alteram o mundo de um estado  
para outro:  
Pegar a banana;  
Subir na caixa;  
Empurrar a caixa;  
Caminhar no chão da sala;  
Nem todos os movimentos são possíveis em cada estado do  
mundo. Por exemplo, “pegar a banana” somente é possível se  
o macaco estiver em cima da caixa, diretamente em baixo da  
banana e o macaco ainda não possuir a banana.  
Exemplo: Macaco e as Bananas  
Formalizando o problema em Prolog é possível estabelecer a  
seguinte relação:  
move(Estado1,Movimento,Estado2)  
Onde:  
Estado1 é o estado antes do movimento (pré-condição);  
Movimento é o movimento executado;  
Estado2 é o estado após o movimento (efeito);  
Exemplo: Macaco e as Bananas  
O movimento “pegar a banana” pode ser definido por:  
move(  
estado(no_centro, acima_caixa, no_centro, não_tem),  
pegar_banana,  
estado(no_centro, acima_caixa, no_centro, tem)  
)
.
Este fato diz que após o movimento “pegar_banana” o  
macaco tem a banana e ele permanece em cima da caixa no  
meio da sala.  
Exemplo: Macaco e as Bananas  
Também é necessário expressar o fato que o macaco no chão pode  
caminhar de qualquer posição “Pos1” para qualquer posição “Pos2”:  
move(  
estado(Pos1, no_chão, Caixa, Banana),  
caminhar(Pos1,Pos2),  
estado(Pos2, no_chão, Caixa, Banana)  
).  
De maneira similar, é possível especificar os movimentos “empurrar” e  
“subir”.  
Exemplo: Macaco e as Bananas  
A pergunta principal que o programa deve responder  
é:  
O macaco consegue, a partir de um estado inicial,  
pegar as bananas?  
Exemplo: Macaco e as Bananas  
Para isso é necessário formular duas regras que definam quando o estado  
final é alcançável:  
Para qualquer estado no qual o macaco já tem a banana, o predicado  
“consegue” certamente deve ser verdadeiro e nenhum movimento é  
necessário:  
consegue(estado(_,_,_,tem)).  
Nos demais casos, um ou mais movimentos são necessários; o macaco pode  
obter a banana em qualquer estado “Estado1” se existe algum movimento de  
banana no “Estado2”:  
Estado1” para algum estado “Estado2” tal que o macaco consegue pegar a  
consegue(Estado1) :- move(Estado1, Movimento, Estado2),  
consegue(Estado2).  
Exemplo: Macaco e as Bananas  
move(  
estado(no_centro, acima_caixa, no_centro, não_tem),  
pegar_banana,  
estado(no_centro, acima_caixa, no_centro,tem)  
).  
move(  
estado(P, no_chão, P, Banana),  
subir,  
estado(P, acima_caixa, P, Banana)  
).  
move(  
estado(P1, no_chão, P1, Banana),  
empurrar(P1, P2),  
estado(P2, no_chão, P2, Banana)  
).  
move(  
estado(P1, no_chão, Caixa, Banana),  
caminhar(P1, P2),  
estado(P2, no_chão, Caixa, Banana)  
).  
consegue(estado(_, _, _, tem)).  
consegue(Estado1) :- move(Estado1, Movimento, Estado2), consegue(Estado2).  
Exemplo: Macaco e as Bananas  
?- consegue(estado(na_porta, no_chão, na_janela, não_tem)).  
estado(na_porta, no_chão, na_janela, não_tem)  
caminhar(na_porta,P2)  
estado(P2, no_chão, na_janela, não_tem)  
empurrar(P2,P2’)  
subir  
backtrack  
estado(na_janela, acima_caixa, na_janela, não_tem)  
estado(P2’, no_chão, P2’, não_tem)  
subir  
estado(P2’, acima_caixa, P2’, não_tem)  
Pegar_banana  
P2’=no_centro  
estado(no_centro,acima_caixa,no_centro,tem)  
Listas  
Lista é uma das estruturas mais simples em Prolog e  
pode ser aplicada em diversas situações.  
Uma lista pode ter qualquer comprimento.  
Uma lista contendo os elementos “ana”, “tênis” e  
pedro” pode ser escrita em Prolog como:  
[
ana, tênis, pedro]  
Listas  
O uso de colchetes é apenas uma melhoria da notação, pois  
internamente listas são representadas como árvores, assim  
como todos objetos estruturados em Prolog.  
Internamente o exemplo [ana, tênis, pedro] é representando  
da seguinte maneira:  
.
ana  
tênis  
pedro  
.
.(ana, .(tênis, .(pedro, []) ) )  
.
[
]
Listas  
?- Lista1 = [a,b,c], Lista2 = .(a,.(b,.(c,[]))).  
Lista1 = [a, b, c]  
Lista2 = [a, b, c]  
?
- Hobbies1 = .(tênis, .(música,[])), Hobbies2 = [esqui, comida], L =  
[ana,Hobbies1,pedro,Hobbies2].  
Hobbies1 = [tênis,música]  
Hobbies2 = [esqui,comida]  
L = [ana, [tênis,música], pedro, [esqui,comida]]  
Listas  
Para entender a representação de listas do Prolog, é  
necessário considerar dois casos:  
Lista vazia [].  
E lista não vazia, onde:  
O primeiro item é chamado de cabeça (head) da lista.  
A parte restante da lista é chamada cauda (tail).  
No exemplo [ana, tênis, pedro]:  
ana é a Cabeça da lista.  
[tênis, pedro] é a Cauda da lista.  
Listas  
Em geral, é comum tratar a cauda como um objeto simples.  
Por exemplo, L = [a,b,c] pode ser escrito como:  
Cauda = [b,c]  
L = [a, Cauda]  
O Prolog também fornece uma notação alternativa para  
separar a cabeça da cauda de uma lista, a barra vertical:  
L = [a | Cauda]  
Operações em Listas - Busca  
Frequentemente existe a necessidade de se realizar  
operações em listas, por exemplo, buscar um  
elemento que faz parte de uma lista.  
Para verificar se um nome está na lista, é preciso  
verificar se ele está na cabeça ou se ele está na cauda  
da lista.  
Operações em Listas - Busca  
A primeira regra para verificar se um elemento X pertence à  
lista é verificar se ele se encontra na cabeça da lista. Isto  
pode ser especificado da seguinte maneira:  
pertence(X,[X|Z]).  
A segunda condição deve verificar se o elemento X pertence  
à cauda da lista. Esta regra pode ser especificada da seguinte  
maneira:  
pertence(X,[W|Z]) :- pertence(X,Z).  
Operações em Listas - Busca  
O programa para buscar por um item em uma lista pode ser  
escrito da seguinte maneira:  
pertence(Elemento,[Elemento|Cauda]).‰  
pertence(Elemento,[Cabeca|Cauda]) :- pertence(Elemento,Cauda).  
Após a definição do programa, é possível interrogá-lo.  
?
- pertence(a,[a,b,c]).  
true  
Operações em Listas - Busca  
?
- pertence(d,[a,b,c]).  
false  
?
- pertence(X,[a,b,c]).  
X = a ;  
X = b ;  
X = c ;  
false  
E se as perguntas forem:  
?
?
- pertence(a,X).  
- pertence(X,Y).  
Existem infinitas respostas.  
Operações em Listas Último Elemento  
O último elemento de uma lista que tenha somente um elemento é o  
próprio elemento:  
ultimo(Elemento, [Elemento]).  
O último elemento de uma lista que tenha mais de um elemento é o  
ultimo elemento da cauda:  
ultimo(Elemento, [Cabeca|Cauda]) :- ultimo(Elemento, Cauda).  
Programa completo:  
ultimo(Elemento, [Elemento]).  
ultimo(Elemento, [Cabeca|Cauda]) :- ultimo(Elemento, Cauda).  
Exemplo: Macaco e as Bananas  
move(  
estado(no_centro, acima_caixa, no_centro, não_tem),  
pegar_banana,  
estado(no_centro,acima_caixa,no_centro,tem)  
).  
move(  
estado(P,no_chão,P,Banana),  
subir,  
estado(P,acima_caixa,P,Banana)  
).  
move(  
estado(P1,no_chão,P1,Banana),  
empurrar(P1,P2),  
estado(P2,no_chão,P2,Banana)  
).  
move(  
estado(P1,no_chão,Caixa,Banana),  
caminhar(P1,P2),  
estado(P2,no_chão,Caixa,Banana)  
).  
consegue(estado(_,_,_,tem),[]).  
consegue(Estado1,[Movimento|Resto]) :- move(Estado1,Movimento,Estado2), consegue(Estado2,Resto).  
Adicionando Novos Fatos a Base de  
Conhecimento  
O predicado assert é utilizado pelo Prolog para adicionar  
novas sentenças na base de conhecimento.  
Exemplos:  
assert(homem(joao)).  
assert(filho(Y,X) :- progenitor(X,Y)).  
Adicionando Novos Fatos a Base de  
Conhecimento  
O predicado assert permite adicionar fatos e regras a base de  
conhecimento.  
Normalmente, o SWI-Prolog compila o código de forma que não é possível  
modificar fatos durante a execução do programa.  
Para indicar ao Prolog que determinada sentença pode ser modificado  
durante a execução do programa é possível utilizar o predicado dynamic.  
Exemplo:  
:- dynamic homem/1.  
Removendo Fatos da Base de  
Conhecimento  
Também é possível remover fatos e regras da base  
de conhecimento utilizando o predicado retract.  
Funciona de forma similar ao assert.  
Exemplos:  
retract(homem(joao)).  
retract(filho(Y,X) :- progenitor(X,Y)).  
Predicados do SWI-Prolog  
O SWI-Prolog inclui diversas sentenças predefinidas para para  
diversos usos, como por exemplo:  
Manipulação de listas;  
Comparação de tipos de dados;  
Leitura e escrita de dados em arquivos;  
Entrada e saída de dados pelo console;  
Manipulação de arquivos;  
Execução de comandos no sistema operacional;  
Entre outros.  
http://www.swi-prolog.org/pldoc/refman/  
Utilizando o SWI-Prolog em C++ e Java  
Download:  
http://www.swi-prolog.org/download/stable  
Configuração - Windows  
Control Panel -> System ->Advanced-> Environment Variables  
Adicionar o diretório “C:\Program Files (x86)\swipl\bin” a variável “PATH” do  
sistema.  
Configuração - Visual Studio  
Include Directory: “C:\Program Files (x86)\swipl\include”  
Configuração - Visual Studio  
Library Directory: “C:\Program Files (x86)\swipl\lib”  
Configuração Visual Studio  
Dependência: libswipl.dll.a  
Exemplo de Programa Prolog  
progenitor(sara,isaque).  
progenitor(abraao,isaque).  
progenitor(abraao,ismael).  
progenitor(isaque,esau).  
progenitor(isaque,jaco).  
progenitor(jaco,jose).  
mulher(sara).  
homem(abraao).  
homem(isaque).  
homem(ismael).  
homem(esau).  
homem(jaco).  
homem(jose).  
filho(Y,X) :- progenitor(X,Y).  
mae(X,Y) :- progenitor(X,Y), mulher(X).  
avo(X,Z) :- progenitor(X,Y), progenitor(Y,Z).  
irmao(X,Y) :- progenitor(Z,X), progenitor(Z,Y).  
ancestral(X,Z) :- progenitor(X,Z).  
ancestral(X,Z) :- progenitor(X,Y), ancestral(Y,Z).  
Exemplo de Programa em C++  
#
#
include <SWI-cpp.h>  
include <iostream>  
using namespace std;  
int main(){  
char* argv[] = {"swipl.dll", "-s", "D:\\teste.pl", NULL};  
_
putenv("SWI_HOME_DIR=C:\\Program Files (x86)\\swipl");  
PlEngine e(3,argv);  
PlTermv av(2);  
av[1] = PlCompound("jose");  
PlQuery q("ancestral", av);  
while (q.next_solution())  
{
cout << (char*)av[0] << endl;  
}
cin.get();  
return 1;  
}
Configuração - Eclipse  
Build Path -> Configure Build Path -> Libraries  
Add External JARs: “C:\Program Files (x86)\swipl\lib\jpl.jar”  
Exemplo de Programa em Java  
import jpl.*;  
import java.lang.System;  
import java.util.Hashtable;  
public class Main  
{
public static void main(String[] args)  
{
Query q1 = new Query("consult", new Term[] {new Atom("D:\\teste.pl")});  
System.out.println("consult " + (q1.query() ? "succeeded" : "failed"));  
Query q2 = new Query("ancestral(X, jose)");  
Hashtable[] solution = q2.allSolutions();  
if (solution != null)  
{
for (int i = 0; i < solution.length; i++)  
System.out.println("X = " + solution[i].get("X"));  
}
}
}
Manual  
http://www.swi-prolog.org/pldoc/index.html  
Bibliografia Complementar  
Bratko, I., “Prolog Programming for Artificial  
Intelligence(3rd edition), Addison Wesley, 2000.  
Clocksin, W.F., Mellish, C.S.,Programming in  
Prolog” (5th edition), Springer, 2003.  
Sterling, L., Shapiro, E.,The Art of Prolog (2th  
edition), MIT Press, 1994.