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

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

相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
山楂树の5 天前
【高等数学】 计算对弧长的曲线积分
数学建模
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode