UNIVERSIDADE REGIONAL DE BLUMENAU
CENTRO DE CIÊNCIAS EXATAS E NATURAIS
CURSO DE CIÊNCIAS DA COMPUTAÇÃO – BACHARELADO
IMPLEMENTAÇÃO DE UM ALGORITMO HEURÍSTICO
PARA PROBLEMAS DE RESTRIÇÕES
ALEXSANDRO SANTOS PIRES
BLUMENAU
2006
2006/2-01
ALEXSANDRO SANTOS PIRES
IMPLEMENTAÇÃO DE UM ALGORITMO HEURÍSTICO
PARA PROBLEMAS DE RESTRIÇÕES
Trabalho de Conclusão de Curso submetido à
Universidade Regional de Blumenau para a
obtenção dos créditos na disciplina Trabalho
de Conclusão de Curso II do curso de Ciências
da Computação — Bacharelado.
Prof. Jomi Fred Hübner, Doutor - Orientador
BLUMENAU
2006
2006/2-01
IMPLEMENTAÇÃO DE UM ALGORITMO HEURÍSTICO
PARA PROBLEMAS DE RESTRIÇÕES
Por
ALEXSANDRO SANTOS PIRES
Trabalho aprovado para obtenção dos créditos
na disciplina de Trabalho de Conclusão de
Curso II, pela banca examinadora formada
por:
Presidente:
______________________________________________________
Prof. Jomi Fred Hübner, Doutor – Orientador, FURB
Membro:
______________________________________________________
Prof. Paulo César Rodacki Gomes, Doutor – FURB
Membro:
______________________________________________________
Prof. Mauro Marcelo Mattos, Doutor – FURB
Blumenau, 15 de dezembro de 2006.
Dedico este trabalho a todos os familiares e
amigos, especialmente aqueles que me
ajudaram diretamente na realização deste, a
comunidade científica de computação e
inteligência artificial e ao meu orientador.
AGRADECIMENTOS
À Deus, pela oportunidade de fazer este trabalho.
À minha família, que mais do que nunca, esteve tão presente.
À minha namorada Iloara Cláudia Gutz por ser compreensiva com minha dedicação
intensa a este trabalho e por estar sempre me motivando para a conclusão do mesmo.
Aos meus amigos, pelos empurrões e cobranças.
Ao meu orientador, Jomi Fred Hübner, por ter acreditado na conclusão deste trabalho,
e me ajudado nas horas mais difíceis.
Ao bolsista de iniciação científica em inteligência artificial, Karlyson Schubert Vargas,
por ter ajudado na compreensão de itens relacionados ao dynDCSP e CCB.
A sr. Áureo Alves, representante da Clicheria Blumenau, por me dar a oportunidade de
me dedicar integralmente a realização deste trabalho por um mês.
Ao Russell e Norvig, por criarem uma obra didática magnífica sobre inteligência
artificial.
A melhor forma de prever o futuro é inventá-lo.
Alan Kay.
RESUMO
Este trabalho apresenta a implementação do algoritmo de busca-com-retrocesso para resolver
problemas de satisfação de restrições (PSR) ou em inglês, Constraint Satisfaction Problem
(CSP). Também há a integração com um projeto que permite a descrição CSPs através de uma
linguagem de alto nível, para que os mesmos sejam consistidos, modelados e resolvidos pelo
algoritmo implementado. O algoritmo conta com heurísticas de variável mais restritiva,
variável mais restringida e conflitos mínimos na obtenção da solução dos problemas. A
especificação foi feita utilizando o Enterprise Architect (EA) com a Unifield Modeling
Language (UML) e a implementação na linguagem Java com a Integrated Development
Environment (IDE) Eclipse.
Palavras-chave: Busca-com-retrocesso. Problema de satisfação de restrições. PSR. Conflitos
mínimos.
ABSTRACT
This work presents the implementation of the search algorithm with backtracking to solve
constraint satisfaction problem (CSP). Also it has the interation with a project that allows the
description of CSPs in a high level language so that the same either consisted, shaped and
solved for implemented algorithm. The algorithm has heuristics: more restrictive variable,
more retricted variable and minimun conflicts in the attainment of the solution of the problem.
The specification was made using the Enterprise Architect with the Unifield Modeling
Language (UML) and the implementation in the Java language with the Integrated
Development Environment (IDE) Eclipse.
Key-words: Backtracking. Constraint satisfaction problem. CSP. Minimun conflicts.
LISTA DE ILUSTRAÇÕES
Figura 1 – Mapa da Austrália ................................................................................................... 16
Quadro 1 – Definição do problema de coloração de mapas modelado em CSP ...................... 16
Figura 2 – Uma solução possível para o problema das n-rainhas com n=8 ............................. 17
Figura 3 – Parte de uma árvore de busca gerada pelo algoritmo busca-com-retrocesso.......... 18
Quadro 2 – Algoritmo de busca-com-retrocesso...................................................................... 18
Quadro 3 – Algoritmo de busca local com a heurística de conflitos mínimos......................... 20
Figura 4 – Parte 1 do exemplo de busca local com conflitos mínimos .................................... 21
Figura 5 – Parte 2 do exemplo de busca local com conflitos mínimos .................................... 21
Figura 6 – Parte 3 do exemplo de busca local com conflitos mínimos .................................... 22
Quadro 4 – Especificação do CSP para o problema da Figura 1.............................................. 23
Quadro 5 – Especificação da linguagem para construção de CSP/COP do CCB .................... 23
Quadro 6 – Especificação de domínio...................................................................................... 23
Quadro 7 – Exemplo de especificação do domínio .................................................................. 23
Quadro 8 – Especificação de variáveis..................................................................................... 23
Quadro 9 – Exemplo de especificação das variáveis................................................................ 24
Quadro 10 – Exemplo de especificação das restrições............................................................. 24
Figura 7 – Tela do editor do CCB ............................................................................................ 25
Figura 8 – Visão geral do CCB ................................................................................................ 25
Quadro 11 – Exemplo da especificação de um CSP com a biblioteca do dynDCSP ............... 26
Quadro 12 – Problema das n-rainhas especificado com a biblioteca do dynDCSP ................. 27
Figura 9 – Pacotes do dynDCSP............................................................................................... 28
Figura 10 – Classes do pacote CSP do dynDCSP .................................................................... 28
Figura 11 – Diagrama de casos de uso ..................................................................................... 31
Figura 12 – Diagrama de atividades ......................................................................................... 32
Figura 13 – Diagrama de classes .............................................................................................. 33
Quadro 13 – Método pesquisaComRetrocesso da classe resolveCSP ..................... 36
Quadro 14 – Método retrocessoRecursivo da classe resolveCSP.......................... 37
Quadro 15 – Método ehCompleta da classe resolveCSP ............................................... 38
Quadro 16 – Método getVarSemValor da classe resolveCSP...................................... 38
Quadro 17 – Saída do console da resolução de um CSP.......................................................... 39
Quadro 18 – Método getVariavelMaisRestritiva da classe resolveCSP ........... 39
Quadro 19 – Método ordenarVariavelMaisRestritiva da classe resolveCSP.. 40
Quadro 20 – Método ordenarVariavelMaisRestringida da classe resolveCSP41
Quadro 21 – Método getVariavelMaisRestringida da classe resolveCSP ......... 42
Quadro 22 – Método iniciaConflitosMinimos da classe ConflitosMinimos .... 42
Quadro 23 – Método getValorConflitosMinimos da classe ConflitosMinimos43
Quadro 24 – Método getNumeroConflitos da classe ConflitosMinimos.............. 43
Quadro 25 – Método getVariaveisConflitantes da classe ConflitosMinimos44
Quadro 26 – Método getViolacoes da classe ConflitosMinimos ............................ 44
Quadro 27 – Método atribuicaoAleatoria da classe ConflitosMinimos ........... 45
Quadro 28 – Método selecionaVarAleatoria da classe ConflitosMinimos....... 45
Quadro 29 – Método getDominio da classe ConflitosMinimos ................................. 45
Quadro 30 – Inserção de um comboBox na classe BuilderGUI ........................................ 46
Quadro 31 – Inserção do método pesquisaComRetrocesso na classe BuilderGUI.. 46
Quadro 32 – Arquivo de lote executa.bat......................................................................... 46
Quadro 33 – Classe GeraInterfaceCCB ........................................................................... 47
Figura 14 – Interface do CCB................................................................................................... 47
Figura 15 – Tela abrir arquivo.................................................................................................. 48
Figura 16 – Tela do CBB com um CSP especificado .............................................................. 48
Figura 17 – Seleção do método de resolução ........................................................................... 49
Figura 18 – Tela do CBB com um CSP especificado e resolvido com heurística ................... 50
Figura 19 – VC das execuções: problema da Figura 1 ............................................................. 51
Figura 20 – Tempo médio das execuções: problema da Figura 1 ............................................ 52
Figura 21 – Problema de coloração de mapas com domínios diferentes. ................................ 52
Quadro 34 – Código fonte do problema de coloração de mapas com domínios diferentes ..... 53
Figura 22 – VC das execuções: coloração de mapas com domínios diferentes. ...................... 53
Figura 23 – Tempo médio das execuções: coloração de mapas com domínios diferentes ...... 54
Figura 24 – VC nas execuções: n-rainhas com n=4 ................................................................. 54
Figura 25 – Tempo médio das execuções: n-rainhas com n=4 ................................................ 55
LISTA DE SIGLAS
PSR – Problema de Satisfação de Restrição
VAR – Variável
AO – Austrália Ocidental
TN – Território Norte
Q – Queensland
AM – Austrália Meridional
NGS – Nova Gales do Sul
V – Victoria
T – Tazmânia
SUMÁRIO
1 INTRODUÇÃO.................................................................................................................. 12
1.1 OBJETIVOS DO TRABALHO ........................................................................................ 13
1.2 ESTRUTURA DO TRABALHO ...................................................................................... 14
2 FUNDAMENTAÇÃO TEÓRICA .................................................................................... 15
2.1 CONSTRAINT SATISFACTION PROBLEM..................................................................... 15
2.2 BUSCA-COM-RETROCESSO ........................................................................................ 17
2.3 HEURÍSTICAS ................................................................................................................. 19
2.4 CSP && COP BUILDER .................................................................................................. 22
2.5 DYNDCSP ......................................................................................................................... 25
2.6 TRABALHOS CORRELATOS........................................................................................ 29
3 DESENVOLVIMENTO DO TRABALHO ..................................................................... 30
3.1 REQUISITOS PRINCIPAIS DO PROBLEMA A SER TRABALHADO....................... 30
3.2 ESPECIFICAÇÃO ............................................................................................................ 30
3.2.1 Diagrama de casos de uso ............................................................................................... 30
3.2.2 Diagrama de atividades ................................................................................................... 31
3.2.3 Diagrama de classes ........................................................................................................ 32
3.3 IMPLEMENTAÇÃO ........................................................................................................ 34
3.3.1 Técnicas e ferramentas utilizadas.................................................................................... 35
3.3.1.1 Implementação do algoritmo busca-com-retrocesso .................................................... 35
3.3.1.2 Implementação da heurística variável mais restritiva................................................... 39
3.3.1.3 Implementação da heurística variável mais restringida................................................ 41
3.3.1.4 Implementação da heurística de conflitos mínimos em busca local............................. 42
3.3.1.5 Integração com o CCB.................................................................................................. 45
3.3.2 Operacionalidade da implementação .............................................................................. 46
3.4 RESULTADOS E DISCUSSÃO ...................................................................................... 50
4 CONCLUSÕES.................................................................................................................. 56
4.1 EXTENSÕES .................................................................................................................... 57
REFERÊNCIAS BIBLIOGRÁFICAS ................................................................................. 58
12
1 INTRODUÇÃO
Assim como a informática de maneira geral desperta interesse em quem a descobre,
muitos estudantes de ciência da computação entusiasmam-se com a disciplina de Inteligência
Artificial. Neste contexto, há um tópico interessante chamado problema de satisfação de
restrições (PSR) ou, em inglês, Constraint Satisfaction Problem (CSP).
O CSP pode ser definido por um conjunto de variáveis e por um conjunto de restrições,
onde cada variável tem um domínio não-vazio de valores possíveis, conforme Russell e
Norvig (2004, p. 135). Cada restrição envolve algum subconjunto das variáveis e especifica
combinações de valores contidos no seu domínio e que são permitidos para esse subconjunto.
Um estado do problema é definido por uma atribuição de valores a alguma ou todas as
variáveis, sendo que uma atribuição que não viola nenhuma restrição é uma atribuição válida.
Uma solução para o CSP é uma atribuição para todas as variáveis que satisfaz todas as
restrições.
O problema de coloração de mapas é um exemplo clássico de um problema que pode
ser traduzido para os moldes do CSP, onde se deseja colorir, com um número definido de
cores, um mapa no qual há uma área definida e finita de regiões, sendo que as vizinhas não
podem ter a mesma cor. Isso se torna algo complexo de ser resolvido por um ser humano
quando há muitas regiões, um alto grau de vizinhança e poucas cores.
Para a utilização prática das técnicas de CSP, é necessário utilizar algum sistema de
buscas que verifique todas as variáveis envolvidas. Dentre eles, pode-se citar o de busca-comretrocesso, que é um algoritmo de busca recursiva e em profundidade que gera nodos em
níveis de uma árvore, tentando buscar uma solução para o CSP. Caso não ache a solução no
nível atual da árvore, ele retorna um nível e continua a busca, sucessivamente. Há também
algoritmos de busca local que criam um estado inicial para a atribuição com valores aleatórios
atribuídos as variáveis, verificando se já se encontrou a solução, senão altera uma variável
com um outro valor de cada vez.
Para minimizar os custos de busca, há a necessidade de aplicar heurísticas1 de busca e
de uso geral, como exemplo, a de conflitos mínimos. Ela dá preferência para o valor que
resulta no número de conflitos com outras variáveis já atribuídas. Assim como a heurística de
conflitos mínimos, há outras heurísticas existentes como a de variável mais restritiva e
1
Para Rich e Knight (1993, p. 49), a palavra heurística vem do grego heuriskein, que significa “descobrir”.
13
variável mais restringida.
Para a especificação de CSPs, é utilizado um projeto que permite especificar CSPs
através de objetos em Java e em uma linguagem própria de alto nível, que é interpretada
através de um parser e gera uma instância de objetos em Java que representam o CSP
informado. Este projeto, denominado dynDCSP, é descrito em Santos (2005) e foi
desenvolvido em Java pelo Grupo de Inteligência Artificial (GIA) da Universidade Regional
de Blumenau (FURB). Neste projeto, está incluso a ferramenta CSP && COP Builder (CCB)
que interpreta uma especificação de CSP, mas não possui nenhum algoritmo para a resolução
de CSPs. Para resolver este problema, implementou-se o algoritmo busca-com-retrocesso,
utilizou-se a representação de CSP disponibilizado pelo dynDCSP e integrou-o ao CCB.
Atualmente, há uma integração entre um algoritmo de resolução de CSPs e o CCB,
presente no projeto dynDCSP, também desenvolvido pelo GIA da FURB. Porém, o algoritmo
implementado foi concebido para resolver os CSPs de forma distribuída, ou seja, em diversos
computadores. Neste trabalho, o algoritmo busca-com-retrocesso é implementado de forma
centralizada2 uma vez que já há um algoritmo de resolução distribuída no projeto dynDCSP.
A implementação também utiliza heurísticas na busca pela solução do CSP informado.
1.1 OBJETIVOS DO TRABALHO
O objetivo deste trabalho é implementar o algoritmo de busca-com-retroceso para
solucionar CSPs, disponibilizando heurísticas para a obtenção da solução, e integrando-o com
a ferramenta CCB, sendo capaz de informar um CSP por meio de uma linguagem para o
retorno de uma solução obtida através da busca efetuada pelo algoritmo. O trabalho a ser
implementado também deve poder ser utilizado como uma ferramenta didática, com
documentação da programação a ser feita e também podendo ser equiparada com os
algoritmos que a literatura propõe.
2
Centralizada pelo fato de toda a execução e processamento ser realizado localmente em um só computador.
14
1.2 ESTRUTURA DO TRABALHO
O conteúdo deste trabalho está dividido em três capítulos. O capítulo 2 apresenta a
fundamentação teórica contendo um estudo detalhado sobre constraint satisfaction problem
(seção 2.1), sobre o algoritmo de busca-com-retrocesso (seção 2.2), sobre heurísticas (seção
2.3), sobre o CSP && COP Builder (seção 2.4), sobre o dynDCSP (seção 2.5) e os trabalhos
correlatos (seção 2.6).
O capítulo 3 abrange o desenvolvimento do trabalho, contendo os requisitos principais
do problema a ser trabalhado (seção 3.1), especificação do sistema (seção 3.2), e a
implementação (3.3) é subdividido em técnicas e ferramentas utilizadas (seção 3.3.1) e
operacionalidade da implementação, que apresenta o funcionamento do sistema com estudo
de caso. É apresentado também os resultados e discussão (seção 3.4) do trabalho.
As conclusões do trabalho são evidenciadas no capítulo 4 que tem uma subseção que
demonstra as extensões (seção 4.1) possíveis para este trabalho.
15
2 FUNDAMENTAÇÃO TEÓRICA
A fundamentação teórica contém 5 seções que servirão de base para o entendimento
deste trabalho. A seção 2.1 trata dos aspectos, conceitos fundamentais e exemplos de CSP, a
seção 2.2 demonstra o algoritmo busca-com-retrocesso, a seção 2.3 apresenta a descrição das
heurísticas, a seção 2.4 demonstra a ferramenta CSP && COP Builder que é utilizado em
conjunto com a implementação do algoritmo de resolução de CSPs, a seção 2.5 mostra o
projeto dynDCSP, que oferece a representação de CSPs através de objetos em Java. Por fim, a
seção 2.6 explana sobre os trabalhos correlatos.
2.1 CONSTRAINT SATISFACTION PROBLEM
Para a modelagem de um problema CSP são necessários alguns conceitos básicos que
garantirão uma abordagem adequada para o problema. Formalmente, de acordo com Russell e
Norvig (2004, p. 135), pode-se definir um CSP como sendo um conjunto de variáveis, V1, V2,
...,Vn, e um conjunto de restrições, R1, R2, ..., Rm. Cada variável Vi tem um domínio Di, sendo
que o mesmo não pode ser vazio, e cada restrição Rj envolve um subconjunto de variáveis Vi
que especificam combinações para um valor aceitável para esse subconjunto. Um estado do
problema é tido como uma atribuição de valores a uma ou todas as variáveis ({Xi = vi, Xj = vj,
...}) e será uma solução para o CSP somente se um conjunto de atribuições for consistente
com todas as restrições.
Um exemplo prático de problema de satisfação de restrições é o de coloração de
mapas, como mencionado anteriormente. Na Figura 1 (a) é demonstrado o mapa dos
principais estados e territórios da Austrália e ao lado, na Figura 1 (b), um grafo, representando
como o problema pode ser estruturado, com os nós representando os estados e as arestas a
relação direta de vizinhança.
16
Fonte: Russell e Norvig (2004, p. 135).
Figura 1 – Mapa da Austrália
Modelando o problema como um CSP, as variáveis são os estados do mapa, as
restrições do problema são a não repetição da cor de um estado em outro estado vizinho e o
domínio de cada variável, as cores que podem colorir cada estado. A definição e uma solução
possível para este problema é apresentada no Quadro 1.
Variáveis = { AO, TN, Q, NGS, V, AM, T }
Restrições = { (AO ≠ TN),
(AO ≠ AM),
(TN ≠ AO),
(TN ≠ AM),
(TN ≠ Q)
...,
(NGS ≠ V) }
Domínio para as variáveis = { vermelho, verde, azul }
Solução possível = { (AO = vermelho),
(TN = verde),
(Q = vermelho),
(NGS = verde),
(V = vermelho),
(AM = azul),
(T = vermelho) }
Quadro 1 – Definição do problema de coloração de mapas modelado em CSP
Nas literaturas que contemplam CSP, geralmente é encontrado o problema das nrainhas. De acordo com Russell e Norvig (204, p. 67), é um problema interessante para testes
de algoritmos de busca e consiste em posicionar um número informado de rainhas em um
tabuleiro de xadrez de forma que não haja possibilidade de ataque entre nenhuma delas.
Também se considera a regra do xadrez em que a rainha se movimenta quantos passos sejam
necessários sendo que sua movimentação é feita na horizontal, vertical ou na diagonal.
Na especificação do problema das n-rainhas, geralmente é definido que o número de
rainhas seja igual ao número de linhas e colunas do tabuleiro, portanto, para o problema
17
proposto cada rainha é disposta em uma linha do tabuleiro e a numeração associada é
provinda do seu domínio e é relacionada com a coluna em que ela está, por exemplo, “R1 =
2” significa que a rainha número um está posicionada na coluna 2 da sua linha número um.
Na Figura 2, é ilustrado uma solução possível para o problema das n-rainhas, com n =
8 num tabuleiro de xadrez de tamanho 8x8. Nota-se que nenhuma delas está em posição de
ataque, ou seja, na mesma linha, coluna ou diagonal.
Fonte: Tsang (1993, p. 2).
Figura 2 – Uma solução possível para o problema das n-rainhas com n=8
2.2 BUSCA-COM-RETROCESSO
De acordo com Russell e Norvig (2004, p. 138), busca-com-retrocesso é um tipo de
busca recursiva e em profundidade que atribui valores a um nodo da árvore de busca, se
aprofundando pela esquerda, e toda vez que encontra uma inconsistência na atribuição de
algum valor, decorrente das restrições, retorna (efetua um retrocesso) e tenta pelo ramo mais
próximo à direita, e mesmo se não houver mais, retorna um nível da árvore e continua a busca
até o encontro da solução. Conforme Tsang (1993, p. 37), o algoritmo fará um retrocesso para
18
à última decisão quando o mesmo não conseguir continuar.
A Figura 3 traz o exemplo de parte da árvore de busca gerada pelo algoritmo buscacom-retrocesso aplicado ao exemplo de coloração de mapas, demonstrado na Figura 1. Ele
inicia gerando um valor para cada nodo do nível atual e se aprofunda pelo nodo da esquerda,
gerando novos sucessores e assim por diante. Caso um sucessor não satisfaça as condições das
restrições, ele retorna e gera o próximo sucessor da direita, caso contrário, ele retorna mais
um nível e faz as mesmas verificações sucessivamente.
Fonte: Campos (2003).
Figura 3 – Parte de uma árvore de busca gerada pelo algoritmo busca-com-retrocesso
No Quadro 2, é apresentado o algoritmo de busca-com-retrocesso proposto por Russell
e Norvig (2004).
função PESQUISA-COM-RETROCESSO(psr) retorna uma solução ou falha
retornar RETROCESSO-RECURSIVO({}, psr)
função RETROCESSO-RECURSIVO(atribuição, psr) retorna uma solução ou falha
se atribuição é completa então retornar atribuição
var <- SELECIONAR-VARIAVEL-NÃO-ATRIBUÍDA(VARIÁVEIS[psr],atribuição,psr)
para cada valor em VALORES-DE-ORDEM-NO-DOMÍNIO(var, atribuição, psr) faça
se valor é consistente com atribuição de acordo com RESTRIÇõES[psr] então
adicionar {var = valor} a atribuição
resultado <- RETROCESSO-RECURSIVO(atribuição,psr)
se resultado ≠ falha então retornar resultado
remover {var = valor} de atribuição
retornar falha
Fonte: Russell e Norvig (2004, p. 139).
Quadro 2 – Algoritmo de busca-com-retrocesso
19
A expressão busca-com-retrocesso é utilizada para indicar uma busca em
profundidade que escolhe valores para uma variável de cada vez e que efetua
o retrocesso quando uma variável não tem valores válidos restantes a serem
atribuídos. [...] Além disso, ele estende a atribuição corrente para gerar um
sucessor, em vez de copiá-lo. (RUSSELL; NORVIG, 2004, p. 138).
O algoritmo consiste basicamente em criar uma árvore com os nodos contendo as
atribuições dos valores do domínio às variáveis feitas até o momento e se for consistente, ele
continua a buscar por novas atribuições para chegar a uma atribuição completa, ou seja, uma
solução, senão, ele apaga esse nodo e retorna tentando novamente com um valor diferente, e
assim sucessivamente. Caso não consiga mais retornar e não tenha mais variáveis nem valores
do domínio para serem atribuídos, o algoritmo retorna como falha, o que denomina a não
existência de uma solução para o CSP informado.
2.3 HEURÍSTICAS
Heurísticas aplicadas em algoritmos de busca procuram basicamente reduzir o número
de passos até que se chegue à solução, pois para muitos problemas, de acordo com Russell e
Norvig (2004, p. 109-110), o que importa é a configuração final do problema, e não a ordem
em que ele foi resolvido. Ainda, segundo Rich e Knight (1993, p. 76), heurísticas são também
estratégias de busca que podem ser escritas independentemente de qualquer tarefa ou domínio
de problema em particular.
Nos algoritmos de resolução de CSP cabe a agregação da heurística de conflitos
mínimos. De acordo com Filho et al. (1998), ela seleciona o valor que resulta no número
mínimo de conflitos com outras variáveis, portanto, quando for atribuir esse valor, sabe-se
que este será mais aceito para ser atribuído a outras variáveis. Assim como esta, e ainda de
acordo com Filho et al. (1998), outras heurísticas também podem ser aplicadas ao algoritmo
de resolução de CSP como a de variável mais restritiva, que prefere a variável envolvida no
maior número de restrições e variável mais restringida, onde é preferida a variável com menos
valores em seu domínio.
Conforme Russell e Norvig (2004, p. 140), a heurística de variável mais restritiva
consiste em selecionar a variável envolvida no maior número de restrições. Para isso, deve-se
inicialmente obter a lista de variáveis do CSP e verificar uma a uma e utilizar por primeiro a
que tem a maior a quantidade de restrições em que ela é afetada, obtendo assim, logicamente,
20
uma maior possibilidade de atribuições futuras, diminuindo o número de conflitos posteriores.
Para a variável mais restringida, que é a heurística da variável que pode assumir o menor
número de valores, também se deve obter a lista de variáveis do CSP e verificar uma a uma a
quantidade de valores do domínio que ela pode assumir usando por primeiro, a variável que
tiver a menor quantidade, o que logicamente deixará as atribuições posteriores com uma
maior liberdade de atribuições com relação à quantidade de valores do domínio.
Segundo Russell e Norvig (2004, p.146), conflitos mínimos é uma heurística que
prefere pelo valor do domínio da variável que tenha o menor número de conflitos com outras
variáveis. Ela pode ser aplicada em um algoritmo de busca local. Ainda segundo Russell e
Norvig (2004, p. 146), algoritmos de busca local utilizam uma formulação de estados
completos, ou seja, o estado inicial atribui um valor a cada variável e a função sucessor altera
um valor de uma variável de cada vez.
Por exemplo, no problema das 8 rainhas, o estado inicial poderia ser uma
configuração aleatória de 8 rainhas em 8 colunas, e a função sucessor
escolheria uma rainha e consideraria a possibilidade de movê-la para outro
lugar em sua coluna. [...] Na escolha de um novo valor para uma variável, a
heurística mais obvia é selecionar o valor que resulta no número mínimo de
conflitos com outras variáveis – a heurística de conflitos mínimos.
(RUSSELL; NORVIG, 2004, p. 146).
No Quadro 3 é demonstrado o algoritmo de busca local com a heurística de conflitos
mínimos proposto por Russell e Norvig (2004).
função CONFLITOS-MÍNIMOS(psr, max_etapas) retorna uma solução ou falha
entradas: psr, um problema de satisfação de restrições
max_etapas, o número de etapas permitidas antes de desistir
corrente <- uma atribuição inicial completa para psr
para i=1 até max_etapas faça
se corrente é uma solução para psr então retornar corrente
var<- uma variável em conflito escolhida ao acaso a partir de VARIÁVEIS[psr]
valor<- um valor v para var que minimiza CONFLITOS(var,v,corrente,psr)
definir var = valor em corrente
retornar falha
Fonte: Russell e Norvig (2004, p. 146).
Quadro 3 – Algoritmo de busca local com a heurística de conflitos mínimos
Como exemplo, pode-se citar o problema das 8-rainhas. O algoritmo de busca local
iniciou com uma configuração aleatória das rainhas no tabuleiro conforme a Figura 4.
Verificou-se as rainhas que estavam em conflito, as rainhas 4 e a 8, selecionando uma
aleatoriamente – neste passo a 8. Logo após conta-se os conflitos gerados para cada posição
em que pode ser movida e é escolhido aleatoriamente entre os dois conflitos mínimos gerados.
Por fim deste passo, é movido a rainha para esta nova posição.
21
Fonte: adaptado de Russell e Norvig (2004, p. 147).
Figura 4 – Parte 1 do exemplo de busca local com conflitos mínimos
Com a nova configuração do tabuleiro, é verificado a consistência e detectado que
ainda há inconsistência com as restrições, sendo elas com as rainhas 6 e 8, conforme a Figura
5. É escolhida aleatoriamente – neste passo a 6. Conta-se os conflitos gerados para cada
posição em que pode ser movida e é escolhido o menor valor de conflito mínimo, neste caso o
valor que gerou 0 conflitos, ou seja, a posição na coluna A. É movido a rainha para esta nova
posição.
Fonte: adaptado de Russell e Norvig (2004, p. 147).
Figura 5 – Parte 2 do exemplo de busca local com conflitos mínimos
22
É novamente verificado a consistência e confirmado uma atribuição completa,
conforme a Figura 6. Obteve-se a solução com apenas 2 passos realizados pela busca local
com a heurística de conflitos mínimos.
Fonte: adaptado de Russell e Norvig (2004, p. 147).
Figura 6 – Parte 3 do exemplo de busca local com conflitos mínimos
2.4 CSP && COP BUILDER
O CCB foi desenvolvido para ser usado em conjunto com o dynDCSP, que também foi
implementado pelo GIA, e possui algoritmos de resolução de CSPs de forma distribuída, em
inglês, Distributed Constraint Satisfaction Problem (DCSP) e ainda uma biblioteca capaz de
representar CSPs através de classes em Java. Para que um DCSP seja resolvido na plataforma
dynDCSP, deve-se informar um código fonte que descreve o CSP/ Constraint Optimization
Problem (COP), para que o parser do CCB gere como saída instâncias de objetos que
representam o CSP/COP e disponibilize-as novamente para a plataforma do dynDCSP para
que o mesmo a resolva em um dos seus algoritmos distribuídos.
Com o CSP && COP Builder é possível especificar um CSP/COP a partir de uma
linguagem de alto nível, não sendo necessário manipular códigos fontes de especificação CSP
para a montagem dos domínios, variáveis e restrições.
No Quadro 4, é demonstrado como pode ficar o exemplo da Figura 1, definido na
23
linguagem de alto nível utilizada pelo parser da ferramenta CCB.
Csp
Id: coloração de mapas;
Version: 1.0;
Description: exemplo de definição CSP na linguagem do CCB;
Domains
// as cores como domínio. 1 = vermelho, 2 = verde e 3 = azul
cores : {1,2,3}
Variables
// Os estados como variáveis
ao, tn, q, ngs, v, am, t: cores;
Constraints
//as restrições de vizinhança, note que “t” não tem vizinhança alguma, logo
// não terá restrições.
ao != tn;
ao != am;
tn != am;
tn != q;
am != q;
am != ngs;
am != v;
q != ngs;
ngs != v;
Quadro 4 – Especificação do CSP para o problema da Figura 1
Para a representação de um CSP/COP, a linguagem definida para o CCB segue
basicamente a sintaxe demonstrada no Quadro 5.
Csp | Cop
Id: string; // identificador do problema
Version: float; // versão do problema
Description: string; // descrição do problema
Domains
// definição dos domínios
Variables
// definições das variáveis do problema
Constraints
// restrições do problema (identificador opcional)
Quadro 5 – Especificação da linguagem para construção de CSP/COP do CCB
Em Domains, deve-se definir os domínios como no Quadro 6.
dominio_id : {elemento_dominio_1, elemento_dominio_2, ..., elemento_dominio_n};
Quadro 6 – Especificação de domínio
Os elementos do domínio devem ser declarados como numerais inteiros, conforme
demonstrado no Quadro 7.
// A representação: cores = {verde, vermelho, amarelo} deverá ser especificada da
// seguinte forma:
cores : {1, 2, 3};
Quadro 7 – Exemplo de especificação do domínio
Já as variáveis são declaradas conforme descrito no Quadro 8.
variavel_id : dominio_id;
Quadro 8 – Especificação de variáveis
Após o identificador de cada variável, deve-se colocar o domínio pertencente a ela.
Pode-se ainda identificar várias variáveis pertencentes a um só domínio, separando as com
24
vírgula na identificação das mesmas. No Quadro 9, tem-se um exemplo das definições das
variáveis.
// Uma variável com o domínio “cores”
x1 : cores;
// Quatro variáveis com o domínio “cores”
x1, x2, x3, x4 : cores;
Quadro 9 – Exemplo de especificação das variáveis
Por fim, as restrições são especificadas por expressões numéricas e lógicas. Sua
sintaxe é similar a do Java e tem uma série de funções embutidas como exibida no Quadro 10.
// Operadores/expressões lógicas e relacionais
&& (e)
-- (ou)
‘ (ou exclusivo)
!= (diferente)
== (igualdade)
allDifferent ([lista de variáveis, separadas por vírgula]) (todas diferentes)
// Operadores numéricos
+ (adição)
- (subtração)
* (multiplicação)
/ (divisão)
Sin(valor) (seno(em graus))
Cos(valor) (cosseno(em graus))
// Exemplo de Expressões:
x1 != x2; (x1 deve ser diferente de x2)
allDiff([x1, x2, x3, x4]); (x1, x2, x3 e x4 devem ser diferentes uma das outras)
(x1 + 1) == x4 (a expressão: variável x1 mais 1, deve ser igual a variável x4)
Quadro 10 – Exemplo de especificação das restrições
A interface do CCB é demonstrada na Figura 7. O código fonte contendo a
especificação do CSP na linguagem de alto nível do CCB deve ser digitada ou aberta em um
arquivo no CCB para que o mesmo possa interpretá-la, gerando uma instância do CSP/COP
para que seja usado no framework dynDCSP ou em outra aplicação, no caso, este trabalho,
como na Figura 8.
25
Fonte: Santos (2006, p. 2).
Figura 7 – Tela do editor do CCB
Fonte: Santos (2006, p.1).
Figura 8 – Visão geral do CCB
2.5 DYNDCSP
O dynDCSP tem uma biblioteca em Java chamada CSP que provê a representação de
CSPs a partir de classes, onde podem ser gerados objetos de atribuição, variáveis, restrições,
domínios, o próprio objeto CSP entre outros. No Quadro 11, tem-se um exemplo da
26
representação de um problema CSP em código Java com a biblioteca CSP do dynDCSP.
package helloCSP;
import
import
import
import
import
import
import
csp.CSP;
csp.Constraint;
csp.Value;
csp.Variable;
csp.domains.IntegerDomain;
csp.exp.VariableExpression;
csp.exp.logic.DifferentExpression;
/**
* The Makoto's x1/x2/x3 example
*
* @author jomi
*/
public class HelloCSP extends CSP {
/** Creates a new instance of HelloCSP */
public HelloCSP() {
super("HelloCSP");
// domains
IntegerDomain e1 = new IntegerDomain("oneVl");
e1.addValue(new Value(new Integer(2)));
IntegerDomain e2 = new IntegerDomain("twoVl");
e2.addValue(new Value(new Integer(1)));
e2.addValue(new Value(new Integer(2)));
// variables
Variable x1 = new Variable("x1");
x1.setDomain(e2);
addVariable(x1);
Variable x2 = new Variable("x2");
x2.setDomain(e1);
addVariable(x2);
Variable x3 = new Variable("x3");
x3.setDomain(e2);
addVariable(x3);
// constraints
Constraint c1 = new Constraint();
c1.setExpression(new DifferentExpression(new VariableExpression(x1), new
VariableExpression(x3)));
addConstraint(c1);
Constraint c2 = new Constraint(newDifferentExpression(
newVariableExpression(x2), new VariableExpression(x3)));
addConstraint(c2);
}
}
Fonte: Santos (2006).
Quadro 11 – Exemplo da especificação de um CSP com a biblioteca do dynDCSP
De posse dessa biblioteca, é possível definir CSPs a partir de um código em Java. A
classe
Domain
possui métodos onde é possível criar diversos domínios, cada um deles
rotulados por uma string, para que sejam atribuídos a variáveis. É possível adicionar valores
ou mesmo intervalos na classe Domain. No Quadro 11, tem-se o domínio oneV1 com o valor 2,
objeto da classe Value. As variáveis são da classe Variable que também são rotuladas por uma
27
string
e é possível através do método
setDomain,
As restrições são representadas pela classe
indicar a qual domínio a variável pertence.
Constraint
que pelo método
setExpression
é
possível definir as restrições das variáveis, como a de diferença, com a classe
DifferentExpression.
Quanto ao problema das n-rainhas, no qual sua instanciação deve ser feita informando
o número de rainhas ao construtor da classe como parâmetro. O código fica conforme o
Quadro 12.
//Suprimido imports, saídas de console e alguns comentários para uma melhor
visualização do código em todos os quadros seguintes
public class NQueensCSP extends CSP {
public NQueensCSP(int n) {
super("NQueensCSP");
// creating domains, they are equal for all n-queens
Domain queensDomain = new IntegerDomain("queensDomain", 1, n);
// creating PriorityVariable's to represent the queens
for (int i = 0; i < n; i++) {
Variable av = new Variable("q" + (i + 1));
av.setDomain(queensDomain);
addVariable(av);
}
// creating the constrains for all queens
ArrayList varExpressions = new ArrayList();
Iterator itv = getVariables().iterator();
while (itv.hasNext()){
varExpressions.add(
new VariableExpression( (Variable)itv.next() ));
}
addConstraint( new Constraint(new AllDifferentExpression(varExpressions)));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
Variable xi = (Variable) getVariable("q" + (i + 1));
Variable xj = (Variable) getVariable("q" + (j + 1));
VariableExpression varXi = new VariableExpression(xi);
VariableExpression varXj = new VariableExpression(xj);
AbsExpression ae =
new AbsExpression(new SubtractionExpression(varXi,varXj));
ConstantExpression ce =
new ConstantExpression(new Value( new Integer(Math.abs(i - j))));
DifferentExpression de = new DifferentExpression(ce, ae);
addConstraint(new Constraint(de));
}
}
}
}
Fonte: Santos (2006).
Quadro 12 – Problema das n-rainhas especificado com a biblioteca do dynDCSP
O framework dynDCSP possui dois pacotes, um capaz de representar um CSP e o
outro permite a resolução de DCSPs conforme diagrama de pacotes apresentado na Figura 9.
28
Fonte: Santos (2005, p. 38).
Figura 9 – Pacotes do dynDCSP
Na figura 10, tem-se a visão geral do pacote CSP que contém as classes
Domain, Variable, Value, CSP, Expression
Assignment,
e Constraint para a definição de um CSP.
Fonte: Santos (2005, p. 39).
Figura 10 – Classes do pacote CSP do dynDCSP
29
2.6 TRABALHOS CORRELATOS
O Gnu Prolog é um compilador da linguagem Prolog e também um solucionador de
problemas moldados em CSP. Segundo Dias (2003), ele possui diversas funcionalidades
aplicadas à resolução e definição de CSPs, tais como: variáveis de domínio finito totalmente
integradas com as variáveis e inteiros do Prolog; não é necessário descrever explicitamente o
domínio; restrições podem ser declaradas como termos de primitivas simples e definições de
restrições predefinidas. O Gnu Prolog foi desenvolvido com a linguagem C e utiliza a técnica
de propagação para resolver os CSPs, em particular, a arc-consistency (AC), demonstrada em
Hentenryck (1989 apud DIAS, 2003).
Outro trabalho correlato é o descrito em Tralamazza (2004), que apresenta a
implementação um algoritmo para problema de satisfação de restrição distribuída utilizando
orientação a objetos, a linguagem Java e o algoritmo Asynchronous Weak Commitment
(AWC) como relatado por Yokoo (2001 apud TRALAMAZZA, 2004). Além da
implementação do algoritmo, Tralamazza (2004), aplicou duas heurísticas, conflitos mínimos
e a de valor menos utilizado, que dá a preferência de atribuição para o valor menos utilizado
nas restrições, conforme descrito em Filho et al. (1998).
Um trabalho correlato mais recente (SANTOS, 2005) descreve a implementação de um
algoritmo para a solução de Distributed Constraint Optimization Problem (DCOP),
denominado Asynchronous Distributed Optimization (Adopt), executando-o em um ambiente
distribuído. Foi implementado em Java e um dos objetivos desse trabalho foi especificar uma
modelagem molecular como sendo um CSP/DCSP, visto que há semelhança estrutural entre
uma molécula e um grafo, como descrito em Santos (2005). Utilizou-se da plataforma
dynDCSP no seu trabalho, porém efetuou modificações para que o mesmo pudesse solucionar
COPs, refatorando e incluindo algumas classes.
30
3 DESENVOLVIMENTO DO TRABALHO
As seções subseqüentes apresentam a implementação, especificação e integração do
algoritmo busca-com-retrocesso com heurísticas utilizando recursos do dynDCSP e integrado
com o CCB.
3.1 REQUISITOS PRINCIPAIS DO PROBLEMA A SER TRABALHADO
Os principais requisitos deste trabalho são:
a) implementação do algoritmo busca-com-retrocesso;
b) validação dos resultados obtidos com o algoritmo;
c) implementação das heurísticas:
-
variável mais restritiva;
-
variável mais restringida;
-
conflitos mínimos.
d) validação dos resultados obtidos com o algoritmo e as heurísticas;
e) integrar o algoritmo com o CCB.
3.2 ESPECIFICAÇÃO
Na especificação do trabalho, foi utilizado a ferramenta Enterprise Architect (EA) com
Unified Modeling Language (UML) e em conjunto com o paradigma de orientação a objetos.
Os diagramas são apresentados em seções: diagrama de casos de uso (seção 3.2.1), diagrama
de atividades (seção 3.2.2) e diagrama de classes (seção 3.2.3).
3.2.1
Diagrama de casos de uso
Na Figura 11, é demonstrado o diagrama de casos de uso. O ator usuário do sistema
31
informa o CSP, seleciona a heurística desejada e por fim pode pedir pra resolver o CSP.
Figura 11 – Diagrama de casos de uso
3.2.2
Diagrama de atividades
O diagrama da Figura 12 mostra o diagrama de atividades do algoritmo de busca-comretrocesso da seguinte forma:
a) início do algoritmo;
b) é informado um CSP para o algoritmo;
c) é guardado o tempo inicial e inicializado com o valor zero o número de
verificações de consistência;
d) inicia-se o retrocesso recursivo;
e) se encontrou a solução, calcula o tempo total, exibe tempo total e número de
verificações de consistência, retorna a atribuição completa;
f) senão, calcula o tempo total, exibe tempo total e número de verificações de
consistência e retorna nulo;
g) final do algoritmo.
32
Figura 12 – Diagrama de atividades
3.2.3
Diagrama de classes
O diagrama de classes demonstrado na Figura 13 contém quatro classes:
Conflitos Mínimos, CSP
e
Assignment.
As classes
CSP
e
Assignment
ResolveCSP,
são provenientes da
biblioteca do dynDCSP já foram especificadas em Santos (2005) e são demonstradas no
diagrama apenas para se verificar a ordem de dependência entre essas classes, por isso não
serão detalhadas.
A classe
possui seis atributos:
ResolveCSP
verificações de consistência;
sendo
0
chaveHeuristica,
para não utilizar heurística,
restringida e
3
processamento
1
listVarMaisRestritiva
heurísticas
um
variável mais restritiva e
que
ArrayList
inteiro que conta o número de
inteiro que seleciona qual heurística utilizar
para variável mais restritiva,
para conflitos mínimos,
das
vc,
descHeuristica, long
deve
ser
2
para variável mais
que armazena o tempo de
descontado
do
tempo
total,
que deve armazenar a lista ordenada da heurística
listVarMaisRestringida
ordenada da heurística variável mais restringida.
um
ArrayList
que deve armazenar a lista
33
Figura 13 – Diagrama de classes
Os métodos da classe ResolveCSP são:
a)
pesquisaComRetrocesso
que deve ser enviado como parâmetro o CSP e um inteiro
que seleciona a heurística a ser usada, e por fim retorna um
atribuição completa ou
null.
Assignment,
uma
É por este método que se inicia a busca por uma
solução do CSP;
b)
retrocessoRecursivo
é o método que tornará possível a recursividade do
algoritmo. Deve ser enviado como parâmetro a atribuição e o CSP e retorna um
boolean
c)
para permitir o retrocesso no caso da atribuição não ser consistente;
ehCompleta
verifica se a atribuição está completa, ou seja, se todas as variáveis do
CSP tem um valor válido atribuído. Deve ser enviado como parâmetro o CSP e a
atribuição e retorna um boolean;
d)
getVarSemValor
é um método que retorna a primeira variável não atribuída da lista
de variáveis do CSP. Deve ser enviado como parâmetro a atribuição, o CSP e caso
não haja variáveis que ainda não foram atribuídas, retorna null;
e)
tempoDeExecucao
simplesmente calcula e exibe o tempo de execução em segundos
dado como parâmetros um tempo inicial e um tempo final em nanosegundos.
f)
ordenarVariavelMaisRestritiva
com
a
heurística
de
listVarMaisRestritiva
g)
getVarMaisRestritiva
classe
é o método que ordena as variáveis de acordo
variável
mais
restritiva
no
atributo
de
classe
e deve-se enviar como parâmetro o CSP;
retorna uma variável da seqüência obtida pelo atributo de
listVarMaisRestritiva
e que ainda não foi atribuído, por isso, deve-se
34
enviar a atribuição como parâmetro;
h)
ordenarVariavelMaisRestringida
é o método que ordena as variáveis de acordo
com a heurística de variável mais restringida no atributo de classe
listVarMaisRestringida
i)
getVarMaisRestringida
classe
e deve-se enviar como parâmetro o CSP;
retorna uma variável da seqüência obtida pelo atributo de
listVarMaisRestringida
e que ainda não foi atribuído, por isso, deve-se
enviar a atribuição como parâmetro.
A classe
contém o algoritmo de busca local com a heurística de
ConflitosMinimos
conflitos mínimos. Segue os métodos da classe ConflitosMinimos.
a)
iniciaConflitosMinimos
é o método que retorna uma atribuição completa ou
null
quando enviado como parâmetros o CSP e um inteiro que denomina a quantidade
de etapas na busca efetuada pela heurística;
b)
getValorConflitosMinimos
é o método que se deve enviar uma variável, o CSP e a
atribuição retornando um Value contendo o valor de conflitos mínimos;
c)
getNumeroConflitos
retorna um inteiro contendo o número de conflitos que
variável e o valor enviados como parâmetro causam. Também deve ser enviado
como parâmetros a atribuição e o CSP;
d)
getVariaveisConflitantes
retorna uma lista com as variáveis conflitantes contidas
na atribuição, que deve ser enviado como parâmetro juntamente com o CSP;
e)
getViolacoes
é o método que retorna um int que denomina o número de violações
que a variável e valor enviados como parâmetro criam com relação às restrições;
f)
atribuicaoAleatoria
retorna uma atribuição com valores aleatórios atribuídos a
variáveis. Um detalhe fundamental é que a atribuição aleatória não é
necessariamente uma atribuição completa, cabe ao algoritmo de busca local efetuar
essa verificação. Deve ser enviado como parâmetro o CSP;
g)
selecionaVarAleatoria
é o método que retorna uma variável de forma aleatória,
dado uma lista de variáveis como parâmetro;
h)
getDominio
retorna um ArrayList com o domínio enviado como parâmetro.
3.3 IMPLEMENTAÇÃO
A seção implementação está dividida em 2 seções. A primeira (seção 3.3.1), denota as
35
técnicas e ferramentas utilizadas ao longo da implementação deste trabalho enquanto a
segunda (seção 3.3.1), demonstra a operacionalidade da implementação.
3.3.1
Técnicas e ferramentas utilizadas
A implementação deste trabalho foi realizada com as técnicas de orientação a objetos
que proporciona a linguagem de programação Java versão 5.0 e o ambiente de programação
Eclipse versão 3.1.
Juntamente com o Java e o Eclipse, utilizou-se também o framework dynDCSP que
disponibilizou toda uma solução para definição de CSPs por intermédio de classes em Java e
do CCB, parte integrante do dynDCSP, que possibilita a definição de um CSPs em uma
linguagem de alto nível para que o mesmo faça a interpretação e gere os objetos provindos
das classes que o dynDCSP disponibiliza.
É importante citar que mesmo o trabalho utilizando o Java, a literatura expõe
algoritmos de forma estruturada. Portanto, mesmo este trabalho contendo classes, métodos e
relações conforme o paradigma de orientação a objetos recomenda, a programação dos
métodos em si, foi feita de forma estruturada, o que facilita a didática, tendo a mesma
seqüência e programação que é demonstrada nos algoritmos recomendados por Russel e
Norvig(2004).
3.3.1.1 Implementação do algoritmo busca-com-retrocesso
A primeira parte da implementação deste trabalho foi programar o algoritmo de
resolução de CSPs busca-com-retrocesso. Durante a etapa de desenvolvimento, o mesmo
sofreu diversas melhorias com relação ao código em Java, até obter-se um algoritmo com
código simples e objetivo. O algoritmo de busca-com-retrocesso ficou implementado de
acordo com o Quadro 13, o Quadro 14, o Quadro 15 e com o Quadro 16.
No Quadro 13 é apresentado parte do código da classe
pesquisaComRetrocesso.
Pode-se verificar que o método
resolveCSP
com o método
pesquisaComRetrocesso
inicia o
algoritmo para a busca da solução do CSP. Ao chamar este método, devem ser enviados como
parâmetros o objeto csp e um inteiro que fará o papel de um seletor para a heurística desejada.
Observa-se que logo de início, é guardado o tempo inicial e também seleciona a heurística que
36
foi acionada com o parâmetro
usarHeuristica
vazia, é efetuado um condicional
if
e que logo após criar o objeto de atribuição
chamando o método recursivo
retrocessoRecursivo,
enviando como parâmetros a atribuição e o CSP, para que seja criado a árvore de busca, e
quando finalizar, ele deverá retornar
true
ou
false,
sinalizando se foi encontrada ou não a
solução, para aí sim calcular o tempo de execução, número de verificações de consistência e
retornar para o método ou a atribuição completa ou nulo.
public Assignment pesquisaComRetrocesso(CSP csp,int usarHeuristica){
//Seta qual heurística será usada
chaveHeuristica = usarHeuristica;
//Determina heurística
switch(chaveHeuristica){
case 1:
//Ordena lista de variavel mais restritiva
ordenarVariavelMaisRestritiva(csp);
break;
case 2:
//Ordena lista de variavel mais restringida
ordenarVariavelMaisRestringida(csp);
break;
case 3:
//Pega tempo inicial da heuristica
tInicial = System.nanoTime();
//Tenta resolver pelos conflitos mínimos
Assignment confMinAtrib =
new ConflitosMinimos().iniciaConflitosMinimos(csp,50,this);
//se achou resposta
if(confMinAtrib != null){
//calcula e exibe o tempo de execução
tempoExecucao(tInicial,System.nanoTime(),descHeuristica);
//retorna a atribuição completa
return confMinAtrib;
};
}
//Pega tempo inicial
long tInicial = System.nanoTime();
//Cria o objeto de atribuiçao vazia
Assignment atribuicao = new Assignment();
//Inicia retrocesso recursivo RETROCESSO-RECURSIVO( {}, psr )
if (retrocessoRecursivo(atribuicao,csp)) {
//calcula e exibe o tempo de execução
tempoExecucao(tInicial,System.nanoTime(),descHeuristica);
//retorna a atribuição completa
return atribuicao;
} else {
//calcula e exibe o tempo de execução
tempoExecucao(tInicial,System.nanoTime(),descHeuristica);
//retorna nulo, ou seja, não há solução para o CSP
return null;
}
}
Quadro 13 – Método pesquisaComRetrocesso da classe resolveCSP
No quadro 14, é demonstrado o método
classe resolveCSP.
retrocessoRecursivo
também incluso na
37
private boolean retrocessoRecursivo(Assignment atrib, CSP csp) {
//Se atribuição está completa
if( ehCompleta(atrib, csp) ){
//Então retorna a Atribuição completa
return true;
}
//var <- SELECIONAR VARIAVEL NAO ATRIBUIDA
Variable var = null;
switch(chaveHeuristica){
case 0:
var = getVarSemValor(atrib, csp);
break;
case 1:
var = Heuristicas.getVarMaisRestritiva(atrib);
break;
case 2:
var = Heuristicas.getVarMaisRestringida(atrib);
break;
}
//Para cada valor do Domínio faça
Iterator i = var.getDomain().iterator();
while(i.hasNext()){
Value v = (Value)i.next();
//adiciona valor e variável na Atribuição
atrib.putVariableValue(var, v);
//Incrementa verificações de consistência
vc++;
//Se valor é consistente na atribuição
if (csp.isConsistent(atrib)){
//resultado <- RETROCESSO RECURSIVO(atribuicao,csp)
if (retrocessoRecursivo(atrib,csp)) {
//retorna resultado
return true;
}
}
//Remove variável e valor da Atribuição
atrib.removeVariable(var);
}
//retorna resultado falso
return false;
}
Quadro 14 – Método retrocessoRecursivo da classe resolveCSP
No início do método
método
ehCompleta
retrocessoRecursivo
é efetuado um condicional
if
com o
enviando a atribuição e o CSP como parâmetros que verifica se a
atribuição é completa, retornando
true.
Caso a atribuição não esteja completa, é selecionada
uma variável que ainda não foi atribuída, utilizando heurística, ou não, dependendo da entrada
inicial do algoritmo com a chave
chaveHeuristica.
Se não foi utilizado heurística na seleção
da variável, é apenas retornada uma da lista de variáveis do objeto
getVarSemValor,
csp
com o método
enviando como parâmetros a atribuição para descobrir quais variáveis já
foram atribuídas e o objeto csp para obter a lista de variáveis.
Após, para cada valor do domínio da variável selecionada, é adicionado a variável e o
valor na atribuição e verificado se a consistência com as restrições é mantida com o método
isConsistent,
condicional
encontrado na classe
if,
e retornado
true
CSP
da biblioteca dynDCSP. Sendo sim, é feito mais um
é feita a recursividade chamando o próprio método
38
retrocessoRecursivo.
Caso contrário, a atribuição inconsistente é removida e é continuado o
laço iterativo de cada valor do domínio da variável.
Quando a árvore montada tiver uma atribuição completa, os métodos subseqüentes
chamados recursivamente, retornaram true sucessivamente até o algoritmo chegar no método
pesquisaComRetrocesso,
que é o primeiro nível da busca, para retornar a atribuição, o mesmo
pode-se dizer quando não se consegue achar a consistência com as atribuições, retornando
false,
e por fim o método pesquisaComRetrocesso retornando null.
A seguir, o Quadro 15 exibe o método
ehCompleta
que verifica se a atribuição é
completa.
public boolean ehCompleta(Assignment atrib, CSP csp){
int atribSize = atrib.size();
int varsSize = csp.getVariables().size();
return atribSize == varsSize;
}
Quadro 15 – Método ehCompleta da classe resolveCSP
O método ehCompleta avalia o tamanho das listas de atribuição e das variáveis do CSP,
se os tamanhos forem iguais, retorna true, senão false. Esse método se tornou simples pois a
atribuição sempre será consistente antes da sua chamada, bastando apenas verificar se o
tamanho da lista atribuição corresponde com o tamanho da lista de variáveis do CSP.
O método getVarSemValor é um método que meramente retorna a primeira variável não
atribuída da lista de variáveis. As variáveis do CSP são percorridas e é efetuado o condicional
if
para verificar se a variável atual da lista ainda não foi atribuída, caso verdadeiro, retorna-se
a variável, caso contrário, continua-se percorrendo até achar a variável que ainda não foi
atribuída. Ocorrendo o término da lista, ou seja, não havendo nenhuma variável sem valor, é
retornado null. No Quadro 16 e demonstrado o método getVarSemValor.
private Variable getVarSemValor(Assignment atrib, CSP csp){
ArrayList variaveis = new ArrayList();
variaveis = (ArrayList)csp.getVariables();
for(int i=0; i < variaveis.size(); i++){
Variable var = (Variable)variaveis.get(i);
if(!atrib.contains(var)){
return var;
}
}
return null;
}
Quadro 16 – Método getVarSemValor da classe resolveCSP
Com o algoritmo busca-com-retrocesso implementado, a validação do mesmo foi
efetuada com o problema de coloração de mapas, e com sucesso, obteve-se como solução a
saída do console conforme o Quadro 17.
39
Algoritmo Iniciado...
*** Atribuicao Completa! ***
Verificações de Consistência = 21
Tempo de execução= 0.007523861 segundos.
{v=azul, tn=verde, t=azul, q=azul, ngs=verde, ao=azul, am=vermelho}
Quadro 17 – Saída do console da resolução de um CSP
Como se pode observar no Quadro 17, o algoritmo busca-com-retrocesso executou
quatorze verificações de consistência (VC), ou seja, chamou o método
isConsistent
do CSP
quatorze vezes. O tempo de execução do algoritmo foi de 0,007523861 segundos e obteve
como resposta para o problema, a atribuição {v=verde, tn=azul, t=vermelho, q=verde,
ngs=azul, ao=verde, am=vermelho}, uma solução consistente para o problema.
3.3.1.2 Implementação da heurística variável mais restritiva
Ao invés do algoritmo busca-com-retrocesso chamar o método
chamado o método
getVariavelMaisRestritiva
getVarSemValor,
é
quando a heurística é ativada. A
implementação é apresentada no Quadro 18.
//Retorna a primeira variavel mais restrita não atribuída
private Variable getVariavelMaisRestritiva(Assignment atrib){
//Para todas as variáveis da lista de mais restritas
for(int i=0;i < listVarMaisRestritiva.size();i++){
//se a variável mais restritiva atual não foi atribuída
if(!atrib.contains((Variable)listVarMaisRestritiva.get(i))){
//então retorna a variável mais restritiva atual
return (Variable)listVarMaisRestritiva.get(i);
}
}
//Retorna null caso não haja mais variáveis mais restritivas não atribuídas
return null;
}
Quadro 18 – Método getVariavelMaisRestritiva da classe resolveCSP
Para obter a variável mais restrita não atribuída, deve ocorrer antes o método
ordenarVariávelMaisrestritiva,
que pega a lista de todas as variáveis do CSP e as ordena em
ordem crescente de acordo com o maior número de restrições. Implementou-se a heurística de
variável mais restritiva, conforme o Quadro 19 onde contém o seu algoritmo nas linhas de
comentário, que são antecedidas por //.
40
//***HEURÍSTICA*** = VARIÁVEL MAIS RESTRITIVA (VAR COM O MAIOR NRO DE RESTRIÇÕES)
private void ordenarVariavelMaisRestritiva(CSP csp){
//Inicializa o maior número de restrições
int maiorNumRestricoes = 0;
//Map para guardar a variável e o número de restrições
Map<Variable,Integer> mapVariavelRestricoes = new HashMap<Variable,Integer>();
//Enquanto há restrições
Collection r = csp.getConstraints();
Iterator it = r.iterator();
while(it.hasNext()){
//Pega próxima restrição
Constraint cons = (Constraint) it.next();
//Pega a expressão da restrição
Expression exp = cons.getExpression();
//Pega as envolvidas na expressão da restrição
ArrayList variaveisDaExpressao = (ArrayList)exp.getVariables();
//Para cada variável da expressão
for(int i=0;i<variaveisDaExpressao.size();i++){
//Pega a variavel atual
Variable variavelAtual = (Variable)variaveisDaExpressao.get(i);
//se variável já está no map
if(mapVariavelRestricoes.containsKey(variavelAtual)){
//pega o qde atual de restrições
int qdeAtual = mapVariavelRestricoes.get(variavelAtual);
//remove do map
mapVariavelRestricoes.remove(variaveisDaExpressao.get(i));
//insere no map com a qde incrementada com 1
mapVariavelRestricoes.put(variavelAtual,qdeAtual+1);
//Se a qdeAtual+1 for o maior número de restrições
if((qdeAtual+1 > maiorNumRestricoes)){
//o maior número de restrições é o atual
maiorNumRestricoes= qdeAtual+1;
}
}else{
//senão adiciona a variável com 1 restrição
mapVariavelRestricoes.put(variavelAtual,1);
//Se a qdeAtual(1) for o maior número de restrições
if((1 > maiorNumRestricoes)){
//o maior número de restrições é o atual
maiorNumRestricoes= 1;
}
}
}
}
//ORDENAÇÃO
for (int x=maiorNumRestricoes;x >= 0;x--){
for(int i=0;i < csp.getVariables().size();i++){
Variable var= (Variable)csp.getVariables().get(i);
//Se lista acabou, sobrou as vars sem restrição, entao adicionar todas
if(x==0){
if(!listVarMaisRestritiva.contains(var)){
listVarMaisRestritiva.add(var);
}
}else{
if(mapVariavelRestricoes.containsKey(var))
if((int)mapVariavelRestricoes.get(var) == x)
listVarMaisRestritiva.add(var);
}
}
}
}
Quadro 19 – Método ordenarVariavelMaisRestritiva da classe resolveCSP
41
3.3.1.3 Implementação da heurística variável mais restringida
Observa-se no Quadro 20 a implementação da heurística de variável mais restringida,
contendo em suas linhas de comentário, o algoritmo da mesma.
//***HEURÍSTICA***= VARIÁVEL MAIS RESTRINGIDA (VAR MENOR NRO DE VALORES DO DOMÍNIO)
private void ordenarVariavelMaisRestringida(CSP csp){
//Lista de seleção das variáveis
Map<Variable,Integer> mapVariavelQtde = new HashMap<Variable,Integer>();
//Menor quantidade de valores do domínio
int menorQtde = Integer.MAX_VALUE;
//Maior quantidade de valores do domínio
int maiorQtde = 0;
//Pega a lista de variaveis do CSP
ArrayList variaveis = (ArrayList)csp.getVariables();
//Para cada variável do CSP
for(int i=0;i<variaveis.size();i++){
//Inicia quantidade atual com 0
int qtdeAtual=0;
//Pega a variavel atual
Variable variavelAtual = (Variable)variaveis.get(i);
//Para cada valor do dominio da variável
Iterator it = variavelAtual.getDomain().iterator();
while(it.hasNext()){
it.next();
//incrementa quantidade de valores do domínio
qtdeAtual++;
}
//Se menor quantidade, guarda
if(qtdeAtual<menorQtde )
menorQtde= qtdeAtual;
//Se maior quantidade, guarda
if(qtdeAtual>maiorQtde)
maiorQtde= qtdeAtual;
//adiciona variavel e quantidade na lista
mapVariavelQtde.put(variavelAtual,qtdeAtual);
}
//ORDENAÇÃO
for (int x=menorQtde;x <= maiorQtde;x++){
for(int i=0;i < csp.getVariables().size();i++){
//Se lista acabou, sobrou as vars sem restrição, entao adicionar todas
if(x==0){
if(!listVarMaisRestringida.contains(csp.getVariables().get(i))){
listVarMaisRestringida.add((Variable)csp.getVariables().get(i));
}
}else{
if((int)mapVariavelQtde.get(csp.getVariables().get(i)) == x)
listVarMaisRestringida.add((Variable)csp.getVariables().get(i));
}
}
}
}
Quadro 20 – Método ordenarVariavelMaisRestringida da classe resolveCSP
Assim como na heurística de variável mais restritiva é chamado um método para
retornar a primeira variável mais restritiva não atribuída, a heurística de variável mais
restringida funciona da mesma forma, só que ordenando a lista de variáveis do CSP de forma
decrescente pela quantidade de valores do seu domínio. Pode-se observar o método
getVariavelMaisRestringida
no Quadro 21.
42
//Retorna a primeira variavel mais restringida não atribuída
private Variable getVariavelMaisRestringida(Assignment atrib){
//Para todas as variáveis da lista de mais restringidas
for(int i=0;i < listVarMaisRestringida.size();i++){
//se a variável mais restringida atual não foi atribuída
if(!atrib.contains((Variable)listVarMaisRestringida.get(i))){
//então retorna a variável mais restringida atual
return (Variable)listVarMaisRestringida.get(i);
}
}
//Retorna null caso não haja mais variáveis mais restringidas não atribuídas
return null;
}
Quadro 21 – Método getVariavelMaisRestringida da classe resolveCSP
3.3.1.4 Implementação da heurística de conflitos mínimos em busca local
A busca local com a heurística de conflitos mínimos é um algoritmo independente de
pré-processamento que se inicia antes do algoritmo de busca-com-retrocesso e caso ele
encontre a solução, é terminado o algoritmo ou caso contrário, é iniciado a busca-comretrocesso.
Para
iniciar
iniciaConflitosMinimos
esta
da Classe
busca
heurística,
ConflitosMinimos.
é
necessário
chamar
o
método
No Quadro 22 é possível visualizar o
algoritmo implementado da heurística de conflitos mínimos.
//Inicia Heurística de Conflitos Mínimos
public Assignment conflitosMinimos(CSP csp,int maximoEtapas){
//Inicia a atribuição com uma estado aleatório de valores
Assignment corrente = atribuicaoAleatoria(csp);
//Para cada passo de etapas
for(int i=1;i <= maximoEtapas;i++){
//Se o CSP é consistente e a atribuição é completa
if((csp.isConsistent(corrente))&&(ehCompleta(corrente,csp)))
//retorna a corrente(atribuição)
return corrente;
//Senão, seleciona uma variável aleatória da lista de conflitantes
Variable varConflitante =
selecionaVarAleatoria(getVariaveisConflitantes(csp,corrente));
//Seleciona o valor de conflitos mínimos pra variável conflitante escolhida
Value valorConflitoMinimo =
getValorConflitosMinimos(varConflitante,csp,corrente);
//remove a variavel e valor antigos da atribuição
corrente.removeVariable(varConflitante);
//Insere variavel e novo valor a atribuição
corrente.putVariableValue(varConflitante,valorConflitoMinimo);
}
//Se acabou tentativas, retorna null
return null;
}
Quadro 22 – Método iniciaConflitosMinimos da classe ConflitosMinimos
O método
getValorConflitosMinimos
retorna o valor que gera o número mínimo de
conflitos para uma variável enviada como parâmetro. Este método é apresentado no Quadro
23.
43
private Value getValorConflitosMinimos(Variable var,CSP csp, Assignment atrib){
//Map para os valores e conflitos
Map<Value,Integer> selectCM = new HashMap<Value,Integer>();
//Conflitos mínimos recebe o maior inteiro possível
int conflitosMinimos = Integer.MAX_VALUE;
Iterator i = var.getDomain().iterator();
//Enquanto tem valores do domínio da variável
while(i.hasNext()){
Value valor = (Value)i.next();
//Pega a quantidade de conflitos atuais
int conflitosAtual= getNumeroConflitos(var,valor,atrib,csp);
//Insere valor e conflitos atuais
selectCM.put(valor,conflitosAtual);
//Se conflito atual for menor que conflitos mínimos
if(conflitosAtual < conflitosMinimos){
//Conflitos mínimos é o atual
conflitosMinimos= conflitosAtual;
}
}
//Escolher o valor de conflito mínimo aleatório
List vars = new ArrayList();
i = var.getDomain().iterator();
while(i.hasNext()){
Value valor = (Value)i.next();
if(selectCM.get(valor) == conflitosMinimos)
vars.add(valor);
}
Collections.shuffle(vars);
//Retorna o primeiro da lista aleatória
return (Value)vars.get(0);
}
Quadro 23 – Método getValorConflitosMinimos da classe ConflitosMinimos
O método getNumeroConflitos retorna a quantidade de conflitos que uma variável gera
ao ser atribuída com o valor enviado como parâmetro. Sua implementação é apresentada no
Quadro 24.
private int getNumeroConflitos(Variable variavelConflitante, Value valor,
Assignment atrib,CSP csp) {
//Pega uma cópia da atribuicao
Assignment copiaAtrib = (Assignment)atrib.clone();
//remove a variavel conflitante da cópia
copiaAtrib.removeVariable(variavelConflitante);
//atribui novo valor na cópia
copiaAtrib.putVariableValue(variavelConflitante, valor);
//pega as variáveis conflitantes
//List varsConflitantes = getVariaveisConflitantes(csp,copiaAtrib);
//retorna o nro de conflitos(nro de vars conflitantes)
int nroConflitos = getViolacoes(csp, copiaAtrib,variavelConflitante);
return nroConflitos;
}
Quadro 24 – Método getNumeroConflitos da classe ConflitosMinimos
O método
getVariaveisConflitantes
retorna uma lista com as variáveis que estão em
conflito na atribuição. Este método é apresentado no Quadro 25.
44
private List getVariaveisConflitantes(CSP csp,Assignment atrib) {
List variaveisConflitantes = new ArrayList();
List variaveis = csp.getVariables();
//Para cada variável do CSP
for(int i=0;i<variaveis.size();i++){
//pega a variavel atual
Variable variavelAtual = (Variable)variaveis.get(i);
//Se não é satisfeito com o valor
if (getViolacoes(csp,atrib,variavelAtual) != 0)
//Variável é conflitante!
variaveisConflitantes.add(variavelAtual);
}
return variaveisConflitantes;
}
Quadro 25 – Método getVariaveisConflitantes da classe ConflitosMinimos
Para obter o número de violações de uma variável é utilizado o método
getViolacoes.
Este mesmo método é utilizado para saber se uma atribuição é consistente, retornando 0 para a
possibilidade. Este método é apresentado no Quadro 26.
private int getViolacoes(CSP csp, Assignment atrib, Variable var) {
//Numero de violações
int violacoes = 0;
Collection r = csp.getConstraints();
Iterator it = r.iterator();
//Enquanto tiver restrições
while(it.hasNext()){
//Próxima restrição
Constraint cons = (Constraint) it.next();
//Pega a expressão
Expression exp = cons.getExpression();
//Pega as variaveis da expressão
ArrayList variaveis = (ArrayList)exp.getVariables();
//Se variavel foi atribuída
if (variaveis.contains(var)) {
try {
//Se tem violação
if (!cons.eval(atrib))
//Incrementa violações
violacoes++;
} catch (VariableNotFoundException e) {
e.printStackTrace();
}
}
}
//retorna as violações
return violacoes;
}
Quadro 26 – Método getViolacoes da classe ConflitosMinimos
O método
atribuicaoAleatoria
gera uma atribuição aleatória para o CSP informado,
podendo a mesma ser consistente ou não. Este método é apresentado no Quadro 27.
45
private Assignment atribuicaoAleatoria(CSP csp){
Assignment atribuicao = new Assignment();
//Para cada variavel do CSP
for(int i=0; i< csp.getVariables().size(); i++){
//Pega a variavel
Variable variavel = (Variable)csp.getVariables().get(i);
//Pega um valor aleatório
Domain dominio = variavel.getDomain();
//System.out.println(dom);
List listDominio = getDominio(dominio);
Collections.shuffle(listDominio);
Value v = (Value)listDominio.get(0);
//Atribui Valor a Variável
atribuicao.putVariableValue(variavel,v);
}
//Retorna Atribuição
return atribuicao;
}
Quadro 27 – Método atribuicaoAleatoria da classe ConflitosMinimos
Para obter uma variável aleatória a partir de uma lista de variáveis, usa-se o método
selecionaVarAleatoria.
Esse método é mostrado no Quadro 28.
private Variable selecionaVarAleatoria(List vars){
Random randomGenerator;
randomGenerator = new Random();
int index = randomGenerator.nextInt(vars.size());
return (Variable)vars.get(index);
}
Quadro 28 – Método selecionaVarAleatoria da classe ConflitosMinimos
O método
getDominio
retorna um
ArrayList
de um domínio enviado como parâmetro.
No Quadro 29 pode-se visualizar este método.
private ArrayList getDominio(Domain d){
ArrayList dominio = new ArrayList();
Iterator i = d.iterator();
while(i.hasNext()){
Value v = (Value)i.next();
dominio.add(v);
}
return dominio;
}
Quadro 29 – Método getDominio da classe ConflitosMinimos
3.3.1.5 Integração com o CCB
Para a integração deste trabalho com o CCB, não bastou só a adaptação deste para que
o mesmo funcione com o CCB. Foi necessário importar os pacotes e classes que
implementam o CCB e editá-las a fim de remover as referências com o framework DynDCSP
pois o mesmo funcionava somente a partir da execução deste framework.
Os pacotes importados foram os de interface, de análise semântica e de análise
sintática. No pacote
ui,
que contém a interface do CCB foi modificado a classe
BuilderGUI
46
para que se pudesse selecionar através de um
comboBox
a heurística desejada conforme o
Quadro 30.
box = new Choice();
box.addItem("Only Backtracking");
box.addItem("Backtracking with V+Rtt");
box.addItem("Backtracking with V+Rtg");
box.addItem("Backtracking with MinC");
toolBar.add(box);
Quadro 30 – Inserção de um comboBox na classe BuilderGUI
Ao invés do botão
buildProblemFile
da classe
Build
gerar os objetos da classe CSP com o método
BuilderGUI,
este mesmo botão foi modificado para
Solve
e além
de gerar os objetos do CSP, enviá-los para o algoritmo busca-com-retrocesso resolver e
retornar a atribuição, exibindo o sucesso ou não da resposta para o problema encontrado. A
modificação é demonstrada no Quadro 31.
private void buildProblemFile(){
if ( saveFile() ){
errorMessages.setText("--- COMPILING ----\n\r");
getBuilder().buildProblem(file);
Iterator i = getBuilder().getBuiltProblems().values().iterator();
while(i.hasNext()){
resolveCSP.BuiltProblem ccb = (resolveCSP.BuiltProblem)i.next();
Assignment result = new ResolveCSP().pesquisaComRetrocesso(
ccb.getProblem(),box.getSelectedIndex());
errorMessages.setText("--- RESULT ---- \n\r"+result.toString());
}
}
}
Quadro 31 – Inserção do método pesquisaComRetrocesso na classe BuilderGUI
3.3.2
Operacionalidade da implementação
Para a operacionalidade da implementação, deve-se ter a pasta com todo o projeto
ResolveCSP,
abri-la e executar o arquivo de lote
executa.bat
ou executar a linha de comando
conforme o Quadro 32, que é o mesmo conteúdo do arquivo de lote.
java -classpath bin;lib/dcsp.jar resolveCSP.GeraInterfaceCCB
Quadro 32 – Arquivo de lote executa.bat
É possível também executá-lo através da IDE Eclipse, abrindo o projeto ResolveCSP, e
executar como um aplicativo Java a classe geraInterfaceCCB demonstrada no Quadro 33. Esta
classe contém o método
CSP.
main
que executa e exibe a interface do CCB para a resolução de um
47
package resolveCSP;
import ui.BuilderGUI;
public class GeraInterfaceCCB {
public static void main(String[] args) {
new BuilderGUI().show();
}
}
Quadro 33 – Classe GeraInterfaceCCB
Para executar o CCB é necessário importar a classe
interface do CCB e criar um método
BuilderGUI
main.
para poder executar o método
ui.BuilderGUI,
que contém a
Após é preciso criar um objeto da classe
show.
Logo após executar o programa pela forma
escolhida, é exibido a tela conforme a Figura 14.
Figura 14 – Interface do CCB
Após o início de interface, é possível especificar um CSP no primeiro campo de texto
disponível observando de cima para baixo, ou mesmo abrir um arquivo de texto contendo o
CSP previamente salvo pelo CCB.
Para verificar a operacionalidade do trabalho, especificou-se um CSP do problema de
coloração com o mapa de Santa Catarina. Considerou-se as como regiões do problema, as
cidades do estado e o domínio contendo 6 cores. A especificação na linguagem de alto nível
do CCB teve quase 1922 linhas.
Para abrir o arquivo de texto que deverá conter a especificação de um CSP, deve-se
clicar no menu File e depois em Open ou pressionar CTRL
+ O
ou ainda clicar no botão abrir na
48
barra de ferramentas do programa. Logo após, aparecerá uma tela similar ao da Figura 15.
Figura 15 – Tela abrir arquivo
Localiza-se e seleciona-se o arquivo desejado e clica-se em
open
similar a da Figura 16.
Figura 16 – Tela do CBB com um CSP especificado
e será exibido a tela
49
Com o CSP definido na tela, deve-se escolher o método de resolução do CSP, assim
como na Figura 17.
Figura 17 – Seleção do método de resolução
Se é preferido só a busca-com-retrocesso, seleciona-se a primeira opção,
Backtracking.
Only
Se é desejado a busca-com-retrocesso com a heurística de variável mais
restritiva, seleciona-se a segunda opção
Backtracking with V+Rtt.
Caso seja preferido a
busca-com-retrocesso com a heurística de variável mais restringida, seleciona-se a opção
Backtracking
with
V+Rtg.
Ou ainda, se é preferido a heurística de conflitos mínimos,
seleciona-se a quarta e última opção Backtracking
with MinC.
Neste último caso, o algoritmo
de busca local com a heurística de conflitos mínimos será iniciado e caso não encontre a
solução em um número de 50 etapas, é iniciado o algoritmo de busca-com-retrocesso.
Depois de selecionada a opção de busca com a heurística, é possível clicar em
Solve
para iniciar o algoritmo de busca com a opção de heurística desejada, assim como na Figura
18.
50
Figura 18 – Tela do CBB com um CSP especificado e resolvido com heurística
3.4 RESULTADOS E DISCUSSÃO
Os resultados que serão mostrados, foram obtidos a partir de um notebook com
processador AMD Athlon 64bits 3200+ com 512Mb de memória RAM (Random Access
Memory) e sistema operacional Microsoft Windows XP Professional. É importante salientar
que todo o processamento e tempo gasto pelas heurísticas está sendo ignorado, já que a
gerência do tempo gasto com elas, é obtido implementando métodos de gerência como o de
consistência de arcos, existentes em Russell e Norvig (2004). Com relação ao algoritmo e
heurística de conflitos mínimos optou-se por 50 como limite de passos máximos que este
algoritmo pode efetuar, pois, conforme Russell e Norvig (2004, p.147), a heurística de
conflitos mínimos por busca local resolve até mesmo o problema de um milhão de rainhas em
uma média de 50 etapas. Nesta busca heurística, é considerado todo o tempo de busca, para
demonstrar como o tempo de processamento da heurística influencia no tempo decorrido do
início até a solução do problema.
51
Para realizar uma análise dos trabalhos correlatos em relação a este trabalho, optou-se
por somente incluir o Gnu Prolog. Isso deve-se ao mesmo ser o único trabalho correlato que
utiliza um algoritmo de busca centralizada. Somente será apresentado o mesmo quando
houverem comparações com relação ao tempo de execução, devido ao mesmo não exibir o
número de verificações de consistência que efetua.
Ao executar o algoritmo aplicado ao problema de coloração de mapas da Figura 1 por
10 vezes seguidas e calculando a média das execuções, observa-se na Figura 19 que houve um
ganho nítido comparado ao algoritmo de busca-com-retrocesso com o mesmo algoritmo
aplicado a heurística de variável mais restritiva e o de conflitos mínimos. Na busca pelo
solução do CSP, o algoritmo de busca-com-retrocesso teve que gerar 21 nodos no seu grafo,
ou seja, teve de verificar a consistência da atribuição 21 vezes, enquanto o mesmo algoritmo
aplicado a heurística de variável mais restritiva, gerou 15 nodos. A heurística de conflitos
mínimos diminuiu ainda mais o número de verificações de consistência para somente 8. Notase que foi obtido um ganho expressivo apesar de ser um problema relativamente simples para
o algoritmo. Não foi testado esse problema com a heurística de variável mais restringida
devido ao fato do problema não possuir domínios diferentes para cada variável, tornando
assim desnecessário a sua aplicação.
Verificações de Consistência (VC)
25
21
20
15
15
10
8
5
0
Busca-com-retrocesso
Busca-com-retrocesso com
variável mais restritiva
Conflitos Mínimos
Figura 19 – VC das execuções: problema da Figura 1
Calculando a média dos tempos de execução em milisegundos, obteve-se o gráfico da
Figura 20. O Gnu Prolog teve um tempo 9 vezes melhor que o menor tempo obtido por este
trabalho. Isso se deve ao fato do mesmo utilizar mais heurísticas e métodos de verificação
prévia como a de consistência de arcos. Nota-se que o algoritmo busca-com-retrocesso obteve
52
ganho quando aplicado a heurística de variável mais restritiva. A heurística de conflitos
mínimos gastou mais de 5 vezes o tempo que o algoritmo de busca-com-retrocesso, porém
obteve a solução com menos VC, conforme a Figura 16.
40,0
34,8
Tempo em milisegundos
35,0
30,0
25,0
20,0
15,0
7,4
10,0
5,0
5,5
0,6
0,0
Gnu Prolog
Busca-comretrocesso
Busca-comretrocesso com
Variável mais
restritiva
Conflitos Mínimos
Figura 20 – Tempo médio das execuções: problema da Figura 1
Para obter soluções com menor número de VC com a heurística de variável mais
restringida, especificou-se um CSP de coloração de mapas com domínios diferentes aplicados
às variáveis do CSP.
As restrições deste problema podem ser observadas no grafo conforme a Figura 21.
Figura 21 – Problema de coloração de mapas com domínios diferentes.
A especificação deste CSP no CCB ficou conforme o Quadro 34.
53
Csp
Id: Coloracao mapas com dominios diferentes;
Version: 1.0;
Description: Coloracao de mapas. Autor Alexsandro S Pires;
Domains
cores1 : {1};
cores2 : {1,2};
cores3 : {1,2,3};
Variables
A, B, C : cores3;
D, E, F : cores2;
G, H : cores1;
Constraints
A != B;
A != C;
A != E;
A != G;
A != H;
B != E;
B != F;
C != E;
C != F;
D != F;
E != F;
F != G;
Quadro 34 – Código fonte do problema de coloração de mapas com domínios diferentes
Ao executar este CSP por 10 vezes seguidas, e obtendo-se a média das verificações de
consistência, obteve-se o resultado conforme a Figura 22. O resultado obtido com este
problema foi ainda maior aplicado as heurísticas. Houve um ganho de no mínimo 20% se
comparado as execuções heurísticas do que só o algoritmo de busca-com-retrocesso. É
importante citar que a heurística de conflitos mínimos não encontrou a solução em 2
execuções das 10 feitas, devido a isto, sua média das verificações de consistência ficou um
pouco menor que a de variável mais restringida.
Verificações de Consistência (VC)
80
73
70
60
50
40
29
30
20
14
12,4
Busca-comretrocesso com
variável mais
restringida
Conflitos Mínimos
10
0
Busca-comretrocesso
Busca-comretrocesso com
variável mais restritiva
Figura 22 – VC das execuções: coloração de mapas com domínios diferentes.
54
No Figura 23, é evidenciado novamente o ganho de tempo obtido pelas heurísticas que
o Gnu Prolog implementa, sendo neste caso 4 vezes mais rápido que o melhor tempo deste
trabalho. Também se observa a eficiência da heurística de variável mais restringida diminuir o
tempo de 23,5 milisegundos para apenas 6,3 milisegundos, um ganho de mais de 300%.
Comparando a Figura 22 com a Figura 23 e observando os resultados dos conflitos mínimos,
verifica-se novamente a elevação do tempo enquanto se considera o tempo gasto pela
heurística, já que as VC foram praticamente iguais se comparado com a heurística de variável
mais restringida.
60
Tempo em milisegundos
49,7
50
40
30
23,5
17,1
20
6,3
10
1,5
0
Gnu Prolog
Busca-comretrocesso
Busca-comretrocesso com
variável mais
restritiva
Busca-comConflitos Mínimos
retrocesso com
variável mais
restringida
Figura 23 – Tempo médio das execuções: coloração de mapas com domínios diferentes
No problema das n-rainhas com n=4, fez-se também uma série de 10 execuções para
cada algoritmo e heurística, obtendo o gráfico da Figura 24.
Verificações de Consistência (VC)
70
60
58
58
58
50
40
30
16,8
20
10
0
Busca-comretrocesso
Busca-comretrocesso com
variável mais restritiva
Busca-comretrocesso com
variável mais
restringida
Figura 24 – VC nas execuções: n-rainhas com n=4
Conflitos Mínimos
55
Nota-se que somente houve ganho com a heurística de conflitos mínimos, isso se deve
ao fato do problema das n-rainhas ter domínios iguais onde todas as variáveis possuem o
mesmo número de valores do domínio, o que anula a heurística de variável mais restringida e
também possui restrições entre todas as variáveis de forma idêntica, sendo as variáveis
diferentes de todas as outras, anulando a heurística de variável mais restritiva. Com a busca
local e a heurística de conflitos mínimos obteve-se ganho médio superior a 300% se
comparado com o gasto na busca pelas outras heurísticas.
Nas comparações de tempo com este problema, exibido na Figura 25, este trabalho
obteve um ganho em relação ao Gnu Prolog, evidenciados na heurística de variável mais
restringida. Isso se deve ao problema aplicado ser mais complexo e as heurísticas do Gnu
Prolog estarem gastando mais tempo. Com relação o tempo do algoritmo busca-comretrocesso, o mesmo com a variável mais restritiva e o Gnu Prolog praticamente obteve-se o
mesmo tempo. Evidencia-se novamente um maior tempo gasto pelo algoritmo de busca local
com a heurística de conflitos mínimos.
Tempo em milisegundos
60,0
52,6
50,0
40,0
30,0
20,0
18,7
17,5
19,0
10,6
10,0
0,0
Gnu Prolog
Busca-comretrocesso
Busca-comBusca-comConflitos Mínimos
retrocesso com retrocesso com
variável mais
variável mais
restritiva
restringida
Figura 25 – Tempo médio das execuções: n-rainhas com n=4
56
4 CONCLUSÕES
A implementação do algoritmo busca-com-retrocesso se mostrou eficaz na resolução
de CSPs com todos os problemas testados. Demonstrou soluções concisas com as restrições e
domínios informados. Quando se aliou o algoritmo busca-com-retrocesso com as heurísticas,
pode-se verificar o poder de minimizar o custo da busca com rotinas de escolha que se
baseiam no domínio e nas restrições. É evidente o ganho do algoritmo com as heurísticas
presentes neste trabalho. Elas se mostraram eficientes, reduzindo o custo na busca pela
solução do CSP, o que satisfaz as expectativas que a literatura aponta para sua utilização.
Diante desses resultados, tem-se a conclusão de que o trabalho atendeu a todos os objetivos
previamente formulados.
A ferramenta utilizada para a implementação, a IDE Eclipse, se mostrou adequada a
esta implementação. Ela forneceu todo o material necessário a uma implementação bem
sucedida como a possibilidade de depurar o programa, a possibilidade de explorar as classes
por pacotes, e o auto-complemento de código. A especificação deste trabalho, desenvolvida
com o EA, se mostrou adequada a UML. Os pacotes de especificação de CSP que o dynDCSP
disponibiliza, funcionou de maneira adequada em todas as situações testadas, tendo uma
documentação que facilitou o entendimento e utilização das classes e métodos que o mesmo
disponibiliza. O CCB também funcionou da maneira esperada em todas as situações, tendo
uma interface simples de operar, porém só era muito atrelado ao dynDCSP, tendo que
executar o dynDCSP para usar o CCB.
Como vantagens, pode-se citar a implementação do algoritmo em Java, o que torna a
aplicação portável a diversas plataformas de sistema operacionais, além de ser integrada com
o editor do CCB, deixando assim um trabalho completo com editor, compilador e algoritmo
de resolução heurístico, podendo a mesma ser uma ferramenta didática onde o professor pode
ensinar seus alunos sobre CSP, os alunos especificarem os CSPs neste trabalho para verem os
resultados da busca e também demonstrar como o CSP é resolvido por um algoritmo de busca
heurístico. Cientificamente, pode-se demonstrar como as heurísticas se mostram eficientes
quando se deseja reduzir o espaço de busca e também como um algoritmo de busca local
heurístico pode resolver problemas complexos em poucas etapas de busca a solução. Também
é didático pela forma com que foi programada, ou seja, idêntica a literatura, o que facilita o
entendimento e compreensão.
Como limitações mais importantes, podem-se citar o uso de heurísticas combinadas, ou
57
seja, combinar a heurística de variável mais restritiva com a heurística de conflitos mínimos, o
tempo de processamento das heurísticas combinada com a do algoritmo serem maiores do que
só o algoritmo e as heurísticas não terem visão em mais de um nível da árvore de resolução,
onde poderia ser detectado problemas futuros e não criar ramificações por aquele valor do
domínio que sempre dará a impossibilidade do CSP ser consistente.
4.1 EXTENSÕES
Como extensão mais importante de trabalhos futuros, pode-se citar a implementação
de mais heurísticas como a de consistência de arcos, uma depuração detalhada dos algoritmos
e a implementação de um algoritmo de ordenação nas heurísticas, para obter um tempo
melhor na resolução do CSP quando aplicado as heurísticas. Pois como Russell e Norvig
(2004, p. 140) salientam, se levar em conta o tempo gasto com o algoritmo mais o tempo e o
custo extra para calcular as heurísticas, o tempo total poderá ser maior que simplesmente o
algoritmo busca-com-retrocesso, e que este custo pode ser gerenciado com os métodos de
verificação prévia das variáveis, com a consistência de arcos e propagação de restrições.
58
REFERÊNCIAS BIBLIOGRÁFICAS
CAMPOS, P. G. Resolução de problemas por meio de resolução de restrições. Recife,
[2003]. Disponível em: <http://www.cin.ufpe.br/~in1006/2003/CSP.ppt>. Acesso em: 20 set.
2006.
DIAS, D. The Gnu Prolog web site. France, 2003. Disponível em: <http://gnuprolog.inria.fr/>. Acesso em: 8 abr. 2006.
CARVALHO FILHO, E. C. B. et al. Constraint satisfaction problems. Recife, [1998?].
Disponível em: <http://www.cin.ufpe.br/~compint/aulas-IAS/csp.ppt>. Acesso em: 10 abr.
2006.
RICH, E.; KNIGHT, K. Inteligência artificial. Tradução Maria Cláudia Santos Ribeiro
Ratto. São Paulo: Makron, 1993.
RUSSELL, S. J.; NORVIG, P. Inteligência artificial. Tradução PubliCare Consultoria. Rio
de Janeiro: Elsevier, 2004.
SANTOS, F. Implementação distribuída do algoritmo Adopt. 2005. 115 f. Trabalho de
Conclusão de Curso (Bacharelado em Ciências da Computação) – Centro de Ciências Exatas
e Naturais, Universidade Regional de Blumenau, Blumenau.
_______. ccb_short_guide.pdf. Blumenau, 2006. 1 arquivo (98 Kbytes). Adobe Acrobat
Reader 7. Disponível em:
<http://www.inf.furb.br/gia/dynDCSP/doc/ccb/ccb_short_guide.pdf>. Acesso em: 9 abr.
2006.
TRALAMAZZA, D. M. Desenvolvimento de um algoritmo para problema de satisfação
de restrição distribuída. 2004. 37 f. Trabalho de Conclusão de Curso (Bacharelado em
Ciências da Computação) – Centro de Ciências Exatas e Naturais, Universidade Regional de
Blumenau, Blumenau.
TSANG, E. Foundations of constraint satisfaction. London: Academic Press, 1993.
Download

implementação de um algoritmo heurístico para problemas de