ShortestLinkedHeuristic 最短链路策略算法
基于贪心思想,每次选择一条没有被选择过的权重最小的边,检查是否与已有的边构成循环或者引起某个顶点分叉,如果没有则加入H。重复这个过程直到所有的边都被检查过。
输入:无向连通图
输出:TSP路径
思路
首先给出关于无向图的所有边和权重,以及所有顶点,接着按照ShortestLinkedHeuristic算法思路,构造路线集合H,每次从边集合E中取出权重最小的边,如果这条边与H不会形成一个循环,并且不会导致路线分叉,则将这条边加入路线集合H;直到边集合E为空,从H中找到两个度为1的顶点,将它们相连,使路线连通(无向图可能需要满足完全图的条件
运行环境
- Python3.6
- Numpy 1.17.3
代码函数说明
- ShortestLinkedHeuristic(G, visited, label)
- 任选一个城市开始,到达离它最近的城市,然后从该城市出发,选择离它最近的未访问过的城市,重复该过程,直到所有城市都被访问过,再回到开始城市。
代码实现
from copy import deepcopy
def has_cycle(G):
"""
判断无向图是否有环
:param G: example {0: [1,2],1: [3], 2: []}
:return:True无环,False有环
"""
V = set()
U = dict()
cycle_set = []
def dfs(u, v):
V.add(u)
for x in G.get(u, []):
if x not in V:
U[x] = u
dfs(x, u)
elif x != v:
try:
path = []
_x = u
while _x != x:
path.insert(0, _x)
_x = U[_x]
path.insert(0, _x)
except:
path = []
cycle_set.append(path + [x])
for x in G:
if x not in V:
dfs(x, x)
return len(cycle_set) == 0
def ShortestLinkedHeuristic(G, visited, label):
"""
最短链接策略
:param G: [[u,v,w]]
:param visited: 顶点
:param label: 标签
:return:路径
"""
_G = {}
H = []
for v in visited:
_G.update({v:[]})
E = G.copy()
while len(E)>0:
min_u, min_v = -1, -1
min_w = 10000003
for u,v,w in E:
if w < min_w:
min_u,min_v,min_w = u,v,w
E.remove([min_u,min_v,min_w])
__G = deepcopy(_G)
__G[min_u].append(min_v)
if(has_cycle(__G)):
_G = __G
H.append((min_u, min_v))
V = {}
for v in visited:
V.update({v:0})
for u, v in H:
V[u]+=1
V[v]+=1
_u, _v = -1, -1
for u in V:
if V[u] == 1:
if _u == -1:
_u = u
else:
_v = u
break
if _u != -1 and _v != -1:
H.append((_u, _v))
result = []
for u, v in H:
result.append((label[u], label[v]))
return result
visited = [0,1,2,3]
G = [
[0,1,20],
[0,2,15],
[0,3,35],
[1,2,10],
[1,3,25],
[2,3,12]
]
label = ['a', 'b', 'c', 'd']
result = ShortestLinkedHeuristic(G, visited, label)
print(result)
无向完全图
运行结果
[('b', 'c'), ('c', 'd'), ('a', 'b'), ('a', 'd')]