1 # -*- coding:utf-8 -*-
2
3 import matplotlib.pyplot as plt
4 import random
5 import time
6 import itertools
7 import urllib
8 import csv
9
10 __author__ = 'Kalpan'
11
12 """
13 All Tours Algorithm:生成所有的路径,选择最短的那条
14 """
15 #alltours = itertools.permutations
16
17 def alltours_tsp(cities):
18 """
19 生成所有可能的路线,返回最短路线集
20 :param cities:城市的集合
21 :return:
22 """
23 return shortest_tour(alltours(cities))
24
25 def shortest_tour(tours):
26 """
27 选择最短的路线集
28 :param tours:路线集
29 :return:
30 """
31 return min(tours, key=tour_length)
32
33 def tour_length(tour):
34 """
35 计算路线tour的长度
36 :param tour:
37 :return:
38 """
39 return sum(distance(tour[i], tour[i-1]) for i in range(len(tour)))
40
41 # 将city当做点来代替,并以复数的形式表示
42 Point = complex
43 City = Point
44
45 def X(point):
46 """
47 点的横坐标
48 :param city:
49 :return:
50 """
51 return point.real
52
53 def Y(point):
54 """
55 返回点的纵坐标
56 :param point:
57 :return:
58 """
59 return point.imag
60
61 def distance(A, B):
62 """
63 计算A,B两点之间的距离
64 :param A:
65 :param B:
66 :return:
67 """
68 return abs(A-B)
69
70
71 def cities(n, width=900, height=600, seed=42):
72 """
73 随机生成城市数据集
74 :param num:
75 :return:
76 """
77 random.seed(seed * n) # 故意设置固定的seed,为了确保得到的cities集合是固定的
78 return frozenset(City(random.randrange(width), random.randrange(height))
79 for c in range(n))
80
81 # 画出路线图
82 def plot_tour(tour):
83
84 plot_lines(list(tour) + [tour[0]]) # +[tour[0]], 回到最初的起点
85
86 def plot_lines(points, style='bo-'):
87 """
88 画出一系列点的连线
89 :param points:
90 :param style:
91 :return:
92 """
93 plt.plot(list(map(X, points)), list(map(Y, points)) # 3.0的坑,map()不在直接返回list, 需要list调用
94 , style)
95 plt.axis('scaled')
96 plt.axis('off')
97
98 def plot_tsp(algorithm, cities):
99 """
100 选择一种算法,并画出该算法最短路径
101 :param algorithm:
102 :param cities:
103 :return:
104 """
105 # 计算算法执行的时间
106 t0 = time.clock()
107 tour = algorithm(cities)
108 t1 = time.clock()
109 assert valid_tour(tour, cities)
110 plot_tour(tour)
111 plt.show()
112 print("{} city tour with length {:.1f} in {:.3f} secs for {}"
113 .format(len(tour), tour_length(tour), t1-t0, algorithm.__name__))
114
115 def valid_tour(tour, cities):
116 """
117 检查该路径是否为有效路径,
118 :param tour:
119 :param cities:
120 :return:
121 """
122 return set(tour) == set(cities) and len(tour) == len(cities) # 经过每个城市,且每个城市只经过一次
123
124
125 """
126 在进行路径选择的过程中, 我们选择的是全排列,相对于{1, 2, 3} 三座城市,就有六种可能
127 → [(1,2,3),(1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
128 这里出现了重复,至少在计算最短路径时,(1, 2, 3), (2, 3, 1) 和 (3, 1, 2)所得的结果显然相同,它们按着相同的序列排列
129 针对该算法的改进:
130 我们只计算以某个城市开始,让其他的城市全排列,确定所得到的序列中没有重复
131 改进前,10 city tour with length 2291.8 in 45.799 secs for alltours_tsp
132 改进后,10 city tour with length 2291.8 in 5.172 secs for alltours_tsp
133 """
134
135 def alltours(cities):
136 """
137 返回一个路径的链表,每一个元素是组城市的排列,而且都以同一个城市开始
138 :param cities:
139 :return:
140 """
141 start = first(cities)
142 return [[start] + Tour(rest)
143 for rest in itertools.permutations(cities - {start})]
144
145 def first(collection):
146 return next(iter(collection))
147
148 Tour = list