1 算法介绍
1.1 TSP介绍
“旅行商问题”(Traveling Salesman Problem,TSP)可简单描述为:一位销售商从n个城市中的某一城市出发,不重复地走完其余n-1个城市并回到原出发点,在所有可能路径中求出路径长度最短的一条。
旅行商的路线可以看作是对n城市所设计的一个环形,或者是对一列n个城市的排列。由于对n个城市所有可能的遍历数目可达(n-1)!个,因此解决这个问题需要O(n!)的计算时间。而由美国密执根大学的Holland教授发展起来的遗传算法,是一种求解问题的高效并行全局搜索方法,能够解决复杂的全局优化问题,解决TSP问题也成为遗传算法界的一个目标。
1.2 遗传算法求解tsp模型
巡回旅行商问题(TSP)是一个组合优化方面的问题,已经成为测试组合优化新算法的标准问题。应用遗传算法解决 TSP 问题,首先对访问城市序列进行排列组合的方法编码,这保证了每个城市经过且只经过一次。接着生成初始种群,并计算适应度函数,即计算遍历所有城市的距离。然后用最优保存法确定选择算子,以保证优秀个体直接复制到下一代。采用有序交叉和倒置变异法确定交叉算子和变异算子。
算法流程
旅行商问题的遗传算法实现
1.初始群体设定
一般都是随机生成一个规模为 N 的初始群体。在这里,我们定义一个s行t列的pop矩阵来表示群体,t 为城市个数 + 1,即 N + 1,s 为样本中个体数目。在本文探讨了 30 个城市的 TSP 问题,此时 t 取值 31,该矩阵中每一行的前 30 个元素表示经过的城市编号,最后一个元素表示适应度函数的取值,即每个个体所求的距离。
2.适应度函数的设计是根据个体适应值对其优劣判定的评价函数。在该问题中用距离的总和作为适应度函数,来衡量求解结果是否最优。
3.选择指以一定的概率从群体中选择优胜个体的操作,它是建立在群体中个体适应度评估基础上的。为了加快局部搜索的速度,在算法中采用最优保存策略的方法,即将群体中适应度最大的个体直接替换适应度最小的个体。它们不进行交叉和变异运算,而是直接复制到下一代,以免交叉和变异运算破坏种群中的优秀解答。
4.交叉算子是产生新个体的主要手段。它是指将个体进行两两配对,以交叉概率 Pc 将配对的父代个体的部分结构加以替换重组生成新个体的操作。本文中采用有序交叉法来实现。有序交叉法的步骤描述如下:
5.变异操作是以较小的概率 Pm 对群体中个体编码串上的某位或者某些位作变动,从而生成新的个体。本文中采用倒置变异法:假设当前个体 X为(1 3 7 4 8 0 5 9 6 2),如果当前随机概率值小于 Pm,则随机选择来自同一个体的两个点mutatepoint(1) 和 mutatepoint(2),然后倒置两点的中间部分,产生新的个体。例如,假设随机选择个体 X 的两个点“7”和“9”,则倒置该两个点的中间部分,即将“4805”变为“5084”,产生新的个体 X 为(1 3 7 5 0 8 4 9 6 2)。
6.终止条件为循环一定的代数。
1.3 模拟退火算法
模拟退火算法在处理全局优化、离散变量优化等困难问题中,具有传统优化算法无可比拟的优势。模拟退火算法的思想最早由Metorpolis等提出的。其出发点是基于物理中固体物质的退火过程与一般的组合优化问题之间的相似性。模拟退火法是一种通用的优化算法,其物理退火过程由以下三部分组成:
1)*加温过程:*其目的是增强粒子的热运动,使其偏离平衡位置。当温度足够高时,固体将熔为液体,从而消除系统原先存在的非均匀状态。
2)*等温过程:*对于与周围环境交换热量而温度不变的封闭系统,系统状态的自发变化总是朝自由能减少的方向进行,当自由能达到最小时,系统达到平衡状态。
3)*冷却过程:*使粒子热运动减弱,系统能量下降,得到晶体结构。其中,加温过程对应算法的设定初温,等温过程对应算法的Metropolis抽样过程,冷却过程对应控制参数的下降。这里能量的变化就是目标函数,我们要得到的最优解就是能量最低态。其中Metropolis准则是SA算法收敛于全局最优解的关键所在,Metropoli、准则以一定的概率接受恶化解,这样就使算法跳离局部最优的陷阱。
2 部分代码
function f = simulated_annealing(D, mute, MAX_ITER) % 模拟退火解决中国省会城市TSP问题的简单实现 % 包含台北,香港,澳门 %% 默认参数设置 clear; if ~exist('mute', 'var') mute = 0; % 是否显示各种提示信息 end if ~exist('MAX_ITER', 'var') MAX_ITER = 50; % 每个温度内的最大状态交换尝试次数 % 这个参数很玄乎没什么固定规律的样子 end if ~exist('D', 'var') data=xlsread('省会经纬坐标.xlsx'); C=data; D=zeros(35,35);% D为城市间的距离矩阵 % 形成两两之间对应的矩阵(对称阵,可以只看上三角或下三角) [LA1,LA2]=meshgrid(C(:,2)); [LO1,LO2]=meshgrid(C(:,1)); % 计算两两之间的距离,单位为公里 R = distance(LA1,LO1,LA2,LO2,almanac('earth','wgs84')); D = num2str(R,'%10.2f'); %disp(D); end %% 模拟退火算法参数设置 rng(0); n = size(D, 1); T_range_factor = exp(0:-0.1:-5); % 温度的范围系数 solution = [1, randperm(n-1) + 1]; % 生成一个解,假定从1开始 if ~mute fprintf('邻域内总共有%d个解。\n', numel(P)); end f = TSP_distance(D, solution); % 求出当前解的总距离 if ~mute disp('初始的路径为:'); disp(solution); disp('路径长度为:'); disp(f); end P = generate_neighbors(solution); % 生成初始解的邻域P TMAX = f; % 温度范围动态地随初始解的好坏而变化(初始解越差,要求探索的需求就越大) T_range = T_range_factor * TMAX; % 尽量保证开始的温度足够高 结束的足够低 first = zeros(1, MAX_ITER); final = zeros(1, MAX_ITER); for t = T_range % 外循环 for i = 1:MAX_ITER % 内循环 index = randi(numel(P), 1); % 产生一个1~|P|之间的随机整数 neighbor = P{index}; % 在P中随机取一个解 f_neighbor = TSP_distance(D, neighbor); % 计算这个解的距离 Pt = exp(-(f_neighbor - f)/t); % 转移概率 if Pt > 1, Pt = 1; end % 说明f_neighbor<f if Pt > rand f = f_neighbor; solution = neighbor; P = generate_neighbors(solution); end % 记录外循环第一轮的转移概率 if ~mute && t == T_range(1) first(i) = Pt; end % 记录外循环最后一轮的转移概率 if ~mute && t == T_range(end) final(i) = Pt; end end if ~mute && t == T_range(1) fprintf('初始温度下的转移概率中位数为%f\n', median(first)); end if ~mute && t == T_range(end) fprintf('最后温度下的转移概率中位数为%f\n', median(final)); end end if ~mute fprintf('最后搜索得到的最优路径为:\n'); disp(solution); disp('路径长度为:'); disp(f); end
3 仿真结果
4 参考文献
[1]谢胜利, 唐敏, 董金祥. 求解TSP问题的一种改进的遗传算法[J]. 计算机工程与应用, 2002, 38(008):58-60.
[2]文艺, and 潘大志. "用于求解TSP问题的改进遗传算法." 计算机科学 43.0z1(2016):90-92.