遗传算法求解TSP源码及解析

1.算法效果

图 1?1算法效果1

图 1?2算法效果2

2.原理说明

TSP问题是指假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。本文使用遗传算法解决att30问题,即30个城市的旅行商问题。

旅行商问题是一个经典的组合优化问题。一个经典的旅行商问题可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。

TSP问题可以分为对称和不对称。在对称TSP问题中,两座城市之间来回的距离是相等的,形成一个无向图,而不对称TSP则形成有向图。对称性TSP问题可以将解的数量减少了一半。所以本次实验的TSP问题使用att48数据,可在tsplib中下载数据包。

演化算法是一类模拟自然界遗传进化规律的仿生学算法,它不是一个具体的算法,而是一个算法簇。遗传算法是演化算法的一个分支,由于遗传算法的整体搜索策略和优化计算是不依赖梯度信息,所以它的应用比较广泛。我们本次实验同样用到了遗传算法(用MATLAB编写)来解决TSP问题。

图 2?1算法流程图

3.源码说明

3.1.主函数

function ga_TSP

global data1 flag1

flag1=1;

close all

CityNum=30; %you chan choose 10, 30, 50, 75

[dislist,Clist]=tsp(CityNum);

%%  需要修改部分参数

inn=30; %初始种群大小

gnmax=100;  %最大代数

% gnmax=20;  %最大代数

pc=0.8; %交叉概率

pm=0.8; %变异概率

%%

%产生初始种群

s=zeros(inn,CityNum);

for i=1:inn

s(i,:)=randperm(CityNum);

end

[~,p]=objf(s,dislist);

gn=1;

ymean=zeros(gn,1);

ymax=zeros(gn,1);

xmax=zeros(inn,CityNum);

scnew=zeros(inn,CityNum);

smnew=zeros(inn,CityNum);

while gn<gnmax+1

for j=1:2:inn

seln=sel(p);  %选择操作

scro=cro(s,seln,pc);  %交叉操作

scnew(j,:)=scro(1,:);

scnew(j+1,:)=scro(2,:);

smnew(j,:)=mut(scnew(j,:),pm);  %变异操作

smnew(j+1,:)=mut(scnew(j+1,:),pm);

end

s=smnew;  %产生了新的种群

[f,p]=objf(s,dislist);  %计算新种群的适应度

%记录当前代最好和平均的适应度

[fmax,nmax]=max(f);

ymean(gn)=1000/mean(f);

ymax(gn)=1000/fmax;

%记录当前代的最佳个体

x=s(nmax,:);

xmax(gn,:)=x;

drawTSP(Clist,x,ymax(gn),gn,0);

gn=gn+1;

end

[min_ymax,index]=min(ymax);

drawTSP(Clist,xmax(index,:),min_ymax,index,1);

%%

% keyboard

% h2=figure(2);

% plot(ymax,‘r‘); hold on;

% plot(ymean,‘b‘);grid;

% title(‘搜索过程‘);

% legend(‘最优解‘,‘平均解‘);

% fprintf(‘遗传算法得到的最短距离:%.2f\n‘,min_ymax);

% fprintf(‘遗传算法得到的最短路线‘);

% disp(xmax(index,:));

%%  绘图

% keyboard

h2=figure(2);

plot(ymax,‘ro--‘);

hold on;

plot(ymean,‘k*--‘);grid;

title(‘搜索过程‘);

fprintf(‘遗传算法得到的最短距离:%.2f\n‘,min_ymax);

fprintf(‘遗传算法得到的最短路线‘);

disp(xmax(index,:));

% set(gca,‘unit‘,‘centimeters‘,‘position‘,[2.5 1.2 25 5.5])

% set(gcf,‘unit‘,‘centimeters‘,‘position‘,[3 3 28 7])%%整个图的信息

set(gca,‘FontName‘,‘Times New Roman‘,‘FontSize‘,14)%设置坐标轴字体大小,字型

set(gcf,‘WindowStyle‘,‘normal‘);

grid  on

box on

h1=legend(‘最优解‘,‘平均解‘);

set(h1,‘box‘,‘off‘, ‘Orientation‘,‘horizontal‘,‘FontSize‘,12,‘FontName‘,‘黑体‘);

xlabel(‘\bf数据个数‘);ylabel(‘\bf数值‘);

grid on

% keyboard

end

%------------------------------------------------

%计算所有种群的适应度

function [f,p]=objf(s,dislist)

