列了这个是因为在学习过程中,会有很多文章,可能时间稍微久点了,用起来因为版本迭代,函数可能发生了变化,但你也不确实到底是什么问题。。这样指明版本,可以避免很多复现的困惑。
import numpy as np
import sys
print(sys.version)
print(nx.__version__)
# 3.9.5 (default, May 18 2021, 14:42:02) [MSC v.1916 64 bit (AMD64)]
# 2.5.1
首先,旅行商问题是一个被证明的NPC的问题,所以没有满足多项式时间复杂度的算法,所以只能用近似优化去求解啦。
然后,旅行商问题更普遍有点就是叫求最小哈密顿圈(halmiton circuit)的问题。
哈密顿圈:Hamilton 图就是从一顶点出发每顶点恰通过一次能回到出发点的那种图,即不重复地行遍所有的顶点再回到出发点
注意区别欧拉回路,欧拉回路是通过所有的边
import networkx as nx
# 生成图
G = nx.complete_graph(['L','M','N','Pa','Pe','T'])
names = ['L','M','N','Pa','Pe','T']
weights = [56, 35, 21, 51, 60,
21, 57, 78, 70,
36, 68, 68,
51, 61,
13]
count = 0
for i in range(0,6):
for j in range(i+1,6):
G.edges[names[i], names[j]]['weight'] = weights[count]
count += 1
G.edges(data='weight')
nx.draw(G, with_labels=True, pos=nx.spring_layout(G), font_weight='bold')
nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G), edge_labels=nx.get_edge_attributes(G, 'weight'), label_pos=0.5)
生成了图,下面我们来写两个函数,因为改良圈算法需要基于一条已知的哈密顿路径,进行优化。但是我看很多网上求解这题的时候,包括书上,都手动给了一条,不得不说不是很满意。所以第一个函数,是找一条哈密顿圈。
第二个函数就是改良圈的过程了,其实也很简短,但为了消化这个问题和学了一下networkx这个python库,还是花了好几天。。菜鸡实锤了
def find_halmiton_circuit(G,s,path):
'''
找到一条任意的哈密顿圈,如果有则存到path里,没有则返回False
'''
# 若已经遍历了所有节点了,此时可以判断是否形成闭环。
if len(path) == len(list(G.nodes())):
if path[-1] in dict(G.adj[path[0]]):
path.append(path[0])
return True
else:
return False
# 判断该节点是否已经在路径中
if s not in path:
path.append(s)
else:
return False
print(path)
# # 如果该节点没有后续节点了,返回FALSE
# if G.adj[path[-1]] == None:
# return False
for nbr, datadict in G.adj[path[-1]].items():
if find_halmiton_circuit(G, nbr, path):
return True
return False
def circle_modification(G,path):
# names = list(G.nodes)
n = len(path)
for i in range(n):
for j in range(i+2, n-1):
try:
# 如果存在更短的路径,更换两条边的选择
if G.edges[path[i],path[j]]['weight'] + G.edges[path[i+1],path[j+1]]['weight'] < G.edges[path[i],path[i+1]]['weight'] + G.edges[path[j],path[j+1]]['weight']:
path[i+1:j+1] = path[j:i:-1]
except KeyError:
print(i,j,"not connected")
return True
最后的调用
path = []
s = 'Pe'
if find_halmiton_circuit(G, s, path):
print(path)
print("Found one feasible halmiton circuit")
if circle_modification(G, path):
print(path)
['Pe']
['Pe', 'L']
['Pe', 'L', 'M']
['Pe', 'L', 'M', 'N']
['Pe', 'L', 'M', 'N', 'Pa']
['Pe', 'L', 'M', 'N', 'Pa', 'T']
['Pe', 'L', 'M', 'N', 'Pa', 'T', 'Pe']
Found one feasible halmiton circuit
['Pe', 'Pa', 'L', 'N', 'M', 'T', 'Pe']