来源:

在matlab上实现遗传算法解决TSP旅行者问题 - CSDN博客
https://blog.csdn.net/cordova/article/details/64912680?locationNum=1&fps=1

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

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


问题描述

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

基本思路

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

城市 编码基因
Amsterdam 1
Athens 2
Auckland 3
Bahrain 4
Bangkok 5
Colombo 6
Dubai 7
Frankflurt 8
HK 9
Jakarta 10
Kuala Lumpur 11
London 12
Manila 13

这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]等属于同一种方案。

这种方案的路程代价为:F = 2.2+17.5+14.7+5.4+2.4+3.3+4.8+9.2+3.3+1.2+10.5+10.7+10.4 
= 95.6 (thousand kilometers)

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

函数解释

  • cost.m:用来计算一种方案的路程代价,参数为方案数列染色体和代价矩阵。算法中优选代价小的,淘汰代价大的;
  • crossover.m:染色体交叉,参数为两个父代染色体,交叉失败返回0,否则返回交叉后的两个子代染色体;
  • crosscheck.m:检查两个父代是否可交叉得到有效的子代染色体,因为交叉后如果染色体中出现重复的数字是无效的方案,等于某个城市走了两次同时有的城市没遍历到;
  • generate.m:产生一个随机的染色体,实际是将实力染色体中的基因顺序随机打乱得到;
  • mutation.m:按照一定基因突变概率使参数染色体发生基因突变得到突变后的子代染色体;
  • TSP.m:遗传算法主体,其中采用了精英选择法,将父代的优秀个体加入到下一代的竞争中。

Matlab代码清单

cost.m

% 根据代价矩阵costM计算种群pop的总路程代价
function [value] = cost(pop,costM)% 求得种群的个体数量,从而对每个个体计算代价[NumP,tmp]=size(pop);% 循环对每个个体计算代价for i=1:NumPparent_i = pop(i,:);value_i = 0;% 累加相邻两个城市之间的距离for j=1:12value_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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

crosscheck.m

