-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanneal.py
65 lines (47 loc) · 1.72 KB
/
anneal.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import math
import random
from typing import List, Tuple
from main import score, Flow, Distance, Population
# Globals
STARTING_TEMP = 500.0
ALPHA = 0.99
def gen_population(flow_matrix: Flow, dist_matrix: Distance, n: int) -> Population:
""" Create n solutions and run SA on them. """
population = []
for i in range(n):
population.append(simmulate_annealing(flow_matrix, dist_matrix))
return population
def gen_starting_solution(n: int) -> List[int]:
""" Generates a random permutation. """
solution = list(range(1, n+1))
random.shuffle(solution)
return solution
def swap(permutation: List[int]) -> List[int]:
""" Swaps two random elements of the permutation - will not
swap the same one with itself.
"""
new_perm = list(permutation)
a, b = random.sample(range(len(new_perm)), 2)
new_perm[a], new_perm[b] = new_perm[b], new_perm[a]
return new_perm
def simmulate_annealing(flow_matrix: Flow,
dist_matrix: Distance) -> Tuple[List[int], int]:
""" Simplest version of simmulated annealing at each temp you only run
one itteration. If the new solution is better take it. Otherwise, pick
it proportional to the boltzmann function.
"""
V = gen_starting_solution(len(flow_matrix))
T = STARTING_TEMP
while T > 0.01:
V_prime = swap(V)
E = score(flow_matrix, dist_matrix, V)
E_prime = score(flow_matrix, dist_matrix, V_prime)
if E_prime < E:
V = V_prime
else:
rand = random.uniform(0, 1)
boltzmann = math.exp((-abs(E - E_prime))/T)
if boltzmann > rand:
V = V_prime
T = T * ALPHA
return V, score(flow_matrix, dist_matrix, V)