
Resolver Problemas com Restrições: Introdução a Constraint Satisfaction Problems (CSPs)
Na Inteligência Artificial, muitos problemas podem ser descritos como conjuntos de variáveis que devem satisfazer restrições específicas. Essa abordagem, conhecida como Constraint Satisfaction Problems (CSPs), é uma das ferramentas mais poderosas para simplificar e resolver desafios complexos, como escalonamento de tarefas, design de circuitos, sudoku, mapas coloridos e muito mais.
Neste artigo, vamos explicar os conceitos básicos de CSPs, mostrar técnicas de resolução eficientes e apresentar exemplos práticos para iniciantes.
O Que é um CSP?
Um CSP é um problema definido por:
- Variáveis: Elementos que precisam de um valor.
- Domínios: Conjunto de valores possíveis para cada variável.
- Restrições: Regras que determinam quais combinações de valores são válidas.
💡 Exemplo prático: Resolver um sudoku:
- Variáveis: Cada célula da grade.
- Domínio: Números de 1 a 9.
- Restrições: Nenhum número pode se repetir em uma linha, coluna ou bloco.
Representação de CSPs
Problemas CSP podem ser representados em grafos de restrições:
- Nós: Variáveis.
- Arestas: Restrições entre as variáveis.
Isso facilita a visualização de dependências e ajuda a escolher algoritmos mais eficientes.
Técnicas Clássicas de Resolução
1. Backtracking Search
A técnica mais comum para resolver CSPs: atribui valores a variáveis, recuando (backtrack) quando encontra uma restrição violada.
# Exemplo simplificado de backtracking para CSP
def backtrack(variaveis, dominios, restricoes, atribuicoes={}):
if len(atribuicoes) == len(variaveis):
return atribuicoes
var = [v for v in variaveis if v not in atribuicoes][0]
for valor in dominios[var]:
if all(r(var, valor, atribuicoes) for r in restricoes):
atribuicoes[var] = valor
resultado = backtrack(variaveis, dominios, restricoes, atribuicoes)
if resultado:
return resultado
del atribuicoes[var]
return None
# Problema simples: A != B
variaveis = ['A', 'B']
dominios = {'A': [1, 2], 'B': [1, 2]}
restricoes = [lambda v, val, a: all(a.get(o) != val for o in a)]
print(backtrack(variaveis, dominios, restricoes))
2. Heurísticas de Busca
Para acelerar o processo:
- MRV (Minimum Remaining Values): Escolhe primeiro a variável com menos valores possíveis.
- Degree Heuristic: Escolhe a variável mais conectada a outras.
- LCV (Least Constraining Value): Escolhe o valor que restringe menos os outros.
3. Forward Checking
Após cada atribuição, elimina valores inconsistentes nos domínios das variáveis restantes, reduzindo o espaço de busca.
4. Propagação de Restrições (AC-3)
Usa um algoritmo que verifica e elimina valores impossíveis, garantindo consistência de arco no grafo de restrições.
5. CSPs como Problemas de Satisfação de Restrições
CSPs podem ser vistos como uma linguagem universal para representar problemas complexos, facilitando a modelagem e a aplicação de algoritmos genéricos.
Aplicações Reais
- Sudoku e Quebra-Cabeças: Resolver jogos e desafios lógicos.
- Escalonamento de Recursos: Planejar horários em universidades ou fábricas.
- Coloração de Mapas: Garantir que regiões vizinhas tenham cores diferentes.
- Configuração de Sistemas: Ajustar automaticamente parâmetros de sistemas complexos.
Comparação de Estratégias
| Estratégia | Vantagem | Desvantagem |
|---|---|---|
| Backtracking | Simples e direto | Pode ser lento em casos grandes |
| Heurísticas | Acelera busca | Requer ajuste manual |
| Forward Checking | Reduz busca cedo | Mais uso de memória |
| AC-3 (Consistência) | Elimina valores impossíveis cedo | Pode ser pesado em grandes CSPs |
Conclusão
CSPs são uma forma poderosa de resolver problemas complexos em IA de maneira sistemática. Ao representar variáveis, domínios e restrições, podemos aplicar algoritmos de backtracking, heurísticas e propagação para encontrar soluções de forma eficiente. Essa abordagem é essencial em áreas como planejamento, jogos, robótica e otimização.
Conteúdo adaptado do livro “Artificial Intelligence: A Modern Approach”, de Stuart Russell e Peter Norvig.