Hamilton回路问题求解
本文分别以最近邻点法和最近插入法求解TSP问题中的Hamilton回路问题。用以下例题作为求解案例
V1 | V2 | V3 | V4 | V5 | V6 | |
---|---|---|---|---|---|---|
V1 | 0 | 10 | 6 | 8 | 7 | 15 |
V2 | 10 | 0 | 5 | 20 | 15 | 16 |
V3 | 6 | 5 | 0 | 14 | 7 | 8 |
V4 | 8 | 20 | 14 | 0 | 4 | 12 |
V5 | 7 | 15 | 7 | 4 | 0 | 6 |
V6 | 15 | 16 | 8 | 12 | 6 | 0 |
最近邻点法
最近邻点法的主要逻辑是通过寻找离当前顶点最近的顶点来寻找回来,这样的计算方式比较简便,但是很多情况下只能找到近似解,找不到最优解。
step1.从网络中找一个点作为起点
step2.从剩下的点中找一个离上一个点最近的点加入
step3.重复step2
step4.将最后加入的点与起点连接。这样就构成了一个回路。
Matlab代码如下:
%% 最近邻点法求解Hamilton回路
clc;clear all;close all;
%% 参数初始化
Start=1; %默认取第一个点作为起点
%初始化邻接矩阵
E=[inf 10 6 8 7 15
10 inf 5 20 15 16
6 5 inf 14 7 8
8 20 14 inf 4 12
7 15 7 4 inf 6
15 16 8 12 6 inf];
%顶点集长度
PointNum=size(E,1);
% 顶点集
V=linspace(1,PointNum,PointNum);
%Hamilton回路解集
HamSolve=[];
%Hamilton回路长度
HamLength=0;
%% 最近邻点法迭代过程
%将起点加入回路解集
HamSolve=[HamSolve,Start];
%将起点从顶点集中去掉
V=setdiff(V,HamSolve);
%当前点
BetweenPoint=Start;
while ~isempty(V)
%找到离起点最近的点
VWeight=min(E(BetweenPoint,V));
Next=find(E(BetweenPoint,:)==VWeight);
%将离起点最近的点加入解集
HamSolve=[HamSolve,Next];
%将找到的点从顶点集中去掉
V=setdiff(V,Next);
%计算Hamilton回路长度
HamLength=HamLength+VWeight;
%将当前点修改为下一个点
BetweenPoint=Next;
end
%将起点加入
HamSolve=[HamSolve,Start]
%计算最后的回路长度
HamLength=HamLength+E(Next,Start)
求解结果:
最近插入法
最近插入法(Nearest Insertion)是Rosenkrantz和Stearns等人在1977年提出的另一种解决TSP问题的算法,它比最近邻点法复杂,但可得到相对满意的解。
%% 最近插入法求解Hamilton回路
clc;clear all;close all;
%% 初始化参数
Start=1; %默认取第一个点作为起点
%初始化邻接矩阵
E=[inf 10 6 8 7 15
10 inf 5 20 15 16
6 5 inf 14 7 8
8 20 14 inf 4 12
7 15 7 4 inf 6
15 16 8 12 6 inf];
%顶点集长度
PointNum=size(E,1);
% 顶点集
V=linspace(1,PointNum,PointNum);
%Hamilton回路
HamSolve=[];
%Hamilton回路长度
HamLength=0;
%% 最近插入法迭代过程
%将起点和终点加入回路解集
HamSolve=[HamSolve,Start,Start];
%将起点从顶点集中去掉
V=setdiff(V,HamSolve);
%当前点
BetweenPoint=Start;
%找到离起点最近的点
VWeight=min(E(BetweenPoint,V));
Next=find(E(BetweenPoint,:)==VWeight);
%Hamilton回路
HamSolve=[HamSolve(1),Next,HamSolve(end)];
%将找到的点从顶点集中去掉
V=setdiff(V,Next);
%计算Hamilton回路长度
HamLength=HamLength+VWeight+E(Next,Start);
%将当前点修改为下一个点
BetweenPoint=Next;
while ~isempty(V)
%Hamilton回路解集
HamPoint=unique(HamSolve);
%找到里当前子回路中顶点最近的顶点
NearestPoint=0;
NearWeight=zeros(1,length(HamPoint));
NearPoint=zeros(1,length(HamPoint));
for Point=1:length(HamPoint)
NearWeight(Point)=min(E(HamPoint(Point),V));
NearPoint(Point)=find(E(HamPoint(Point),:)==NearWeight(Point),1);
end
NearestPoint=NearPoint(find(NearWeight==min(NearWeight)));
%计算回路增量
HamIncrement=zeros(1,length(HamSolve)-1);
for PoinInc=1:(length(HamSolve)-1)
HamIncrement(PoinInc)=E(HamSolve(PoinInc),NearestPoint(1))+E(NearestPoint(1),HamSolve(PoinInc+1))-E(HamSolve(PoinInc),HamSolve(PoinInc+1));
end
[MinHamIncrement,InsertPoint]=min(HamIncrement);
%将点插入Hamilton回路
HamSolve=[HamSolve(1:InsertPoint),NearestPoint(1),HamSolve(InsertPoint+1:end)];
%计算Hamilton回路长度
HamLength=HamLength+MinHamIncrement;
%将已插入的点去除
V=setdiff(V,NearestPoint(1));
end
HamSolve
HamLength
求解结果: