python实现模拟退火算法解决旅行商(TSP)问题

问题重述

旅行商问题(TSP)是一个经典的组合优化问题,也是计算机科学和运筹学中的一个重要问题。在TSP中,旅行商需要从一个城市出发,访问所有其他城市恰好一次,然后返回出发城市,使得所走过的路径总长度最短。这个问题在实际应用中非常常见,比如物流、电路板制作、DNA测序等领域都可以看到TSP的身影。TSP的难点在于随着城市数量的增加,搜索所有可能的路径将变得非常耗时,因为路径的数量是城市数量的阶乘。因此,寻找TSP的最优解是一个非常具有挑战性的任务,尤其是对于大规模问题。有许多算法被提出来解决TSP,包括暴力搜索、动态规划、遗传算法、蚁群算法、模拟退火等。这些算法各有优劣,适用于不同规模和特定类型的TSP问题。在这里我们采用模拟退火算法。

解题思路、方法实现:

解题思路、方法实现:
模拟退火算法(Simulated Annealing)是一种启发式优化算法,受到固体退火过程的启发。该算法通过模拟物质在高温下退火冷却的过程,从而在解空间中跳出局部最优解,寻找全局最优解。
简单来说,模拟退火算法的主要步骤包括:
1 初始化:随机选择一个初始解,并设定初始温度(Temperature)。
2 循环迭代:在当前解的基础上进行微小的扰动,生成一个新解。计算新解的目标函数值(或者称为能量值)和当前解的目标函数值的差异(ΔE)。如果 ΔE 小于0,即新解更优,接受新解。如果 ΔE 大于0,以一定的概率(由一个概率分布计算得出,通常是玻尔兹曼分布)接受新解。这个概率随着温度的降低而减小,但在开始时有较大的概率接受劣解,以便跳出局部最优解。
3 降低温度,通常按照某个固定的降温率进行。
4 终止条件:当温度降低到足够低(接近零)或者达到最大迭代次数时停止算法。最终的解即为所求解。
这种随机性和“接受劣解”的策略使得模拟退火算法有可能避免陷入局部最优解,同时在搜索空间中进行广泛的探索,从而找到更优的解。算法中的温度和接受劣解的概率是关键的参数,它们影响了算法的探索性能。

模拟退火解决TSP问题思路:

在TSP问题中,模拟退火算法在解决旅行商问题(TSP)时的思路是通过在解空间中进行随机游走,模拟“退火”过程中的分子在热系统中的运动。具体步骤如下:
1 初始化解:随机生成一个初始路径,表示旅行商依次访问城市的顺序。
2 设定初始温度:初始时,系统的“温度”很高,容许接受较差的解。初始温度的选择对算法的性能有影响,通常由问题的特性和经验决定。
3 迭代过程:在当前解的基础上进行微小的扰动,例如交换两个城市的顺序,得到一个新的解。计算新解的路径长度与当前解的路径长度之差(ΔE)。如果 ΔE 小于0,即新解更优,直接接受新解。如果 ΔE 大于0,以一定的概率(由温度和 ΔE 决定)接受新解。温度高时,概率较大,有较大可能性接受劣解;随着迭代进行,温度逐渐降低,接受劣解的概率减小,算法越来越趋向于选择更好的解。
4 降低温度:在每个迭代步骤后,通过一个降温策略减小温度。典型的降温策略是乘以一个小于1的因子。
5 终止条件:当温度降低到足够低(接近零)或者达到最大迭代次数时停止算法。此时,当前解即为所求解。

代码实现:

读取tsp文件和距离矩阵文件

python实现模拟退火算法解决旅行商(TSP)问题_第1张图片

根据定义构建模拟退火算法
python实现模拟退火算法解决旅行商(TSP)问题_第2张图片

主程序如下
python实现模拟退火算法解决旅行商(TSP)问题_第3张图片
求解结果

python实现模拟退火算法解决旅行商(TSP)问题_第4张图片

注意:

