遺傳算法實現TSP問題
文章目錄
1.算法介紹
1.1 遺傳算法原理
詳見博客https://blog.csdn.net/lzydelyc/article/details/102906590
1.2 TSP問題描述
2.算法實現
2.1 代碼實現
2.1.1選擇數據
在命令行窗口實現以下語句
然後將mat文件load出來即可。
2.1.2代碼
(1)main函數
%main
clear;
clc;
%%%%%%%%%%%%%%%輸入參數%%%%%%%%
N=25; %%城市的個數
M=100; %%種羣的個數
ITER=1000; %%迭代次數
m=2; %%適應值歸一化淘汰加速指數
Pc=0.8; %%交叉概率
Pmutation=0.05; %%變異概率
%生成城市的座標
load city_25;
%pos=city_100;
%生成城市之間距離矩陣
D=zeros(N,N);
for i=1:N
for j=i+1:N
dis=(pos(i,1)-pos(j,1)).^2+(pos(i,2)-pos(j,2)).^2;
D(i,j)=dis^(0.5);
D(j,i)=D(i,j);
end
end
%生成初始羣體
popm=zeros(M,N);
for i=1:M
popm(i,:)=randperm(N);%隨機排列,比如[2 4 5 6 1 3]
end
%隨機選擇一個種羣
R=popm(1,:);
figure(1);
scatter(pos(:,1),pos(:,2),'rx');%畫出所有城市座標
axis([-3 3 -3 3]);
figure(2);
plot_route(pos,R); %%畫出初始種羣對應各城市之間的連線
axis([-3 3 -3 3]);
%初始化種羣及其適應函數
fitness=zeros(M,1);
len=zeros(M,1);
for i=1:M%計算每個染色體對應的總長度
len(i,1)=myLength(D,popm(i,:));
end
maxlen=max(len);%最大回路
minlen=min(len);%最小回路
fitness=fit(len,m,maxlen,minlen);
rr=find(len==minlen);%找到最小值的下標,賦值爲rr
R=popm(rr(1,1),:);%提取該染色體,賦值爲R
for i=1:N
fprintf('%d ',R(i));%把R順序打印出來
end
fprintf('\n');
fitness=fitness/sum(fitness);
distance_min=zeros(1000+1,1); %%各次迭代的最小的種羣的路徑總長
nn=M;
iter=0;
while iter<=1000
fprintf('迭代第%d次\n',iter);
%選擇操作
p=fitness./sum(fitness);
q=cumsum(p);%累加
for i=1:(M-1)
len_1(i,1)=myLength(D,popm(i,:));
r=rand;
tmp=find(r<=q);
popm_sel(i,:)=popm(tmp(1),:);
end
[fmax,indmax]=max(fitness);%求當代最佳個體
popm_sel(M,:)=popm(indmax,:);
%%交叉操作
nnper=randperm(M);
for i=1:M*Pc*0.5
A=popm_sel(nnper(i),:);
B=popm_sel(nnper(i+1),:);
[A,B]=cross(A,B);
popm_sel(nnper(i),:)=A;
popm_sel(nnper(i+1),:)=B;
end
%%變異操作
for i=1:M
pick=rand;
while pick==0
pick=rand;
end
if pick<=Pmutation
popm_sel(i,:)=Mutation(popm_sel(i,:));
end
end
%%求適應度函數
NN=size(popm_sel,1);
len=zeros(NN,1);
for i=1:NN
len(i,1)=myLength(D,popm_sel(i,:));
end
maxlen=max(len);
minlen=min(len);
distance_min(iter+1,1)=minlen;
fitness=fit(len,m,maxlen,minlen);
rr=find(len==minlen);
fprintf('minlen=%d\n',minlen);
R=popm_sel(rr(1,1),:);
for i=1:N
fprintf('%d ',R(i));
end
fprintf('\n');
popm=[];
popm=popm_sel;
iter=iter+1;
%pause(1);
end
%end of while
figure(3)
plot_route(pos,R);
axis([-3 3 -3 3]);
figure(4)
plot(distance_min);
(2)計算染色體路程代價函數
function len=myLength(D,p)%p是一個排列
[N,NN]=size(D);
len=D(p(1,N),p(1,1));
for i=1:(N-1)
len=len+D(p(1,i),p(1,i+1));
end
end
(3)適應度函數
function fitness=fit(len,m,maxlen,minlen)
fitness=len;
for i=1:length(len)
fitness(i,1)=(1-(len(i,1)-minlen)/(maxlen-minlen+0.0001)).^m;
end
(4)交叉函數
function [A,B]=cross(A,B)
L=length(A);
if L<10
W=L;
elseif ((L/10)-floor(L/10))>=rand&&L>10
W=ceil(L/10)+8;
else
W=floor(L/10)+8;
end
%%W爲需要交叉的位數
p=unidrnd(L-W+1);%隨機產生一個交叉位置
%fprintf('p=%d ',p);%交叉位置
for i=1:W
x=find(A==B(1,p+i-1));
y=find(B==A(1,p+i-1));
[A(1,p+i-1),B(1,p+i-1)]=exchange(A(1,p+i-1),B(1,p+i-1));
[A(1,x),B(1,y)]=exchange(A(1,x),B(1,y));
end
end
(5)交換函數
%對調函數 exchange.m
function [x,y]=exchange(x,y)
temp=x;
x=y;
y=temp;
end
(6)變異函數
function a=Mutation(A)
index1=0;index2=0;
nnper=randperm(size(A,2));
index1=nnper(1);
index2=nnper(2);
%fprintf('index1=%d ',index1);
%fprintf('index2=%d ',index2);
temp=0;
temp=A(index1);
A(index1)=A(index2);
A(index2)=temp;
a=A;
end
(7)畫圖函數
function plot_route(a,R)
scatter(a(:,1),a(:,2),'rx');
hold on;
plot([a(R(1),1),a(R(length(R)),1)],[a(R(1),2),a(R(length(R)),2)]);
hold on;
for i=2:length(R)
x0=a(R(i-1),1);
y0=a(R(i-1),2);
x1=a(R(i),1);
y1=a(R(i),2);
xx=[x0,x1];
yy=[y0,y1];
plot(xx,yy);
hold on;
end
end
2.2 運行結果展示
運行結果展示了(1)城市分佈(2)初始種羣線路(3)最終線路(4)在設定的迭代次數下的路徑長度變化。
此處展示的是城市個數爲25,種羣個數爲50,迭代次數2000,交叉概率0.8,變異概率0.05的情況下的路線情況。
3參數分析
3.1改變種羣數量
城市數量25,迭代總次數2000,交叉概率0.8,變異概率爲0.05
種羣數量 | 迭代達到最短距離的次數 | 最短距離 | 運行時間 |
---|---|---|---|
50 | 364 | 2.000404 | 51.247 |
100 | 506 | 1.938898 | 50.784 |
200 | 1086 | 1.863281 | 51.296 |
300 | 433 | 2.136286 | 47.653 |
由上表可知,最短距離隨着種羣規模的增大先增加後減少,所以種羣數量設置在100-200較好。
3.2改變迭代次數
城市數量25,種羣數量100,交叉概率0.8,變異概率爲0.05
迭代次數 | 迭代達到最短距離的次數 | 最短距離 | 運行時間 |
---|---|---|---|
500 | 392 | 2.044818 | 13.247 |
1000 | 493 | 2.027277 | 27.702 |
2000 | 506 | 1.938898 | 50.784 |
3000 | 506 | 1.914200 | 79.134 |
由上表可知,隨着迭代次數的增大,最短距離會遞減,但是運行時間會增大,並且沒有太大的意義,將迭代次數設在1000-2000較好。
3.3改變交叉概率
城市數量25,種羣數量100,迭代次數2000,變異概率爲0.05
變異概率 | 迭代達到最短距離的次數 | 最短距離 | 運行時間 |
---|---|---|---|
0.2 | 421 | 1.854877 | 27.718 |
0.5 | 319 | 1.823316 | 27.897 |
0.8 | 272 | 1.939617 | 25.606 |
1 | 649 | 2.204067 | 25.912 |
由表中可知交叉概率在0-1上變化時,最短距離呈現出先減小後增大,運行時間隨變異概率增大而減小,交叉概率在0.2-0.8之間較好。
3.4改變變異概率
城市數量25,種羣數量100,迭代次數1000,交叉概率爲0.8
變異概率 | 迭代達到最短距離的次數 | 最短距離 | 運行時間 |
---|---|---|---|
0.005 | 179 | 1.872593 | 24.587 |
0.01 | 448 | 1.916578 | 25.638 |
0.05 | 448 | 1.963113 | 25.255 |
0.5 | 371 | 2.067011 | 39.533 |
變異概率在0.5的時候運行時間過長,呈現出破壞性,變異概率在0.005-0.01之間較好。
3.5改變城市個數
城市數量25,種羣數量100,迭代次數2000,交叉概率爲0.8
城市個數 | 迭代達到最短距離的次數 | 最短距離 | 運行時間 |
---|---|---|---|
10 | 18 | 1.017932 | 15.757 |
25 | 448 | 1.916578 | 25.638 |
50 | 1528 | 3.493564 | 27.444 |
100 | 1984 | 6.706513 | 39.533 |
城市個數在50的時候迭代達到最短距離的次數已經快到2000了,運行時間也越來越長。
注:較優值取於我的實驗結果,不代表標準答案。
一個嘗試:
城市數量100,迭代次數4000的情況下運行:
城市個數過大,迭代次數過多,GA一直不能完全收斂,可能的問題是陷入了局部最優解,因此對GA算法進行改進宜跳出局部最優解,可以採用類似於PSO或者蟻羣算法的思想。