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

模拟退火算法的原理

模拟退火算法(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()
相关推荐
看到我,请让我去学习33 分钟前
Qt— 布局综合项目(Splitter,Stacked,Dock)
开发语言·qt
GUET_一路向前1 小时前
【C语言防御性编程】if条件常量在前,变量在后
c语言·开发语言·if-else·防御性编程
曳渔1 小时前
UDP/TCP套接字编程简单实战指南
java·开发语言·网络·网络协议·tcp/ip·udp
trayvontang1 小时前
Python虚拟环境与包管理工具(uv、Conda)
python·conda·uv·虚拟环境·miniconda·miniforge
伊织code1 小时前
pdfminer.six
python·pdf·图片·提取·文本·pdfminer·pdfminer.six
三千道应用题1 小时前
WPF&C#超市管理系统(6)订单详情、顾客注册、商品销售排行查询和库存提示、LiveChat报表
开发语言·c#·wpf
hqxstudying1 小时前
JAVA项目中邮件发送功能
java·开发语言·python·邮件
咪咪渝粮1 小时前
JavaScript 中constructor 属性的指向异常问题
开发语言·javascript
最初的↘那颗心1 小时前
Java HashMap深度解析:原理、实现与最佳实践
java·开发语言·面试·hashmap·八股文
Q_Q5110082852 小时前
python的软件工程与项目管理课程组学习系统
spring boot·python·django·flask·node.js·php·软件工程