一、问题描述

旅行商问题(TSP)解决的是,假设有一个人要拜访N个城市,要求他从一个城市出发,每个城市都要拜访一次,最后再回到最初的城市,保证所选择的路径长度最短。这是一个典型的NP难问题。用数学的方式表示,其目标函数如下所示:

其中表示城市到城市的距离。

二、算法介绍

1.遗传算法

遗传算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,通过模拟自然进化选择的过程搜索最优解并进行保留。遗传算法是从代表问题可能潜在的解集的一个种群开始的,而一个种群则由经过基因编码的一定数目的个体组成。每个个体实际上是染色体带有特征的实体。染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现是某种基因组合,它决定了个体的形状的外部表现。因此,在一开始需要实现从表现型到基因型的映射即编码工作。由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码,初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代演化产生出越来越好的近似解,在每一代,根据问题域中个体的适应度大小选择个体,并借助于自然遗传学的遗传算子进行组合交叉和变异,产生出代表新的解集的种群。这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码,可以作为问题近似最优解。

2.基本概念

  • 种群:不同生物个体形成的种群,生物的进化以种群的形式进行,这样的群体称为种群;
  • 个体:组成种群的单个生物;
  • 基因:带有遗传信息的DNA片段,在遗传算法中用编码的方式来体现;
  • 适应度:表示某一个体对环境的适应能力,也表示该个体繁殖后代的能力,适应度越强,后代存活概率越大,在遗传算法中会通过一个映射函数进行量化处理;
  • 遗传:通过繁殖过程,自带将从父母双方各获取一部分基因,形成新的自己的基因,这个过程中会发生基因的复制、交叉,也会以较低的概率发生基因突变,在遗传算法中会通过编码后的基因,依据交叉算子、变异算子来进行处理,得到新的基因编码,来模拟遗传的过程。
  • 自然选择:环境适应度高的个体参与繁殖的机会比较多,相应的后代会越来越多,而适应度较低的个体繁殖的机会比较少,后代就会越来越少,在遗传算法中通过选择算子对适应度较高的个体进行选择,来模拟自然选择的过程。

3.基本步骤

  1. 种群初始化:根据问题特征设计合适的初始化操作(初始化操作应尽量简单,时间复杂度不易过高)对种群中的N个个体进行初始化操作;
  2. 个体评价:根据优化的目标函数计算种群中个体的适应值;
  3. 迭代设置:设置种群最大迭代次数,并令当前迭代次数为1;
  4. 个体选择:设计合适的选择算子来对种群个体进行选择,被选择的个体将进入交配池中组成父代种群,用于交叉变换以产生新的个体。选择策略要基于个体适应值来进行,个体适应值在目标适应值内被选择的概率大一些。常用的选择策略有轮盘赌选择,锦标赛选择等;
  5. 交叉算子:根据交叉概率(预先指定,一般为0.9)来判断父代个体是否需要进行交叉操作。交叉算子要根据被优化问题的特性来设计,它是整个遗传算法的核心,它被设计的好坏将直接决定整个算法性能的优劣;
  6. 变异算子:根据变异概率(预先指定,一般为0.1)来判断父代个体是否需要进行变异操作。变异算子的主要作用是保持种群的多样性,防止种群陷入局部最优,所以其一般设计为一种随机变换。

通过交叉变异操作以后父代种群生成了新的子代种群,令种群迭代次数,进行下一轮的迭代操作,直至迭代次数达到最大的迭代次数。在进行完一轮“遗传变异”之后,我们用适应度函数对这些新的后代进行验证,如果函数判定他们适应度足够,那么就会用它们从总体替代掉那些适应度不够的“染色体”,当进行X次迭代之后,或者达到事前定义的进化次数,再或者其适应度函数达到了预先定义的值等条件,则终止循环。此时求得的值作为问题的近似最优解。

三、实例

城市坐标为A(81,8),B(93,37),C(85,45),D(75,36),E(60,55),F(70,57),G(86,80),H(89,75),I(73,75),J(69,69),以城市A为起点,通过遗传算法求得一次性经过所有城市的路径中总里程最短的路径。

建立城市坐标数据集data.txt文件

81    8
93    37
85    45
75    36
60    55
70    57
86    80
89    75
73    75
69    69

主程序

