旅行家问题:TSP 最近邻算法解决方案

一、说明

        旅行推销员问题 (TSP) 是一个众所周知的优化问题,它试图找到访问一组给定城市并返回起始城市的最短路径。

        TSP是一个NP-hard(非确定性多项式时间hard)问题。没有已知的算法可以解决多项式时间内所有可能的输入。随着城市数量的增加,可能的游览数量呈指数级增长,因此对于大型问题实例,详尽地搜索最佳解决方案在计算上是不可行的。

二、结决方案讨论

        有几种解决方案可以有效地找到接近最优的解决方案。一种方法是使用近似算法。这些算法提供接近最优但不一定最优的解决方案。它们以最优性换取效率,从而可以更快地计算解决方案。一种众所周知的近似算法是最近邻算法。

        这是一种贪婪的方法。贪婪的标准是选择最近的城市。

        最近邻算法是 TSP 的简单直观的近似值。它从一个任意城市开始,反复选择最近的未访问城市,直到所有城市都被访问过。

        让我们从德国挑选 5 个城市:柏林、科隆、法兰克福、汉堡和慕尼黑。

# coordinates of cities

berlin = {"lat":52.5200, "lon": 13.4050}
hamburg = {"lat":53.5511, "lon": 9.9937}
munich = {"lat":48.1351, "lon": 11.5820}
cologne = {"lat":50.9375, "lon": 6.9603}
frankfurt = {"lat":50.1109, "lon": 8.6821}
cities = [berlin, hamburg, munich, cologne, frankfurt]

我们可以计算每个城市之间的差异并完成一个距离矩阵。

import math

def calculate_distance(city1, city2):
    """distance between two cities"""
    lat1, lon1 = city1["lat"], city1["lon"]
    lat2, lon2 = city2["lat"], city2["lon"]
    radius = 6371  # Radius of the Earth in kilometers
    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)
    a = math.sin(dlat / 2) ** 2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) ** 2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    distance = radius * c
    return distance
def get_distance_matrix(cities):
    """populate distance matrix"""
    num_cities = len(cities)
    distances = [[0] * num_cities for _ in range(num_cities)]
    for i in range(num_cities):
        for j in range(i + 1, num_cities):
            dist = distance_between(cities[i], cities[j])
            distances[i][j] = int(dist)
            distances[j][i] = int(dist)
    return distances

distances = get_distance_matrix(cities)
for row in distances:
    print(row)

"""
[0, 255, 504, 477, 423]
[255, 0, 612, 356, 392]
[504, 612, 0, 456, 304]
[477, 356, 456, 0, 152]
[423, 392, 304, 152, 0]
"""

距离矩阵。

三、算法

  1. 从任意城市开始作为当前城市。柏林
  2. 将当前城市标记为已访问。
  3. 重复以下步骤,直到访问完所有城市:

一个。查找最近的未访问城市。汉堡

b.搬到最近的未访问城市。

c. 将最近的未访问城市标记为已访问。

d. 将当前城市与最近的未访问城市之间的距离添加到游览总长度中。

4.访问完所有城市后,返回起始城市完成游览。

四、python实现

def solve_tsp_nearest(distances):
    num_cities = len(distances)
    visited = [False] * num_cities
    tour = []
    total_distance = 0
    
    # Start at the first city
    current_city = 0
    tour.append(current_city)
    visited[current_city] = True
    
    
    # Repeat until all cities have been visited
    while len(tour) < num_cities:
        nearest_city = None
        nearest_distance = math.inf

        # Find the nearest unvisited city
        for city in range(num_cities):
            if not visited[city]:
                distance = distances[current_city][city]
                if distance < nearest_distance:
                    nearest_city = city
                    nearest_distance = distance

        # Move to the nearest city
        current_city = nearest_city
        tour.append(current_city)
        visited[current_city] = True
        total_distance += nearest_distance

    # Complete the tour by returning to the starting city
    tour.append(0)
    total_distance += distances[current_city][0]

    return tour, total_distance

tour, total_distance = solve_tsp_nearest(distances)

print("Tour:", tour)
print("Total distance:", total_distance)

"""
Tour: [0, 1, 3, 4, 2, 0]
Total distance: 1571
"""

让我们在真实的地图上绘制它。

import folium
m = folium.Map(location=[52.52, 13.405], zoom_start=6)

cities = [(52.5200, 13.4050), (53.5511, 9.9937), (48.1351, 11.5820), (50.9375, 6.9603), (50.1109, 8.6821)]
for i in range(len(cities)):
    folium.Marker(location=cities[i], tooltip=f"City {i}").add_to(m)

paths = [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
for path in paths:
    start_city = cities[path[0]]
    end_city = cities[path[1]]
    folium.PolyLine(locations=[start_city, end_city], color='red').add_to(m)

min_cost_path = [0, 1, 3, 4, 2, 0]
for i in range(len(min_cost_path)-1):
    start_city = cities[min_cost_path[i]]
    end_city = cities[min_cost_path[i+1]]
    folium.PolyLine(locations=[start_city, end_city], color='green').add_to(m)

地图上的TSP。图片由作者提供。

五、后记

        旅行家问题是一个基于图论的问题,其目的是在给定的图中找到一条路径,使得路径经过包含所有节点的最小总权重。该问题的解决方法可以采用蚁群算法、遗传算法、贪心算法等。

        其中,蚁群算法是一种模拟蚂蚁寻食的行为来求解优化问题的算法。蚂蚁在寻找食物的过程中,会释放信息素标记路径,其他蚂蚁会根据信息素来选择路径。通过模拟这个行为,可以让蚂蚁在给定的图中找到最优路径。

        遗传算法则是模拟生物进化的过程来求解问题的算法。在遗传算法中,初始种群的个体会经过选择、交叉、变异等操作,逐步进化出更适合问题的解决方案。通过适当的设置遗传算法的参数和操作,可以在旅行家问题中得到较好的解决方案。

        贪心算法是一种利用局部最优解来得到全局最优解的算法。在旅行家问题中,可以采用贪心策略选择距离当前节点最近的未访问节点作为下一个访问点。虽然贪心算法不一定能得到最优解,但是其计算速度快,可以在实际中得到较为实用的解决方案。

        除了以上三种算法,还可以采用动态规划、深度优先搜索、分支限界等算法来解决旅行家问题。具体使用哪种算法需要结合实际问题的特点来选择。奥坎·耶尼根

猜你喜欢

转载自blog.csdn.net/gongdiwudu/article/details/132689846