利用模拟退火算法求解旅行商问题

模拟退火算法的原理

模拟退火算法(Simulated Annealing, SA)是一种全局优化算法,其灵感来源于物理学中的退火过程。在物理退火过程中,通过逐渐降低系统温度,使物质内部的原子从高能量状态慢慢转变到低能量状态,从而达到晶体结构的优化。模拟退火算法借鉴了这种过程,通过随机搜索和逐步降低"温度"来寻找优化问题的全局最优解。

关键概念
  1. 温度(Temperature): 控制搜索过程中的"探索"与"开发"平衡。高温下允许较大范围的随机搜索,低温下逐渐收敛到局部优化。

  2. 状态(State): 问题的一个解。

  3. 能量(Energy): 目标函数的值,反映当前状态的质量。

  4. 接受概率(Acceptance Probability): 用于决定是否接受一个新的状态,即使它的能量较高,以避免陷入局部最优解。

算法步骤
  1. 初始化温度 TT 和初始状态 SS。

  2. 重复以下步骤直到满足停止条件:

    1. 在当前状态 S 的邻域中随机选择一个新的状态 S'。

    2. 计算状态 S′ 的能量差 ΔE=E(S′)−E(S)。

    3. 如果 ΔE≤0,接受新的状态 S′;否则,以概率接受新的状态。

    4. 减少温度 T。

  3. 返回找到的最优状态。

应用

模拟退火算法广泛应用于组合优化问题和实际工程中的复杂优化问题。常见的应用包括:

  1. 旅行商问题(TSP): 通过模拟退火算法寻找最短路径。

  2. 排程问题: 优化工厂生产调度、考试安排等。

  3. 电路设计: 优化芯片设计中的布局和连线。

  4. 神经网络训练: 优化神经网络参数,避免陷入局部最优解。

旅行商问题求解:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 生成随机城市坐标
def generate_cities(num_cities):
    return np.random.rand(num_cities, 2)

# 计算路径长度
def path_length(cities, path):
    """
    计算给定路径的总长度
    :param cities: 城市坐标的二维数组
    :param path: 城市访问顺序的数组
    :return: 路径的总长度
    """
    return np.sum(np.linalg.norm(cities[path] - cities[np.roll(path, -1)], axis=1))

# 交换路径中的两个城市
def swap_cities(path):
    """
    随机交换路径中的两个城市
    :param path: 城市访问顺序的数组
    """
    i, j = np.random.choice(len(path), 2, replace=False)
    path[i], path[j] = path[j], path[i]

# 模拟退火算法
def simulated_annealing(cities, initial_temp, cooling_rate, num_iterations):
    """
    使用模拟退火算法寻找最短路径
    :param cities: 城市坐标的二维数组
    :param initial_temp: 初始温度
    :param cooling_rate: 降温速率
    :param num_iterations: 迭代次数
    :return: 最佳路径及其长度和每次迭代的路径长度
    """
    # 城市数量
    num_cities = len(cities)
    
    # 初始路径为随机顺序
    current_path = np.arange(num_cities)
    np.random.shuffle(current_path)
    
    # 计算初始路径的长度
    current_length = path_length(cities, current_path)
    
    # 初始化最佳路径和长度
    best_path = current_path.copy()
    best_length = current_length
    
    # 初始化温度
    temp = initial_temp

    # 记录路径长度变化
    lengths = []

    # 开始迭代
    for _ in range(num_iterations):
        # 创建新路径,通过交换当前路径中的两个城市
        new_path = current_path.copy()
        swap_cities(new_path)
        
        # 计算新路径的长度
        new_length = path_length(cities, new_path)
        
        # 计算路径长度差
        delta = new_length - current_length

        # 决定是否接受新路径
        if delta < 0 or np.random.rand() < np.exp(-delta / temp):
            current_path = new_path
            current_length = new_length

            # 更新最佳路径
            if new_length < best_length:
                best_path = new_path
                best_length = new_length

        # 降低温度
        temp *= cooling_rate
        
        # 记录当前路径长度
        lengths.append(current_length)

    return best_path, best_length, lengths


# 参数设置
num_cities = 20
initial_temp = 100
cooling_rate = 0.99
num_iterations = 1000

cities = generate_cities(num_cities)
best_path, best_length, lengths = simulated_annealing(cities, initial_temp, cooling_rate, num_iterations)

# 可视化结果
plt.figure(figsize=(10, 5))

# 绘制城市和最佳路径
plt.subplot(1, 2, 1)
plt.plot(cities[:, 0], cities[:, 1], 'o')
for i in range(num_cities):
    plt.text(cities[i, 0], cities[i, 1], str(i))

for i in range(num_cities):
    plt.plot([cities[best_path[i], 0], cities[best_path[(i+1) % num_cities], 0]],
             [cities[best_path[i], 1], cities[best_path[(i+1) % num_cities], 1]], 'r-')

plt.title(f"Best Path (Length: {best_length:.2f})")

# 绘制路径长度随迭代次数的变化
plt.subplot(1, 2, 2)
plt.plot(lengths)
plt.xlabel('Iteration')
plt.ylabel('Path Length')
plt.title('Path Length over Iterations')

plt.tight_layout()
plt.show()
相关推荐
西元.14 分钟前
线程等待与唤醒的几种方法与注意事项
java·开发语言
xcLeigh17 分钟前
计算机视觉入门:从像素到理解的旅程
人工智能·python·opencv·计算机视觉
独好紫罗兰22 分钟前
洛谷题单2-P5717 【深基3.习8】三角形分类-python-流程图重构
开发语言·python·算法
落榜程序员23 分钟前
Java基础-25-继承-方法重写-子类构造器的特点-构造器this的调用
java·开发语言
滴答滴答嗒嗒滴29 分钟前
Python小练习系列 Vol.8:组合总和(回溯 + 剪枝 + 去重)
python·算法·剪枝
forestsea30 分钟前
Java 应用程序CPU 100%问题排查优化实战
java·开发语言
啊阿狸不会拉杆31 分钟前
第十八章:Python实战专题:北京市水资源数据可视化与图书馆书籍管理应用开发
开发语言·python·信息可视化·用户界面
阿ฅ( ̳• ε • ̳)ฅ35 分钟前
C#窗体应用程序连接数据库
开发语言·数据库·c#
学习同学37 分钟前
C++进阶知识复习 1~15
java·开发语言·c++
egoist20231 小时前
【C++指南】一文总结C++二叉搜索树
开发语言·数据结构·c++·c++11·二叉搜索树