Home

Awesome

GA4TSPProblem

在matlab上使用遗传算法解决TSP旅行者问题

TSP问题指的是从一个节点开始遍历其他所有节点并回到初始节点,构成一个哈密顿回路,节点与节点之间距离不同,目标是找到一条回路使得总路程最短,也即就是走最短的路遍历所有节点回到起点。

遗传算法模仿达尔文进化论中优胜劣汰的思想,从随机初始总群开始,不断进化最终选出接近最优解的一代,从而求解出近似最优解

问题描述

下图矩阵展示了不同城市之间的距离,城市到自身的距离为0,现要求从Hong Kong出发,找一条最短的旅游顺序,使得游览所有城市后回到Hong Kong。 这里写图片描述

基本思路

主要是问题的编码阶段,对于TSP问题在遗传算法中编码使用整数编码,使用整数来代表每一个城市,比如这里可以依次使用1,2,3,...,13表示这13个城市,9则代表Hong Kong。

城市编码基因
Amsterdam1
Athens2
Auckland3
Bahrain4
Bangkok5
Colombo6
Dubai7
Frankflurt8
HK9
Jakarta10
Kuala Lumpur11
London12
Manila13

这13个数字的一个排列即是一种路径方案,但注意这条路径是一个环,收尾相接,因此起点是哪个城市是无所谓的,只要数字的相对位置确定,那13种(谁是起点)归并为同一种方案。因此所有可能的方案数为:13!/13 (全排列除以13)

示例染色体:[1 2 3 4 5 6 7 8 9 10 11 12 13],同[2 3 4 5 6 7 8 9 10 11 12 13 1]等属于同一种方案。

每种方案的路程代价即个体的适应度,路程越短代价越小适应度越高。

函数解释

这里写图片描述

matlab代码清单

cost.m

function [value]=cost(parent,costM)

[NumP,tmp]=size(parent);

for i=1:NumP
parent_i = parent(i,:);
value_i = 0;
for j=1:12
    value_i = value_i + costM(parent_i(j),parent_i(j+1));
end
value_i = value_i + costM(parent_i(13),parent_i(1));

value(i,1) = value_i;

end

end

crosscheck.m

%check if the two parent can generate valid children after crossover
function res = crosscheck(parent1,parent2)
res = 0;
for i = 1:12
    p1 = [parent1(:,1:i) parent2(:,i+1:13)];
    p2 = [parent2(:,1:i) parent1(:,i+1:13)];
    if length(p1)==length(unique(p1)) && length(p2)==length(unique(p2))
        res = 1;
    end
end
end

crossover.m

function [child1, child2]=crossover(parent1, parent2)
child1 = 0;
child2 = 0;

if crosscheck(parent1,parent2) == 1
    p1 = [1 1 1 1 1 1 1 1 1 1 1 1 1];
    p2 = [2 2 2 2 2 2 2 2 2 2 2 2 2];
    %make sure the children are valid
    while length(p1)>length(unique(p1)) || length(p2)>length(unique(p2))
        %randomly select a cross point
        crossPoint = randi([1 12]);
        p1 = [parent1(:,1:crossPoint) parent2(:,crossPoint+1:13)];
        p2 = [parent2(:,1:crossPoint) parent1(:,crossPoint+1:13)];
    end
    child1 = p1;
    child2 = p2;
end

end

generate.m

function pop = generate(num)
res = [];
%generate num random populations
for i = 1:num
    tmp = [0 0 0 0 0 0 0 0 0 0 0 0 0];
    tmp0 = [1 2 3 4 5 6 7 8 9 10 11 12 13];
    for j = 1:13
        %random index
        index = randi([1 14-j]);
        tmp(j) = tmp0(index);
        %delete randomly selected element
        tmp0(:,index) = [];
    end
    res = [res;tmp];
end
pop = res;
end

mutation.m

function [child]=mutation(parent,probability)

if rand() <= probability
    P = parent;
    %select two random cities to interchange
    random1 = 0;
    random2 = 0;
    while random1 == random2
        random1 = randi([1 13]);
        random2 = randi([1 13]);
    end
    %mutation
    P(:,[random1,random2])=P(:,[random2,random1]);
    child=P;
else
    child = 0;
end

end

TSP.m

function tmp = TSP()
close all;
clc;

