Fatos são a base do conhecimento em Prolog, mas eles sozinhos são limitados. Se precisássemos declarar cada relação manualmente — como “avô”, “bisavô”, “irmão” — nossa base de conhecimento seria imensa e repetitiva. Regras são a solução: elas nos permitem derivar novos conhecimentos a partir dos fatos existentes. Neste artigo, vamos aprender como criar regras e transformar uma simples árvore genealógica em um sistema poderoso de consultas.
1. O que são regras e por que são essenciais?
Uma regra em Prolog é uma afirmação condicional: “X é verdadeiro se Y e Z forem verdadeiros”. Enquanto fatos são verdades absolutas, regras são verdades dependentes — elas só são verdadeiras quando suas condições são satisfeitas.
🧠 Analogia: Se os fatos são como “Adão é pai de Seth” e “Seth é pai de Enos”, as regras são como “Alguém é avô se for pai do pai de alguém”. As regras capturam o conhecimento geral, não apenas casos específicos.
As regras são essenciais porque permitem:
- Evitar repetição: Não precisamos declarar cada avô explicitamente.
- Generalização: A regra funciona para qualquer pessoa na árvore.
- Manutenção: Se adicionarmos novos fatos, as regras funcionam automaticamente.
- Abstração: Expressamos conceitos de alto nível (avô, irmão) em termos de conceitos mais básicos (pai).
2. Sintaxe: cabeça e corpo
A estrutura básica de uma regra é:
- Cabeça: É o predicado que estamos definindo (ex:
avo(X, Y)).
:-: Lê-se “se” ou “se … então”.
- Corpo: Uma conjunção de objetivos (fatos ou regras) que devem ser verdadeiros para que a cabeça seja verdadeira.
📝 Atenção: A regra termina com ponto final (.), assim como os fatos. A cabeça e o corpo podem ter variáveis que serão compartilhadas.
3. Exemplo clássico: a relação “avô”
A definição de “avô” em Prolog é elegantemente simples:
|
|
avo(X, Y) :- pai(X, Z), pai(Z, Y). |
Interpretação: X é avô de Y se X é pai de Z e Z é pai de Y. A variável Z é compartilhada entre os dois objetivos, representando o pai intermediário (a “ponte” entre avô e neto).
📖 Leitura lógica: “X é avô de Y se existe uma pessoa Z tal que X é pai de Z e Z é pai de Y.”
4. O significado lógico de :- (se)
O operador :- é a espinha dorsal das regras em Prolog. Ele expressa uma implicação lógica:
- Lado direito (corpo): as condições que devem ser satisfeitas.
- Lado esquerdo (cabeça): a conclusão que podemos inferir.
🧩 Lógica: A regra diz: “Se o corpo é verdadeiro, então a cabeça é verdadeira.” O Prolog usa essa regra de trás para frente: quando você pergunta se a cabeça é verdadeira, ele tenta provar o corpo.
5. Adicionando a regra à árvore genealógica
Nosso arquivo familia.pl atualizado com a regra:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
% =========================================== % Árvore genealógica com regras % =========================================== % Fatos - relações básicas pai(adão, cain). pai(adão, abel). pai(adão, seth). pai(seth, enos). pai(enos, cainã). pai(cainã, malalel). mae(eva, cain). mae(eva, abel). mae(eva, seth). % Regras - relações derivadas avo(X, Y) :- pai(X, Z), pai(Z, Y). |
No SWI-Prolog ou SWISH, carregue o arquivo:
6. Consultando a nova regra: avo/2
Agora podemos fazer perguntas que antes seriam impossíveis apenas com fatos:
🔹 Quem é o avô de Enos?
|
|
?- avo(X, enos). X = adão. % Adão é avô de Enos |
🔹 Quem são os netos de Adão?
|
|
?- avo(adão, Neto). Neto = enos ; % Enos é neto de Adão false. |
🔹 Quem são todos os avós e netos?
|
|
?- avo(Avo, Neto). Avo = adão, Neto = enos ; % Adão é avô de Enos Avo = seth, Neto = cainã ; % Seth é avô de Cainã Avo = enos, Neto = malalel ; % Enos é avô de Malalel false. |
💡 Poder da regra: A mesma regra funciona para todas as pessoas na árvore, sem que tenhamos declarado um único fato “avô” explicitamente!
7. Como o Prolog executa uma regra (passo a passo)
Quando você pergunta avo(adão, enos), o Prolog:
Passo 1: Unifica a cabeça da regra avo(X, Y) com a consulta avo(adão, enos) → X = adão, Y = enos.
Passo 2: Substitui as variáveis no corpo: pai(adão, Z), pai(Z, enos).
Passo 3: Tenta satisfazer o primeiro objetivo: pai(adão, Z). Encontra pai(adão, seth) → Z = seth.
Passo 4: Tenta o segundo objetivo com Z = seth: pai(seth, enos) → é verdade!
Passo 5: Todos os objetivos do corpo são verdadeiros → a regra é satisfeita → a consulta retorna true (com X = adão).
🧠 Entenda: Se o segundo objetivo falhasse (ex: pai(seth, X) não encontrasse enos), o Prolog volta atrás (backtracking) e tenta outra solução para o primeiro objetivo.
8. Regra vs. Fatos: elegância e concisão
Com fatos explícitos (ruim):
|
|
avo(adão, enos). avo(seth, cainã). avo(enos, malalel). % E para cada nova pessoa, precisaríamos adicionar mais fatos! % Trabalhoso e propenso a erros. |
Com regra (bom):
|
|
avo(X, Y) :- pai(X, Z), pai(Z, Y). % Uma única linha define TODOS os avôs da árvore! % Se adicionarmos novos fatos, a regra funciona automaticamente. |
A regra é mais elegante porque:
- Concisão: uma linha substitui muitas.
- Generalidade: funciona para qualquer número de pessoas.
- Manutenibilidade: se a definição de avô mudar, só precisamos alterar um lugar.
- Corretude: a lógica é clara e verificável.
9. Predicados definidos pelo usuário vs. primitivos
| Predicados Primitivos (built-in) | Predicados Definidos pelo Usuário |
| Já vêm com o Prolog. | São criados por você. |
Ex: write/1, listing/1, findall/3. | Ex: avo/2, neto/2, irmao/2. |
| São implementados em C/linguagem de baixo nível. | São implementados em Prolog puro (fatos + regras). |
| Não podem ser modificados. | Você pode adicionar ou alterar quantas regras quiser. |
Exemplo: ?- listing(pai). | Exemplo: ?- avo(adão, X). |
💡 Dica: A maioria dos seus programas Prolog será composta de seus próprios predicados, construídos a partir de fatos e regras. Os predicados primitivos são ferramentas auxiliares.
10. Resumo: o poder das regras
O que aprendemos:
- Regras são definições condicionais:
cabeça :- corpo.
- O corpo é uma conjunção de objetivos que devem ser verdadeiros.
- Regras permitem derivar conhecimento a partir de fatos.
- São mais concisas, gerais e fáceis de manter do que fatos explícitos.
- O Prolog executa regras unificando a cabeça e depois provando o corpo.
- Predicados definidos pelo usuário são a espinha dorsal de programas Prolog.
Com regras, sua árvore genealógica se transforma em um sistema de inferência completo. Você pode fazer perguntas complexas sem precisar declarar cada relação individualmente. No próximo artigo, vamos explorar regras com múltiplas definições e recursão — onde as regras se tornam ainda mais poderosas!