实战1:基于遗传算法解决旅行商问题的MATLAB编程(1)程序篇
目录
0.先上程序
1.绪论
2.研究方法
3.使用遗传算法编写TSP问题
4.结果分析
0.先上程序
==1=主函数
GeneticAlgorithm_TSP.m
==2=子函数:
CityDistance.m (计算不同城市之间的距离)
GroupFit.m (得出最短城市路径,最短城市路径样本,适应度函数)
selection.m (选择)
crossover.m (交叉)
Mutation.m (变异)
SwapRepeat.m (重复交换)
SwapGene.m (交换基因)
DrawPath.m (路径描绘)
1.主程序 GeneticAlgorithm_TSP.m
clear;close;clc;
%% Function:Describle the distance between cities
%% Author :sophiaechoz@163.com
%% Date :20210119
%% Define cities coordination
city20=[29 54;71 76;74 78;81 71;25 38;58 35;4 50;
13 40;18 40;24 98;71 44;64 60;69 58;83 69;58 69;54 63;51 67;37 84;
41 94;3 85];
%% Define constant name
N=20; %城市数
city_coordinate=city20; %城市位置,前面已经给点城市的数量,则可以确定城市的坐标。(8,15,20,30)
s=100; %样本数(种群)
c=30; %替换个数
pc=0.8; %交叉概率crossover
pm=0.1; %变异概率mutation
times=3000; %最大迭代次数
time=0; %实际迭代次数
%%初始化变量,设定总群,总适应度以及最短距离以及最小距离。
pop=zeros(s,N+1); %初始种群+适应度,之所以加N+1,因为最后还要回到原点。
pop_fit_aver=[];%总适应度
min_dis=[]; %最短距离
pop_min=[];%最短距离的基因
%初始化,其中s为种群数
for i=1:s
pop(i,1:N)=randperm(N); %%randperm函数产生1-N内任意排列的N维数组。
end
clf
plot(city_coordinate(:,1),city_coordinate(:,2),'bo');%画平均适应度折线图 //一个列向量作为自变量,另一个列向亮作为应变量。
%%变量处理:城市间
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); %%通过城市距离;城市数。pop(城市的随机分布)。s是城市分布的例子个数
sumP=sum;
pop_fit_aver=[pop_fit_aver;sum]; %%构造总群适应度函数
min_dis=[min_dis;min1]; %%构造最小距离 min_dis=min1
pop(:,N+1)=individual_fit; %%列矩阵的个体适应度函数
pop_min=[pop_min;pop(min_index,:)];
%% 选择父代
pop=selection(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);
%% 交叉crossover
if a>pc
;
else
crosspoint=rand(1,2);
crosspoint=floor(crosspoint*N)+1;
[pop(j,:),pop(j+s/2,:)]=Crossover(pop(j,:),pop(j+s/2,:),crosspoint,N);
end
%% 变异mutation
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=selection(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');
2.子程序
CityDistance.m
function [city_distance] = CityDistance(city_coordinate,N)%城市距离矩阵
city_distance=zeros(N,N); %%通过zeros构造
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; %%matlab是以矩阵的思维编写的,则每个距离都会存入city_diatance
end
end
end
GroupFit.m
function [individual_fit,num,min_distance,index] = GroupFit(city_distance,N,pop,s)%种群适应度
individual_distance=zeros(s,1); %%目的是求得最短路劲的值,给定INDIVIDUAL为sx1的矩阵
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; %%individual_distance是一个列矩阵
end
[min_distance,index]=min(individual_distance); %%找到最短的距离
individual_fit=1./individual_distance; %%分子越小,分母越大
num=0;
for i=1:s
num=num+individual_fit(i,1);
end
end
selection.m 选择
function [pop_ok]=selection(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
Crossover.m 交叉
function [a,b]=Crossover(pop1,pop2,crosspoint,N)%交叉
A=pop1;
if(crosspoint(:,1)
Mutation.m 变异
function [a]=Mutation(pop0,N)%变异
crosspoint=rand(1,2);
crosspoint=floor(crosspoint*N)+1;
if(crosspoint(:,1)
SwapRepeat.m (重复交换)
function [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
SwapGene.m (交换基因)
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
DrawPath.m (路径描绘)
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
效果图
(1)城市坐标分布图
(2)总适应度折线图
(3)最优路径图
后记:通俗的讲,旅行商问题以上算法程序,就如同高德等地图一样,给用户最短的路径或最短时间等等问题的解决。
date:20220520\15:37:15
好好学习,天天向上。从今天起恢复更新。
从没有坚持做过一件事,这次我想把它做好,至死不渝。