clear;clc;
% 输入数据
vertexs=importdata('data.txt');          %城市坐标
n=length(vertexs);                        %城市数目
dist=zeros(n);                            %城市距离矩阵
for i = 1:nfor j = 1:ndist(i,j)=distance(vertexs(i,:),vertexs(j,:));end
end
% 遗传算法参数设置
NIND=50;                        %种群大小
MAXGEN=150;                     %迭代次数
Pm=0.9;                         %交叉概率
Pc=0.1;                         %变异概率
pSwap=0.2;                      %选择交换结构的概率
pReversion=0.5;                 %选择逆转结构的概率
pInsertion=0.3;                 %选择插入结构的概率
N=n;                            %染色体长度=城市数目
% 种群初始化
Chrom=InitPop(NIND,N);
% 优化
gen=1;                          %计数器
bestChrom=Chrom(1,:);           %初始全局最优个体
bestL=RouteLength(bestChrom,dist);%初始全局最优个体的总距离
BestChrom=zeros(MAXGEN,N);      %记录每次迭代过程中全局最优个体
BestL=zeros(MAXGEN,1);          %记录每次迭代过程中全局最优个体的总距离
while gen<=MAXGENSelCh=BinaryTourment_Select(Chrom,dist);            %二元锦标赛选择          SelCh=Recombin(SelCh,Pm);                           %OX交叉SelCh=Mutate(SelCh,Pc,pSwap,pReversion,pInsertion); %变异Chrom=SelCh;                                        %将Chrom更新为SelChObj=ObjFunction(Chrom,dist);                        %计算当前代所有个体总距离[minObj,minIndex]=min(Obj);                         %找出当前代中最优个体if minObj<=bestL                                    %将当前代中最优个体与全局最优个体进行比较,如果当前代最优个体更好,则将全局最优个体进行替换bestChrom=Chrom(minIndex,:); bestL=minObj;endBestChrom(gen,:)=bestChrom;                         %记录每一代全局最优个体,及其总距离BestL(gen,:)=bestL;disp(['第' num2str(gen) '次迭代:全局最优路线总距离 = ' num2str(bestL)]); %显示外层循环每次迭代的信全局最优路线的总距离figure(1);                                          %画出每次迭代的全局最优路线图PlotRoute(bestChrom,vertexs(:,1),vertexs(:,2))pause(0.01);gen=gen+1;    %计数器加1
end
figure;                                                 % 打印每次迭代的全局最优个体的总距离变化趋势图
plot(BestL,'LineWidth',1);
title('优化过程')
xlabel('迭代次数');
ylabel('总距离');

距离函数

function dist = distance(a,b)
%a          第一个城市坐标
%b          第二个城市坐标
%dist       两个城市之间距离x = (a(1)-b(1))^2;y = (a(2)-b(2))^2;dist = (x+y)^(1/2);
end
function Dist=ObjFunction(Chrom,dist)
%Chrom           种群
%dist            距离矩阵
%Dist            每个个体的目标函数值,即每个个体的总距离NIND=size(Chrom,1);                     %种群大小Dist=zeros(NIND,1);                      %目标函数初始化为0for i=1:NINDroute=Chrom(i,:);                   %当前个体Dist(i,1)=RouteLength(route,dist);   %计算当前个体的总距离end
end
function L=RouteLength(route,dist)
%route               路线
%dist                距离矩阵
%L                   该路线总距离n=length(route);route=[route route(1)];L=0;for k=1:n i=route(k);j=route(k+1); L=L+dist(i,j); end
end

种群初始化函数

function Chrom=InitPop(NIND,N)
%种群初始化
%NIND        种群大小
%N           染色体长度
%Chrom       随机生成的初始种群Chrom=zeros(NIND,N);                %种群初始化为NIND行N列的零矩阵for i=1:NINDChrom(i,:)=randperm(N);         %每个个体为1~N的随机排列end
end

适应度函数

function FitnV=Fitness(Obj)
%适应度函数,总距离的倒数
%输入Obj:     每个个体的总距离
%输出FitnV:   每个个体的适应度值,即总距离的倒数FitnV=1./Obj;
end

选择函数

