Assim como foi feito para as outras meta-heurísticas, o SA também será implementado para o PMM. E, como nos casos anteriores, o código-fonte da importação dos dados e do cálculo da FO poderão ser reutilizados. O código-fonte do programa principal vai precisar apenas de alguns pequenos ajustes. O Simulated Annealing, em sua primeira versão, não faz uso de nenhuma outra função acessória, como uma busca local, de forma que, será preciso implementar apenas a meta-heurística. Para isso, siga os passos:
Passos
1. Copie o código-fonte disponibilizado a seguir;
2. Cole o código em um editor de textos de sua preferência;
3. Salve o arquivo com o nome: SimulatedAnnealing.py na pasta
C:\AulaPython.
1 import time
2 import math as mat 3 import copy as cpy 4 import random as rand 5 import calcFO as CF 6
7 #gerando a semente
8 rand.seed() 9
10 def SimulatedAnnealing(samax, ti, tc, tx, solIni, numObj, numMoc, vetValObj, vetPesObj, vetCapMoc):
11 ini = time.time() 12 achouT = time.time()
13 #guarda a solucao inicial como a melhor
14 mSol = solIni
15 mFO = CF.calcFO(mSol, numObj, numMoc, vetValObj, vetPesObj, vetCapMoc)
16 #atribui a melhor solucao a sol atual
17 sol = cpy.copy(mSol)
18 FO = CF.calcFO(sol, numObj, numMoc, vetValObj, vetPesObj, vetCapMoc)
19 #inicializa a temperatura
20 temp = ti
21 while temp > tc:
22 #enquanto a temperatura inicial e maior que a temp de congelamento
23 for i in range(samax):
24 #solucao vizinha inicia a partir da solucao atual
25 vSol = cpy.copy(sol)
26 #sorteia uma solucao vizinha
27 vSol[rand.randint(0, numObj-1)] = rand.randint(0, numMoc)
28 #calcula a FO da solucao vizinha
29 vFO = CF.calcFO(vSol, numObj, numMoc, vetValObj, vetPesObj, vetCapMoc )
30 #calculando a variacao
31 delta = FO - vFO
32
33 if delta < 0:
Aula 12. Meta-heurística Simulated Annealing 168
35 sol = cpy.copy(vSol)
36 if vFO > mFO:
37 #se a FO da vizinha e melhor que a FO da FO global aceita
38 mSol = cpy.copy(vSol)
39 achouT = time.time()
40 else:
41 if rand.random() < mat.exp(-(FO - vFO) / temp):
42 #se nao e melhor mas aceita piorar
43 sol = cpy.copy(vSol)
44
45 #resfria a temperatura
46 temp *= tx
47
48 return mSol, (achouT - ini)
Entre as linhas 1 e 5 foi realizada a importação das bibliotecas necessárias para a meta-heurística. Na linha 8 foi gerada a semente aleatória, conforme as orientações da aula7. Na linha 10 inicia a função, cujos argumentos de entrada são: samax referente ao número de iterações, ti para temperatura inicial, tc para temperatura de congelamento,
tx para taxa de resfriamento, solIni para solução inicial e os demais argumentos do
PMM. As variáveis são inicializadas entre as linhas 11 e 20, como a inicialização da melhor solução global na linha 14, da solução corrente na linha 17 e da temperatura corrente na linha 20. O laço externo inicia na linha 21, observe que a condição de manutenção do laço é exatamente igual ao do código base já visto e para garantir que o laço termine quando a temperatura se aproximar da temperatura de congelamento, foi incluída a instrução da linha 46 que é responsável por resfriar a temperatura corrente, com base na taxa de resfriamento.
O laço interno na linha 23 vai garantir as iterações que irão buscar o equilíbrio térmico para cada temperatura avaliada no laço externo. Na linha 25 é inicializada a solução vizinha com a solução corrente, na linha 27 são realizados dois sorteios, o primeiro do objeto, ou seja, aleatoriamente é escolhido um objeto para trocá-lo de mochila, que é o segundo sorteio. Após realizar o sorteio, é feito o cálculo da FO da solução vizinha, conforme a instrução na linha 29, como já temos a FO da solução corrente, então é realizado o cálculo da variação na linha 31. Na linha 33 é verificado se a variação é negativa, pois se essa condição for verdadeira, então a solução será aceita na instrução da linha 35. Se a solução vizinha também for melhor que a solução global, então a solução global é ajustada conforme a linha 38.
Se a variação for positiva ou nula, então temos a situação em que a solução vizinha é pior ou igual, neste caso é realizada a validação da linha 41, seguindo as definições do código base, e em caso verdadeiro a solução será aceita na linha 43. Após finalizar as iterações do laço externo, ou seja, após a temperatura resfriar e atingir a temperatura de congelamento, a solução é retornada ao método que a invocou, conforme a instrução da linha 48. Realize os passos a seguir para testar o SA implementado.
Passos
1. Copie o código-fonte disponibilizado a seguir;
2. Abra o arquivo prgMain.py presente na pasta C:\AulaPython; 3. Cole o código substituindo o código atual do arquivo;
Aula 12. Meta-heurística Simulated Annealing 169
1 import leDados as LD 2 import calcFO as CF
3 import SimulatedAnnealing as SA 4 import heuConAle as HCA
5
6 numObjetos = numMochilas = 0 7 vetValoresObjetos = [] 8 vetPesosObjetos = [] 9 vetCapacidadeMochilas = []
10 numObjetos, numMochilas, vetValoresObjetos, vetPesosObjetos, vetCapacidadeMochilas = LD.leDados()
11
12 solIni = HCA.heuConstrutivaAleatoria(numObjetos, numMochilas) 13
14 samax = ((numMochilas + 1) * numObjetos) * 1 15 tempInicial = 100
16 tempCongelamento = 0.01 17 txResfriamento = 0.975 18
19 #obtendo uma solucao pela meta-heuristica Simulated annealing
20 sol, tempo = SA.SimulatedAnnealing(samax, tempInicial, tempCongelamento, txResfriamento, solIni, numObjetos, numMochilas, vetValoresObjetos, vetPesosObjetos, vetCapacidadeMochilas)
21
22 #calculando a FO da solucao obtida
23 FO = CF.calcFO(sol, numObjetos, numMochilas, vetValoresObjetos, vetPesosObjetos, vetCapacidadeMochilas)
24
25 print "Solucao: ", sol 26 print "FO: ", FO
27 print "Achou em: %.2f " % tempo
Conforme pode ser visto no código-fonte do programa principal, foram realizadas poucas adaptações, a primeira é a linha 3 do código com a importação do arquivo de fonte da função do Simulated Annealing. O segundo ajuste refere-se à configuração dos parâmetros do SA, entre as linhas 14 e 17, em que samax foi definido conforme o número de mochilas e objetos para possibilitar que este tamanho possa se adaptar conforme os dados. tempInicial foi configurado com o valor 100, tempCongelamento foi configurado como 0.01 e txResfriamento com 0.975. Na próxima seção abordamos com mais detalhes sobre a calibração destes parâmetros. O terceiro e último ajuste é a invocação da função responsável por executar a meta-heurística, na linha 20. O restante do código permaneceu inalterado. Agora é possível testar a meta-heurística SA, para executar abra o interpretador do Python e execute o programa principal, conforme o trecho a seguir.
1 >>> runfile('C:/AulaPython/prgMain.py', wdir='C:/AulaPython')
2 Solucao: [1, 3, 3, 1, 1, 1, 1, 2, 3, 3, 2, 0, 3, 3, 0, 0, 2, 1, 0, 3] 3 FO: 9418
4 Achou em: 0.24
Como pode ser visto, no teste realizado para este livro, a FO da "melhor solu-ção"obtida pelo Simulated Annealing, é 9.418 e esta solução foi encontrada em 0.24 segundos. Tudo indica que os parâmetros configurados permitiram uma execução
Aula 12. Meta-heurística Simulated Annealing 170
muito rápida, talvez, por isso, o SA não tenha conseguido uma solução com qualidade melhor. A próxima seção tratará sobre a calibração dos parâmetros, que neste caso, poderá melhorar os resultados do SA.
12.5 Calibração dos parâmetros
O Simulated Annealing possui 4 parâmetros que irão influenciar no seu desempenho em termos de tempo de processamento e eficácia em obter boas soluções. Além disso, estes parâmetros estão relacionados entre si, de forma que, um pode afetar o outro. A temperatura inicial, representada no código base por T0, está associada ao número de estados que o Simulated Annealing vai produzir até atingir a temperatura de con-gelamento, assim, se colocar uma temperatura muito baixa, é provável que o SA faça poucas iterações e obtenha poucos estados térmicos, consequentemente. De forma que, para alguns problemas, é possível que temperaturas iniciais baixas não sejam suficientes para produzir boas soluções. Por outro lado, se calibrar o método com uma temperatura muito alta, é provável que o SA tenha um desempenho ruim em termos de tempo de processamento, deve-se então equilibrar a temperatura inicial de acordo com o problema. Um entendimento sobre a T0é que ela deve ser alta o bastante para permitir movimentos livres entre soluções vizinhas.
Ainda há outro aspecto que deve ser considerado, pois a temperatura inicial é afetada pela temperatura de congelamento, representada no código base pelo Tc, de forma que, não adianta iniciar o SA com uma temperatura muito alta e ao mesmo tempo calibrar a temperatura de congelamento, também com um valor muito alto, ou próximo da temperatura inicial, pois assim, a eficácia em produzir estados térmicos, provavelmente será ruim. Desta forma, é muito comum calibrarmos a temperatura de congelamento com valores muito próximos de zero, como: 0,01, 0,001, etc. Até mesmo para que se assemelhe à temperatura natural de congelamento. Tendo a temperatura de congelamento sempre como próxima de zero, então o desafio será sempre encontrar a melhor temperatura para inicializar o SA.
Como já mencionado, os parâmetros exercem influência uns sobre os outros, e a taxa de resfriamento, representada peloα, também influencia na temperatura inicial,
pois dependendo da taxa de resfriamento a temperatura pode diminuir rápido ou devagar. Este parâmetro deve ser configurado sempre com valores maiores que 0 e menores que 1, ou seja, (0 < α < 1). No geral, se queremos um resfriamento lento, então devemos configurar na faixa (0.8 < α < 0.99), se desejamos um resfriamento mais rápido então podemos adotar a faixa (0 < α < 0.8). Uma sugestão é que este parâmetro seja calibrado com o valor 0.975 ou 0.995.
O quarto parâmetro, número de iterações, representado por SAMax, influencia no equilíbrio térmico que deve ser atingido em cada temperatura que é avaliada pelo SA, durante o processamento. Assim, um valor para SAMax muito pequeno pode dificultar o SA a atingir o equilíbrio térmico, por outro lado, um número muito grande também não traria muitos benefícios, podendo afetar no desempenho, desta forma, é comum que este parâmetro seja calculado com base na dimensão do problema, como foi feito para o PMM, neste livro.
Em resumo, a melhor forma de calibrar os parâmetros é por meio de testes e ava-liação dos resultados. Uma boa estratégia é contabilizar e imprimir um resumo de várias informações ao longo dos testes, por exemplo, contabilizar o número de vizinhos gerados e aceitos, se o número de vizinhos aceitos for alto em relação ao número de vizinhos gerados, isso é um bom indicador.
Aula 12. Meta-heurística Simulated Annealing 171