inn=size(s,1);  %读取种群大小

f=zeros(inn,1);

for i=1:inn

f(i)=CalDist(dislist,s(i,:));  %计算函数值,即适应度

end

f=1000./f‘; %取距离倒数

%根据个体的适应度计算其被选择的概率

fsum=0;

for i=1:inn

fsum=fsum+f(i)^15;% 让适应度越好的个体被选择概率越高

end

ps=zeros(inn,1);

for i=1:inn

ps(i)=f(i)^15/fsum;

end

%计算累积概率

p=zeros(inn,1);

p(1)=ps(1);

for i=2:inn

p(i)=p(i-1)+ps(i);

end

p=p‘;

end

%--------------------------------------------------

%根据变异概率判断是否变异

function pcc=pro(pc)

test(1:100)=0;

l=round(100*pc);

test(1:l)=1;

n=round(rand*99)+1;

pcc=test(n);

end

%--------------------------------------------------

%“选择”操作

function seln=sel(p)

seln=zeros(2,1);

%从种群中选择两个个体,最好不要两次选择同一个个体

for i=1:2

r=rand;  %产生一个随机数

prand=p-r;

j=1;

while prand(j)<0

j=j+1;

end

seln(i)=j; %选中个体的序号

if i==2&&j==seln(i-1)    %%若相同就再选一次

r=rand;  %产生一个随机数

prand=p-r;

j=1;

while prand(j)<0

j=j+1;

end

end

end

end

%------------------------------------------------

%“交叉”操作

function scro=cro(s,seln,pc)

bn=size(s,2);

pcc=pro(pc);  %根据交叉概率决定是否进行交叉操作,1则是,0则否

scro(1,:)=s(seln(1),:);

scro(2,:)=s(seln(2),:);

if pcc==1

c1=round(rand*(bn-2))+1;  %在[1,bn-1]范围内随机产生一个交叉位

c2=round(rand*(bn-2))+1;

chb1=min(c1,c2);

chb2=max(c1,c2);

middle=scro(1,chb1+1:chb2);

scro(1,chb1+1:chb2)=scro(2,chb1+1:chb2);

scro(2,chb1+1:chb2)=middle;

for i=1:chb1 %似乎有问题

while find(scro(1,chb1+1:chb2)==scro(1,i))

zhi=find(scro(1,chb1+1:chb2)==scro(1,i));

y=scro(2,chb1+zhi);

scro(1,i)=y;

end

while find(scro(2,chb1+1:chb2)==scro(2,i))

zhi=find(scro(2,chb1+1:chb2)==scro(2,i));

y=scro(1,chb1+zhi);

scro(2,i)=y;

end

end

for i=chb2+1:bn

while find(scro(1,1:chb2)==scro(1,i))

zhi=logical(scro(1,1:chb2)==scro(1,i));

y=scro(2,zhi);

scro(1,i)=y;

end

while find(scro(2,1:chb2)==scro(2,i))

zhi=logical(scro(2,1:chb2)==scro(2,i));

y=scro(1,zhi);

scro(2,i)=y;

end

end

end

end

%--------------------------------------------------

%“变异”操作

function snnew=mut(snew,pm)

bn=size(snew,2);

snnew=snew;

pmm=pro(pm);  %根据变异概率决定是否进行变异操作,1则是,0则否

if pmm==1

c1=round(rand*(bn-2))+1;  %在[1,bn-1]范围内随机产生一个变异位

c2=round(rand*(bn-2))+1;

chb1=min(c1,c2);

chb2=max(c1,c2);

x=snew(chb1+1:chb2);

snnew(chb1+1:chb2)=fliplr(x);

end

end

%------------------------------------------------

%城市位置坐标

function [DLn,cityn]=tsp(n)

DLn=zeros(n,n);

if n==10

city10=[0.4 0.4439;0.2439 0.1463;0.1707 0.2293;0.2293 0.761;0.5171 0.9414;

0.8732 0.6536;0.6878 0.5219;0.8488 0.3609;0.6683 0.2536;0.6195 0.2634];%10 cities d‘=2.691

for i=1:10

for j=1:10

DLn(i,j)=((city10(i,1)-city10(j,1))^2+(city10(i,2)-city10(j,2))^2)^0.5;

end

end

cityn=city10;

end

if n==30

city30=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;

83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50];%30 cities d‘=423.741 by D B Fogel

for i=1:30

for j=1:30

