一、旅行商问题(Traveling Salesman Problem)介绍
旅行商问题描述如下:假设有若干个城市,且任何两个城市之间的距离是确定的,现有一个旅行商人要拜访这些城市,要求旅行商从某城市出发,必须经过每个城市,且每个城市只能拜访一次,最后要回到出发的城市,问如何确定一条路线使路径长度最短。
详细介绍见blog:LocalSearch之爬山算法
二、遗传算法(Genetic Algorithm)理论介绍
2.1 什么是遗传算法
遗传算法(Genetic Algorithm,GA)起源于对生物系统所进行的计算机模拟研究。它是一种基于自然选择和遗传变异等模仿自然界生物进化机制发展起来的全局性概率搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。与基于导数的解析方法和其他启发搜索方法一样,其在形式上也是一种迭代方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解,其最主要的特点体现在以下几个方面:
(1)遗传算法直接以适应度作为搜索信息,求解问题时,搜索过程不受优化函数连续性的约束,无须导数或其他辅助信息。
(2)遗传算法具有很高的并行性,可以同时搜索解空间的多个区域搜索信息,从而降低算法陷入局部最优解的可能性。
(3)遗传算法具有很强的鲁棒性,在待求解问题为非连续、多峰及有噪声的情况下,它能够以很大的可能性收敛到最优解或近似最优解。
(4)遗传算法具有较高的可扩充性,它易于与其他领域的知识或算法相结合来求解特定问题。
(5)遗传算法的基本思想简单,具有良好的可操作性和简单性。
2.2 遗传算法一般过程
GA算法的伪代码如下[1]:
注:t为种群的代数,P(t)为原始种群,P'(t) 为经过选择、交叉或变异后的子代种群。
伪代码的具体流程如下:
⑴随机生成初始种群P(0);
⑵定义种群代数t,初始值为0;
⑶当种群未达到停止标准时,重复以下步骤;
⑷对当前种群P(t)中的个体进行适应度评估,判断每个个体的好坏;
⑸从当前种群P(t)中选择适应度高的个体构成新的种群P'(t);
⑹对当前种群P'(t)进行交叉、变异等繁殖操作,来产生一群新的更适应环境的个体,形成新的种群,并评估个体的适应度;
⑺基于特定的替换策略来确定初代种群、及繁殖后的种群中的哪些个体能保留下来,并以此组建成新的子代种群;
⑻更新种群繁殖代数t;
⑼直到发现最佳个体或最佳群体后停止循环并输出结果。
图解如下:
从初始种群中选择N个个体构成父代种群,父代种群经过繁殖、交叉、变异产生子代,并将子代中的部分或全部个体替换父代中的个体后,组建出一个新的种群。就这样一代一代不断繁殖、进化,通过这一过程使后代种群比前代种群更加适应环境,末代种群中的最优个体经过解码,作为问题的最优解或近似最优解。
2.3 GA算法的基本组件或要素
⑴解的表示
在GA算法中,染色体对应的是数据或数组,通常由一维的串结构数据来表示。串上各个位置对应基因,而各位置上的值对应基因的取值。基因组成的串就是染色体,或者称为基因型个体(individuals)。一定数量的个体组成群体(population)。群体中个体的数目称为群体的大小(population size),也叫群体规模。
在GA算法中,无法直接处理问题空间的参数,只能处理以基因码串形式表示的个体。所以就要把解的参数形式转换为基因码串的表示形式,这一操作称为编码,实际操作中,二进制编码是最基本的编码方式。
⑵种群初始化
初始种群的好坏对于遗传算法计算结果的优劣和算法的效率有着重要影响。产生初始种群通常有两种方法:一种是完全随机的产生方法,它适用于对待求解问题的解无任何先验知识的情况;另一种是把某些先验知识转化为必须满足的一组要求,然后在满足这些要求的解中随机地选取。初始群体也称为进化的初始代,即第一代(first generation)。
⑶适应度函数
适应度函数也称评价函数,主要是通过个体特征从而判断个体的适应度,是根据目标函数确定的用于区分群体中个体好坏的标准。问题不同,适应度函数的确定标准也不同,对于函数优化问题可直接将目标函数本身作为适应度函数,而复杂系统的适应度函数一般不太直观,需要以目标函数为基础进一步构造。
⑷选择策略
选择是从种群中选出生命力强的染色体产生新种群的过程。依据每个染色体的适应度大小,适应度越大,被选中的概率就越大,其子孙在下一代产生的个数就越多。但适应度较差的个体也不会被完全丢弃,因为其可能会有一些不同的遗传物质,可以增加种群的多样性。常用的选择机制有:
①锦标赛选择 (Tournament selection)
如图,进行规模为3的锦标赛。从种群中随机挑选三个解,然后从选出的3个解中选择最佳解决方案。
②轮盘赌 (Roulette Wheel Selection)
计算每个个体的适应度占适应度总和的比例,并分布在一个圆盘内,旋转圆盘,每次旋转选择一个个体。
③随机遍历抽样 (Stochastic Universal Sampling)
同理,计算比例并分布,等间隔放置四个指针,旋转后选择四个个体(也有可能两个或以上的指针停在同一区域)。
⑸繁殖策略
繁殖策略主要包括交叉、变异两种方法,两者主要区别为交叉的作用对象通常是二元或多元,而变异是作用于单个个体的一元算子。
①交叉算子
交叉算子又称重组算子,当许多染色体相同或后代染色体与上一代没有多大差别时,可通过染色体重组来产生新一代染色体。交叉算子是GA算法区别于其他进化算法的独有特征。它是模仿自然界有性繁殖的基因过程,可以将原有的优良基因遗传到下一代种群中,生成新个体。
交叉率Pc指参加交叉运算的染色体个数占全体染色体总数的比例。Pc的最佳取值与群体大小、变异概率和选择过程有关,常用的比率在区间[0.45,0.95]内。
常用的交叉算子有以下三种:
a) 顺序交叉(Order crossover)
随机选取两个交叉点。对于父代1,复制两点之间的元素遗传给子代,并放在同一相对位置。对于父代2,从交叉点2向交叉点1依次填充,若该元素已在子代中存在则跳过,选择下一个元素;否则将其填充到交叉点2之后,直至所有元素都遗传给子代。
b) 部分映射交叉(Partially mapped crossover)
与顺序交叉一样,随机选择两个交叉点。从亲本1开始,在后代相同的绝对位置,复制两点之间的部分;往后看交叉点2后父代2的元素,是d,但D已经把b替换掉了,所以把b放在d的位置,其余元素同理。
c) 两点交叉(Two-point crossover)
随机选择两个交叉点。所选两点之外的父代元素继承至子代元素,其他元素按照它们在另一个父代元素中出现的顺序排列。
②变异算子
变异算子模拟自然界中生物进化过程中的基因突变现象,从而改变染色体的结构和性状。指将个体编码串中的某些基因位上的值用该基因位上的其他等位基因来替换,从而产生新的个体。例如,设染色体S=11001101,将其第三位上的0变为1,即S=11001101→11101101=S',S'也可以看做原染色体S的子代染色体。
常用的变异算子还是2opt、swap、insert等,类似Local Search的邻域搜索。
变异率Pm是指发生变异的基因位数所占全体染色体基因总位数的比例,取值范围一般为[0.001,0.01]。一些策略将变异概率初始化为1/k,其中k是决策变量的数量,也就是说,平均只有一个变量发生变异。
⑹替换策略
替换阶段涉及双亲和子代种群中幸存者的选择,由于种群数量是固定的,它允许根据给定的策略选择或丢弃个体。常用的替换机制有以下三种:
①世代(整体)替换(Generational replacement):更替将涉及整个种群,子代种群将系统地取代所有父代种群中的个体。
②稳态替换(Steady-state replacement):每一次算法结束只产生一个子代,并用其取代父代群体中最差的个体。
③精英保留策略:精英保留策略是介于这两种极端的替换策略之间的,主要思想是从父代种群中选择并保留n个适应度高的个体,从子代中选择并丢弃n个适应度差的个体,于是把父代的n个精英与子代的剩余个体组合为下一代新种群。
精英保留策略总是在父代和子代中选择最优秀的个体,这会导致更快的早熟收敛。所以有时选择坏的个体是必要的,避免早熟的同时增加多样性。
2.4 参数确定
GA算法中各个参数值的选择和设置对运行的结果和效果有较大影响,如交叉率和变异率虽然都有建议的取值范围,但具体取何值还需进一步确定;种群规模越大,所得解的质量会越好,但同时算法的运行时间也会相应增加,所以种群规模的具体数值要在解的质量和算法的搜索时间中找到一个平衡。
常用的两种确定参数值的方法有预实验和irace调参软件[2],详细步骤可见blog:LocalSearch之模拟退火算法5.1小节
三、遗传算法(Genetic Algorithm)代码/特殊函数介绍
3.1三个适应度算子
(1)Quality质量
适应度仅与解的质量相关。个体质量Quality与TSP距离Cost成反比,距离越大,质量越差,即适应度越小。
单以个体质量作为适应度函数,得到的结果可能过于集中。
(2)Diversity多样性
适应度仅与解的多样性相关。通过计算种群中每个个体间的汉明距离(hamming),判断种群多样性。
汉明距离表示两个(相同长度)字符串对应位置的不同字符的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。
个体多样性记为最近的nCloest个体的距离的均值,距离越大则多样性越大,适应度越大。但单纯用多样性作为适应度函数是不现实的,不能得到很好的结果。
(3)Quality_Diversity综合考虑质量和多样性
适应度与解的质量和解的多样性相关。计算个体质量并进行排名,质量越好(Quality值越大)则排名越高(rank_quality值越大),计算个体多样性并进行排名,多样性越大(Diversity值越大)则排名越高(rank_diversity值越大),个体ii适应度为rank_quality(ii) + (1-par.eliteNum/popSize) * rank_diversity(ii)。
解的质量越高、解的多样性越高,均使得解的适应度越好。
3.2SteadyStateLambda动态替换策略[3]
设置参数:动态种群大小popSizeLambda、种群规模popSize
选择子代种群中的最佳个体(Cost值最小)加入父代种群,下一代种群由上一代和子代的最佳个体构成,此时种群规模处于变动状态。当种群个体超出种群规模(popSize)的数量多于动态种群大小(popSizeLambda)时,则删除种群中的重复解(clone解)和劣解,将种群规模缩减至popSize。
四、用遗传算法解决TSP问题
4.1 TSP问题
(1) 解的表示方式:对城市进行编号,编号序列表示城市的访问顺序,不同的编号序列表示不同的解。
(2) 初始解的生成方式:随机生成编号序列
4.2 解决思路
(1) 设置参数:最大迭代次数maxIter、不改进迭代次数noIter、种群规模popSize、交叉概率crossoverProb、变异概率mutationProb
(2) 设置算子:选择算子、交叉算子、变异算子、适应度算子、替换策略
(3) 初始化种群P0,初始化popSize个个体,每个个体的解为随机序列
(4) 根据适应度算子,评估当前种群中个体的适应度
(5) 根据替换策略确定子代群体大小offspringSize
(6) 根据选择算子,从父代群体中选择个体,初始化子代种群
(7) 根据交叉概率,基于交叉算子对初始化的子代种群进行交叉,更新子代种群
(8) 根据变异概率,基于变异算子对初始化的子代种群进行变异,更新子代种群
(9) 进行种群管理,子代种群按替换策略替换父代种群
(10) 若种群中的最优个体(Cost最小)由于目前最优解(BestSol),则更新BestSol
(11) 若本次迭代较上次迭代未优化,则使迭代未改进次数(it2)加一
(12) 超过最大迭代次数(MaxIter),或超过不改进迭代次数(noIter)不改进,则停止迭代,得到的BestSol即为最优解
4.3代码实现(代码见文末链接)
本文借助Matlab,对TSP问题中经典的st70算例做了分析。参数设定最大迭代次数MaxIter=3000、不改进迭代次数noIter=1000、种群规模popSize=30、交叉概率crossoverProb=0.8、变异概率mutationProb=0.1。为保证结果可复现,采用函数rng确定随机种子。
运用不同算子,得到运行结果如下。其中替换策略为Elitism时,参数精英保留个数eliteNum=10,替换策略为SteadyStateLambda时,参数动态种群大小popSizeLambda=40。
随机种子rng(1):
随机种子rng(2):
从实验结果中可以看出,交叉算子PMX耗时明显大于其他算子;替换策略中精英保留策略得到的结果较好;只考虑种群多样性判断适应度得到结果较差,一般不采用该方法。
五、Memetic算法介绍
由于遗传算法(GA)的探索性较强,为增强其集中性,Memetic在GA的基础上加入了LocalSearch ,可以采用爬山算法、禁忌搜索、VND、VNS等LocalSearch算法,也可以用分支定界、Gurobi求解器或其他精确算法代替LocalSearch部分。但同时LocalSearch的引入会大大增加计算量,使耗时增加。
5.1 Memetic算法伪代码(和GA对比)
(1) 在初始化种群时,对初始种群的个体进行局部搜索
(2) 对父代交叉产生的子代个体进行局部搜索
(3) 对变异产生的子代个体进行局部搜索
5.2 Memetic算法实现
同样,基于Matlab使用Mematic算法解决TSP问题中st70算例。增加VND算法,邻域算子为2opt、swap、insert,邻近解的选择策略为bestImprove。
参数设定最大迭代次数为5000、不改进迭代次数为1000、种群规模为30,交叉概率Pc=0.8、变异概率Pm=0.1。其中替换策略为Elitism时,参数精英保留个数eliteNum=10;替换策略为SteadyStateLambda时,参数动态种群大小popSizeLambda=40;适应度算子计算多样性时,需要的参数nClosest = 5。
为保证结果可复现,以rng函数确定随机种子,并运用不同算子,得到运行结果如下:
由结果可知,使用Mematic算法在各种组合条件下均能得到不错的解。替换策略为Elitism时,一般在100次迭代以内就能得到最优解;替换策略为SteadyStateLambda、SteadyState时,300次迭代以内就能得到最优解。
虽然只有在满足终止条件时程序才会停止运行,需要花费的时间特别长,但就以本次实验来看,300次迭代以内就能得到最优解,总的来说还是可以接受的。
六、GA算法与Memetic算法对比
由图可知,在各策略、算子、参数一致的情况下,第一张图为GA算法的运行结果,5000次迭代完后全局最优解为1190;第二张图为Memetic算法的运行结果,第10次迭代时就已经得到全局最优解675。
可见同等条件下,Memetic算法得到的结果更好,但程序运行耗时却远远大于GA算法。这是由于Memetic中引入了LocalSearch机制,增强了算法的Exploitation能力,提升了算法效果,LocalSearch未做限制,耗时大幅增加。如何提升LocalSearch运算效果同时保证质量提升效果是运用Memetic的关键。
常用减少LocalSearch耗时的方法有缩小邻域搜索空间(仅对最近K个最优希望的邻域空间搜索)、记录搜索历史避免重复无效搜索(之前搜索过证实无效,不再重复搜索)等策略。
七、小结
本文介绍了遗传算法和Memetic算法的基本原理,并结合实例,在Matlab中运用遗传算法解决TSP问题,展示了不同选择和替换策略、不同交叉和变异算子、不同适应度函数和参数等对于实验结果的影响,并对比分析了两种算法的优缺点。
【囿于作者的学术水平,本文的诸多表述或许不够严谨,用途仅限于优化算法入门者的非正式学术交流,不足之处还望各位读者指正。】
参考文献:
[1] Monmarche N . Metaheuristics - From Design to Implementation,2013.
[2] irace官网链接:https://iridia.ulb.ac.be/irace/
[3]Diego Cattaruzza, Nabil Absi, Dominique Feillet, Thibaut Vidal.Hybrid Genetic Search for the CVRP:Open-Source Implementation and SWAP* Neighborhood[J].COMPUTERS & OPERATIONS RESEARCH,2022.
相关资料:
作者:丁子千 刘梦迪
校对:陈慧敏