zoukankan      html  css  js  c++  java
  • 遗传算法求解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('
    ');
    
    fitness=fitness/sum(fitness);
    distance_min=zeros(ITER+1,1);  %%各次迭代的最小的种群的路径总长
    nn=M;
    iter=0;
    while iter<=ITER
        fprintf('迭代第%d次
    ',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
    ',minlen);
        R=popm_sel(rr(1,1),:);
        for i=1:N
            fprintf('%d ',R(i));
        end
        fprintf('
    ');
        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时,越能得到最优解。

  • 相关阅读:
    JS中检测数据类型的方式
    DOM库
    原型应用(将数组去重写到数组的原型上)
    JS学习之原型和原型链模式
    JS学习之闭包、this关键字、预解释、作用域综合
    JS学习之作用域
    JS学习之预解释
    maven gradle 混合使用的问题
    libgdx 开发环境搭建
    maven 安装 jar
  • 原文地址:https://www.cnblogs.com/twzh123456/p/11889833.html
Copyright © 2011-2022 走看看