【数学建模】旅行商问题 python代码

TSP问题在数学建模比赛中考察较多,而网上提供的代码通常是MATLAB版本,我用python复现了一下,以下是python代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as ns #其实可以不用nx库
from math import*
from random import*
import matplotlib
matplotlib.rcParams['font.family']='SimHei'
matplotlib.rcParams['axes.unicode_minus']=False  #这两行代码要一起复制,同时导入mpl库
#导入数据
data=pd.read_excel("D:\数学建模\算法\模拟退火算法\\testdata.xlsx",header=None)
new_data=data.values
matri=np.zeros((144,144))
def Changeapath(ori):   #采用赌轮盘法,从而启发式地路径
    p1=0.33;p2=0.33;
    p=np.random.random()
    if p<p1:
        x1,x2=randint(0,143),randint(0,143)
        m=ori[x1]
        ori[x1]=ori[x2]
        ori[x2]=m
    elif p1+p2>p>=p1:
        x1,x2,x3=randint(0,143),randint(0,143),randint(0,143)
        k=ori[x1:x2+1]
        np.delete(ori,k)
        np.insert(ori,x3,k)
    elif p>=p1+p2:
        x1,x2=randint(1,143),randint(1,143)
        t=ori[x2:x1-1:-1]
        ori[x1:(x2+1)]=t
    return ori

def calculength(path):
    ori_len=0
    for i in range(0,143):
        ori_len+=matri[path[i]][path[i+1]]
    return ori_len


for i in range(0,144):
    for j in range(0,144):
        matri[i][j]=round(sqrt((new_data[j][0]-new_data[i][0])**2+(new_data[j][1]-new_data[i][1])**2),4)


#无需蒙特卡罗模拟,定义初始路径
ori_nodes=np.random.randint(0,143,size=144)
T0=100;T=T0;maxgen=1000;Lk=500;alpha=0.95;minimum=0xffffff;min_result=calculength(ori_nodes)
resultset=[]
for i in range(maxgen):
    for j in range(Lk):#每一个温度下重复Lk次
        path=Changeapath(ori_nodes)
        leng=calculength(path)
        if leng<minimum:
            ori_nodes=path
            minimum=leng
        else:
            p=exp((minimum-leng)/T)
            if random()<p:
                ori_nodes=path
                minimum=leng
                
        #为避免陷入局部最优,再定义一个最小化参数
        if minimum<min_result:
            min_result=minimum
            best_path=path
    resultset.append(min_result)
    T=alpha*T
    
x=np.arange(1,len(resultset)+1)
plt.rcParams.update({'figure.autolayout': True})                                        
plt.plot(x,resultset,color='blue',linewidth=0.7)
plt.xlabel("循环次数")
plt.ylabel("路径长度")
plt.style.use('fivethirtyeight')
plt.axhline(644461.5988000002,linestyle='--',color='red',linewidth=0.5)
plt.text(0,644462,"644461.5988000002",fontsize=10)
plt.annotate("$(394, 644461.6)$",
            xy=(394, 644461.5988000002), xycoords='data',
            xytext=(514, 650000), textcoords='data',
            arrowprops=dict(facecolor='black', shrink=1),
            fontsize=12)
plt.savefig("TSP用模拟退火所求结果.png",dpi=400)
plt.show()
![请添加图片描述](https://img-blog.csdnimg.cn/279dfe9ccd794d2088be0aa0362e2f11.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBARHVvbHVvbHVvcw==,size_20,color_FFFFFF,t_70,g_se,x_16)

求解结果如下,
启发式算法求得的往往是近似解,且解不稳定。
红色虚线为最接近最优解的近似解。
在这里插入图片描述

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值