DLn(i,j)=((city30(i,1)-city30(j,1))^2+(city30(i,2)-city30(j,2))^2)^0.5;

end

end

cityn=city30;

end

if n==50

city50=[31 32;32 39;40 30;37 69;27 68;37 52;38 46;31 62;30 48;21 47;25 55;16 57;

17 63;42 41;17 33;25 32;5 64;8 52;12 42;7 38;5 25; 10 77;45 35;42 57;32 22;

27 23;56 37;52 41;49 49;58 48;57 58;39 10;46 10;59 15;51 21;48 28;52 33;

58 27;61 33;62 63;20 26;5 6;13 13;21 10;30 15;36 16;62 42;63 69;52 64;43 67];%50 cities d‘=427.855 by D B Fogel

for i=1:50

for j=1:50

DLn(i,j)=((city50(i,1)-city50(j,1))^2+(city50(i,2)-city50(j,2))^2)^0.5;

end

end

cityn=city50;

end

if n==75

city75=[48 21;52 26;55 50;50 50;41 46;51 42;55 45;38 33;33 34;45 35;40 37;50 30;

55 34;54 38;26 13;15 5;21 48;29 39;33 44;15 19;16 19;12 17;50 40;22 53;21 36;

20 30;26 29;40 20;36 26;62 48;67 41;62 35;65 27;62 24;55 20;35 51;30 50;

45 42;21 45;36 6;6 25;11 28;26 59;30 60;22 22;27 24;30 20;35 16;54 10;50 15;

44 13;35 60;40 60;40 66;31 76;47 66;50 70;57 72;55 65;2 38;7 43;9 56;15 56;

10 70;17 64;55 57;62 57;70 64;64 4;59 5;50 4;60 15;66 14;66 8;43 26];%75 cities d‘=549.18 by D B Fogel

for i=1:75

for j=1:75

DLn(i,j)=((city75(i,1)-city75(j,1))^2+(city75(i,2)-city75(j,2))^2)^0.5;

end

end

cityn=city75;

end

% if n==30

%     city30=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;

%         83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50];%30 cities d‘=423.741 by D B Fogel

%     for i=1:30

%         for j=1:30

%             DLn(i,j)=((city30(i,1)-city30(j,1))^2+(city30(i,2)-city30(j,2))^2)^0.5;

%         end

%     end

%     cityn=city30;

% end

end

%%

%------------------------------------------------

%适应度函数

function F=CalDist(dislist,s)

DistanV=0;

n=size(s,2);

for i=1:(n-1)

DistanV=DistanV+dislist(s(i),s(i+1));

end

DistanV=DistanV+dislist(s(n),s(1));

F=DistanV;

end

%------------------------------------------------

%画图

function drawTSP(Clist,BSF,bsf,p,f)

global data1 flag1

CityNum=size(Clist,1);

for i=1:CityNum-1

plot([Clist(BSF(i),1),Clist(BSF(i+1),1)],[Clist(BSF(i),2),Clist(BSF(i+1),2)],‘ms-‘,‘LineWidth‘,2,‘MarkerEdgeColor‘,‘b‘,‘MarkerFaceColor‘,‘b‘);

text(Clist(BSF(i),1),Clist(BSF(i),2),[‘  ‘,int2str(BSF(i))]);

text(Clist(BSF(i+1),1),Clist(BSF(i+1),2),[‘  ‘,int2str(BSF(i+1))]);

hold on;

end

plot([Clist(BSF(CityNum),1),Clist(BSF(1),1)],[Clist(BSF(CityNum),2),Clist(BSF(1),2)],‘ms-‘,‘LineWidth‘,2,‘MarkerEdgeColor‘,‘b‘,‘MarkerFaceColor‘,‘b‘);

title([num2str(CityNum),‘城市TSP‘]);

if f==0&&CityNum~=10

text(5,5,[‘第 ‘,int2str(p),‘ 代‘,‘  最短距离为 ‘,num2str(bsf)]);

else

text(5,5,[‘最终搜索结果:最短距离 ‘,num2str(bsf),‘, 在第 ‘,num2str(p),‘ 代达到‘]);

end

data1(flag1)=bsf;

flag1=flag1+1;

sum(Clist);

if CityNum==10

if f==0

text(0,0,[‘第 ‘,int2str(p),‘ 代‘,‘  最短距离为 ‘,num2str(bsf)]);

else

text(0,0,[‘最终搜索结果:最短距离 ‘,num2str(bsf),‘, 在第 ‘,num2str(p),‘ 代达到‘]);

