数学建模学习(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):当前解的相邻解集合,通过一定规则生成。

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

相关推荐
数字芯片实验室2 小时前
分享一个可以学习正则表达式的网址:Pythex.org
学习·正则表达式
陈洪奇2 小时前
注册中心学习笔记整理
笔记·学习
光影少年2 小时前
从前端转go开发的学习路线
前端·学习·golang
fen_fen7 小时前
学习笔记(32):matplotlib绘制简单图表-数据分布图
笔记·学习·matplotlib
萝卜青今天也要开心11 小时前
2025年上半年软件设计师考后分享
笔记·学习
amazinging12 小时前
北京-4年功能测试2年空窗-报培训班学测开-第四十七天
python·学习·selenium
吃货界的硬件攻城狮12 小时前
【STM32 学习笔记】SPI通信协议
笔记·stm32·学习
一个天蝎座 白勺 程序猿12 小时前
Python练习(1)Python基础类型操作语法实战:20道实战题解与案例分析(上)
开发语言·python·学习
努力的小帅13 小时前
STM32单片机_3
stm32·单片机·嵌入式硬件·学习·stm32c8t6