% 检查两个父代个体是否可以交叉得到有效的两个子代个体
function res = crosscheck(parent1,parent2)res = 0;% 对每个交叉点进行交叉看是否至少有一个交叉点是有效的for i = 1:12p1 = [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;endend
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

crossover.m

% 染色体交叉
function [child1, child2]=crossover(parent1, parent2)% 如果父代不可交叉子代置0表示无效child1 = 0;child2 = 0;if crosscheck(parent1,parent2) == 1p1 = [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];% 确保子代有效while length(p1)>length(unique(p1)) || length(p2)>length(unique(p2))% 随机选择交叉点crossPoint = randi([1 12]);p1 = [parent1(:,1:crossPoint) parent2(:,crossPoint+1:13)];p2 = [parent2(:,1:crossPoint) parent1(:,crossPoint+1:13)];endchild1 = p1;child2 = p2;end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

generate.m

% 将基本的染色体序列随机打乱构造随机个体,可以构建num个随机个体
function pop = generate(num)res = [];% 算法思路是将tmp0中剩余的基因随机抽取依次填入tmp,当tmp0中的基因全部随机填入tmp后得到随机个体for i = 1:numtmp = [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% 随机下标index = randi([1 14-j]);tmp(j) = tmp0(index);% 删除从tmp0染色体中被随机选中的基因tmp0(:,index) = [];end% 组装得到的随机个体res = [res;tmp];endpop = res;
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

mutation.m

% 基因突变,按照突变概率,随机交换个体中的某两个基因
function [child]=mutation(parent,probability)if rand() <= probabilityP = parent;% 随机选择两个不同的基因交换位置random1 = 0;random2 = 0;while random1 == random2random1 = randi([1 13]);random2 = randi([1 13]);end% 开始突变(交换位置)P(:,[random1,random2]) = P(:,[random2,random1]);child=P;else% 没有发生突变child = 0;end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

TSP.m

% 遗传算法求解TSP旅行商问题
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:MaxGenerationchildpop = [];childpopsize = [0 0];%generate enough childrenwhile 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~=0childpop = [childpop;child1];endif child2~=0childpop = [childpop;child2];endif child3~=0childpop = [childpop;child3];endchildpopsize = size(childpop);end% Elite: parentpop and childpop are added together before sorting for the best popsize to continueallpop = [parentpop;childpop];[A,index] = sort(cost(allpop,costM),1,'ascend');orderdallpop = allpop(index,:);%parentpop of current generationparentpop = 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') xlabel('迭代的次数');
ylabel('路途代价');
title('GA algorithm for TSP problem')end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88

结果

进行了200代进化,大约在50代以后收敛,得到近似最优方案的最小路程代价为40.2。

最优染色体为:

[2 8 12 1 9 13 3 10 11 5 6 7 4]

等效于Hong Kong为起点的:

[9 13 3 10 11 5 6 7 4 2 8 12 1]

解码得到最佳方案为:

Hong Kong - Manila - Auckland - Jakarta - Kuala Lumpur - Bangkok - Colombo - Dubai - Bahrain - Athens - Frankflurt - London - Amsterdam - Hong Kong

并不是每次运行都会得到绝对最优解,遗传算法容易早熟陷入局部最优解。

自己运行的:

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

基于GA的TSP问题相关推荐

  1. 基于遗传算法求解TSP问题(旅游路径规划,Python实现,超详细,可视化,结果分析)

    ps:作者是很用心写的,如果觉得不错,请给作者一点鼓励噢!(点赞收藏评论噢) 基于遗传算法求解TSP问题 摘要 巡回旅行商问题(TSP)是组合优化中的经典问题.常见的TSP问题求解算法例如穷举法.贪心 ...

  2. 【建模算法】基于遗传算法求解TSP问题(matlab求解)

    [建模算法]基于遗传算法求解TSP问题(matlab求解) TSP (traveling salesman problem,旅行商问题)是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增 ...

  3. 《MATLAB智能算法30个案例》:第4章 基于遗传算法的TSP算法

    <MATLAB智能算法30个案例>:第4章 基于遗传算法的TSP算法 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB智能算法30个案例分析>是 ...

  4. 基于CHNN求解TSP问题

    目录 基于CHNN求解TSP问题 CHNN CHNN的网络结构 CHNN状态方程 CHNN的能量函数 TSP问题 基于CHNN求解TSP问题的思路 1. 分析问题,将TSP的状态用数学符号描述出来 1 ...

  5. MATLAB遗传算法GA求解TSP旅行商问题,可选PMX交叉、OX交叉及其它多种交叉方式,在算法中引入2-opt变异算子

    MATLAB遗传算法GA求解TSP旅行商问题,可选PMX交叉.OX交叉及其它多种交叉方式,在算法中引入2-opt变异算子.进化逆转算子提高算法局部搜索能力,利用国际通用的TSPLIB数据集中的eil5 ...

  6. 遗传算法GA求解TSP问题

    目录 一.遗传算法基本思想 二.遗传算法的主要步骤 三 .遗传编码 1.二进制编码 2.实数编码 四.遗传算法流程 五.例题 一.遗传算法基本思想 遗传算法(Genetic Algorithm, GA ...

  7. 基于遗传算法解决TSP问题(Matlab代码实现)

    目录 1 概述 2 运行结果 3 Matlab代码实现 4 结语 5 参考文献 1 概述 旅行商问题是一个经典的路径规划问题,传统TSP假设客户位置和客户之间旅行时间是固定不变的,而在现实生活中交通状 ...

  8. 基于遗传算法求解TSP问题(JAVA)

    一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...

  9. dijikstra 旅行商问题_第27期:基于旅行商问题(TSP)的配送网络优化—R实现

    回国后,没有时间休息,一是工作不能耽误,二是很多杂乱的事情要处理,因此,公众号很久没有更新,实在抱歉! 本期的推文是关于旅行商问题(TSP)的配送网络优化,也是因为最近在指导学生参加省大学生现代物流设 ...

最新文章

  1. nero linux iso,NeroLINUX下载_NeroLINUX官方下载_NeroLINUX4.0.0.0-华军软件园
  2. 基于深度学习的低光照图像增强方法总结(2017-2019)| CSDN博文精选
  3. oracle 修改用户密码_干货!数据库安全之Oracle数据库安全加固
  4. python 自定义异常和主动抛出异常(raise)的操作
  5. bpsk信道编码matlab,信道编码-研究日记_3 10/14/2016
  6. tcp out of order解决_Java解决CAS机制中ABA问题的方案
  7. pandas错误之: in pandas._libs.hashtable.PyObjectHashTable.get_item
  8. solr学习篇(三) solr7.4 连接MySQL数据库
  9. iChart--地图显示人口统计
  10. C语言,有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中
  11. 笔试题————一套实用的渗透测试岗位面试题
  12. 「BZOJ4763」雪辉
  13. 外贸用什么邮箱好,如何选择一个好用的外贸企业邮箱
  14. 比尔盖茨小时候的故事
  15. 教你羊肉炒菠菜的做法
  16. 计算机组成原理7-主存储器—存储器与CPU的连接
  17. 百度传课html,百度传课电脑版
  18. python mysql连接池 知乎_使用python脚本部署mariadb主从架构
  19. Web直接打印走过的那些坑
  20. 本科男友吐槽研究生女友沉迷做实验,不爱打扮!网友:不看好恋人学历差距大......

热门文章

  1. 理清那么多个OO(面向对象)
  2. 如何在JavaScript中实现链接列表
  3. javascript函数式_JavaScript中的函数式编程—结合实际示例(第1部分)
  4. 当前路径_[JSP] 07 JSP 路径问题
  5. 线程组多次调用_详细分析 Java 中启动线程的正确和错误方式
  6. UI培训教程分享:APP启动页UI界面设计
  7. 【软件测试培训】了解jmeter分布式测试
  8. html中怎么隐藏复选框,隐藏复选框字段HTML
  9. Java基础学习总结(9)——this关键字
  10. Java基础学习总结(3)——抽象类