1. 程式人生 > 實用技巧 >TSP旅行商問題

TSP旅行商問題

求解的問題,burma.tsp裡面的內容

1   16.47   96.10
2   16.47   94.44
3   20.09   92.54
4   22.39   93.37
5   25.23   97.24
6   22.00   96.05
7   20.47   97.02
8   17.20   96.29
9   16.30   97.38
10   14.05   98.12
11   16.53   97.38
12   21.52   95.59
13   19.41   97.13
14   20.09   94.55

主程式

為方便呼叫,已經將所有的模組整合到一個程式內。

import
random import math import matplotlib.pyplot as plt import re #-------引數部分--------# generation=[] fitvalue=[] # dict={ # 1:[16.47,96.10],2:[16.47,94.44],3:[20.09,92.54], # 4:[22.39,93.37],5:[25.23,97.24],6:[22.00,96.05], # 7:[20.47,97.02],8:[17.20,96.29],9:[16.30,97.38], # 10:[14.05,98.12],11:[16.53,97.38],12:[21.52,95.59],
# 13:[19.41,97.13],14:[20.09,94.55] # } #修改部位1。此部分的字典操作應該採用檔案讀寫的方式來完成 crossrate=4 mutationrate=1 size=30 popgeneration=400 #——————————————這裡是交叉的模組——————————# def crossOver(population): ret = [] for i in range(0,int(len(population)/2)): cplist1=[] cplist2=[] register1=[] register2
=[] crossval1=[] crossval2=[] x1=random.choice(population) target=0 while target!=1: x2=random.choice(population) if x2!=x1: target=1 if x2==x1: continue # print('隨機抽出兩個不同的母體',(x1,x2)) while len(cplist1)<=crossrate: #隨機抽crossrate條染色體位置傳給子代 crossposition=random.randrange(0,13) if crossposition not in cplist1: #保證隨機取得交叉位置不重複 cplist1.append(crossposition) crossval1.append(x1[crossposition]) # print('母體1傳給子代的交叉位置%s,交叉位置值%s' %(cplist1,crossval1)) for i in range(0,14): if i not in cplist1: cplist2.append(i) crossval2.append(x2[i]) # print('母體2傳給子代的交叉位置%s,交叉位置值%s' %(cplist2,crossval2)) for i1 in range(0,14): if i1 not in cplist1: #單體長度14,如果是交叉位置上的就傳值,如果不是就傳d register1.append('d') if i1 in cplist1: register1.append(x1[i1]) # print('母體1交叉位置形成子代1副本',register1) for i2 in x2: if i2 not in crossval1: #給d更換的值不能與已經存在的值重複 for xp in range(0,len(register1)): if register1[xp]=='d': #用於定位d的位置 register1[xp]=i2 break # print('交叉後的子體1',register1) for p1 in range(0,14): if p1 not in cplist2: register2.append('d') if p1 in cplist2: register2.append(x2[p1]) # print('母體2交叉位置形成子代1副本',register2) for p2 in x1: if p2 not in crossval2: for xp1 in range(0,len(register2)): if register2[xp1]=='d': register2[xp1]=p2 break # print('交叉後的子體2',register2) ret.append(register1) ret.append(register2) print('交叉完成後的種群',ret) return ret #——————————————這裡是變異的模組——————————# def mutation(population): ret=[] for i in population: porbility=random.uniform(0,1) if porbility<mutationrate: a=random.randrange(0,14) b=random.randrange(0,14) trans=i[a] trans1=i[b] i[a]=trans1 i[b]=trans ret.append(i) else: ret.append(i) # print('變異完成後的種群',ret) return ret #——————————————————這裡是產生隨機種群的模組——————————# def creatPop(popsize): ret1=[] for i in range(0,popsize): ret=[] # while(len(ret)<=13): # x=random.randrange(1,15) # if x not in ret: #xulie # ret.append(x) # ret1.append(ret) #根據上次說的改進,可以使用random亂序來生成 for i1 in range(0,14): ret.append(i1+1) random.shuffle(ret) ret1.append(ret) print('生成的初代種群',ret1) return ret1 creatPop(2) #——————————————————這裡是將檔案內的資料讀取出來並放入字典的程式——————————# dict={} fil=open('burma14.tsp','r',encoding='utf8') #r代表讀操作,且開啟時按utf8 for i in range(0,14): readtext=fil.readline() readline=re.split('[ ]',readtext) for i in range(0,4): readline.remove('') dict.update({int(readline[0]):[float(readline[1]),float(readline[2])]}) print(dict) #————————————————這裡是適應度函式值的計算模組—————— def fitNess(population): ret=[] for i in population: # print(i) distance = 0 s=0 for xp in range(0,len(i)-1): # print(dict[i[s]]) # print(dict[i[s+1]]) distance=distance+((dict[i[s]][0]-dict[i[s+1]][0])**2+(dict[i[s]][1]-dict[i[s+1]][1])**2)**(1/2) # print(distance) #每兩個相鄰的點位求距離 s=s+1 distance=distance+((dict[i[0]][0]-dict[i[13]][0])**2+(dict[i[0]][1]-dict[i[13]][1])**2)**(1/2) #最後再求終點到起點的距離 ret.append(distance) print('計算並集內個體適應度',ret) return ret def popChoice(population): ret=[] ret1=[] dict1={} unionpop=[] for i in start: unionpop.append(i) for i1 in population: unionpop.append(i1) print('新老種群並集',unionpop) fitlist=fitNess(unionpop) for xp in range(0,len(fitlist)): dict1.update({fitlist[xp]:unionpop[xp]}) print(dict1) fitlist.sort() print(fitlist) for xp1 in fitlist: ret.append(dict1[xp1]) print(ret) for xp2 in range(0,size): if ret[xp2] not in ret1: ret1.append(ret[xp2]) print(ret1) print('最優適應度值為',fitlist[0]) fitvalue.append(fitlist[0]) return ret1 a=creatPop(size) start=a for i in range(0,popgeneration): b=crossOver(start) c=mutation(b) d=popChoice(c) print('第%s世代,他的最優解為%s' %(i+1,d[0])) start=d for i1 in range(0,popgeneration): generation.append(i1) plt.plot(generation,fitvalue) plt.ylabel('fitness value') #為y軸加註釋 plt.xlabel('generation') #為x軸加註釋 plt.show()