遗传算法求解TSP问题
问题还是模拟退火算法文章里面的问题
遗传算法求解的参数设定如下:种群大小 M=50;最大代数 G=10。交叉率Pc=1 ,交叉概率为1能保证种群的充分进化;变异率Pm=0.1 ,一般而言,变异发生的可能性较小
(1)编码策略
采用十进制编码,用随机序列w0,w1,w2…w101 作为染色体,其中0<wi<1 ( i=1,2,3,…),w0=0 ,w101=1 ;每一个随机序列都和种群中的一个个体相对应,例如,9个目标问题的一个染色体为
[0.23,0.82,0.45,0.74,0.87,0.11,0.56,0.69,0.78],
其中编码位置 i代表目标 ,位置 i的随机数表示目标 i在巡回中的顺序,将这些随机数按升序排列得到如下巡回
6-1-3-7-8-4-9-2-5
(2) 初始种群
(3)目标函数
目标函数为侦察所有目标的路径长度,适应度函数就取为目标函数
min f(pi0,pi1,…,pi101) =Σdpi(i)-pi(i+1)
(4) 交叉操作
例如
设交叉点为第四个基因处,则
交叉操作的方式有很多种选择,应该尽可能选取好的交叉方式,保证子代能继承父代的优良特性。
(5)变异操作
变异也是实现群体多样性的一种手段,同时也是全局寻优的保证。具体设计如下,按照给定的变异率,对选定变异的个体,随机地取三个整数,满足 1<u<v<w<100把u,v 之间(包括 u和 v)的基因段插到w 后面。
(6)选择
采用确定性的选择策略,也就是说在父代种群和子代种群中选择目标函数值最小的 个个体进化到下一代,这样可以保证父代的优良特性被保存下来。
python代码实现
#程序文件Pex17_2.py
import numpy as np
from numpy.random import randint, rand, shuffle
from matplotlib.pyplot import plot, show, rc
a=np.loadtxt("Pdata17_2.txt")
xy,d=a[:,:2],a[:,2:]; N=len(xy)
w=50; g=10 #w为种群的个数,g为进化的代数
J=[];
for i in np.arange(w):
c=np.arange(1,N-1); shuffle(c)
c1=np.r_[0,c,101]; flag=1
while flag>0:
flag=0
for m in np.arange(1,N-3):
for n in np.arange(m+1,N-2):
if d[c1[m],c1[n]]+d[c1[m+1],c1[n+1]]<\
d[c1[m],c1[m+1]]+d[c1[n],c1[n+1]]:
c1[m+1:n+1]=c1[n:m:-1]; flag=1
c1[c1]=np.arange(N) #这一步是因为后面有个argsort:表示对数据进行从小到大进行排序,返回数据的索引值
J.append(c1)
J=np.array(J)/(N-1)
for k in np.arange(g):
A=J.copy()
c1=np.arange(w); shuffle(c1) #交叉操作的染色体配对组
c2=randint(2,100,w) #交叉点的数据
for i in np.arange(0,w,2):
temp=A[c1[i],c2[i]:N-1] #保存中间变量
A[c1[i],c2[i]:N-1]=A[c1[i+1],c2[i]:N-1]
A[c1[i+1],c2[i]:N-1]=temp
B=A.copy()
by=[] #初始化变异染色体的序号
while len(by)<1: by=np.where(rand(w)<0.1)
by=by[0]; B=B[by,:]
G=np.r_[J,A,B]
ind=np.argsort(G,axis=1) #把染色体翻译成0,1,…,101
NN=G.shape[0]; L=np.zeros(NN)
for j in np.arange(NN):
for i in np.arange(101):
L[j]=L[j]+d[ind[j,i],ind[j,i+1]]
ind2=np.argsort(L)
J=G[ind2,:]
path=ind[ind2[0],:]; zL=L[ind2[0]]
xx=xy[path,0]; yy=xy[path,1]; rc('font',size=16)
plot(xx,yy,'-*'); show() #画巡航路径
print("所求的巡航路径长度为:",zL)
所求的巡航路径长度为: 41879.87855580798