最小生成樹演算法求解TSP
阿新 • • 發佈:2021-10-15
最小生成樹求解TSP問題
步驟:
首先根據輸入生成TSP地圖資料,然後利用克魯斯卡爾(Kruskal)和普利姆(prim)演算法求解這個TSP問題,最後用圖畫出來。
演算法思想:
克魯斯卡爾演算法的核心思想是:在帶權連通圖中,不斷地在邊集合中找到最小的邊,如果該邊滿足得到最小生成樹的條件,就將其構造,直到最後得到一顆最小生成樹
普利姆演算法的核心步驟是:在帶權連通圖中,從圖中某一頂點v開始,此時集合U={v},重複執行下述操作:在所有u∈U,w∈V-U的邊(u,w)∈E中找到一條權值最小的邊,將(u,w)這條邊加入到已找到邊的集合,並且將點w加入到集合U中,當U=V時,就找到了這顆最小生成樹。
演算法程式碼(python)
Kruskal
# kruskal edge_count = 0 for i in range(size): for j in range(i): if 0 < distance[i][j] < 999998: edge_count += 1 kruskal_list = [] edge_list = [] for i in range(size): for j in range(i+1, size): edge_list.append([i, j, distance[i][j]]) edge_list.sort(key=lambda a: a[2]) group = [[i] for i in range(size)] for edge in edge_list: for i in range(len(group)): if edge[0] in group[i]: m = i if edge[1] in group[i]: n = i if m != n: kruskal_list.append(edge) group[m] = group[m] + group[n] group[n] = []
Prim
# Prim prim_list = [] selected_node = [0] candidate_node = [i for i in range(1, size)] while len(candidate_node) > 0 : min_dis = 999998 for i in selected_node: for j in candidate_node: if distance[i][j] < min_dis: min_dis = distance[i][j] cur_node = i next_select_node = j prim_list.append([cur_node, next_select_node, min_dis]) selected_node.append(next_select_node) candidate_node.remove(next_select_node)
程式碼測試:
(1)
15個城市迅速收斂
(2)
100個城市可以快速收斂
(3)
1000個城市無法快速收斂
原始碼:
import numpy as np
import matplotlib.pyplot as plt
size = int(input("城市個數:"))
scale = int(input("比例尺:"))
MAX_ = 999999
coord = []
distance = np.zeros((size, size))
i = 0
while i < size:
x = np.random.rand() * scale
y = np.random.rand() * scale
if [x, y] not in coord:
coord.append([x, y])
i = i + 1
coord = np.array(coord)
for i in range(size):
for j in range(size):
if i == j :
distance[i][j] = MAX_
else:
distance[i][j] = distance[j][i] = np.linalg.norm(coord[i] - coord[j])
# kruskal
edge_count = 0
for i in range(size):
for j in range(i):
if 0 < distance[i][j] < 999998:
edge_count += 1
kruskal_list = []
edge_list = []
for i in range(size):
for j in range(i+1, size):
edge_list.append([i, j, distance[i][j]])
edge_list.sort(key=lambda a: a[2])
group = [[i] for i in range(size)]
for edge in edge_list:
for i in range(len(group)):
if edge[0] in group[i]:
m = i
if edge[1] in group[i]:
n = i
if m != n:
kruskal_list.append(edge)
group[m] = group[m] + group[n]
group[n] = []
# Prim
prim_list = []
selected_node = [0]
candidate_node = [i for i in range(1, size)]
while len(candidate_node) > 0 :
min_dis = 999998
for i in selected_node:
for j in candidate_node:
if distance[i][j] < min_dis:
min_dis = distance[i][j]
cur_node = i
next_select_node = j
prim_list.append([cur_node, next_select_node, min_dis])
selected_node.append(next_select_node)
candidate_node.remove(next_select_node)
print(coord)
print(distance)
print("----------------------Kruskal-----------------------")
print(np.array(kruskal_list))
print("----------------------Prim-----------------------")
print(np.array(prim_list))
fig = plt.figure(1, (45, 15))
ax1 = fig.add_subplot(131)
ax1.set_title("MAP{}".format(size))
ax1.plot(coord[:, 0], coord[:, 1], 'o')
ax2 = fig.add_subplot(132)
ax2.set_title("Kruskal")
x = []
y = []
for t_list in kruskal_list:
ax2.plot([coord[t_list[0], 0], coord[t_list[1], 0]], [coord[t_list[0], 1], coord[t_list[1], 1]])
ax3 = fig.add_subplot(133)
ax3.set_title("Prim")
for t_list in prim_list:
ax3.plot([coord[t_list[0], 0], coord[t_list[1], 0]], [coord[t_list[0], 1], coord[t_list[1], 1]])
plt.show()