基于差分、粒子群算法下的TSP优化对比
TSP问题,即旅行商问题(Traveling Salesman Problem),是数学领域中的一个著名问题。以下是对TSP问题的详细解释:
一、问题定义
假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求所选的路径路程为所有路径中的最小值。
二、问题分类
TSP问题可大致分为对称TSP问题和非对称TSP问题。所谓对称指的是在模型中,城市u到城市v的距离与城市v到城市u的距离是一样的,其在图中的体现就是对称TSP问题的输入一般是无向图。而非对称TSP问题的输入往往是有向图。
三、求解方法
1. **暴力枚举**:通过穷举所有可能的路径来找到最短路径,但这种方法的时间复杂度极高,当城市数量较多时,计算量会呈指数级增长,因此在实际应用中并不可行。
2. **动态规划**:动态规划是解决TSP问题的一种有效方法。它通过将问题分解为更小的子问题,并存储子问题的解来避免重复计算。具体来说,可以定义一个状态dp[S][v],表示从顶点v出发,访问集合S中的所有顶点(不包括v),并最终回到起点的最短路径长度。通过逐步扩展已访问的顶点集合S,可以计算出dp[S][v]的值,并最终找到最短路径。动态规划方法的时间复杂度仍然较高,但相对于暴力枚举已经有了显著的降低。
3. **近似算法**:由于TSP问题是NP-hard的,不存在多项式时间的精确算法。因此,研究人员开始研究TSP问题的近似算法。在度量空间(即满足三角不等式的空间)下,存在多种近似算法,如Christofides算法、k-opt算法和Lin–Kernighan算法等。这些算法可以在较短的时间内找到一个近似最优解,虽然其解的质量可能略逊于精确算法,但在实际应用中通常已经足够好。
四、实际应用
TSP问题在多个领域都有广泛的应用,如物流配送、电路设计、基因测序等。在这些领域中,需要找到一条最短路径或最优路径来优化成本或提高效率。
五、具体实现
这里将介绍采用差分进化算法、粒子群算法进行处理TSP问题。
主要从计算距离和适应度函数优化来寻找最优的距离。
(一)差分进化算法(改进)
下面是差分进化算法处理优化过程:
%% 改进的差分进化算法
function [pop] = DE1(NP,D,pop,F0,CR,DM,G,Tmax,best,Xbest)
for i=1:NP
r1=1;r2=1;r3=1;%使得个体满足变异条件.此处与Java有点不一样,他是从1开始
while(r1==r2||r1==r3||r2==r3||r1==i||r2==i||r3==i)
r1=ceil(NP*rand(1)); %保持其中的r1,r2,r3互异,这样做的目的是为了防止种群的单一性
r2=ceil(NP*rand(1));
r3=ceil(NP*rand(1));
end
%% 变异操作
for j=1:D
if G<=(Tmax/2)
v(i,j)=pop(r1,j)+F0*(pop(r2,j)-pop(r3,j));
elseif G>(Tmax/2)
v(i,j)=pop(i,j)+F0*(pop(best,j)-pop(i,j))+F0*(pop(r1,j)-pop(r2,j));
end
end
%% 交叉
Z=randi([1,D],1,1);
r=rand;
for j = 1:D
if (r<=CR) || (j==Z)
u(i,j)=v(i,j);
else
u(i,j)=pop(i,j);
end
end
%% 选择
if PathLength(DM,u(i,:))<PathLength(DM,pop(i,:))
pop(i,:)=u(i,:);
end
end
for i=1:NP
if PathLength(DM,Xbest)>PathLength(DM,pop(i,:))
Xbest=pop(i,:);
best=i;
end
end
end
(二)粒子群算法(传统)
%% 粒子群算法
%------给定初始化条件----------------------------------------------
% c1学习因子1------c1,c2的取值通常在2左右
% c2学习因子2
% w惯性权重--------通常取[0,1]
% M最大迭代次数-----迭代次数根据自己的需要进行设定
% D搜索空间维数(未知数个数)-----
% N初始化群体个体数目---------通常来说对于种群数和个体数之间的关系并没有准确的一个比例,通常来说设置为N=[5D,10D],如果种群和个体数相差太多会影响收敛性
function y =PSO(NP,pop,DM,p,pg,v,y) %创建粒子群算法函数,可以直接调用
%% 初始化参数
c1=1.5;
c2=2.5;
w=0.5;
%% 更新种群
for i=1:NP %更新速度、位移
v(i,:)=w*v(i,:)+c1*rand*(y(i,:)-pop(i,:))+c2*rand*(pg-pop(i,:));
pop(i,:)=pop(i,:)+v(i,:); %更新之后的点
if PathLength(DM,pop(i,:))< p(i) %使用选择函数
p(i)= PathLength(DM,pop(i,:));
y(i,:)=pop(i,:);%更新个体极值
end
if p(i)< PathLength(DM,pg) %选择保存最优值
pg=y(i,:);
end
end
end
这其中涉及到最重要的处理过程就是PathLength函数,具体如下:
%% 计算各个体的路径长度
% 输入:
% D 两两城市之间的距离
% Chrom 个体的轨迹
function len=PathLength(D,Chrom)
[~,Chrom]=sort(Chrom,2,'ascend');
[~,col]=size(D);
NIND=size(Chrom,1);
len=zeros(NIND,1);
for i=1:NIND
p=[Chrom(i,:) Chrom(i,1)];
i1=p(1:end-1);
i2=p(2:end);
len(i,1)=sum(D((i1-1)*col+i2));
end
为了更好的对比算法之间的优势,将其进行封装对比,具体如下:
%% 差分进化算法解决TSP问题,用最短的距离走完所有的城市
clc
clear
close all
%% 初始化参数
F0=0.8; %变异因子
CR=0.2; %交叉概率
yita=0.99; %退火控制参数
T=0.01; %初始模拟温度
MaxGens=2000;%迭代次数
x_high=500;%上界
x_low=-500;%下界
%% 数据集1
% X =[16.47,96.10
% 16.47,94.44
% 20.09,92.54
% 22.39,93.37
% 25.23,97.24
% 22.00,96.05
% 20.47,97.02
% 17.20,96.29
% 16.30,97.38
% 14.05,98.12
% 16.53,97.38
% 21.52,95.59
% 19.41,97.13
% 20.09,92.55];
%% 数据集2
X = [1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;...
3238 1229;4196 1044;4312 790;4386 570;3007 1970;2562 1756;...
2788 1491;2381 1676;1332 695;3715 1678;3918 2179;4061 2370;...
3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;3507 2376;...
3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;...
2370 2975]; %31 个省会城市坐标
DM=Distanse(X);%距离计算
D=length(X);%数据集的维度
NP=8*D;%种群数
%% 初始化种群
pop=rand(NP,D)*(x_high-x_low)+x_low;
pop1=rand(NP,D)*(x_high-x_low)+x_low;
pop2=rand(NP,D)*(x_high-x_low)+x_low;
%% 适应度值
fit=PathLength(DM,pop);
fit1=PathLength(DM,pop1);
fit2=PathLength(DM,pop2);
%% 初次迭代值
trace(1)=min(fit);
trace1(1)=min(fit1);
trace2(1)=min(fit2);
%% 计算各个粒子的适应度,并初始化Pi和Pg(粒子群算法)
v=rand(NP,D)*(x_high-x_low)+x_low;
for i=1:NP
p(i)=PathLength(DM,pop2(i,:)); %计算初始粒子的适应度值
y(i,:)=pop2(i,:); %个体极值中的变量值等于粒子的初始值---为了后期进行保存全局最优值
end
pg=pop2(NP,:); %Pg为全局最优值---将初始位置的最后一列元素赋给全局最优值---目的在于保存全局最优值
for i=1:(NP-1)
if PathLength(DM,pop2(i,:)) <PathLength(DM,pg)
pg=pop2(i,:); %更新全局最优值,保存最优值
end
end
%% 差分进化(DE1)最好个体求解
Xbest=pop1(1,:);
for i=2:NP
if PathLength(DM,Xbest)>PathLength(DM,pop1(i,:))
Xbest=pop1(i,:);
best=i;
end
end
%% 主程序
for gen=1:MaxGens
%% 传统差分进化算法
pop = DE(NP,D,pop,F0,CR,DM);
%% 改进变异算子改进的差分进化算法(DE1)
[pop1] = DE1(NP,D,pop1,F0,CR,DM,gen,MaxGens,best,Xbest);
%pop1 = Metr_DE(NP,D,pop1,F0,CR,DM,yita,T);
%% 粒子群算法
pop2 = PSO(NP,pop2,DM,p,pg,v,y);
%% 寻找出最优路径
fit=PathLength(DM,pop);
fit1=PathLength(DM,pop1);
fit2=PathLength(DM,pop2);
[trace(gen+1),d]=min(fit);
[trace1(gen+1),d]=min(fit1);
[trace2(gen+1),d]=min(fit2);
tt=min(fit);
tt1=min(fit1);
tt2=min(fit2);
end
%% 可视化
disp(['传统差分下的最优距离:', num2str(tt)]);
disp(['改进变异算子的差分下的最优距离:', num2str(tt1)]);
disp(['粒子群下的最优距离:', num2str(tt2)]);
figure(1)
[~,pop(d,:)]=sort(pop(d,:),2,'ascend');
DrawPath(X,pop(d,:))
title('传统差分进化算法优化TSP的最优路径')
figure(2)
[~,pop1(d,:)]=sort(pop1(d,:),2,'ascend');
DrawPath(X,pop1(d,:))
title('改进变异算子的差分进化优化TSP的最优路径')
figure(3)
[~,pop2(d,:)]=sort(pop2(d,:),2,'ascend');
DrawPath(X,pop2(d,:))
title('粒子群算法优化TSP的最优路径')
figure(4);
plot(trace,'b-','linewidth',2);
hold on
plot(trace1,'r--','linewidth',2);
hold on
plot(trace2,'g--','linewidth',2);
title('各算法TSP最优化距离对比');
xlabel('迭代次数');
ylabel('最优距离');
legend('传统差分进化','改进变异算子的差分进化','粒子群算法');
从上可以看出,经过改进的差分进化算法有着明显的效果!