Notas de Aula - Prolog

Computadores servem para fazer as coisas mais rápido. Se você tem a descrição de um procedimento, pode dá-la ao computador. Para isso é necessária uma linguagem. Entre tantas outras disponíveis, Prolog é uma das mais interessantes e será o assunto destas notas.

Comparada com uma linguagem procedural típica como Pascal, Prolog é bem diferente. Em Pascal temos:

entrada -----> programa ----> saída

Em Prolog:

pergunta ----> mundo -----> resposta

ou seja, o programa é a descrição de um mundo artificial, inventado pelo programador. Sobre este mundo são feitas perguntas (a "entrada" do programa) e suas respostas são a saída.

Prolog trabalha com a noção de "mundo fechado", ou seja, tudo o que não for descrito como verdadeiro é considerado falso. Não existe o "não sei", que tanto sucesso trouxe a Sócrates. Por exemplo:

mundo: ama(pedro,sara).

pergunta: ?- ama(pedro,sara).
resposta: Yes

pergunta: ?- ama(pedro,maria).
resposta: No

No mundo diz-se apenas que Pedro ama Sara (com iniciais minúsculas pois são constantes; veremos isto mais tarde). Portanto, Pedro não ama Maria, nem ninguém além de Sara.
 

Sintaxe


O mundo é descrito através de fatos e regras. É preciso conhecer a sintaxe destas cláusulas, e também das perguntas, para poder programar em Prolog.
 

Constantes e Variáveis


Em Prolog, os identificadores são formados por letras, dígitos e sublinhado (underscore, em inglês: o caractere "_"), e tem que começar com letra ou sublinhado. Os identificadores que têm inicial minúscula representam constantes. Aqueles com inicial maiúscula são variáveis. Os que se iniciam com sublinhado são variáveis anônimas.

Exemplo de constantes: casa, maria, pedro, comer.

Exemplo de variáveis: X, Valor, Casa_propria, Tail, _ignore.
 

Fatos e Regras


A descrição do mundo em Prolog se faz através de fatos e regras. Mas antes vamos falar de termos.

gosta(pedro,sara)
    |             \       \
predicado argumentos

Um termo é formado por um funtor (constante) e por uma lista de argumentos separados por vírgula e envoltos em parêntesis. Embora os argumentos possam ser constantes ou variáveis, o funtor é sempre constante. Um fato é um termo seguido de ponto final.

Exemplo: gosta(pedro,sara).

Uma regra possui cabeça e cauda separadas pelo sinal ":-" que significa "if", e termina em ponto final. A cabeça é um termo, e a cauda é uma conjunção de termos, ou seja, uma lista de termos separados por vírgula, que significa "and" no sentido lógico.

Exemplo: gosta(pedro,X) :- bonita(X), alegre(X).

Esta cláusula significa que Pedro gosta de todos os objetos X tais que X é bonita e X é alegre. Em outras palavras, Pedro gosta de X "se" X é bonita e X é alegre.

Fatos e regras são cláusulas. O escopo de uma variável se limita à cláusula onde ela se encontra. Assim, as três ocorrências de X acima se referem à mesma variável, mas as duas ocorrências de X abaixo são variáveis diferentes:

gosta(pedro,X).
ama(jorge,X).
 

Perguntas


Prolog é uma linguagem interpretada e seu interpretador usa como prompt o sinal "?-". Uma pergunta tem a mesma sintaxe da cauda de uma regra. Ao receber uma pergunta, Prolog trata cada um dos termos dela como metas a serem verificadas contra o banco de dados (descrição do mundo). Se a meta casa com um fato, ela é tida como verdadeira. Dizemos que a meta foi satisfeita. Se a meta casa com a cabeça de uma regra, ela produz sub-metas para cada termo da cauda da regra. Se uma meta não casa com nenhum fato nem com a cabeça de nenhuma regra, ela falha, ou seja, é considerada falsa. A falha de uma meta desencadeia o backtracking.

Casamentos podem levar à instanciação de variáveis. Na verdade, este e' o único meio de "atribuir" valores a variáveis em Prolog.
 

Backtracking


Cada meta possui seu próprio ponteiro ao banco de dados no caso de uma busca. A ordem das cláusulas no banco é importante, pois é nesta ordem que elas são testadas para cada meta. Se uma meta A falha, a resposta dada por Prolog é "No", a não ser que a meta tenha uma meta anterior a ela numa conjunção. Neste caso ocorre uma tentativa de re-satisfação da meta anterior: seu casamento corrente é desfeito (inclusive com desinstanciação de variáveis) e seu ponteiro no banco de dados é avançado em busca de outros casamentos. Se encontrados, a meta A é tentada novamente e assim por diante., num vai-e-vem de satisfação, falha e re-satisfação, até que a pergunta que deu origem a tudo tenha todas as metas satisfeitas ou falhe.
 

Corte


O corte (!) é um predicado pré-definido, meta-lógico, sem argumentos e que sempre é satisfeito, mas nunca é re-satisfeito. Além disso, se for feita uma tentativa de re-satisfação do corte, ele não apenas falha como também causa a falha incondicional da meta-mãe (a meta que casou com a cabeça da regra onde está o corte).

O corte é usado para implementar negação (em combinação com o predicado pré-definido fail) ou por questões de eficiência.
 

Aritmética


Prolog possui os predicados pré-definidos +, -, *, /, mas um termo como +(2,3) (que pode também ser escrito em notação infixa: 2 + 3) não é muito diferente de termos como gosta(pedro, sara). Para "executar" a operação aritmética é preciso usar o predicado pré-definido is:

X is 2 + 3

Observe o comportamento de Prolog para a pergunta

?- X = 2 + 3.
X = +(2,3)

e agora para

?- X is 2 + 3.
X = 5

Como se vê, é necessário um is para efetuar a operação. O predicado is requer que no seu lado direito haja uma expressão aritmética válida e com todos os argumentos possuindo valores numéricos. Isso inclui as variáveis, que devem estar instanciadas com valores numéricos.
 

Listas, estruturas, unificação


Ainda falta escrever...
 

Notas feitas `as pressas por J. Meidanis, Dez/2000.