基于组合遗传粒子群算法的旅行商问题求解
生活随笔
收集整理的這篇文章主要介紹了
基于组合遗传粒子群算法的旅行商问题求解
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
問題描述
一個(gè)商品推銷員要去若干個(gè)城市推銷商品,該推銷員從一個(gè)城市出發(fā),需要經(jīng)過所有城市后,回到出發(fā)地。應(yīng)如何選擇行進(jìn)路線,以使總的行程最短。
對(duì)于n個(gè)城市的TSP,本文利用python分別實(shí)現(xiàn)混合粒子群算法對(duì)該問題的求解。
混合粒子群
混合粒子群算法的基本運(yùn)算過程如下
流程圖如圖
代碼
語言:python
第一步初始化參數(shù)
import numpy as np import matplotlib.pyplot as pltclass Hybrid_POS_TSP(object):def __init__(self, data, num_pop=200):self.num_pop = num_pop # 群體個(gè)數(shù)self.data = data # 城市坐標(biāo)self.num = len(data) # 城市個(gè)數(shù)# 群體的初始化和路徑的初始化self.chrom = np.array([0] * self.num_pop * self.num).reshape(self.num_pop, self.num)#shape(num_pop,num)self.fitness = [0] * self.num_pop#一個(gè)個(gè)體一個(gè)適應(yīng)度函數(shù)# 路徑矩陣,函數(shù)matrix_dis同遺傳算法self.matrix_distance = self.matrix_dis()距離函數(shù),加入類Hybrid_POS_TSP
# 計(jì)算城市間的距離函數(shù) n*n, 第[i,j]個(gè)元素表示城市i到j(luò)距離def matrix_dis(self):res = np.zeros((self.num, self.num))for i in range(self.num):for j in range(i + 1, self.num):res[i, j] = np.linalg.norm(self.data[i, :] - self.data[j, :]) # 求二階范數(shù) 就是距離公式res[j, i] = res[i, j]return res隨機(jī)產(chǎn)生初始化群體函數(shù),加入類Hybrid_POS_TSP
# 隨機(jī)產(chǎn)生初始化群體函數(shù)def rand_chrom(self):rand_ch = np.array(range(self.num)) ## num 城市個(gè)數(shù) 對(duì)應(yīng)染色體長(zhǎng)度 城市=14for i in range(self.num_pop): # num_pop # 群體個(gè)數(shù) 200np.random.shuffle(rand_ch) # 打亂城市染色體編碼self.chrom[i, :] = rand_ch#.chrom 父代self.fitness[i] = self.comp_fit(rand_ch)# 計(jì)算單個(gè)染色體的路徑距離值,可利用該函數(shù)更新fittnessdef comp_fit(self, one_path):res = 0for i in range(self.num - 1):res += self.matrix_distance[one_path[i], one_path[i + 1]] # matrix_distance n*n, 第[i,j]個(gè)元素表示城市i到j(luò)距離res += self.matrix_distance[one_path[-1], one_path[0]] # 最后一個(gè)城市 到起點(diǎn)距離return res路徑可視化函數(shù),加入類Hybrid_POS_TSP
def out_path(self, one_path):res = str(one_path[0] + 1) + '-->'for i in range(1, self.num):res += str(one_path[i] + 1) + '-->'res += str(one_path[0] + 1) + '\n'print(res)兩條路徑的交叉函數(shù):將每個(gè)個(gè)體與該個(gè)體的個(gè)體極值和當(dāng)前群體的群體極值進(jìn)行交叉操作。代碼加入類Hybrid_POS_TSP
#兩條路徑的交叉函數(shù):將每個(gè)個(gè)體與該個(gè)體的個(gè)體極值和當(dāng)前群體的群體極值進(jìn)行交叉操作def cross_1(self, path, best_path):#path為 個(gè)體最優(yōu) ,best_path為群體最優(yōu)r1 = np.random.randint(self.num)#隨機(jī)產(chǎn)生小于num的整數(shù)r2 = np.random.randint(self.num)#隨機(jī)產(chǎn)生小于num的整數(shù)while r2 == r1:#如果兩者相等r2 = np.random.randint(self.num)#重新產(chǎn)生r2left, right = min(r1, r2), max(r1, r2)#left 為(r1,r2)小者,right 為(r1,r2)大者cross = best_path[left:right + 1]#交叉片段為 群體最優(yōu)中的(r1:r2)片段#下面的for 循環(huán)是為了確保 個(gè)體染色體(0:(num-(right-left+1)) 片段 不含有 cross中的元素。for i in range(right - left + 1):#有(r2-r1)次遍歷for k in range(self.num):#遍歷個(gè)體染色體中的每一個(gè)值if path[k] == cross[i]:#如果當(dāng)前個(gè)體染色體元素path[k] 是cross之內(nèi)path[k:self.num - 1] = path[k + 1:self.num] #則修改path[k:num - 1] 片段,同時(shí)末尾補(bǔ)0 (也就是說把不屬于cross的個(gè)體染色體元素 往前趕path[-1] = 0path[self.num - right + left - 1:self.num] = cross#把個(gè)體染色體(num-(right-left+1):num ) 片段 和群體交叉return path變異函數(shù):對(duì)單個(gè)染色體隨機(jī)交換兩個(gè)點(diǎn)的位置。代碼加入類Hybrid_POS_TSP
def mutation(self, path):#path 個(gè)體染色體r1 = np.random.randint(self.num)#隨機(jī)生成小于num的整數(shù)r2 = np.random.randint(self.num)#隨機(jī)生成小于num的整數(shù)while r2 == r1:#如果r1==r2r2 = np.random.randint(self.num)#則r2再重新生成path[r1], path[r2] = path[r2], path[r1]#交換片段return path主函數(shù)
#data = np.random.rand(20, 2) * 10 # 隨機(jī)產(chǎn)生20個(gè)城市坐標(biāo) def main(data, max_n=200, num_pop=200):#迭代次數(shù)max_n200 群體個(gè)數(shù)num_pop=200Path_short = Hybrid_POS_TSP(data, num_pop=num_pop) # 混合粒子群算法類Path_short.rand_chrom() # 初始化種群# 初始化路徑繪圖fig, ax = plt.subplots()x = data[:, 0]y = data[:, 1]ax.scatter(x, y, linewidths=0.1)for i, txt in enumerate(range(1, len(data) + 1)):ax.annotate(txt, (x[i], y[i]))res0 = Path_short.chrom[0]x0 = x[res0]y0 = y[res0]for i in range(len(data) - 1):plt.quiver(x0[i], y0[i], x0[i + 1] - x0[i], y0[i + 1] - y0[i], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.quiver(x0[-1], y0[-1], x0[0] - x0[-1], y0[0] - y0[-1], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.show()print('初始染色體的路程: ' + str(Path_short.fitness[0]))#定義6個(gè)容器 分別存放個(gè)體極值,個(gè)體染色體,群體最優(yōu)極值,群體最優(yōu)染色體,每一次迭代后的最優(yōu)極值,每一次迭代后最優(yōu)個(gè)體染色體 (容器定義的樣子要和染色體個(gè)數(shù)等一致)# 存儲(chǔ)個(gè)體極值的路徑和距離best_P_chrom = Path_short.chrom.copy()# 個(gè)體極值 路徑 (個(gè)體染色體)best_P_fit = Path_short.fitness.copy()#個(gè)體極值 距離min_index = np.argmin(Path_short.fitness)#最優(yōu)個(gè)體的index序號(hào)#存儲(chǔ)當(dāng)前種群極值的路徑和距離best_G_chrom = Path_short.chrom[min_index, :]#存儲(chǔ)當(dāng)前種群極值的路徑(群體最優(yōu)染色體)best_G_fit = Path_short.fitness[min_index]#存儲(chǔ)當(dāng)前種群極值的距離(群體最優(yōu)極值)# 存儲(chǔ)每一步迭代后的最優(yōu)路徑和距離best_chrom = [best_G_chrom]#當(dāng)代最優(yōu)個(gè)體best_fit = [best_G_fit]#當(dāng)代最優(yōu)極值# 復(fù)制當(dāng)前群體進(jìn)行交叉變異x_new = Path_short.chrom.copy()# 進(jìn)入迭代 更新個(gè)體極值,個(gè)體染色體,群體最優(yōu)極值,群體最優(yōu)個(gè)體,存放當(dāng)代最優(yōu)個(gè)體,存放當(dāng)代最優(yōu)極值for i in range(max_n):#遍歷迭代# 更新當(dāng)前的個(gè)體極值 和路徑 #for j in range(num_pop):#遍歷每一個(gè)個(gè)體if Path_short.fitness[j] < best_P_fit[j]:#best_P_fit[j] = Path_short.fitness[j]#更新個(gè)體極值best_P_chrom[j, :] = Path_short.chrom[j, :]#更新個(gè)體極值路徑# 更新當(dāng)前種群的群體極值min_index = np.argmin(Path_short.fitness)best_G_chrom = Path_short.chrom[min_index, :]#群體極值 路徑best_G_fit = Path_short.fitness[min_index]#群體極值# 添加 每一次迭代后的 當(dāng)代全局最優(yōu)個(gè)體和解極值if best_G_fit < best_fit[-1]:#best_G_fit 全局極值 best_fit每一步迭代后的最優(yōu)極值best_fit.append(best_G_fit)#best_chrom.append(best_G_chrom)else:best_fit.append(best_fit[-1])best_chrom.append(best_chrom[-1])#遍歷每一個(gè)個(gè)體,將個(gè)體與當(dāng)代最優(yōu)個(gè)體進(jìn)行有條件交叉;個(gè)體有條件自我變異。條件都為(個(gè)體適應(yīng)度是否更好,如果是則交叉變異# 將每個(gè)個(gè)體與個(gè)體極值和當(dāng)前的群體極值進(jìn)行交叉for j in range(num_pop):#遍歷每一個(gè)個(gè)體 # 與當(dāng)代極值交叉x_new[j, :] = Path_short.cross_1(x_new[j, :], best_G_chrom)fit = Path_short.comp_fit(x_new[j, :])if fit < Path_short.fitness[j]:Path_short.chrom[j, :] = x_new[j, :]Path_short.fitness[j] = fit# 變異x_new[j, :] = Path_short.mutation(x_new[j, :])fit = Path_short.comp_fit(x_new[j, :])if fit <= Path_short.fitness[j]:Path_short.chrom[j] = x_new[j, :]Path_short.fitness[j] = fitif (i + 1) % 20 == 0:print('第' + str(i + 1) + '步后的最短的路程: ' + str(Path_short.fitness[min_index]))print('第' + str(i + 1) + '步后的最優(yōu)路徑:')Path_short.out_path(Path_short.chrom[min_index, :]) # 顯示每一步的最優(yōu)路徑Path_short.best_chrom = best_chromPath_short.best_fit = best_fit#畫出最優(yōu)路徑res1 = Path_short.best_chrom[-1]x0 = x[res1]y0 = y[res1]for i in range(len(data) - 1):plt.quiver(x0[i], y0[i], x0[i + 1] - x0[i], y0[i + 1] - y0[i], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.quiver(x0[-1], y0[-1], x0[0] - x0[-1], y0[0] - y0[-1], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.show()return Path_short # 返回結(jié)果類if __name__ == '__main__':# 路徑坐標(biāo)np.random.seed(10)data = np.random.rand(20, 2) * 10 # 隨機(jī)產(chǎn)生20個(gè)城市坐標(biāo)main(data,)結(jié)果:
開始路徑
結(jié)果路徑
作者:電氣余登武。寫作不容易,點(diǎn)個(gè)贊再走。
總結(jié)
以上是生活随笔為你收集整理的基于组合遗传粒子群算法的旅行商问题求解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 银行积分怎么兑换
- 下一篇: pandas基本数据处理