function Selch=BinaryTourment_Select(Chrom,dist)
%Chrom           种群
%dist            距离矩阵
%Selch           二元锦标赛选择出的个体Obj=ObjFunction(Chrom,dist);            %计算种群目标函数值,即每个个体的总距离FitnV=Fitness(Obj);                     %计算每个个体的适应度值,即总距离的倒数[NIND,N]=size(Chrom);                   %NIND-种群个数、N-种群长度Selch=zeros(NIND,N);                    %初始化二元锦标赛选择出的个体for i=1:NINDR=randperm(NIND);                   %生成一个1~NIND的随机排列index1=R(1);                        %第一个比较的个体序号index2=R(2);                        %第二个比较的个体序号fit1=FitnV(index1,:);               %第一个比较的个体的适应度值(适应度值越大,说明个体质量越高)fit2=FitnV(index2,:);               %第二个比较的个体的适应度值%如果个体1的适应度值 大于等于 个体2的适应度值,则将个体1作为第i选择出的个体if fit1>=fit2Selch(i,:)=Chrom(index1,:);else%如果个体1的适应度值 小于 个体2的适应度值,则将个体2作为第i选择出的个体Selch(i,:)=Chrom(index2,:);endend
end

遗传因子交叉函数

function SelCh=Recombin(SelCh,Pc)
% 交叉操作
%SelCh    被选择的个体
%Pc       交叉概率
% SelCh   交叉后的个体NSel=size(SelCh,1);for i=1:2:NSel-mod(NSel,2)if Pc>=rand %交叉概率Pc[SelCh(i,:),SelCh(i+1,:)]=OX(SelCh(i,:),SelCh(i+1,:));endend
end
function [a,b]=OX(a,b)
%输入:a和b为两个待交叉的个体
%输出:a和b为交叉后得到的两个个体L=length(a);while 1r1=randsrc(1,1,[1:L]);r2=randsrc(1,1,[1:L]);if r1~=r2s=min([r1,r2]);e=max([r1,r2]);a0=[b(s:e),a];b0=[a(s:e),b];for i=1:length(a0)aindex=find(a0==a0(i));bindex=find(b0==b0(i));if length(aindex)>1a0(aindex(2))=[];endif length(bindex)>1b0(bindex(2))=[];endif i==length(a)breakendenda=a0;b=b0;breakendend
end

遗传因子变异函数

function SelCh=Mutate(SelCh,Pm,pSwap,pReversion,pInsertion)
% 变异操作
%SelCh           被选择的个体
%Pm              变异概率
%pSwap           选择交换结构的概率
%pReversion      选择逆转结构的概率
%pInsertion      选择插入结构的概率
%SelCh           变异后的个体NSel=size(SelCh,1);for i=1:NSelif Pm>=randindex=Roulette(pSwap,pReversion,pInsertion);route1=SelCh(i,:);if index==1                %交换结构route2=Swap(route1);elseif index==2            %逆转结构route2=Reversion(route1);else                       %插入结构route2=Insertion(route1);endSelCh(i,:)=route2;endend
end

在变异情况下发生交换、逆转、插入变异的概率选择函数

function index=Roulette(pSwap,pReversion,pInsertion)
%pSwap           选择交换结构的概率
%pReversion      选择逆转结构的概率
%pInsertion      选择插入结构的概率
%index           最终选择的邻域结构p=[pSwap pReversion pInsertion];r=rand;c=cumsum(p);index=find(r<=c,1,'first');
end

遗传因子交换结构函数

function route2=Swap(route1)
%交换操作
%route1          原路线1
%route2          经过交换结构变换后的路线2n=length(route1);seq=randperm(n);I=seq(1:2);i1=I(1);i2=I(2);route2=route1;route2([i1 i2])=route1([i2 i1]);
end

遗传因子逆转结构函数

function route2=Reversion(route1)
%逆转变换
%route1          路线1
%route2          经过逆转结构变换后的路线2n=length(route1);seq=randperm(n);I=seq(1:2);i1=min(I);i2=max(I);route2=route1;route2(i1:i2)=route1(i2:-1:i1);
end

遗传因子插入结构函数

function route2=Insertion(route1)
%插入变换
%route1          路线1
%route2          经过插入结构变换后的路线2n=length(route1);seq=randperm(n);I=seq(1:2);i1=I(1);i2=I(2);if i1<i2route2=route1([1:i1-1 i1+1:i2 i1 i2+1:end]);elseroute2=route1([1:i2 i1 i2+1:i1-1 i1+1:end]);end
end

