1. TSP问题概述

TSP问题即旅行商问题,是数学领域的著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要使求得的路径路程为所有路径之中的最小值。

2. 基于遗传算法的TSP问题求解

      (1)基因编码

      针对TSP问题,编码规则通常采用实数(n进制)编码,即每个染色体仅从1到n的整数里面取一个值,每个个体的长度为n,n为城市总数。即用一串基因编码表示遍历的城市顺序,如:(2 3 4 5 1 7 9 8 6),表示九个城市中,先经过城市2,再经过城市3,以此类推。

    (2)交叉算子设计

     采用部分匹配交叉(PMX)法:先随机产生两个交叉点,定义这两点间的区域为匹配区域,并交换两个父代的匹配区域。

     父代A:872|130|9546

     父代B:983|567|1420

     TEMP A:872|567|9546

     TEMP B:983|130|1420

对于TEMP A、TEMP B中匹配区域以外出现的数码重复,要依据匹配区域内的位置逐一进行替换。匹配关系:1<------>5   3<----->6   7<---->0

     子代A:802|567|9143

     子代B:986|130|5427

     (3)变异算子设计

      对于TSP问题,一般采用倒位变异法,即首先在父体中随机选择两截断点,然后将该两点所夹的子串中的城市进行反序。

例如;

设原个体:(1 2 3 4 5 6 7 8 9)

随机选择两点:(1 2|3 4 5 6| 7 8 9)

倒位后的个体:(1 2 |6 5 4 3|7 8 9)

     (4)适应度函数

     TSP问题的目标是路径总长度为最短,可以用常数L除以某个体的路径总长度作为该个体的是适应度函数。


3 . 算法步骤

Step1:参数设置及种群初始化;

Step2;适应度评价;

Step3:轮盘赌选择;

Step4:部分匹配交叉;

Step5:倒位变异;

Step6:适应度评价;

Step7:终止条件判断,若未达到终止条件,则转到step3;

Step8:输出结果。

4.实现代码

%功能:基于遗传算法的TSP问题求解
function GA_for_TSP
clc;clear all;close all;
%初始化数据
    city_num=30;
    [city_distance,city_coordinate]=tsp_info(city_num);%距离矩阵和城市坐标
    
    pop=100;ger=800;pc=0.8;pm=0.2;history_best=inf;
    for i=1:pop
        individual(i,:)=randperm(city_num);%产生1~30之间的随机排列数
    end
    [fitness,f]=evaluate_fitness(individual,city_distance);
    it=1;
    while it<=ger
        disp(it)
        new_individual=select(fitness,individual);%轮盘赌
        new_individual=cross(new_individual,pc);
        new_individual=mutation(new_individual,pm);
        [fitness,f]=evaluate_fitness(new_individual,city_distance);
        %取出最佳适应度的个体
        [best_fitness,best_index]=max(fitness);
        [worst_fitness,worst_index]=min(fitness);
        best_f=f(best_index);
        best_individual=new_individual(best_index,:);
        new_individual(worst_index,:)=best_individual;
        plot_dsp(city_coordinate,best_individual,best_f,it);
        individual=new_individual;
        if best_f<history_best
            history_best=best_f;
            history_best_individual=best_individual;
            best_individual_last(it,:)=best_f;%???
        else
            best_individual_last(it,:)=history_best;
        end
        it=it+1;
    end
   
    disp(sprintf('最短路径:%2.5f',history_best))
    disp('路径方案:')
    disp(sprintf('%4d',history_best_individual));
    %给每个城市标号
    for i=1:size(city_coordinate,1)
        text(city_coordinate(i,1),city_coordinate(i,2),num2str(i));
    end
    
    figure(2)
    plot(best_individual_last,'r');hold on;
    title('搜索过程');
    legend('最优路径长度');
    gtext(['(' num2str(it-1) ',' num2str(history_best) ')']);
