遺傳演算法解決TSP問題
阿新 • • 發佈:2021-10-27
旅行商問題,即TSP問題(Traveling Salesman Problem)又譯為旅行推銷員問題、貨郎擔問題,是數學領域中著名問題之一。
假設有一個旅行商人要拜訪n個城市,他必須選擇所要走的路徑,路徑的限制是每個城市只能拜訪一次,而且最後要回到原來出發的城市。
路徑的選擇目標是要求得的路徑路程為所有路徑之中的最小值。
選用python和matplotlib.pyplot圖形化
import math import copy import random import numpy as np import matplotlib.pyplot as plt from numpy.lib.function_base import average class TSP(): citys_position=[] #城市座標 population=[] #種群陣列 fitness=[] #適應度陣列 citys_size=10 #城市個數 population_size=100 #種群大小 rate_crossover=0.1 #交叉率 rate_mutation=0.01 #變異率 iteration_num=200 #最大迭代次數 best_dist=0x3f3f3f3f3f #記錄最優距離 dist_list=[] #記錄當前距離 best_dist_list=[] #記錄最優距離 best_individual=[] #記錄目前最優旅行方案 #載入城市座標 def load_citys_position(self): self.citys_position=[ [18,54],[87,76],[74,78],[71,71],[25,38], [58,35],[4,50],[13,40],[18,40],[24,42], # [71,44],[64,60],[68,58],[83,69],[58,69], # [54,62],[51,67],[37,84],[41,94],[2,99] ] #載入初始種群 def load_population(self): for i in range(self.population_size): temp=[] while len(temp)<self.citys_size: ite = random.randint(0,self.citys_size-1) if ite not in temp: temp.append(ite) self.population.append([]) for j in temp: self.population[i].append(j) # print(self.population) #初始化 def __init__(self): self.load_citys_position() self.load_population() self.get_fitness() self.choice() #城市距離-染色體權值 def city_dist(self,i,j): x=self.citys_position[i] y=self.citys_position[j] return math.sqrt(pow(x[0]-y[0],2)+pow(x[1]-y[1],2)) #種群距離集 def population_dist(self): now_dist_list=[] for i in range(len(self.population)): now_dist=0 for j in range(1,len(self.population[i])): now_dist+=self.city_dist(self.population[i][j],self.population[i][j-1]) now_dist_list.append(now_dist) return now_dist_list #適應度函式 def get_fitness(self): self.dist_list=self.population_dist() now_best_dist=min(self.dist_list) now_best_dist_index=self.dist_list.index(now_best_dist) now_fitness=[] if now_best_dist<self.best_dist: self.best_dist_list.append(now_best_dist) self.best_dist=now_best_dist self.best_individual=self.population[now_best_dist_index] else : self.best_dist_list.append(self.best_dist) for i in range(len(self.dist_list)): now_fitness.append(self.best_dist/self.dist_list[i]) self.fitness=now_fitness # print("self.best_dist:",self.best_dist," now_dist_list:",now_dist_list) # print("self.fitness:",self.fitness) #變異 def mutation(self): for i in range(len(self.population)): now_rate=random.random() if(now_rate<self.rate_mutation): #隨機出兩個點進行片段翻轉 index1=random.randint(0,len(self.population[i])-1) index2=random.randint(0,len(self.population[i])-1) if index1>index2: temp=index1 index1=index2 index2=temp self.population[i][index1:index2]=list(reversed(self.population[i][index1:index2])) #交叉互換 def crossover(self): last_index=-1; for i in range(len(self.population)): now_rate=random.random(); if(now_rate<self.rate_crossover): if(last_index==-1): last_index=i else : #順序交叉,保留前一個染色體的中間段,交換兩端 index1=random.randint(0,len(self.population[last_index])-1) index2=random.randint(0,len(self.population[last_index])-1) if index1>index2: temp=index1 index1=index2 index2=temp temp_list=[] #取出中間段 for j in range(index1,index2+1): temp_list.append(self.population[last_index][j]) next_gen=[] #儲存交叉互換後的基因 index_temp=0 for j in range(len(self.population[i])): if self.population[i][j] not in temp_list: next_gen.append(self.population[i][j]) else : next_gen.append(temp_list[index_temp]) index_temp+=1 self.population[last_index]=next_gen #賦新基因 last_index=i; #選擇函式 def choice(self): #最優解覆蓋 for i in range(len(self.fitness)): if self.fitness[i]<0.5: # print("self.fitness[i]:",self.fitness[i]," self.dist_list[i]:",self.dist_list[i]," best_dist:",self.best_dist) # print("self.population[i]:",self.population[i],"self.best_individual:",self.best_individual) # print(" ") self.population[i]=self.best_individual self.fitness[i]=1 #進化,主函式 def evolution(self): now_iteration_num=0 while now_iteration_num<self.iteration_num: now_iteration_num+=1 self.crossover() self.mutation() self.get_fitness() self.choice() #視覺化資料 def plot_show(self): print("self.best_dist",end=":") print(self.best_dist) print("self.best_individual",end=":") print(self.best_individual) x1=[] y1=[] x2=[] y2=[] for i in range(len(self.citys_position)): x1.append(self.citys_position[i][0]) y1.append(self.citys_position[i][1]) for i in range(len(self.best_individual)): x2.append(self.citys_position[self.best_individual[i]][0]) y2.append(self.citys_position[self.best_individual[i]][1]) print("x1:",end="") print(x1) print("y1:",end="") print(y1) print("x2:",end="") print(x2) print("y2:",end="") print(y2) plt.title("citys_position") plt.scatter(x1,y1,color='r',marker='o' ); #畫點 plt.figure(); plt.title("best_route") plt.plot(x2,y2,color='r',marker='o' ); #畫點 for i in range(len(x2)): plt.text(x2[i],y2[i],i+1) plt.figure(); plt.title("best_dist_change") plt.plot(self.best_dist_list,color='r') plt.show() def main(): tsp=TSP() tsp.evolution() tsp.plot_show() if __name__ == '__main__': main()