Em Prolog, a base de dados é geralmente estática: os fatos e regras são definidos no arquivo e não mudam durante a execução. No entanto, muitas aplicações precisam de flexibilidade — adicionar novos dados, remover informações obsoletas ou modificar regras em tempo de execução. Para isso, o Prolog oferece uma base de dados dinâmica.
1. O Conceito de Base de Dados Dinâmica
Uma base de dados dinâmica permite que cláusulas (fatos e regras) sejam adicionadas ou removidas durante a execução do programa. Isso é útil para:
- Sistemas interativos (ex: cadastro de usuários).
- Bases de conhecimento que evoluem.
- Algoritmos que constroem soluções incrementalmente.
- Memorização de resultados (memoização).
2. A Diretiva :‑ dynamic
Para tornar um predicado dinâmico, usamos a diretiva :- dynamic seguida do nome e aridade do predicado.
|
1 2 3 4 5 |
% Declara que o predicado joga/2 é dinâmico :- dynamic joga/2. % Agora podemos adicionar e remover fatos joga/2 em tempo de execução |
Sem essa declaração, tentar modificar um predicado resultaria em erro.
3. Predicados de Manipulação
O Prolog fornece três predicados principais para manipular a base de dados dinâmica:
| Predicado | Descrição |
|---|---|
asserta/1 |
Adiciona uma cláusula no início da base de dados (antes das existentes). |
assertz/1 |
Adiciona uma cláusula no final da base de dados (depois das existentes). |
retract/1 |
Remove a primeira cláusula que unifica com o argumento. |
retractall/1 |
Remove todas as cláusulas que unificam com o argumento. |
Além disso, listing/0 ou listing(predicado) exibe a base de dados atual.
4. Programa 6.1: Jogadores
Vamos começar com uma base de dados simples de jogadores e seus esportes:
|
1 2 3 4 5 6 7 8 |
% Declara que joga/2 é dinâmico :- dynamic joga/2. % Fatos iniciais joga(pelé, futebol). joga(guga, tênis). |
Para ver a base atual, use listing(joga) ou listing/0.
|
1 2 3 4 5 6 |
?- listing(joga). :- dynamic joga/2. joga(pelé, futebol). joga(guga, tênis). true. |
5. Adicionando Novos Fatos com assertz/1
assertz/1 adiciona um fato no final da base.
|
1 2 3 4 5 6 7 8 9 |
?- assertz(joga(maradona, futebol)). true. ?- listing(joga). :- dynamic joga/2. joga(pelé, futebol). joga(guga, tênis). joga(maradona, futebol). % Adicionado no final true. |
Como resultado, a consulta joga(X, futebol) retorna os jogadores na ordem em que foram inseridos.
|
1 2 3 |
?- joga(X, futebol). X = pelé ; X = maradona. |
6. Adicionando com asserta/1
asserta/1 adiciona um fato no início da base.
|
1 2 3 4 5 6 7 8 9 10 |
?- asserta(joga(robinho, futebol)). true. ?- listing(joga). :- dynamic joga/2. joga(robinho, futebol). % Adicionado no início joga(pelé, futebol). joga(guga, tênis). joga(maradona, futebol). true. |
Agora, joga(X, futebol) retorna robinho primeiro:
|
1 2 3 4 |
?- joga(X, futebol). X = robinho ; X = pelé ; X = maradona. |
7. Removendo Fatos com retract/1
retract/1 remove a primeira cláusula que unifica com o argumento.
|
1 2 3 4 5 6 7 8 9 |
?- retract(joga(guga, tênis)). true. ?- listing(joga). :- dynamic joga/2. joga(robinho, futebol). joga(pelé, futebol). joga(maradona, futebol). true. |
Também podemos remover usando variáveis:
|
1 2 3 4 5 6 7 8 |
?- retract(joga(maradona, _)). true. ?- listing(joga). :- dynamic joga/2. joga(robinho, futebol). joga(pelé, futebol). true. |
Importante: O retract/1 remove apenas a primeira cláusula
que unifica. Para remover todas, use retractall/1.
|
1 2 3 4 5 6 |
?- retractall(joga(_, futebol)). true. ?- listing(joga). :- dynamic joga/2. true. % Nenhum fato restante |
8. Exemplo Prático: Sistema de Agenda
Vamos construir um pequeno sistema de agenda telefônica usando base dinâmica:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
:- dynamic telefone/2. % Adicionar um contato add_contato(Nome, Numero) :- assertz(telefone(Nome, Numero)). % Remover um contato remove_contato(Nome) :- retractall(telefone(Nome, _)). % Buscar um número buscar_numero(Nome, Numero) :- telefone(Nome, Numero). % Listar todos os contatos listar_contatos :- telefone(Nome, Numero), write(Nome), write(' - '), write(Numero), nl, fail. listar_contatos. |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
?- add_contato(joao, '1234-5678'). true. ?- add_contato(maria, '8765-4321'). true. ?- listar_contatos. joao - 1234-5678 maria - 8765-4321 true. ?- buscar_numero(joao, N). N = '1234-5678'. ?- remove_contato(joao). true. ?- listar_contatos. maria - 8765-4321 true. |
9. Cuidados e Boas Práticas
O uso de base de dados dinâmica é poderoso, mas requer atenção:
- Ordene com cuidado: A ordem dos fatos afeta a ordem das soluções e o backtracking.
- Evite efeitos colaterais inesperados: Modificar a base durante uma consulta pode causar comportamentos imprevisíveis.
-
Use
retractcom unificação específica: Se usar variáveis, certifique-se de que elas estão instanciadas para evitar remoções indesejadas. -
Organize o código: Declare todos os predicados dinâmicos no início do arquivo
com
:- dynamic.
10. Exercícios Propostos
-
Sistema de Estoque: Crie um predicado dinâmico
estoque(Produto, Quantidade)com funções para adicionar, remover e consultar produtos. Inclua verificação de quantidade negativa. -
Histórico de Operações: Implemente um sistema que registra todas as operações
(adições e remoções) em um predicado
log/2com timestamp. -
Memoização: Implemente
fib_memo(N, F)que calcula Fibonacci armazenando resultados já calculados para reutilização. -
Base de Alunos: Crie um sistema de cadastro de alunos com
aluno(Nome, Nota)e funções para adicionar, remover, e calcular a média da turma.
11. Conclusão
A base de dados dinâmica é um recurso poderoso que estende a capacidade do Prolog
para aplicações interativas e em evolução. Com asserta/1, assertz/1
e retract/1, podemos:
- Construir sistemas que aprendem com novos dados.
- Implementar caches e memoização para otimização.
- Criar interfaces interativas com o usuário.
- Manter bases de conhecimento atualizadas.
Use com responsabilidade: base dinâmica é uma ferramenta poderosa, mas seu uso indevido pode tornar o programa difícil de depurar. Sempre documente os predicados dinâmicos e planeje a estratégia de modificação da base.