%end
    %******************Data子程序tsp_info***************************
    function [city_distance,city_coordinate]=tsp_info(city_num)
        %fid=fopen('city_coordinate.txt','r');
        %city_coordinate=fscanf(fid,'%d',[50,2]);
        %fclose(fid);
        city_coordinate=[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];
        for i=1:city_num
            for j=1:city_num
                city_distance(i,j)=sqrt((city_coordinate(i,1)-city_coordinate(j,1))^2+(city_coordinate(i,2)-city_coordinate(j,2))^2);
            end
        end
    %********************The end of tsp_info*****************
    
    
    
    %********************适应度-->evaluate_fitness*************************
        function [fitness,f]=evaluate_fitness(individual,city_distance)
            [M,N]=size(individual);
            for i=1:M
                temp=0;
                for j=1:N-1
                    temp=temp+city_distance(individual(i,j),individual(i,j+1));
                end
                f(i)=temp+city_distance(individual(i,N),individual(i,1));
                fitness(i)=1000/f(i);
            end
    %*********************************the end*************************************
    
       
    %*************************轮盘赌-->selcet***********************************
        function new_individual=select(fitness,individual)
            [m,n]=size(fitness');
            for i=1:m
                fit(i)=fitness(i)^20;
            end
            %fit=fitness.^20;
            for i=1:m
                sp(i)=fit(i)/sum(fit);
            end
            for i=2:m
                sp(i)=sp(i-1)+sp(i);
            end
            for i=1:m
                p=rand(1);
                j=1;
                while(p>sp(j))%找到sp(j)大于p的 j 值
                    j=j+1;
                end
                new_individual(i,:)=individual(j,:);
            end
     %***************************The End***********************************
   
     
   
     
     %**************************交叉子程序*****************************
     %功能:片段交叉
         function new_individual=cross(new_individual,pc)
             [M,N]=size(new_individual);
             %先将顺序打乱
             for i=1:M
                 point=unidrnd(M-i+1);%产生随机数
                 temp=new_individual(i,:);
                 new_individual(i,:)=new_individual(i+point-1,:);
                 new_individual(i+point-1,:)=temp;
             end
             for i=1:2:M-1
                 if pc>rand(1)
                     %产生两个交叉位置
                     location_num1=round(rand(1)*(N-2))+1;
                     location_num2=round(rand(1)*(N-2))+1;
                     min_location=min([location_num1,location_num2]);
                     max_location=max([location_num1,location_num2]);
                     %交换相邻两行的片段
                     middle=new_individual(i,min_location+1:max_location);
                     new_individual(i,min_location+1:max_location)=new_individual(i+1,min_location+1:max_location);
                     new_individual(i+1,min_location+1:max_location)=middle;
                     %交叉完之后检查个体序号是否有重复
                     for j=1:min_location%前半段
                         while find(new_individual(i,min_location+1:max_location)==new_individual(i,j))
                             num=find(new_individual(i,min_location+1:max_location)==new_individual(i,j));
                             new_num=new_individual(i+1,min_location+num);
                             new_individual(i,j)=new_num;
                         end
                         while find(new_individual(i+1,min_location+1:max_location)==new_individual(i+1,j))
                             num=find(new_individual(i+1,min_location+1:max_location)==new_individual(i+1,j));
                             new_num=new_individual(i,min_location+num);
                             new_individual(i+1,j)=new_num;
                         end
                     end
                     
                     for j=max_location+1:N%后半段
                         while find(new_individual(i,1:max_location)==new_individual(i,j))
                             num=find(new_individual(i,1:max_location)==new_individual(i,j));
                             new_num=new_individual(i+1,num);
                             new_individual(i,j)=new_num;
                         end
                         while find(new_individual(i+1,1:max_location)==new_individual(i+1,j))
                             num=find(new_individual(i+1,1:max_location)==new_individual(i+1,j));
                             new_num=new_individual(i,num);
                             new_individual(i+1,j)=new_num;
                         end
                     end
                 end
             end
             %***************************The End***************************
             
    
             
      %************************画图:plot_dsp*************************************
     function plot_dsp(city_coordinate,best_individual,best_fitness,it)
     [city_num,city]=size(city_coordinate);
     for i=1:city_num-1
         plot([city_coordinate(best_individual(i),1),city_coordinate(best_individual(i+1),1)],...
             [city_coordinate(best_individual(i),2),city_coordinate(best_individual(i+1),2)],...
             'm.-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','b');
         hold on;grid on;
     end
     plot([city_coordinate(best_individual(city_num),1),city_coordinate(best_individual(1),1)],...
         [city_coordinate(best_individual(city_num),2),city_coordinate(best_individual(1),2)],...
             'm.-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','b');
         title([num2str(city_num),'城市数量TSP问题']);grid on;
         hold off;
         pause(0.05);
     %**************************the end************************************       
     
     
     %***************************变异子程序*******************************
     %功能:变异子函数,片段倒序
         function new_individual=mutation(new_individual,pm)
             [M,N]=size(new_individual);%M:个体数,N:城市数
             for i=1:N
                 if rand(1)<pm
                     location_num1=round(rand(1)*(N-2))+1;%产生1~N-1之间的随机数
                     location_num2=round(rand(1)*(N-2))+1;
                     min_location=min([location_num1,location_num2]);%变异片段的最小序号
                     max_location=max([location_num1,location_num2]);%变异片段的最大序号
                     new_individual(i,min_location:max_location)=new_individual(i,max_location:-1:min_location);
                 end
             end
         %***************** The End ***************************


更多推荐

遗传算法求解旅行商(TSP)问题