遗传算法求解TSP问题

一、简介

  遗传算法是基于达尔文的生物进化论,是人工智能算法的的重要分支,主要用于解决一类求最优解问题。如旅行商(TSP)问题。

  遗传算法是将状态当成染色体,状态里的每一个决策都是染色体上的一个基因。然后根据实际情况生成一个适应度函数,计算每一串染色体对环境的适应度。让适应度高的遗传到下一代,适应度低的淘汰掉,另外在实现的过程中也许会发生变异,导致一些决策改变。除此之外,遗传算法是随机性近似算法,所以当我们运用该算法时必须采取措施使其收敛到全局最优解,并且尽量提高达到最优解的概率。遗传算法除了设计适应度函数以外,还有很重要的三个部分:选择,交叉,变异。

 

二、遗传算法实现步骤

1.评估每条染色体所对应个体的适应度。

2.遵照适应度越高,选择概率越大的原则,从种群中选择两个个体作为父方和母方。

3.抽取父母双方的染色体,进行交叉,产生子代。

4.对子代的染色体进行变异。

5.重复2,3,4步骤,直到新种群的产生。

 

三、遗传算法求解TSP实现步骤

1.确定影响因素

   城市序列、城市个数N、种群个数M、交叉概率Pc、变异概率Pmutation等;

2.初始化数据

 2.1初始化影响因素:城市序列、城市个数N、种群个数M、交叉概率Pc、变异概率Pmutation

 2.2 初始化数据:读入数据源,将坐标转换为距离矩阵(标准化欧式距离)

3.计算种群适应度
  已知任意两个城市之间的距离,每个染色体可计算出总距离,因此可以将一个随机全排列的总距离的倒数作为适应度函数,即距离越短,适应度函数越好。

4.迭代
选择算子:赌轮选择策略挑选下一代个体。
交叉运算:在交叉概率的控制下,对群体中的个体两两进行交叉。
变异运算:在变异概率的控制下,对群体中的个体两两进行变异,即对某一个体的基因进行随机调整。
计算新的种群适应度以及个体累积概率,并更新最优解。
将新种群复制到旧种群中,准备下一代进化(迭代)。

5.输出
输出迭代过程中产生的最短路径长度以及最短路径。

四、代码实现

  main.m(主函数):

%main
clear;
clc;
%%%%%%%%%%%%%%%输入参数%%%%%%%%
N=25;               %%城市的个数
M=100;               %%种群的个数
ITER=2000;               %%迭代次数
%C_old=C;
m=2;                %%适应值归一化淘汰加速指数
Pc=0.8;             %%交叉概率
Pmutation=0.05;       %%变异概率
%%生成城市的坐标
pos=randn(N,2);
%%生成城市之间距离矩阵
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(ITER+1,1);  %%各次迭代的最小的种群的路径总长
nn=M;
iter=0;
while iter<=ITER
    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);
%    A=popm_sel(nnper(1),:);
 %   B=popm_sel(nnper(2),:);
    %%
    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(1),:)=A;
  %      popm_sel(nnper(2),:)=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);

  cross.m(交叉操作函数):

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

  exchange.m(对调函数):

function [x,y]=exchange(x,y)
temp=x;
x=y;
y=temp;
 
end

  fit.m(适应度函数):

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

  Mutation.m(变异函数):

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

  mylength.m(染色体的路程代价函数):

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

   plot_route.m(连点画图函数):

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

五、实验结果与分析

  分别测试城市序列、城市个数N、种群个数M、交叉概率Pc、变异概率Pmutation等影响因素对实验结果的影响

 1、不同城市序列对实验结果的影响:

 

 

 

 

 

 

 

 

 

 

 

 

  分析:在本算法实现过程中,城市序列采用随机生成,当城市序列不同时,算法运行时间和最短回路距离也会不同。

 

2、种群个数M(其他因素不变)对实验结果的影响:

M=100,城市个数N=35,其坐标分别如下:(在后面的测试中各城市坐标均如下所示)

 

 

 M=100(如图显示约迭代1100次得到最短回路距离为20.92):

 

 

 M=80(如图显示约迭代1000次得到最短回路距离为23.25)

 

 

 M=60(如图显示约迭代1400次得到最短回路距离为23.59)

 

 M=40(如图显示约迭代1750次得到最短回路距离为24.06)

 

 

 

分析:如上4组数据所示,当种群规模增大时,算法收敛到最优解的可能性越大,全局搜索能力也有所增强;另外可以看出当种群规模增大后,在解空间中搜索时,可以在相对较少的代数中找到最优解,进化代数也随着种群规模的增大而变小了。种群规模越大算法结果越精确,适应度越好。

 

3、交叉概率Pc对实验结果的影响

Pc=0.8(如图显示约迭代1000次得到最短回路距离为22.21)

 

 Pc=0.6(如图显示约迭代900次得到最短回路距离为23.08)

 Pc=0.4(如图显示约迭代1100次得到最短回路距离为23.36)

 

 

 

 

 

  Pc=0.2(如图显示约迭代1700次得到最短回路距离为22.23)

 

 

 

 Pc=0.01(如图显示约迭代1800次得到最短回路距离为25.14)

 

 

 

 分析:如以上五组测试数据和运行结果可以看出,当交叉概率越小,迭代次数越大且得不到最优解,当交叉概率越大时,迭代次数越是且得到的结果更优。所以交叉概率较大时,结果越优。

 

4、变异概率Pmutation对实验结果的影响

Pmutation=0.05(如图显示约迭代1100次得到最短回路距离为22.57)

 

 

 

 Pmutation=0.1(如图显示约迭代1600次得到最短回路距离为21.52)

 

 

 

 Pmutation=0.3(如图显示约迭代1500次得到最短回路距离为23.20)

 

 

 

 Pmutation=0.6(如图显示约迭代2000次得到最短回路距离为28.56)

 

 

 

  Pmutation=0.005(如图显示约迭代1700次得到最短回路距离为24.38)

 

 

 

 分析:如以上五组测试数据和运行结果可以看出,当变异概率大于0.1时,变异概率越大,迭代次数越大且最短回路距离也变得越大,得不到最优解。当变异概率小于0.1时,变异概率越小,迭代次数越大且最短回路距离也变得越大,也无法得到最优解!!所以当变异概率越接近0.1时,越能得到最优解。

posted @ 2019-11-19 23:51  积极废人  阅读(2221)  评论(0编辑  收藏  举报