禁忌搜索算法解决TSP问题

禁忌搜索算法解决TSP问题

    • 流程图
    • 数据集
    • 关键要素
    • 代码
    • 部分结果展示

流程图

禁忌搜索算法解决TSP问题_第1张图片

数据集

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

关键要素

  1. 初始解产生:采用基于最近邻居构造启发式的贪婪算法生成初始解
  2. 邻域生成:采用2-opt邻域
  3. 禁忌对象:以迭代生成的局部最优解为禁忌对象
  4. 禁忌表长度(禁忌任期):取固定值,为城市的个数
  5. 迭代次数:设定为100

代码

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(lin105)
num_city=len(location)#城市总数
table_len=num_city#禁忌表长度
taboo_table=[] #禁忌表
iters=100 #迭代次数


#==========================================
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(num_city):
        dis_mat_each=[]
        for j in range(num_city):
            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_new):
    dis_list=[]
    for each in path_new:
        dis=0
        for j in range(num_city-1):
            dis=dis_mat[each[j]][each[j+1]]+dis
        dis=dis_mat[each[num_city-1]][each[0]]+dis#回家
        dis_list.append(dis)
    return dis_list

#寻找上一个最优路径对应的所有领域解
def find_newpath(path_best):
    path_new=[]
    for i in range(1,num_city-1):
        for j in range(i+1,num_city):
            path=path_best.copy()
            path[i:j+1]=list(reversed(path[i:j+1]))
            path_new.append(path)
    return path_new

#==========================================
#点对点距离矩阵
dis_mat=distance_p2p_mat()

#设置初始解
path_initial=[]
initial=greedy_solution(location)
path_initial.append(initial)
#print(path_initial)

#加入禁忌表
taboo_table.append(initial)

#求初始解的路径长度
dis_list=cal_newpath(dis_mat,path_initial)
dis_best=min(dis_list)#最短距离
path_best=path_initial[dis_list.index(dis_best)]#对应的最短路径方案
#print(path_best)

#初始期望
expect_dis=dis_best
expect_best=path_best
value=[dis_best]

start=time.time()
for iter in range(iters):#迭代
    #寻找全领域新解
    path_new=find_newpath(path_best)
    #print(path_new)
    #求出所有新解的路径长度
    dis_new=cal_newpath(dis_mat,path_new)
#    print(dis_new)
    #选择路径
    dis_best=min(dis_new)#最短距离
    path_best=path_new[dis_new.index(dis_best)]#对应的最短路径方案
    if dis_best < expect_dis:#最短的<期望
        expect_dis=dis_best
        expect_best=path_best#更新两个期望
        if path_best in taboo_table:
            taboo_table.remove(path_best)
            taboo_table.append(path_best)
        else:
            taboo_table.append(path_best)
    else:#最短的还是不能改善期望
        if path_best in taboo_table:#在禁忌表里
            dis_new.remove(dis_best)
            path_new.remove(path_best)
            dis_best=min(dis_new)#求不在禁忌表中的最短距离
            path_best=path_new[dis_new.index(dis_best)]#对应的最短路径方案
            taboo_table.append(path_best)
        else:#不在禁忌表
            taboo_table.append(path_best)
    if len(taboo_table)>=table_len:
        del taboo_table[0]
    value.append(dis_best)
end=time.time()
time=end-start
print('运行时间:',round(time))
print('最短距离',round(expect_dis))
print('最短路径:',expect_best)
### 绘制迭代改进后的路线图
   
x=[]
y=[]
expect_best.append(expect_best[0])
for i in range(0, len(expect_best)):
    plt.scatter(location[expect_best[i]][0], location[expect_best[i]][1],color='b')
    x.append(location[expect_best[i]][0])
    y.append(location[expect_best[i]][1])
plt.plot(x,y)
plt.title("satisfactory solution of TA:%d"%(round(expect_dis)))
plt.show()

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

部分结果展示


数据集 运行时间(s) 最短距离 官方距离
att48 1 34406 33533
路线图 迭代下降图
禁忌搜索算法解决TSP问题_第2张图片 禁忌搜索算法解决TSP问题_第3张图片

数据集 运行时间(s) 最短距离 官方距离
eil76 4 555 538
路线图 迭代下降图
禁忌搜索算法解决TSP问题_第4张图片 禁忌搜索算法解决TSP问题_第5张图片

数据集 运行时间(s) 最短距离 官方距离
lin105 9 14717 14379
路线图 迭代下降图
禁忌搜索算法解决TSP问题_第6张图片 禁忌搜索算法解决TSP问题_第7张图片

你可能感兴趣的:(python,算法)