end

end

hold off;

pause(0.02);

% keyboard

end

3.2.子函数1

function qiankun_tec

global data1 flag1 mm data

flag1=1;

% mainly amended by Chen Zhen, 2012~2016

close all

% CityNum=30; %you chan choose 10, 30, 50, 75

% [dislist,Clist]=tsp(CityNum);

load data

[mm nn]=size(data);

CityNum=mm;

[dislist,Clist]=tsp(CityNum);

inn=30; %初始种群大小

gnmax=500;  %最大代数

% gnmax=20;  %最大代数

pc=0.8; %交叉概率

pm=0.8; %变异概率

%产生初始种群

s=zeros(inn,CityNum);

for i=1:inn

s(i,:)=randperm(CityNum);

end

[~,p]=objf(s,dislist);

gn=1;

ymean=zeros(gn,1);

ymax=zeros(gn,1);

xmax=zeros(inn,CityNum);

scnew=zeros(inn,CityNum);

smnew=zeros(inn,CityNum);

while gn<gnmax+1

for j=1:2:inn

seln=sel(p);  %选择操作

scro=cro(s,seln,pc);  %交叉操作

scnew(j,:)=scro(1,:);

scnew(j+1,:)=scro(2,:);

smnew(j,:)=mut(scnew(j,:),pm);  %变异操作

smnew(j+1,:)=mut(scnew(j+1,:),pm);

end

s=smnew;  %产生了新的种群

[f,p]=objf(s,dislist);  %计算新种群的适应度

%记录当前代最好和平均的适应度

[fmax,nmax]=max(f);

ymean(gn)=1000/mean(f);

ymax(gn)=1000/fmax;

%记录当前代的最佳个体

x=s(nmax,:);

xmax(gn,:)=x;

drawTSP(Clist,x,ymax(gn),gn,0);

gn=gn+1;

end

[min_ymax,index]=min(ymax);

drawTSP(Clist,xmax(index,:),min_ymax,index,1);

%%

% keyboard

% h2=figure(2);

% plot(ymax,‘r‘); hold on;

% plot(ymean,‘b‘);grid;

% title(‘搜索过程‘);

% legend(‘最优解‘,‘平均解‘);

% fprintf(‘遗传算法得到的最短距离:%.2f\n‘,min_ymax);

% fprintf(‘遗传算法得到的最短路线‘);

% disp(xmax(index,:));

%%  绘图

% keyboard

h2=figure(2);

plot(ymax,‘ro--‘);

hold on;

plot(ymean,‘k*--‘);grid;

title(‘搜索过程‘);

fprintf(‘遗传算法得到的最短距离:%.2f\n‘,min_ymax);

fprintf(‘遗传算法得到的最短路线‘);

disp(xmax(index,:));

% set(gca,‘unit‘,‘centimeters‘,‘position‘,[2.5 1.2 25 5.5])

% set(gcf,‘unit‘,‘centimeters‘,‘position‘,[3 3 28 7])%%整个图的信息

set(gca,‘FontName‘,‘Times New Roman‘,‘FontSize‘,14)%设置坐标轴字体大小,字型

set(gcf,‘WindowStyle‘,‘normal‘);

grid  on

box on

h1=legend(‘最优解‘,‘平均解‘);

set(h1,‘box‘,‘off‘, ‘Orientation‘,‘horizontal‘,‘FontSize‘,12,‘FontName‘,‘黑体‘);

xlabel(‘\bf数据个数‘);ylabel(‘\bf数值‘);

grid on

% keyboard

end

%------------------------------------------------

%计算所有种群的适应度

function [f,p]=objf(s,dislist)

inn=size(s,1);  %读取种群大小

f=zeros(inn,1);

for i=1:inn

f(i)=CalDist(dislist,s(i,:));  %计算函数值,即适应度

end

f=1000./f‘; %取距离倒数

%根据个体的适应度计算其被选择的概率

fsum=0;

for i=1:inn

fsum=fsum+f(i)^15;% 让适应度越好的个体被选择概率越高

end

ps=zeros(inn,1);

for i=1:inn

ps(i)=f(i)^15/fsum;

end

%计算累积概率

p=zeros(inn,1);

p(1)=ps(1);

for i=2:inn

p(i)=p(i-1)+ps(i);

end

p=p‘;

end

%--------------------------------------------------

%根据变异概率判断是否变异

function pcc=pro(pc)

test(1:100)=0;

