Tips: The following information is from chatgpt, and the following content is only used as a personal study record
Article directory
1. Use the CW algorithm to solve the TSP problem
The TSP problem refers to the Traveling Salesman Problem, which is a classic combinatorial optimization problem. The problem can be described as: Given a map containing n cities, the traveling salesman needs to start from one city, pass through all the cities in turn, and finally return to the starting city. The traveling salesman must go through all the cities, and each city can only go through once. The traveling salesman is free to choose any city as the starting point, and asks how to plan the travel route so that the total distance is the shortest
The CW-Saving Algorithm is a heuristic algorithm for solving the Traveling Salesman Problem (TSP). Its goal is to find a Hamiltonian circuit that is as short as possible. But since the CW algorithm is an approximate algorithm, it is not guaranteed to find the minimum solution of the TSP problem, but for practical problems, its solution is usually very close to the optimal solution and has good time complexity. Moreover, the CW algorithm is also applicable to large-scale problems, which makes it very useful in practice.
Two, the code
1. Code
code show as below:
import math
# 计算两个城市之间的距离
def dist(a, b):
return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
# 在未访问城市中查找距离当前城市最近的城市
def find_nearest(city, cities, visited):
nearest_dist = float('inf')
nearest_city = None
for c in cities:
if c not in visited and c != city:
d = dist(city, c)
if d < nearest_dist:
nearest_dist = d
nearest_city = c
return nearest_city, nearest_dist
# 计算每对城市之间的节约成本
def find_savings(cities):
savings = []
for i in range(len(cities)):
for j in range(i+1, len(cities)):
d = dist(cities[i], cities[j])
savings.append((i, j, d))
return sorted(savings, key=lambda x: x[2], reverse=True)
# 构建城市之间的最小生成树
def minimum_spanning_tree(cities):
mst = []
visited = set([cities[0]])
while len(visited) < len(cities):
nearest_dist = float('inf')
nearest_edge = None
for v in visited:
c, d = find_nearest(v, cities, visited)
if d < nearest_dist:
nearest_dist = d
nearest_edge = (v, c)
mst.append(nearest_edge)
visited.add(nearest_edge[1])
return mst
def find_euler_tour(mst):
tour = []
stack = [mst[0][0]]
while len(stack) > 0:
v = stack[-1]
for e in mst:
if e[0] == v and e[1] not in tour:
tour.append(e[1])
stack.append(e[1])
break
elif e[1] == v and e[0] not in tour:
tour.append(e[0])
stack.append(e[0])
break
else:
stack.pop()
return tour
def euler_to_tsp(euler_tour):
tsp_path = [euler_tour[0]]
for i in range(1, len(euler_tour)):
if euler_tour[i] != tsp_path[-1]:
tsp_path.append(euler_tour[i])
tsp_path.append(euler_tour[0])
return tsp_path
def solve_tsp(cities):
# 计算节约成本
savings = find_savings(cities)
# 构建最小生成树
mst = minimum_spanning_tree(cities)
# 找到欧拉回路
euler_tour = find_euler_tour(mst)
# 将欧拉回路转换为TSP路径
tsp_path = euler_to_tsp(euler_tour)
# 计算TSP路径的总长度
tsp_length = sum([dist(tsp_path[i], tsp_path[i+1]) for i in range(len(tsp_path)-1)])
return tsp_path, tsp_length
main function:
if __name__ == '__main__':
cities = [(1,1),(1,3),(2,2),(3,1),(3,3)]
tsp_path, tsp_length=solve_tsp(cities)
print(f'tsp_path:{
tsp_path}')
print(f'tsp_length:{
tsp_length}')
2. Output
The above code can be run directly and successfully. After running the above code locally, the output is:
tsp_path:[(2, 2), (1, 1), (1, 3), (3, 1), (3, 3), (2, 2)]
tsp_length:9.656854249492381
3. City coordinates
The city coordinates can be changed at will, as needed