旅行商問題,即TSP問題(Traveling Salesman Problem)又譯為旅行推銷員問題、貨郎擔問題,是數學領域中著名問題之一。假設有一個旅行商人要拜訪n個城市,他必須選擇所要走的路徑,路徑的限制是每個城市只能拜訪一次,而且最后要回到原來出發的城市。路徑的選擇目標是要求得的路徑路程為所有路徑之中的最小值。
1 #!/user/bin/env python 2 # -*- coding:utf-8 -*- 3 4 # TSP旅行商問題:若干個城市,任意兩個城市之間距離確定,要求一旅行商從某城市 5 # 出發必須經過每一個城市且只能在每個城市逗留一次,最后回到原出發城市,試 6 # 確定一條最短路徑使旅行費用最少 7 8 # 遍歷算法 9 10 # 給定某條路徑,計算它的成本 11 def distcal(path, dist): 12 # 計算路徑成本(路徑,距離) 13 sum_dist = 0 # 總成本 14 for j in range(0, len(path) - 1): 15 di = dist[int(path[j]) - 1][int(path[j + 1]) - 1] # 查找第j和j+1個城市之間的成本 16 sum_dist = sum_dist + di # 累加 17 di = dist[int(path[len(path) - 1]) - 1][path[0] - 1] # 最后一個城市回到初始城市的成本 18 sum_dist = sum_dist + di 19 return sum_dist # 返回路徑的成本 20 21 22 # 遞歸,構造所有可能路徑 23 def perm(l): # 構造路徑(城市列表) 24 if (len(l)) <= 1: # 只有一個城市,選擇這個城市 25 return [l] 26 r = [] # 空列表 27 for i in range(len(l)): # 對每個城市,構建不包括這個城市的所有可能序列 28 s = l[:i] + l[i + 1:] # 去除當前城市的列表 29 p = perm(s) # 調用自身,構造不包含這個城市的序列 30 for x in p: 31 r.append(l[i:i + 1] + x) # 將序列和該城市合並,得到完整的序列 32 return r 33 34 35 if __name__ == '__main__': 36 city = [1, 2, 3, 4, 5] 37 38 dist = ((0, 1, 3, 4, 5), 39 (1, 0, 1, 2, 3), 40 (3, 1, 0, 1, 2), 41 (4, 2, 1, 0, 1), 42 (5, 3, 2, 1, 0)) 43 44 for i in range(0, 5): 45 print(dist[i][:]) 46 47 print('=============') 48 49 allpath = perm(city) # 調用路徑產生函數,產生所有可能的路徑 50 51 optimal = 1000000 # 初始化最優路徑的總成本和索引號 52 53 index = 1 54 55 for i in range(0, len(allpath)): 56 pd = distcal(allpath[i], dist) 57 if pd < optimal: # 比較是否總成本更低,如果是替換最優解 58 optimal = pd 59 index = i 60 # print(pd) 61 62 print(optimal) 63 print(allpath[index]) 64 ------------------------------------------------------------------------ 65 (0, 1, 3, 4, 5) 66 (1, 0, 1, 2, 3) 67 (3, 1, 0, 1, 2) 68 (4, 2, 1, 0, 1) 69 (5, 3, 2, 1, 0) 70 ============= 71 9 72 [1, 2, 3, 4, 5]
1 #!/user/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import random 5 6 # 給定某條路徑,計算它的成本 7 def distcal(path, dist): 8 # 計算路徑成本(路徑,距離) 9 sum_dist = 0 # 總成本 10 for j in range(0, len(path) - 1): 11 di = dist[int(path[j]) - 1][int(path[j + 1]) - 1] # 查找第j和j+1個城市之間的成本 12 sum_dist = sum_dist + di # 累加 13 di = dist[int(path[len(path) - 1]) - 1][path[0] - 1] # 最后一個城市回到初始城市的成本 14 sum_dist = sum_dist + di 15 return sum_dist # 返回路徑的成本 16 17 # 構造隨機路徑 18 def randompath(inc): # Inc城市列表 19 allcity = inc[:] # 城市列表 20 path = [] # 路徑 21 loop = True 22 while loop: 23 if 1 == len(allcity): # 如果是最后一個城市 24 tmp = random.choice(allcity) 25 path.append(tmp) 26 loop = False # 結束 27 else: # 如果不是最后一個城市 28 tmp = random.choice(allcity) # 在城市列表中隨機選擇一個城市 29 path.append(tmp) # 添加路徑 30 allcity.remove(tmp) # 在城市列表中移除該城市 31 return path 32 33 if __name__ == '__main__': 34 city = [1, 2, 3, 4, 5] 35 36 dist = ((0, 1, 3, 4, 5), 37 (1, 0, 1, 2, 3), 38 (3, 1, 0, 1, 2), 39 (4, 2, 1, 0, 1), 40 (5, 3, 2, 1, 0)) 41 42 for i in range(0, 5): 43 print(dist[i][:]) 44 45 print('=============') 46 47 num = 10 # 隨機產生10條路徑 48 49 optimal = 1000000 # 初始化最優路徑的總成本和索引號 50 51 for i in range(0, num): 52 pd = distcal(randompath(city), dist) 53 if pd < optimal: # 比較是否總成本更低,如果是替換最優解 54 optimal = pd 55 print(pd) 56 57 print(optimal) 58 ------------------------------------------------------------ 59 (0, 1, 3, 4, 5) 60 (1, 0, 1, 2, 3) 61 (3, 1, 0, 1, 2) 62 (4, 2, 1, 0, 1) 63 (5, 3, 2, 1, 0) 64 ============= 65 9 66 12 67 11 68 14 69 12 70 11 71 14 72 9 73 14 74 9 75 最優: 9