l=round(100*pc);

test(1:l)=1;

n=round(rand*99)+1;

pcc=test(n);

end

%--------------------------------------------------

%“选择”操作

function seln=sel(p)

seln=zeros(2,1);

%从种群中选择两个个体,最好不要两次选择同一个个体

for i=1:2

r=rand;  %产生一个随机数

prand=p-r;

j=1;

while prand(j)<0

j=j+1;

end

seln(i)=j; %选中个体的序号

if i==2&&j==seln(i-1)    %%若相同就再选一次

r=rand;  %产生一个随机数

prand=p-r;

j=1;

while prand(j)<0

j=j+1;

end

end

end

end

%------------------------------------------------

%“交叉”操作

function scro=cro(s,seln,pc)

bn=size(s,2);

pcc=pro(pc);  %根据交叉概率决定是否进行交叉操作,1则是,0则否

scro(1,:)=s(seln(1),:);

scro(2,:)=s(seln(2),:);

if pcc==1

c1=round(rand*(bn-2))+1;  %在[1,bn-1]范围内随机产生一个交叉位

c2=round(rand*(bn-2))+1;

chb1=min(c1,c2);

chb2=max(c1,c2);

middle=scro(1,chb1+1:chb2);

scro(1,chb1+1:chb2)=scro(2,chb1+1:chb2);

scro(2,chb1+1:chb2)=middle;

for i=1:chb1 %似乎有问题

while find(scro(1,chb1+1:chb2)==scro(1,i))

zhi=find(scro(1,chb1+1:chb2)==scro(1,i));

y=scro(2,chb1+zhi);

scro(1,i)=y;

end

while find(scro(2,chb1+1:chb2)==scro(2,i))

zhi=find(scro(2,chb1+1:chb2)==scro(2,i));

y=scro(1,chb1+zhi);

scro(2,i)=y;

end

end

for i=chb2+1:bn

while find(scro(1,1:chb2)==scro(1,i))

zhi=logical(scro(1,1:chb2)==scro(1,i));

y=scro(2,zhi);

scro(1,i)=y;

end

while find(scro(2,1:chb2)==scro(2,i))

zhi=logical(scro(2,1:chb2)==scro(2,i));

y=scro(1,zhi);

scro(2,i)=y;

end

end

end

end

%--------------------------------------------------

%“变异”操作

function snnew=mut(snew,pm)

bn=size(snew,2);

snnew=snew;

pmm=pro(pm);  %根据变异概率决定是否进行变异操作,1则是,0则否

if pmm==1

c1=round(rand*(bn-2))+1;  %在[1,bn-1]范围内随机产生一个变异位

c2=round(rand*(bn-2))+1;

chb1=min(c1,c2);

chb2=max(c1,c2);

x=snew(chb1+1:chb2);

snnew(chb1+1:chb2)=fliplr(x);

end

end

%------------------------------------------------

%城市位置坐标

function [DLn,cityn]=tsp(n)

DLn=zeros(n,n);

if n==10

city10=[0.4 0.4439;0.2439 0.1463;0.1707 0.2293;0.2293 0.761;0.5171 0.9414;

0.8732 0.6536;0.6878 0.5219;0.8488 0.3609;0.6683 0.2536;0.6195 0.2634];%10 cities d‘=2.691

for i=1:10

for j=1:10

DLn(i,j)=((city10(i,1)-city10(j,1))^2+(city10(i,2)-city10(j,2))^2)^0.5;

end

end

cityn=city10;

end

if n==30

city30=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;

83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50];%30 cities d‘=423.741 by D B Fogel

for i=1:30

for j=1:30

DLn(i,j)=((city30(i,1)-city30(j,1))^2+(city30(i,2)-city30(j,2))^2)^0.5;

end

end

cityn=city30;

end

if n==50

city50=[31 32;32 39;40 30;37 69;27 68;37 52;38 46;31 62;30 48;21 47;25 55;16 57;

17 63;42 41;17 33;25 32;5 64;8 52;12 42;7 38;5 25; 10 77;45 35;42 57;32 22;

27 23;56 37;52 41;49 49;58 48;57 58;39 10;46 10;59 15;51 21;48 28;52 33;

58 27;61 33;62 63;20 26;5 6;13 13;21 10;30 15;36 16;62 42;63 69;52 64;43 67];%50 cities d‘=427.855 by D B Fogel

for i=1:50

for j=1:50

