All Tours Algorithm

  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
posted @ 2015-03-24 22:21  Kalpan  阅读(135)  评论(0)    收藏  举报