遗传算法解决TSP问题MATLAB实现(详细)

本文共2105个字,预计阅读时间需要7分钟。

问题定义:巡回旅行商问题

给定一组n个城市和俩俩之间的直达距离,寻找一条闭合的旅程,使得每个城市刚好经过一次且总的旅行距离最短。

TSP问题也称为货郎担问题,是一个古老的问题。最早可以追溯到1759年Euler提出的骑士旅行的问题。1948年,由美国兰德公司推动,TSP成为近代组合优化领域的典型难题。

TSP是一个具有广泛的应用背景和重要理论价值的组合优化问题。 近年来,有很多解决该问题的较为有效的算法不断被推出,例如Hopfield神经网络方法,模拟退火方法以及遗传算法方法等。

TSP搜索空间随着城市数n的增加而增大,所有的旅程路线组合数为(n-1)!/2。在如此庞大的搜索空间中寻求最优解,对于常规方法和现有的计算工具而言,存在着诸多计算困难。借助遗传算法的搜索能力解决TSP问题,是很自然的想法。

基本遗传算法可定义为一个8元组:

  • (SGA)=(C,E,P0,M,Φ,Г,Ψ,Τ)
  • C ——个体的编码方法,SGA使用固定长度二进制符号串编码方法;
  • E ——个体的适应度评价函数;
  • P0——初始群体;
  • M ——群体大小,一般取20—100;
  • Ф——选择算子,SGA使用比例算子;
  • Г——交叉算子,SGA使用单点交叉算子;
  • Ψ——变异算子,SGA使用基本位变异算子;
  • Т——算法终止条件,一般终止进化代数为100—500;
  • 问题的表示
    • 对于一个实际的待优化问题,首先需要将其表示为适合于遗传算法操作的形式。用遗传算法解决TSP,一个旅程很自然的表示为n个城市的排列,但基于二进制编码的交叉和变异操作不能适用。
    • 路径表示是表示旅程对应的基因编码的最自然,最简单的表示方法。它在编码,解码,存储过程中相对容易理解和实现。例如:旅程(5-1-7-8-9-4-6-2-3)可以直接表示为(5 1 7 8 9 4 6 2 3)
  • 产生初始种群

一是完全随机产生,它适合于对问题的解无任何先验知识的情况。随机性较强,因而也较公正

二是某些先验知识可转变为必须满足的一组要求,然后在满足这些要求的解中在随机地选取样本。这样选择初始种群可使遗传算法更快的达到最优解。种群有一定的目标性和代表性,但取例不如完全随机的广泛,而且先验知识是否可靠也是一个问题

  • 适应度函数

遗传算法在进化搜索中基本不利用外部信息,仅以适应度函数为依据,利用种群中每个个体的适应度值来进行搜索。TSP的目标是路径总长度为最短,路径总长度的倒数就可以为TSP的适应度函数:

  • 选择

一般地说,选择将使适应度较大(优良)个体有较大的存在机会,而适应度较小(低劣)的个体继续存在的机会也较小。简单遗传算法采用赌轮选择机制,令Σfi表示群体的适应度值之总和,fi表示种群中第i个染色体的适应度值,它产生后代的能力正好为其适应度值所占份额fi/Σfi。

  • 交叉

基于路径表示的编码方法,要求一个个体的染色体编码中不允许有重复的基因码,也就是说要满足任意一个城市必须而且只能访问一次的约束。基本遗传算法的交叉操作生成的个体一般不能满足这一约束条件。

部分匹配交叉操作要求随机选取两个交叉点,以便确定一个匹配段,根据两个父个体中两个交叉点之间的中间段给出的映射关系生成两个子个体。

  • 变异

遗传算法解决TSP 问题基于二进值编码的变异操作不能适用,不能够由简单的变量的翻转来实现

在TSP问题中个体的编码是一批城市的序列,随机的在这个序列抽取两个城市,然后交换他们的位置。这样就实现了个体编码的变异,算法如下:

  1. 产生两个0到1之间的随机实数;
  2. 将这两个随机实数转化为0到n(城市数)-1之间的随机整数;
  3. 将这两个随机整数指代的城市进行交换;

流程图

代码

主函数代码:

calculateDistance.m

crossover.m

fitness.m

mutate.m

paint.m

Read.m

结果

测试数据:

初始状态:

最终状态:

收敛曲线图:

可以看到,当城市数量适中时,迭代500次最短路径长度有收敛的趋势。

当城市数目较多时

迭代500次,仍然不收敛,可能的问题是陷入了局部最优解。

总结与观点

  • 难点是交叉算法的设计,由于TSP问题和一般的NP问题不一样,每个个体的每个维度具有唯一性,因此在交叉的时候要注意不能有重复的值。本次实验采用的是部分匹配交叉,先从第一个父代选出一个偏移量,从偏移量后的部分点加入到子代,接下来从第二个父代选择第一代没有选择的部分点移到子代中。
  • 当城市数量较多时,大于50个城市,迭代多次,GA仍然不收敛,可能的问题是陷入了局部最优解,因此对GA算法进行改进怡跳出局部最优解,可以采用类似于PSO或者蚁群算法的思想。

数据集下载

https://github.com/xyjigsaw/Dataset

113 位极客在 “遗传算法解决TSP问题MATLAB实现(详细)” 留下足迹

  1. 为什么适应度计算的时候不是用总路径长度的倒数,是为了标准化一下吗?

      • 感觉这个选择和网上看的轮盘赌选择算法不太一样,这个是分两次随机的从种群中选择四个染色体作候选,然后选这几个中的最好的作为父代,来交叉产生下一个子代,感觉有点像变化后的贪心,轮盘赌的话不是应该根据累计的概率选吗

  2. 请问一下,就是嗯我是刚接触MATLAB的,感觉这个题跟我碰到的是差不多的给出来了30个点的经纬度从第一个点出发每个点都要遍历回到原点求最短路径不太会改

  3. up请问怎么固定一个终点让其余随机点走完最后都往终点走,还有就是你的这个是随机起点跟终点吗

    • 这个代码可以随机起点也可以读取文件。如果要固定终点可以将编码的最后一位写死。

  4. TSP问题不是要求最后结果是闭合路径么,大神你的这个程序能不能针对这个问题稍微调整一下啊

  5. 错误使用 fgets
    文件标识符无效。使用 fopen 生成有效的文件标识符。

    出错 fgetl (line 32)
    [tline,lt] = fgets(fid);

    出错 Read (line 5)
    tline = fgetl(fid);

    出错 main (line 5)
    [cityNum,cities] = Read(‘dsj1000.tsp’);
    新手不知道咋弄

  6. 我用了你的代码为啥他把所有城市全画出来了,我是新手小白,想问下你哪个请输入城市数量50怎么来的

  7. 这个代码里面除了种群数量和迭代次数需要自己设置一下以外,别的代码还需要改吗?我的运行结果收敛不到最优值唉

  8. 我用了你的代码为啥他把所有城市全画出来了,我是新手小白,想问下你哪个请输入城市数量50怎么来的

  9. 错误使用 randi
    第一个输入必须为正标量整数值 IMAX,或者为两个整数值 [IMIN IMAX] (IMIN 小于或等于 IMAX)。

    出错 crossover (line 11)
    offset = randi(setSize);

    请问这是什么问题啊

  10. 出错 fgetl (line 32)
    [tline,lt] = fgets(fid);

    出错 Read (line 5)
    tline = fgetl(fid);

    请问一下为什么会出现这两个错误啊

评论