DLn(i,j)=((city50(i,1)-city50(j,1))^2+(city50(i,2)-city50(j,2))^2)^0.5;

end

end

cityn=city50;

end

if n==75

city75=[48 21;52 26;55 50;50 50;41 46;51 42;55 45;38 33;33 34;45 35;40 37;50 30;

55 34;54 38;26 13;15 5;21 48;29 39;33 44;15 19;16 19;12 17;50 40;22 53;21 36;

20 30;26 29;40 20;36 26;62 48;67 41;62 35;65 27;62 24;55 20;35 51;30 50;

45 42;21 45;36 6;6 25;11 28;26 59;30 60;22 22;27 24;30 20;35 16;54 10;50 15;

44 13;35 60;40 60;40 66;31 76;47 66;50 70;57 72;55 65;2 38;7 43;9 56;15 56;

10 70;17 64;55 57;62 57;70 64;64 4;59 5;50 4;60 15;66 14;66 8;43 26];%75 cities d‘=549.18 by D B Fogel

for i=1:75

for j=1:75

DLn(i,j)=((city75(i,1)-city75(j,1))^2+(city75(i,2)-city75(j,2))^2)^0.5;

end

end

cityn=city75;

end

global mm data

if n==mm

city30=data;

for i=1:mm

for j=1:mm

DLn(i,j)=((city30(i,1)-city30(j,1))^2+(city30(i,2)-city30(j,2))^2)^0.5;

end

end

cityn=city30;

end

end

%%

%------------------------------------------------

%适应度函数

function F=CalDist(dislist,s)

DistanV=0;

n=size(s,2);

for i=1:(n-1)

DistanV=DistanV+dislist(s(i),s(i+1));

end

DistanV=DistanV+dislist(s(n),s(1));

F=DistanV;

end

%------------------------------------------------

%画图

function drawTSP(Clist,BSF,bsf,p,f)

global data1 flag1

CityNum=size(Clist,1);

for i=1:CityNum-1

plot([Clist(BSF(i),1),Clist(BSF(i+1),1)],[Clist(BSF(i),2),Clist(BSF(i+1),2)],‘ms-‘,‘LineWidth‘,2,‘MarkerEdgeColor‘,‘b‘,‘MarkerFaceColor‘,‘b‘);

text(Clist(BSF(i),1),Clist(BSF(i),2),[‘  ‘,int2str(BSF(i))]);

text(Clist(BSF(i+1),1),Clist(BSF(i+1),2),[‘  ‘,int2str(BSF(i+1))]);

hold on;

end

plot([Clist(BSF(CityNum),1),Clist(BSF(1),1)],[Clist(BSF(CityNum),2),Clist(BSF(1),2)],‘ms-‘,‘LineWidth‘,2,‘MarkerEdgeColor‘,‘b‘,‘MarkerFaceColor‘,‘b‘);

title([num2str(CityNum),‘城市TSP‘]);

if f==0&&CityNum~=10

text(5,5,[‘第 ‘,int2str(p),‘ 代‘,‘  最短距离为 ‘,num2str(bsf)]);

else

text(5,5,[‘最终搜索结果:最短距离 ‘,num2str(bsf),‘, 在第 ‘,num2str(p),‘ 代达到‘]);

end

data1(flag1)=bsf;

flag1=flag1+1;

sum(Clist);

if CityNum==10

if f==0

text(0,0,[‘第 ‘,int2str(p),‘ 代‘,‘  最短距离为 ‘,num2str(bsf)]);

else

text(0,0,[‘最终搜索结果:最短距离 ‘,num2str(bsf),‘, 在第 ‘,num2str(p),‘ 代达到‘]);

end

end

hold off;

pause(0.02);

% keyboard

end

3.3.子函数2

function [ output_args ] = simulated ( input_args )

%UNTITLED Summary of this function goes here

%   Detailed explanation goes here

clc

a = 0.99;       % 温度衰减函数的参数

t0 = 99; tf = 0.1; t = t0;

ML = 500;     % Markov链长度

coordinates = [

1   41 94;   2  37 84;  3   54  67;

4    25 62;    5   7  64;  6    2     99;

7    68 58;    8  71 44;   9     54   62;

10  83 69;    11   64 60;    12   18   54;

13  22 60;    14   83 46;    15   91   38;

16  25 38;    17   24 42;    18   58   69;

19  71 71;    20   74 78;    21   87   76;

22  18 40;    23   13 40;    24   82   7;

25  62 32;    26   58 35;    27   45   21;

28  41 26;    29   44 35;    30   4     50;

];

