[python] CWアルゴリズムを使ってTSP問題を解く

ヒント: 以下の情報は chatgpt からのものであり、以下の内容は個人的な学習記録としてのみ使用されます


1. CW アルゴリズムを使用して TSP 問題を解決する

TSP 問題は、古典的な組み合わせ最適化問題である巡回セールスマン問題を指します。問題は次のように説明できます: n 個の都市を含む地図が与えられた場合、巡回セールスマンは 1 つの都市から始めて、すべての都市を順番に通過し、最後に最初の都市に戻る必要があります。巡回セールスマンはすべての都市を通過する必要があり、各都市は 1 回しか通過できません。巡回セールスマンは出発地として任意の都市を自由に選択し、総距離が最短になるように移動ルートをどのように計画するかを尋ねます

CW-Saving Algorithm は、巡回セールスマン問題 (TSP) を解決するためのヒューリスティック アルゴリズムです。その目標は、できるだけ短いハミルトン閉路を見つけることです。ただし、CW アルゴリズムは近似アルゴリズムであるため、TSP 問題の最小解を見つけることが保証されているわけではありませんが、実際の問題では、その解は通常、最適解に非常に近く、時間計算量も良好です。さらに、CWアルゴリズムは大規模な問題にも適用できるため、実際に非常に役立ちます。

二、コード

1.コード

コードは以下のように表示されます:

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

メイン機能:

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.出力

The above code can be run directly and successfully. 上記のコードをローカルで実行すると、出力は次のようになります。

tsp_path:[(2, 2), (1, 1), (1, 3), (3, 1), (3, 3), (2, 2)] tsp_length:
9.656854249492381

3.都市座標

都市座標は、必要に応じて自由に変更できます

おすすめ

転載: blog.csdn.net/CBCY_csdn/article/details/130393559