我们这里采用的数据集和下列博客的数据集一样,这篇博客给出了不使用txt数据,自定义距离矩阵的代码

https://blog.csdn.net/qq_49370210/article/details/134609526

总的代码

import random
import math

# 读取 .tsp 文件以获取元数据
def read_tsp_file(filename):
    metadata = {}
    with open(filename, 'r') as file:
        lines = file.readlines()
        for line in lines:
            if line.startswith("DIMENSION"):
                metadata["num_cities"] = int(line.split(":")[1])
            # 可以根据需要解析其他元数据
            
    return metadata

# 读取距离矩阵文件 .d
def read_distance_matrix(filename, num_cities):
    with open(filename, 'r') as file:
        lines = file.readlines()
    
    # 解析距离矩阵
    distance_matrix = []
    for line in lines:
        row = [int(dist) for dist in line.strip().split()]
        distance_matrix.append(row)
    
    return distance_matrix

# 计算路径长度
def calculate_path_length(path, distance_matrix):
    total_distance = 0
    for i in range(len(path) - 1):
        total_distance += distance_matrix[path[i]][path[i + 1]]
    total_distance += distance_matrix[path[-1]][path[0]]  # 回到起始城市
    return total_distance


# 模拟退火算法
def simulated_annealing(distance_matrix, initial_temperature, cooling_rate, num_iterations):
    current_solution = random.sample(range(len(distance_matrix)), len(distance_matrix))
    current_energy = calculate_path_length(current_solution, distance_matrix)
    best_solution = current_solution
    best_energy = current_energy
    temperature = initial_temperature

    for _ in range(num_iterations):
        # 生成新解
        new_solution = current_solution[:]
        # 随机选择两个位置交换
        i, j = random.sample(range(len(new_solution)), 2)
        new_solution[i], new_solution[j] = new_solution[j], new_solution[i]
        new_energy = calculate_path_length(new_solution, distance_matrix)

        # 计算能量差
        delta_energy = new_energy - current_energy

        # 如果新解更优,或者以一定概率接受劣解
        if delta_energy < 0 or random.random() < math.exp(-delta_energy / temperature):
            current_solution = new_solution
            current_energy = new_energy

            # 更新最优解
            if current_energy < best_energy:
                best_solution = current_solution
                best_energy = current_energy

        # 降低温度
        temperature *= (1 - cooling_rate)

    return best_solution, best_energy

'''
if __name__ == "__main__":
    num_cities = 5
	custom_distance_matrix = np.array([
    [0, 10, 20, 15, 30],   # 城市0到其他城市的距离
    [10, 0, 25, 20, 35],   # 城市1到其他城市的距离
    [20, 25, 0, 12, 28],   # 城市2到其他城市的距离
    [15, 20, 12, 0, 22],   # 城市3到其他城市的距离
    [30, 35, 28, 22, 0]    # 城市4到其他城市的距离
	])
    initial_temperature = 1000  # 初始温度
    cooling_rate = 0.003  # 冷却率
    num_iterations = 1000000

    distance_matrix = read_distance_matrix(custom_distance_matrix, num_cities)

    best_path, best_distance = simulated_annealing(distance_matrix, initial_temperature, cooling_rate, num_iterations)

    print("最短路径:", best_path)
    print("最短距离:", best_distance)

'''

# 主程序
if __name__ == "__main__":
    tsp_metadata = read_tsp_file("dantzig42.tsp")
    initial_temperature = 1000  # 初始温度
    cooling_rate = 0.003  # 冷却率
    num_iterations = 1000000
    #distance_matrix = read_distance_matrix("dantzig42_d.txt",42)
     #不使用tsp文件
    distance_matrix = read_distance_matrix("dantzig42_d.txt", tsp_metadata["num_cities"])

    best_path, best_distance = simulated_annealing(distance_matrix, initial_temperature, cooling_rate, num_iterations)

    print("最短路径:", best_path)
    print("最短距离:", best_distance)


111

你可能感兴趣的:(python,模拟退火算法,开发语言)