Matlab遗传算法用于旅行商问题优化TSP
Matlab遗传算法用于旅行商问题优化
要求
利用遗传算法求旅行商问题的优化路径。设D={dij}是由城市i和j之间的距离组成的距离矩阵,旅行商问题就是求出一条通过所有城市且每个城市只通过一次的具有最短距离的回路。采用所遍历城市的顺序来表示各个个体的编码串,其等位基因为N个整数值或N个记号。以城市的遍历次序作为遗传算法的编码,目标函数取路径长度。在群体初始化、交叉操作和变异操作中考虑TSP问题的合法性约束条件(即对所有的城市做到不重不漏)。
设计利用遗传算法进行优化求解的程序,针对8个、15个、20个、30个城市情况下,分别给出最优路径下的城市顺序结果。
第一步:参数编码和初始群体设定
一般来说遗传算法对解空间的编码大多采用二进制编码形式,但对于TSP一类排序问题,采用对访问城市序列进行排列组合的方法编码,即某个巡回路径的染色体个体是该巡回路径的城市序列。
针对TSP问题,编码规则通常是N取进制编码,即每个基因仅从1到N的整数里面取一个值,每个个体的长度为N,N为城市总数。定义一个s行t列的pop矩阵来表示群体,t为城市个数N+1,即N+1,s为样本中个体数目。针对30个城市的TSP问题,t取值31, 即矩阵每一行的前30个元素表示经过的城市编号,最后一个元素表示经过这些城市要走的距离。
参数编码和初始群体设定程序为:
pop=zeros(s,N+1);%初始种群+适应度 for i=1:s %初始化 pop(i,1:N)=randperm(N); end
第二步:计算路径长度的函数设计
在TSP的求解中,用距离的总和作为适应度函数,来衡量求解结果是否最优。将POP矩阵中每一行表示经过的距离的最后一个元素作为路径长度。
两个城市m和n间的距离为:
dmn=(xm−xn)2+(ym−yn)2 .
d_{mn} = \sqrt{(x_m-x_n)^2+(y_m-y_n)^2}\,.
dmn=(xm−xn)2+(ym−yn)2.
通过样本的路径长度可以得到目标函数和自适应度函数。根据t的定义,两两城市组合数共有t-2组,则目标函数为:
J(t)=∑j=1t−2d(j)
J(t) = \sum_{j=1}^{t-2} d(j)
J(t)=j=1∑t−2d(j)
自适应度函数取目标函数的倒数,即:
f(t)=1J(t)
f(t) = \frac{1}{J(t)}
f(t)=J(t)1
第三步:计算选择算子
选择就是从群体中选择优胜个体、淘汰劣质个体的操作,它是建立在群体中个体适应度评估基础上。仿真中采用最优保存方法,即将群体中适应度最大的c个个体直接替换适应度最小的c个个体。
function [pop_ok]=ChooseParents(pop,N,s,c)%选择父代 pop=sortrows(pop,N+1); for i=1:c pop(i,:)=pop(s+1-i,:); end randIndex=randperm(size(pop,1)); pop=pop(randIndex,:); pop_ok=pop; end
第四步:计算交叉算子
交叉算子在遗传算法中起着核心的作用,它是指将个体进行两两配对,并以交叉概率将配对的父代个体加以替换重组而生成新个体的操作。
• 有序交叉法实现的步骤是:
步骤 1 随机选取两个交叉点crosspoint(1)和crosspoint(2); 步骤 2 两后代先分别按对应位置复制双亲X1和X2匹配段中的两个子串A1和B1; 步骤 3 在对应位置交换双亲匹配段以外的城市,如果交换后,后代X1中的某一城市a与子串中A1的城市重复,则将该城市取代子串B1与A1中的城市a具有相同位置的新城市,直到与子串A1中的城市均不重复为止,对后代X2也采用同样方法。
function [a,b]=CrossVariation(pop1,pop2,crosspoint,N)%交叉 A=pop1; if(crosspoint(:,1)<crosspoint(:,2)) pop1(crosspoint(:,1):crosspoint(:,2))=pop2(crosspoint(:,1):crosspoint(:,2)); pop2(crosspoint(:,1):crosspoint(:,2))=A(1,crosspoint(:,1):crosspoint(:,2)); while 1 tbl = tabulate(pop1(1:N)); if (tbl(:,3)<=(100/N)) break; end [pop1,pop2]=SwapRepeat(tbl,pop1,pop2,crosspoint(:,1),crosspoint(:,2),N);%基因去重 end else pop1(crosspoint(:,2):crosspoint(:,1))=pop2(crosspoint(:,2):crosspoint(:,1)); pop2(crosspoint(:,2):crosspoint(:,1))=A(1,crosspoint(:,2):crosspoint(:,1)); while 1 tbl = tabulate(pop1(1:N)); if (tbl(:,3)<=(100/N)) break; end [pop1,pop2]=SwapRepeat(tbl,pop1,pop2,crosspoint(:,2),crosspoint(:,1),N);%基因去重 end end a=pop1;b=pop2; end
第五步:计算变异算子
变异操作是以变异概率对群体中个体串某些基因位上的基因值作变动。
这里采用倒置变异法:假设当前个体X为(1 3 7 4 8 0 5 9 6 2 ),如果当前随机概率值<变异概率,则随机选择来自同一个体的两个点mutatepoint(1)和mutatepoint(2),然后倒置该两个点的中间部分,产生新的个体。例如,假设随机选择个体X的两个点“7”和“9”,则倒置该两个点的中间部分,即将“4805”变为“5084”,产生新的个体X为(1 3 7 5 0 8 4 9 6 2)。
function [a]=Mutation(pop0,N)%变异 crosspoint=rand(1,2); crosspoint=floor(crosspoint*N)+1; if(crosspoint(:,1)<crosspoint(:,2)) sub=pop0(crosspoint(:,1):crosspoint(:,2)); sub=SwapGene(sub,crosspoint(:,1),crosspoint(:,2));%交换 pop0(crosspoint(:,1):crosspoint(:,2))=sub; else sub=pop0(crosspoint(:,2):crosspoint(:,1)); sub=SwapGene(sub,crosspoint(:,2),crosspoint(:,1));%交换 pop0(crosspoint(:,2):crosspoint(:,1))=sub; end a=pop0; end
结果及分析
当城市个数为8个时,初始化样本个数为100个,交叉概率为0.9,变异概率为0.2,最大迭代次数为200次,初始样本随机生成。
MATLAB总代码
function genetic_TSP1 clc;close all;clear all; N=30;%城市数 city_coordinate=tsp(N);%城市位置 s=100;%样本数 c=30;%替换个数 pc=0.9;%交叉概率 pm=0.2;%变异概率 times=5000; %最大迭代次数 time=0; %实际迭代次数 pop=zeros(s,N+1);%初始种群+适应度 pop_fit_aver=[];%总适应度 min_dis=[];%最短距离 pop_min=[];%最短距离的基因 for i=1:s %初始化 pop(i,1:N)=randperm(N); end clf plot(city_coordinate(:,1),city_coordinate(:,2),'ro');%画平均适应度折线图 for i=1:N test_t=num2str(i); text(city_coordinate(i,1),city_coordinate(i,2),test_t);%标号 end grid on; title('城市位置分布图'); xlabel('x'); ylabel('y'); city_distance=CityDistance(city_coordinate,N);%城市间距离 [individual_fit,sum,min1,min_index]=GroupFit(city_distance,N,pop,s);%适应度 sumP=sum; pop_fit_aver=[pop_fit_aver;sum]; min_dis=[min_dis;min1]; pop(:,N+1)=individual_fit; pop_min=[pop_min;pop(min_index,:)]; pop=ChooseParents(pop,N,s,c);%选择父代 for i=1:times time=time+1; E_new_new=[]; %子代 for j=1:s/2 a=rand(1); b=rand(1); if a>pc %交叉 ; else crosspoint=rand(1,2); crosspoint=floor(crosspoint*N)+1; [pop(j,:),pop(j+s/2,:)]=CrossVariation(pop(j,:),pop(j+s/2,:),crosspoint,N); end if b>pm ; else pop(j,:)=Mutation(pop(j,:),N); pop(j+s/2,:)=Mutation(pop(j+s/2,:),N); end E_new_new=[E_new_new;pop(j,:);pop(j+s/2,:)]; end [individual_fit,sum,min1,min_index]=GroupFit(city_distance,N,E_new_new,s); sumS=sum; pop_fit_aver=[pop_fit_aver;sum]; min_dis=[min_dis;min1]; E_new_new(:,N+1)=individual_fit; pop_min=[pop_min;E_new_new(min_index,:)]; if(abs(sumS-sumP)<0.001)%退出条件 break; end pop=ChooseParents(E_new_new,N,s,c); end [a,min_index]=min(min_dis); a time1=1:time+1; figure%画平均适应度折线图 plot(time1,min_dis,'k.'); grid on; title('每代最小值散点图'); xlabel('迭代次数'); ylabel('最短距离'); figure%画平均适应度折线图 plot(time1,pop_fit_aver); grid on; title('总适应度折线图'); xlabel('迭代次数'); ylabel('每代总适应度'); figure%画最优路径 DrawPath(city_coordinate,pop_min,min_index,N) grid on; title('最优路径图'); xlabel('x'); ylabel('y'); end function [city_distance] = CityDistance(city_coordinate,N)%城市距离矩阵 city_distance=zeros(N,N); for i=1:N for j=1:N city_distance(i,j)=((city_coordinate(i,1)-city_coordinate(j,1))^2+... (city_coordinate(i,2)-city_coordinate(j,2))^2)^0.5; end end end function [individual_fit,num,min_distance,a] = GroupFit(city_distance,N,pop,s)%种群适应度 individual_distance=zeros(s,1); for j=1:s sum_distance=0; for i=1:N-1 sum_distance=sum_distance+city_distance(pop(j,i),pop(j,i+1)); end sum_distance=sum_distance+city_distance(pop(j,N),pop(j,1)); individual_distance(j,1)=sum_distance; end [min_distance,a]=min(individual_distance); individual_fit=1./individual_distance; num=0; for i=1:s num=num+individual_fit(i,1); end end function [pop_ok]=ChooseParents(pop,N,s,c)%选择父代 pop=sortrows(pop,N+1); for i=1:c pop(i,:)=pop(s+1-i,:); end randIndex=randperm(size(pop,1)); pop=pop(randIndex,:); pop_ok=pop; endfunction [a,b]=SwapRepeat(tbl,pop1,pop2,c1,c2,N)%基因去重 i=100/N; for k=1:(c1-1) if tbl(pop1(k),3)>i kk=find(pop1(c1:c2)==pop1(k))+c1-1; kkk=pop1(k); pop1(k)=pop2(kk); pop2(kk)=kkk; end end for k=c2+1:N if tbl(pop1(k),3)>i kk=find(pop1(c1:c2)==pop1(k))+c1-1; kkk=pop1(k); pop1(k)=pop2(kk); pop2(kk)=kkk; end end a=pop1; b=pop2; end function [a,b]=CrossVariation(pop1,pop2,crosspoint,N)%交叉 A=pop1; if(crosspoint(:,1)<crosspoint(:,2)) pop1(crosspoint(:,1):crosspoint(:,2))=pop2(crosspoint(:,1):crosspoint(:,2)); pop2(crosspoint(:,1):crosspoint(:,2))=A(1,crosspoint(:,1):crosspoint(:,2)); while 1 tbl = tabulate(pop1(1:N)); if (tbl(:,3)<=(100/N)) break; end [pop1,pop2]=SwapRepeat(tbl,pop1,pop2,crosspoint(:,1),crosspoint(:,2),N); end else pop1(crosspoint(:,2):crosspoint(:,1))=pop2(crosspoint(:,2):crosspoint(:,1)); pop2(crosspoint(:,2):crosspoint(:,1))=A(1,crosspoint(:,2):crosspoint(:,1)); while 1 tbl = tabulate(pop1(1:N)); if (tbl(:,3)<=(100/N)) break; end [pop1,pop2]=SwapRepeat(tbl,pop1,pop2,crosspoint(:,2),crosspoint(:,1),N); end end a=pop1;b=pop2; end function [a]=SwapGene(sub,c1,c2)%交换 kk=ceil((c2-c1)/2); kkk=(c2-c1)+2; for k=1:kk kkkk=sub(k); sub(k)=sub(kkk-k); sub(kkk-k)=kkkk; end a=sub; end function [a]=Mutation(pop0,N)%变异 crosspoint=rand(1,2); crosspoint=floor(crosspoint*N)+1; if(crosspoint(:,1)<crosspoint(:,2)) sub=pop0(crosspoint(:,1):crosspoint(:,2)); sub=SwapGene(sub,crosspoint(:,1),crosspoint(:,2)); pop0(crosspoint(:,1):crosspoint(:,2))=sub; else sub=pop0(crosspoint(:,2):crosspoint(:,1)); sub=SwapGene(sub,crosspoint(:,2),crosspoint(:,1)); pop0(crosspoint(:,2):crosspoint(:,1))=sub; end a=pop0; end function DrawPath(city_coordinate,E_new_new,min_index,N)%画路径图 k=E_new_new(min_index,1:N) %plot(kkk(:,1),kkk(:,2),'b');%画平均适应度折线图 plot(city_coordinate(:,1),city_coordinate(:,2),'bo'); hold on; for i=1:N-1 plot([city_coordinate(k(i),1),city_coordinate(k(i+1),1)],[city_coordinate(k(i),2),city_coordinate(k(i+1),2)],'r','LineWidth',2); test_t=num2str(i); text(city_coordinate(k(i),1),city_coordinate(k(i),2),test_t); hold on; end test_t=[num2str(N)]; text(city_coordinate(k(N),1),city_coordinate(k(N),2),test_t); end function [cityn]=tsp(n) %城市位置 if n==8 city8=[0.1 0.1; 0.9 0.5; 0.9 0.1; 0.45 0.9; 0.9 0.8; 0.7 0.9; 0.1 0.45; 0.45 0.1]; cityn=city8; elseif n==15 city15=[0.1 0.1;0.9 0.5;0.9 0.1; 0.45 0.9; 0.9 0.8; 0.7 0.9; 0.1 0.45; 0.45 0.1; 0.3 0.75; 0.2 0.1; 0.31 0.22; 0.35 0.25; 0.10 0.75; 0.80 0.35; 0.12 0.45]; cityn=city15; elseif n==20 city20=[0.1 0.1;0.9 0.5;0.9 0.1;0.45 0.9; 0.9 0.8;0.7 0.9;0.1 0.45;0.45 0.1;0.3 0.75; 0.2 0.1;0.31 0.22;0.35 0.25;0.10 0.75; 0.80 0.35;0.12 0.45;0.67 0.17;0.85 0.32; 0.6 0.9;0.70 0.15;0.66 0.22]; cityn=city20; elseif n==30 city30=[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;7 64;22 60;25 62;62 32;87 7;91 38;83 46;41 26;45 21;44 35]; cityn=city30; end end
- 遗传算法 求解旅行商 TSP 问题,matlab代码
- 遗传算法(GA)学习笔记---旅行商问题(TSP)
- 利用Matlab优化工具箱求解旅行商最短路径问题
- Matlab遗传算法优化问题求解的演示样例代码
- 遗传算法GA及其在旅行商问题TSP上的研究
- 遗传算法(GA)学习笔记---旅行商问题(TSP)
- TSP_旅行商问题 - 遗传算法(四)
- python实现遗传算法求解TSP旅行商问题(详细解释)
- C语言编写遗传算法解决TSP旅行商问题
- TSP_旅行商问题 - 遗传算法(四)
- TSP_旅行商问题 - 遗传算法(四)
- 利用Matlab以蚁群算法(Ant Colony Algorithm)求解不闭合的旅行商问题(Travelling Salesman Problem, TSP)并进行可视化
- TSP_旅行商问题 - 遗传算法(四)
- Python动态展示遗传算法求解TSP旅行商问题
- 遗传算法(GA)学习笔记---旅行商问题(TSP)
- TSP_旅行商问题 - 遗传算法(四)
- 网络分析优化旅行商问题TSP算法资源
- 遗传算法与TSP问题的MATLAB实现
- TSP_旅行商问题 - 遗传算法(四)
- 遗传算法求解旅行商(TSP)问题