Exercícios Práticos com Regras em Prolog

Árvore Genealógica — do zero à regras complexas

Neste post vamos construir uma base de conhecimento genealógica completa e definir diversas relações usando regras. O exercício é baseado na árvore genealógica da Figura 1.2 do livro-texto, que descreve três gerações de uma família.

1. A Árvore Genealógica

A figura apresenta a seguinte estrutura familiar (nomes fictícios):

avô João e avó Maria ├── pai Carlos e mãe Ana │ ├── filho Pedro │ ├── filha Clara │ └── filho Lucas └── tia Beatriz e tio Roberto ├── primo João Jr. └── prima Sofia

Relações de parentesco (pai/mãe):

  • João é pai de Carlos e Beatriz.
  • Maria é mãe de Carlos e Beatriz.
  • Carlos é pai de Pedro, Clara e Lucas.
  • Ana é mãe de Pedro, Clara e Lucas.
  • Beatriz é mãe de João Jr. e Sofia.
  • Roberto é pai de João Jr. e Sofia.

📝 2. Definindo os Fatos Básicos

Exercício 1: Crie um arquivo familia.pl e defina os fatos pai/2 e mae/2 com base na árvore acima.

Sua vez: Escreva os fatos no Prolog. Depois, carregue o arquivo e teste as consultas:

?- pai(joao, carlos). → deve retornar true.
?- mae(ana, pedro). → deve retornar true.
?- pai(X, pedro). → deve listar X = carlos.

Solução:

⚧️ 3. Adicionando homem/1 e mulher/1

Exercício 2: Para definirmos relações como “filho” e “filha”, precisamos saber o gênero de cada pessoa. Adicione os fatos homem/1 e mulher/1.

Sua vez: Liste todos os homens e mulheres da árvore.

?- homem(pedro).true
?- mulher(clara).true
?- homem(X). → deve listar todos os homens.

Solução:

4. Regra gerou/2

Exercício 3: Defina a regra gerou(X, Y) que é verdadeira se X é pai ou mãe de Y.

Sua vez: Crie a regra gerou/2 usando os fatos já definidos.

?- gerou(maria, carlos).true
?- gerou(carlos, lucas).true
?- gerou(X, pedro). → deve listar X = carlos e X = ana.

Solução:

A regra usa dois cláusulas (ou é pai ou é mãe). O Prolog tenta a primeira, se falhar, tenta a segunda.

5. Desafios — Definindo Relações Derivadas

Agora vamos construir relações mais complexas. Para cada uma:

  1. Desenhe o grafo de relacionamento (nós = pessoas, arcos = relações).
  2. Codifique a regra em Prolog.
  3. Teste com as consultas sugeridas.

a) filho/2 e filha/2

Grafo para filho/2: pai(X, Y) → Y é descendente mae(X, Y) → Y é descendente homem(Y) → Y é do sexo masculino Exemplo: Carlos → (pai) → Pedro Carlos → (pai) → Lucas Ana → (mae) → Pedro Ana → (mae) → Lucas e Y é homem (pedro, lucas)

Sua vez: Defina filho(Y, X) (Y é filho de X) e filha(Y, X) (Y é filha de X).

?- filho(pedro, carlos).true
?- filha(clara, ana).true
?- filho(X, carlos). → deve listar X = pedro, lucas.

Solução:

Raciocínio: Para ser filho(a), a pessoa deve ser descendente (pai ou mãe) e ter o gênero correspondente.

b) tio/2 e tia/2

Grafo para tio/2: T é tio de S se: 1. T é irmão de um dos pais de S 2. T é homem Caminho: T → (irmao) → Pai/Mãe de S T é homem

Sua vez: Defina tio(T, S) e tia(T, S).

?- tio(roberto, pedro).true (Roberto é irmão de Carlos)
?- tia(beatriz, lucas).true (Beatriz é irmã de Carlos)
?- tio(X, clara). → deve listar X = roberto.

Dica: Você precisará primeiro definir irmao/2 (já vimos) e irma/2 (versão feminina).

Solução:

Raciocínio: T é tio(a) se é irmão(ã) de um dos pais de S. Usamos as regras irmao/2 e irma/2 como auxiliares.

c) primo/2 e prima/2

Grafo para primo/2: P1 é primo de P2 se: 1. P1 e P2 têm um tio em comum 2. Não são irmãos 3. P1 é homem (para primo) Caminho: P1 → (pai/mãe) → Tio(a) comum → (pai/mãe) → P2

Sua vez: Defina primo(P1, P2) e prima(P1, P2).

?- primo(joao_jr, pedro).true (João Jr. e Pedro são primos)
?- prima(sofia, clara).true (Sofia e Clara são primas)
?- primo(X, lucas). → deve listar X = joao_jr.

Dica: Use a regra tio/2 ou tia/2 que você acabou de definir.

Solução:

Raciocínio: Para ser primo(a), a pessoa deve ter um tio(a) em comum com a outra, e não ser a mesma pessoa. Incluímos as quatro combinações possíveis (tio/pai, tia/mae, etc.) para garantir que a relação funcione em ambos os sentidos.

d) avo/2 (avô/avó)

Grafo para avo/2: A é avô/avó de N se: 1. A é pai/mãe de um dos pais de N 2. A é homem (para avô) ou mulher (para avó) Caminho: A → (pai/mãe) → P → (pai/mãe) → N

Sua vez: Defina avo(A, N) (avô) e avo(A, N) (avó).

?- avo(joao, pedro).true (João é avô de Pedro)
?- avo(maria, lucas).true (Maria é avó de Lucas)
?- avo(X, clara). → deve listar X = joao, maria.

Solução:

Raciocínio: O avô/avó é pai/mãe de um dos pais da criança. Usamos o gênero para diferenciar avô de avó.

📊 6. Visualizando as Relações com UML

Abaixo está a representação UML das principais relações que definimos, usando o formato PlantUML:

Diagrama UML mostrando as relações pai/mãe e algumas relações derivadas (irmão, primo).

7. Por que praticar com regras?

  • Pensamento lógico: Cada regra é uma pequena prova lógica que você constrói.
  • Reuso: Regras como irmao/2 e tio/2 podem ser combinadas para construir outras mais complexas.
  • Validação constante: Testar cada regra com consultas ajuda a garantir que a lógica está correta antes de avançar.
  • Base para IA: Sistemas especialistas e bases de conhecimento são construídos exatamente assim.

Dica final: Sempre comece com um grafo ou diagrama antes de codificar. Isso ajuda a visualizar as conexões e evita erros de lógica. Depois, codifique e teste exaustivamente.

Conclusão

Neste exercício, construímos uma árvore genealógica completa e definimos 8 relações derivadas usando apenas fatos básicos e regras. A prática de desenhar o grafo antes de codificar e validar com consultas é fundamental para dominar o Prolog.

Próximos passos: Tente adicionar mais pessoas na árvore, ou definir relações como bisavo/2, sobrinho/2 ou cunhado/2. Quanto mais você praticar, mais natural se torna o raciocínio lógico!


“A lógica é a anatomia do pensamento.” — John Locke

Deixe um comentário