模拟退火算法求解TSP问题

模拟退火算法解决TSP问题

流程图

在这里插入图片描述

数据集

att48.tsp、eil76.tsp、lin105.tsp【下载链接】

关键要素

  1. 贪心构造初始解
  2. 邻居解生成:2-opt邻域
  3. 解的评价:线路总距离
  4. 解的接受准则:Metropolis接受准则
    在这里插入图片描述
  5. t 初 温 t_{初温} t=累计求和(各点距其他点的最长距离)-累计求和(各点距其他点的最短距离) t 结 束 t_{结束} t=0.01【这个自己设就行】
  6. 降温函数:采取指数冷却,底数取0.99
  7. 终止条件:外循环结束,温度降到0.01以下时;内循环结束,迭代1000次。

代码

import random
import numpy as np
import math
import pandas as pd
import copy
import matplotlib.pyplot as plt
import time

def data_deal(city):
    city = np.array(city[0][6:len(city) - 1])
    city_name = city.tolist()
    chu_li = []
    for i in range(0, len(city_name)):
        temp = city_name[i].split()
        del temp[0]
        for x in range(0, 2):
            temp[x] = eval(temp[x])
        chu_li.append(temp)
    return chu_li

a280 = pd.read_csv(r'a280.tsp', encoding='utf-8-sig', header=None)
att48 = pd.read_csv(r'att48.tsp', encoding='utf-8-sig', header=None)
ch150 = pd.read_csv(r'ch150.tsp', encoding='utf-8-sig', header=None)
eil76 = pd.read_csv(r'eil76.tsp', encoding='utf-8-sig', header=None)
lin105 = pd.read_csv(r'lin105.tsp', encoding='utf-8-sig', header=None)

location=data_deal(att48) #更换上述数据集,求得对应满意解
num_city=len(location)#城市总数


def temperature():
    sum_max=0
    sum_min=0
    for i in dis_mat:
        temp=i[:]
        del temp[temp.index(0)]
        sum_max+=max(temp)
        sum_min+=min(temp)
    t=sum_max-sum_min
    return t

def distance(city_a, city_b):
    # dist代表距离
    x = city_a[0] - city_b[0]
    y = city_a[1] - city_b[1]
    dist = (x ** 2 + y ** 2) ** 0.5
    return dist

def greedy_solution(city):
    temp=city[:]
    for i  in range(0,len(city)-1):
        dis = distance(temp[i], temp[i+1])
        for j in range(i+2,len(city)):
            t=distance(temp[i],temp[j])
            if  t<dis:
                dis=t
                temp[i+1],temp[j]=temp[j],temp[i+1]
    route=[]
    for i in temp:
        route.append(city.index(i))
        
    return route

#==========================================
#对称矩阵,两个城市之间的距离
def distance_p2p_mat():
    dis_mat=[]
    for i in range(len(location)):
        dis_mat_each=[]
        for j in range(len(location)):
            dis=math.sqrt(pow(location[i][0]-location[j][0],2)+pow(location[i][1]-location[j][1],2))
            dis_mat_each.append(dis)
        dis_mat.append(dis_mat_each)
   # print(dis_mat)
    return dis_mat

#计算所有路径对应的距离
def cal_newpath(dis_mat,path):
    dis=0
    for j in range(num_city-1):
        dis=dis_mat[path[j]][path[j+1]]+dis
    dis=dis_mat[path[num_city-1]][path[0]]+dis#回家
    return dis

#点对点距离矩阵
dis_mat=distance_p2p_mat()
#初始路径
path=greedy_solution(location)
#初始距离
dis=cal_newpath(dis_mat,path)
#初始温度
initial_t=temperature() #初始温度
lowest_t=0.01 #最低温度
#迭代参数
M=(num_city-1)*(num_city-2)/2 #当连续多次都不接受新的状态,开始改变温度
iteration=1000 #设置迭代次数
alpha=0.99 #指数降温的底数

t_current=initial_t #当前温度
n=0
value=[]
start=time.time()
while (t_current>lowest_t):#外循环,改变温度
    count_m=0#M的计数
    count_iter=0#迭代次数计数
    while (count_m<M and count_iter<iteration):#内循环,连续多次不接受新的状态或者是迭代多次,跳出内循环        
        i=0
        j=0
        while(i==j):#防止随机了同一城市
            i=random.randint(1,num_city-1)
            j=random.randint(1,num_city-1)
        path_new=path.copy()
        path_new[i:j+1]=list(reversed(path_new[i:j+1]))
        #计算新解的距离
        dis_new=cal_newpath(dis_mat,path_new)
        #求差
        dis_delta=dis_new-dis
        #取0-1浮点随机数
        rand=random.random()
        #计算指数函数的值
        temp=-dis_delta/t_current if -dis_delta/t_current<700 else 700
        exp_d=math.exp(temp)
        #选择
        if dis_delta<0:
            path=path_new
            dis=dis_new
        elif exp_d>rand:
            path=path_new
            dis=dis_new    
        else:
            count_m=count_m+1
        count_iter=count_iter+1
    value.append(dis)
    n=n+1
    t_current=t_current*alpha#改变温度
end=time.time()
#外循环结束
time=end-start
dis_min=dis
path_min=path
print('运行时间:',round(time))
print('最短距离:',round(dis_min))
print('最短路径:',path_min)

### 绘制迭代改进后的路线图
x=[]
y=[]
path_min.append(path_min[0])
for i in range(0, len(path_min)):
    plt.scatter(location[path_min[i]][0], location[path_min[i]][1],color='b')
    x.append(location[path_min[i]][0])
    y.append(location[path_min[i]][1])
plt.plot(x,y)
plt.show()

### 绘制每次迭代后总距离数值下降图
plt.plot(value,color='r')
for i in range(len(value)):
    plt.scatter(i,value[i],color='b')
plt.show()

部分结果展示


数据集运行时间(s)最短距离官方距离
att48213360833533
路线图迭代下降图

数据集运行时间(s)最短距离官方距离
eil7622561538
路线图迭代下降图

数据集运行时间(s)最短距离官方距离
lin105381458114379
路线图迭代下降图

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值