绘图函数

function PlotRoute(route,x,y)
%route           路线
%x,y             x,y坐标route=[route route(1)];plot(x(route),y(route),'k-o','MarkerSize',10,'MarkerFaceColor','w','LineWidth',1.5);xlabel('x');ylabel('y');
end

最终运行结果如下所示:

迭代过程如下所示:

最终的最优路径为A-D-E-F-J-I-G-H-C-B-A,最优值为175.0171。

遗传算法求解TSP问题(matlab实现)相关推荐

  1. 【老生谈算法】matlab实现遗传算法求解TSP问题——TSP问题

    遗传算法求解TSP问题MATLAB实现 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]遗传算法求解TSP问题MATLAB实现 ...

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

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

  3. 【Matlab】 遗传算法求解TSP问题

    [Matlab] 遗传算法求解TSP问题 文章目录 [Matlab] 遗传算法求解TSP问题 前言 一.问题描述 二.实验设计 1.问题案例 2.读入数据 3.适应度计算 4. 选择子代 5. 结果输 ...

  4. 人工智能导论——遗传算法求解TSP问题实验

    一.实验目的: 熟悉和掌握遗传算法的原理.流程和编码策略,并利用遗传算法求解组合优化问题,理解求解TSP问题的流程并测试主要参数对结果的影响. 二.实验原理: 旅行商问题,即TSP问题(Traveli ...

  5. 局部搜索、模拟退火和遗传算法求解TSP问题

    模拟退火和遗传算法求解TSP问题 源代码传送门:GITHUB 数据传送门:TSPLIB 文章目录 模拟退火和遗传算法求解TSP问题 摘要 1 导言 1.1 问题重述 1.2 TSP问题选择 1.3 思 ...

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

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

  7. 【运筹优化】GA遗传算法求解TSP问题(Java实现)

    文章目录 代码 Genome基因类 GeneticAlgorithm_TSP遗传算法类 运行结果 代码 Genome基因类 import lombok.Data; import lombok.NoAr ...

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

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

  9. ga tsp matlab,遗传算法(GA)求解TSP问题MATLAB程序

    本程序求解常见的组合优化问题TSP问题,如果仅仅是用一个程序去求解一个优化问题,显然这样的工作意义并不大.主要是因为求解的好坏往往是很难评价的,另外尤其对于遗传算法来说,遗传算法交叉 变异方法不同,交 ...

  10. 【人工智能导论】遗传算法求解TSP问题(含源码github)

    源程序:Github链接 Symmetric traveling salesman problem (TSP) Given a set of n nodes and distances for eac ...

最新文章

  1. 开发者关心的十个数据库技术问题
  2. HTTP协议无状态中的 状态 到底指的是什么?
  3. HTML5的data-*自定义属性
  4. 常见mysql性能优化方法
  5. ajax mysql项目 react_React16时代,该用什么姿势写 React ?
  6. (三)HTML 规范
  7. phpMailer 配置 企业邮局 163
  8. Python清华源或豆瓣源安装包
  9. Linux/Ubuntu 单机配置Hbase
  10. 交出娃哈哈,宗庆后还是不放心?
  11. 数据库之间的远程操作
  12. 修改cas登陆页面-服务器端
  13. strcmp()函数用法及其详解
  14. linux for java programer
  15. 58域内路由和域间路由
  16. 无法启动此程序因为计算机中丢失vcruntime140_1.dll
  17. python时间差计算器时分秒_python 实现日期计算器
  18. ERROR 1819 (HY000) Your password does not satisfy the current policy requirements
  19. Codeforces Round #451 (Div. 2)
  20. python的udp攻击

热门文章

  1. sentinel限流入门
  2. 生信步骤|转录组测序上游分析:hisat2+samtools+stringtie
  3. 数据库的概念设计与逻辑设计
  4. FLASHBACK TABLE用法介绍
  5. 送20本豆瓣高分技术图书!
  6. Android 版本号---版本名
  7. 用计算机计算告白密码,阿拉伯数字高级表白密码 很火的表白密码
  8. Binding的学习与使用
  9. NavigationController 常用方法归总
  10. 云原生Tekton之触发器Trigger