%----------------------------data area-------------------------------------
% distance from a city to others
Amsterdam    = [0    2.2  18.1 4.8  9.2  8.4  5.2  0.4  9.3  11.3 10.2 0.4  10.4]; %1
Athens       = [2.2  0    17.5 2.8  7.9  6.6  3.3  1.8  8.5  9.8  8.7  2.4  9.6];  %2
Auckland     = [18.1 17.5 0    14.7 9.6  10.9 14.2 18.2 9.1  7.6  8.7  18.3 8.0];  %3
Bahrain      = [4.8  2.8  14.7 0    5.4  3.8  0.5  4.4  6.4  7.0  6.0  5.1  7.4];  %4
Bangkok      = [9.2  7.9  9.6  5.4  0    2.4  4.9  9.0  1.7  2.3  1.2  9.5  2.2];  %5
Colombo      = [8.4  6.6  10.9 3.8  2.4  0    3.3  8.1  4.1  3.3  2.5  8.7  4.6];  %6
Dubai        = [5.2  3.3  14.2 0.5  4.9  3.3  0    4.8  6.0  6.6  5.5  5.5  6.9];  %7
Frankflurt   = [0.4  1.8  18.2 4.4  9.0  8.1  4.8  0    9.2  11.1 10.0 0.6  10.3]; %8
HK           = [9.3  8.5  9.1  6.4  1.7  4.1  6.0  9.2  0    3.3  2.5  9.6  1.1];  %9
Jakarta      = [11.3 9.8  7.6  7.0  2.3  3.3  6.6  11.1 3.3  0    1.2  11.7 2.8];  %10
KualaLumpur  = [10.2 8.7  8.7  6.0  1.2  2.5  5.5  10.0 2.5  1.2  0    10.5 2.5];  %11
London       = [0.4  2.4  18.3 5.1  9.5  8.7  5.5  0.6  9.6  11.7 10.5 0    10.7]; %12
Manila       = [10.4 9.6  8.0  7.4  2.2  4.6  6.9  10.3 1.1  2.8  2.5  10.7 0];    %13
costM = [Amsterdam;Athens;Auckland;Bahrain;Bangkok;Colombo;Dubai;Frankflurt;HK;Jakarta;KualaLumpur;London;Manila];

%mutation probability
pmutation = 1.0;
%max generation
MaxGeneration = 200;
%poputation size
popsize = 20;
%select popsize parents from randomsize generated possible parents
randsize = 200;

%parent generations
parentpop = [];
%best parent of every generation
best_cost = [];

%-------------------generate parent generation-----------------------------
preparentpop = generate(randsize);
[A,index] = sort(cost(preparentpop,costM),1,'ascend');
%orderd preparentpop
orderedpreparentpop = preparentpop(index,:);
%selected top popsize parentpop
parentpop = orderedpreparentpop([1:popsize],:);

%---------------------main revolution loop---------------------------------
for igen = 1:MaxGeneration
    childpop = [];
    childpopsize = [0 0];
    %generate enough children
    while childpopsize(1) < popsize
        % To generate the random index for crossover and mutation 
        ind=randi(popsize,[1 2]) ;
        parent1 = parentpop(ind(1),:);
        parent2 = parentpop(ind(2),:);
        [child1,child2] = crossover(parent1,parent2);
        [child3] = mutation(parent1,pmutation);
        if child1~=0
            childpop = [childpop;child1];
        end
        if child2~=0
            childpop = [childpop;child2];
        end
        if child3~=0
            childpop = [childpop;child3];
        end
        childpopsize = size(childpop);
    end
    
    % Elite: parentpop and childpop are added together before sorting for the best popsize to continue
    allpop = [parentpop;childpop];
    [A,index] = sort(cost(allpop,costM),1,'ascend');
    orderdallpop = allpop(index,:);
    %parentpop of current generation
    parentpop = orderdallpop([1:popsize],:);
    best_cost(igen)=A(1);
end

%display
display('the best parentpop:')
parentpop
display('the lowest cost of every generation:')
best_cost'

figure,plot(1:igen,best_cost,'b') 
title('GA algorithm for TSP problem')

end

实例结果

进行了200代进化,大约在50代以后收敛,得到近似最优方案的最小路程代价为40.2,最优染色体为:[2 8 12 1 9 13 3 10 11 5 6 7 4], 并不是每次运行都会得到绝对最优解,遗传算法容易早熟陷入局部最优解,需要调参优化:

这里写图片描述

Github源码下载:https://github.com/jiangxh1992/GA4TSPProblem