coordinates(:,1) = [];

amount = size(coordinates,1);       % 城市的数目

% 通过向量化的方法计算距离矩阵

dist_matrix = zeros(amount, amount);

coor_x_tmp1 = coordinates(:,1) * ones(1,amount);

coor_x_tmp2 = coor_x_tmp1‘;

coor_y_tmp1 = coordinates(:,2) * ones(1,amount);

coor_y_tmp2 = coor_y_tmp1‘;

dist_matrix = sqrt((coor_x_tmp1-coor_x_tmp2).^2 + ...

(coor_y_tmp1-coor_y_tmp2).^2);

sol_new = 1:amount;         % 产生初始解

% sol_new是每次产生的新解;sol_current是当前解;sol_best是冷却中的最好解;

E_current = inf;E_best = inf;          % E_current是当前解对应的回路距离;

% E_new是新解的回路距离;

% E_best是最优解的

sol_current = sol_new; sol_best = sol_new;

p = 1;                         %统计迭代次数

while t>=tf

for r=1:ML          % Markov链长度

if (rand < 0.5)    % 随机决定是进行两交换还是三交换

% 两交换

ind1 = 0; ind2 = 0;

while (ind1 == ind2)

ind1 = ceil(rand.*amount);

ind2 = ceil(rand.*amount);

end

tmp1 = sol_new(ind1);

sol_new(ind1) = sol_new(ind2);

sol_new(ind2) = tmp1;

else

% 三交换

ind1 = 0; ind2 = 0; ind3 = 0;

while (ind1 == ind2) || (ind1 == ind3) ...

|| (ind2 == ind3) || (abs(ind1-ind2) == 1)

ind1 = ceil(rand.*amount);

ind2 = ceil(rand.*amount);

ind3 = ceil(rand.*amount);

end

tmp1 = ind1;tmp2 = ind2;tmp3 = ind3;

% 确保ind1 < ind2 < ind3

if (ind1 < ind2) && (ind2 < ind3)

elseif (ind1 < ind3) && (ind3 < ind2)

ind2 = tmp3;ind3 = tmp2;

elseif (ind2 < ind1) && (ind1 < ind3)

ind1 = tmp2;ind2 = tmp1;

elseif (ind2 < ind3) && (ind3 < ind1)

ind1 = tmp2;ind2 = tmp3; ind3 = tmp1;

elseif (ind3 < ind1) && (ind1 < ind2)

ind1 = tmp3;ind2 = tmp1; ind3 = tmp2;

elseif (ind3 < ind2) && (ind2 < ind1)

ind1 = tmp3;ind2 = tmp2; ind3 = tmp1;

end

tmplist1 = sol_new((ind1+1):(ind2-1));

sol_new((ind1+1):(ind1+ind3-ind2+1)) = ...

sol_new((ind2):(ind3));

sol_new((ind1+ind3-ind2+2):ind3) = ...

tmplist1;

end

%检查是否满足约束

% 计算目标函数值

E_new = 0;

for i = 1 : (amount-1)

E_new = E_new + ...

dist_matrix(sol_new(i),sol_new(i+1));

end

% 再算上从最后一个城市到第一个城市的距离

E_new = E_new + ...

dist_matrix(sol_new(amount),sol_new(1));

if E_new < E_current

E_current = E_new;

sol_current = sol_new;

if E_new < E_best

% 把冷却过程中最好的解保存下来

E_best = E_new;

sol_best = sol_new;

end

else

% 若新解的目标函数值小于当前解的,

% 则仅以一定概率接受新解

if rand < exp(-(E_new-E_current)./t)

E_current = E_new;

sol_current = sol_new;

else

sol_new = sol_current;

end

end

end

t=t.*a;          % 控制参数t(温度)减少为原来的a倍

end

for i=1:length(coordinates)

plot(coordinates(i,1),coordinates(i,2),‘r*‘);

hold on;

end;

x=coordinates([sol_best sol_best(1)],1);

y=coordinates([sol_best sol_best(1)],2);

plot(x,y);

title([‘循环迭代次数:‘,int2str(ML),‘ 优化最短距离:‘,num2str(E_best)]);

end

原文地址:https://www.cnblogs.com/qiankun-tec/p/10637319.html

时间: 2024-10-11 10:38:20

遗传算法求解TSP源码及解析的相关文章

ngx lua模块源码简单解析

