-
Notifications
You must be signed in to change notification settings - Fork 26
/
tsp.py
120 lines (96 loc) · 3.5 KB
/
tsp.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#coding:utf-8
import numpy as np
import json
import math
from util import *
from args import *
def main():
# Get arguments
args = parse_args()
# Use the corresponding data file
if args.file:
filename = args.file
elif args.data == 'nctu':
filename = "data/nctu.csv"
elif args.data == 'nthu':
filename = "data/nthu.csv"
elif args.data == 'thu':
filename = "data/thu.csv"
else:
print("ERROR: undefined data file")
coordinates = np.loadtxt(filename, delimiter=',')
# Constant Definitions
NUM_NEW_SOLUTION_METHODS = 3
SWAP, REVERSE, TRANSPOSE = 0, 1, 2
# Params Initial
num_location = coordinates.shape[0]
markov_step = args.markov_coefficient * num_location
T_0, T, T_MIN = args.init_temperature, args.init_temperature, 1
T_NUM_CYCLE = 1
# Build distance matrix to accelerate cost computing
distmat = get_distmat(coordinates)
# States: New, Current and Best
sol_new, sol_current, sol_best = (np.arange(num_location), ) * 3
cost_new, cost_current, cost_best = (float('inf'), ) * 3
# Record costs during the process
costs = []
# previous cost_best
prev_cost_best = cost_best
# counter for detecting how stable the cost_best currently is
cost_best_counter = 0
# Simulated Annealing
while T > T_MIN and cost_best_counter < args.halt:
for i in np.arange(markov_step):
# Use three different methods to generate new solution
# Swap, Reverse, and Transpose
choice = np.random.randint(NUM_NEW_SOLUTION_METHODS)
if choice == SWAP:
sol_new = swap(sol_new)
elif choice == REVERSE:
sol_new = reverse(sol_new)
elif choice == TRANSPOSE:
sol_new = transpose(sol_new)
else:
print("ERROR: new solution method %d is not defined" % choice)
# Get the total distance of new route
cost_new = sum_distmat(sol_new, distmat)
if accept(cost_new, cost_current, T):
# Update sol_current
sol_current = sol_new.copy()
cost_current = cost_new
if cost_new < cost_best:
sol_best = sol_new.copy()
cost_best = cost_new
else:
sol_new = sol_current.copy()
# Lower the temperature
alpha = 1 + math.log(1 + T_NUM_CYCLE)
T = T_0 / alpha
costs.append(cost_best)
# Increment T_NUM_CYCLE
T_NUM_CYCLE += 1
# Detect stability of cost_best
if isclose(cost_best, prev_cost_best, abs_tol=1e-12):
cost_best_counter += 1
else:
# Not stable yet, reset
cost_best_counter = 0
# Update prev_cost_best
prev_cost_best = cost_best
# Monitor the temperature & cost
print("Temperature:", "%.2f°C" % round(T, 2),
" Distance:", "%.2fm" % round(cost_best, 2),
" Optimization Threshold:", "%d" % cost_best_counter)
# Show final cost & route
print("Final Distance:", round(costs[-1], 2))
print("Best Route", sol_best)
route = json.dumps(sol_best.tolist())
payloads = [ costs[-1], route, markov_step ]
# Save the result to sqlite
save_sqlite(payloads)
#export to path.json for google map
export2json(filename, sol_best)
# Plot cost function and TSP-route
plot(sol_best.tolist(), coordinates, costs)
if __name__ == "__main__":
main()