数学建模学习(3)——模拟退火算法

一、模拟退火算法解TSP问题

python 复制代码
import random
import numpy as np
from math import e, exp
import matplotlib.pyplot as plt

# 31个城市的坐标
city_loc = [(1304, 2312), (3639, 1315), (4177, 2244), (3712, 1399), (3488, 1535),
            (3326, 1556), (3238, 1229), (4196, 1004), (4312, 790), (4380, 570),
            (3007, 1970), (2562, 1756), (2788, 1491), (2381, 1676), (1332, 695),
            (3715, 1678), (3918, 2179), (4061, 2370), (3780, 2212), (3676, 2578),
            (4029, 2838), (4263, 2931), (3429, 1908), (3507, 2367), (3394, 2643),
            (3439, 3201), (2935, 3240), (3140, 3550), (2545, 2357), (2778, 2826), (2370, 2975)]

T0 = 50000#初始温度
T_end = 15#结束温度
q = 0.98#退火速率
L = 1000#迭代次数

# 两个城市的距离
def dist(a, b):
    x1 = city_loc[a][0]
    x2 = city_loc[b][0]
    y1 = city_loc[a][1]
    y2 = city_loc[b][1]
    distance = ((x2 - x1)**2 + (y2 - y1)**2)**0.5
    return distance

# 路程总长
def totaldistance(a):
    value = 0
    for j in range(30):
        value += dist(a[j], a[j + 1])
    value += dist(a[30], a[0])
    return value

# 初始化一个解 [0,1,2,3..30]
def init_ans():
    ans = []
    for i in range(31):
        ans.append(i)
    return ans

# 产生新解
def creat_new(ans_before):
    ans_after = ans_before[:]
    cuta = random.randint(0, 30)
    cutb = random.randint(0, 30)
    ans_after[cuta], ans_after[cutb] = ans_after[cutb], ans_after[cuta]
    return ans_after

if __name__ == '__main__':
    ans0 = init_ans()
    T = T0
    cnt = 0
    trend = []

    while T > T_end:
        for i in range(L):
            newans = creat_new(ans0)
            old_dist = totaldistance(ans0)
            new_dist = totaldistance(newans)
            df = new_dist - old_dist
            if df >= 0:
                rand = random.uniform(0, 1)
                if rand < 1 / exp(df / T):  #关键步骤,通过概率控制是否将当前产生的新解当作退火分支
                    ans0 = newans
            else:
                ans0 = newans
        T = T * q
        cnt += 1
        now_dist = totaldistance(ans0)
        trend.append(now_dist)
        #print(cnt, "次降温,温度为:", T, " 路程长度为:", now_dist)

    distance = totaldistance(ans0)
    print(distance, ans0)

    # 绘制温度与距离变化图
    plt.plot(trend)
    plt.title("Temperature vs. Distance")
    plt.xlabel("Iteration")
    plt.ylabel("Distance")
    plt.show()

    # 绘制最佳路径图
    fig, ax = plt.subplots(1, 2, figsize=(12, 5), facecolor='#ccddef')
    # 定义子图1标题
    ax[0].set_title("Best route")
    # 画线
    x_coords = [city_loc[i][0] for i in ans0] + [city_loc[ans0[0]][0]]
    y_coords = [city_loc[i][1] for i in ans0] + [city_loc[ans0[0]][1]]
    ax[0].plot(x_coords, y_coords)
    # 画点
    ax[0].scatter(x_coords, y_coords, color='r')
    plt.show()

二、算法介绍

模拟退火算法(Simulated Annealing, SA)是一种用于全局优化问题的随机搜索算法,灵感来自金属退火过程中的物理现象。它通过允许在一定概率下接受较差解,以避免陷入局部最优解,逐渐趋近全局最优解。

模拟退火算法的基本概念

  1. 状态空间:所有可能解的集合。
  2. 目标函数:需要优化的函数,用于评价解的好坏。
  3. 温度参数(T):控制算法接受较差解的概率,温度逐渐降低。
  4. 邻域(Neighborhood):当前解的相邻解集合,通过一定规则生成。

模拟退火算法是一种强大的全局优化方法,通过模拟物理退火过程,在搜索空间中进行广泛探索,逐步收敛到全局最优解。尽管计算复杂度较高,但其简单灵活的特点使其在解决复杂优化问题时具有重要应用价值。根据具体问题的需求,可以灵活调整算法参数和策略,以达到最佳优化效果。

相关推荐
您好啊数模君1 小时前
2025年五一数学建模竞赛&AI辅助&全网专业性第一
数学建模·2025年五一数学建模竞赛·2025年五一数学建模·2025年五一数学建模a题·2025年五一数学建模b题·2025年五一数学建模c题
FAREWELL000752 小时前
C#进阶学习(十六)C#中的迭代器
开发语言·学习·c#·迭代器模式·迭代器
DXM05213 小时前
牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记3-地图基本操作与实战案例
开发语言·笔记·学习·arcgis·c#·ae·arcgis engine
qsmyhsgcs4 小时前
Java程序员转人工智能入门学习路线图(2025版)
java·人工智能·学习·机器学习·算法工程师·人工智能入门·ai算法工程师
Humbunklung5 小时前
PySide6 GUI 学习笔记——常用类及控件使用方法(常用类矩阵QRectF)
笔记·python·学习·pyqt
每次的天空6 小时前
Android学习总结之Java篇(一)
android·java·学习
黑不拉几的小白兔7 小时前
risc-V学习日记(4):RV32I指令集
学习·risc-v
春眠不觉晓♞7 小时前
使用多线程快速向Excel中快速插入一万条数据案例
java·学习·excel
Mabnus7 小时前
文献分享:一种四价双特异性抗体的功能性和IgG样稳定性、药理学和可开发特性研究
学习
岁月不能老8 小时前
Linux-Part8-考试(学习Linux第8天)
linux·运维·学习