ngx lua模块源码简单解析分类: nginx 2014-07-11 11:45 2097人阅读 评论(0) 收藏 举报nginxlua数据结构架构目录(?)[+]对nginx lua模块的整个流程,原理简单解析.由于nginx lua模块相关配置,指令,API非常多,所以本文档只以content_by_lua指令举例说明. 读本文档最好配合读源码. 不适合对nginx和lua一点都不了解的人看.1.相关配置详细配置见 https://github.com/openresty/lua-ngin

基于遗传算法求解TSP问题(Java界面)

近期为做展示,改写了一个遗传算法求TSP的Java界面版,思路代码和 http://blog.csdn.net/wangqiuyun/article/details/12838903 这篇文章思路是一样的,追加了Java用Graphics画点及画线做路径展示,展示部分做得比較粗糙,须要的拿走,效果图例如以下. 下载地址:http://download.csdn.net/detail/wangqiuyun/7406201 另C#界面版:http://blog.csdn.net/wangqiuyun

Retrofit源码设计模式解析(下)

本文将接着<Retrofit源码设计模式解析(上)>,继续分享以下设计模式在Retrofit中的应用: 适配器模式 策略模式 观察者模式 单例模式 原型模式 享元模式 一.适配器模式 在上篇说明CallAdapter.Factory使用工厂模式时,提到CallAdapter本身采用了适配器模式.适配器模式将一个接口转换成客户端希望的另一个接口,使接口本不兼容的类可以一起工作. Call接口是Retrofit内置的发送请求给服务器并且返回响应体的调用接口,包括同步.异步请求,查询.取消.复制等功

基于Linux平台下网络病毒Caem.c源码及解析

Came.c型病毒在这里主要修改了用户的密码,同时对用户的终端设备进行了监视.希望与大家共同交流 转载请注明出处:http://blog.csdn.net/u010484477     O(∩_∩)O谢谢 #define HOME "/" #define TIOCSCTTY 0x540E #define TIOCGWINSZ 0x5413 #define TIOCSWINSZ 0x5414 #define ECHAR 0x1d #define PORT 39617 #define BU

《Android源码设计模式解析》读书笔记——Android中你应该知道的设计模式

断断续续的,<Android源码设计模式解析>也看了一遍,书中提到了很多的设计模式,但是有部分在开发中见到的几率很小,所以掌握不了也没有太大影响. 我觉得这本书的最大价值有两点,一个是从设计模式的角度去理解Android源码,结合着日常开发中的常用类,对设计模式的理解会更加的深刻:另外一个好处就是了解常用模式,再看其他人写的代码的时候,更容易理解代码思路.下面是我的读书笔记和一些思考,设计模式只整理我认为重要的部分. 建造者模式 建造者模式最明显的标志就是Build类,而在Android中最常

第31课:Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结

本課主題 Master 资源调度的源码鉴赏 Spark 的 Worker 是基于什么逻辑去启动 Executor 资源调度管理 任務調度與資源是通過 DAGScheduler.TaskScheduler.SchedulerBackend 等進行的作業調度 資源調度是指應用程序如何獲得資源 任務調度是在資源調度的基礎上進行的,沒有資源調度那麼任務調度就成為了無源之水無本之木 Master 资源调度的源码鉴赏 因為 Master 負責資源管理和調度,所以資源調度方法 scheduer 位於 Mast

《Android源码设计模式解析与实战》读书笔记(十三)

第十三章.备忘录模式 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,有点像是我们平常说的"后悔药". 1.定义 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可将该对象恢复到原先保存的状态. 2.使用场景 (1)需要保存一个对象在某一个时刻的状态或部分状态. (2)如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访

源码深度解析SpringMvc请求运行机制(转)

源码深度解析SpringMvc请求运行机制 本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制.通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的. 1.用户请求处理过程: 1.用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext.localeResolver.themeResolver等对象添加到

iOS开发之Masonry框架源码深度解析

Masonry是iOS在控件布局中经常使用的一个轻量级框架,Masonry让NSLayoutConstraint使用起来更为简洁.Masonry简化了NSLayoutConstraint的使用方式,让我们可以以链式的方式为我们的控件指定约束.本篇博客的主题不是教你如何去使用Masonry框架的,而是对Masonry框架的源码进行解析,让你明白Masonry是如何对NSLayoutConstraint进行封装的,以及Masonry框架中的各个部分所扮演的角色是什么样的.在Masonry框架中,仔细