一. 旅行商问题描述
一位商人要到若干城市去推销商品,已知城市个数和各城市间的路程(或者旅费),要求找到一条从城市1出发,经过所有城市且每个城市只能访问一次,最后回到城市1的路线,使总的路程(或者旅费)最小。
结点数为
N
N
N的TSP问题,其路径组合数量为
(
N
−
1
)
!
(N-1)!
(N−1)!。
二. 邻域搜索算法
1. 邻域的概念
字面意思理解,如上面的表格所示,如果红色表格代表解,那么它旁边的绿色部分表格就是它的邻域。
对应到旅行商问题中,假如有七个城市,那么它的一个解可以如下表示:
1
→
2
→
3
→
4
→
5
→
6
→
7
1\to2\to3\to4\to5\to6\to7
1→2→3→4→5→6→7
即:
则2opt(两点互换产生的邻域)有:
等等
2. 2-opt全邻域搜索求解TSP思路以及matlab实现
算法流程图
matlab程序编写实现
主程序如下:
%% 2-opt 全邻域搜索求解TSP实现
%% 2-opt全邻域搜索算法求解tsp问题
data = initData(); % 存放城市之间距离的矩阵
cityQty = size(data,1); % 城市总数
otherCities = 2:cityQty;
% 随机产生初始解
randCities = otherCities(randperm(cityQty - 1));
xnew = [1 randCities]; % 产生xnew
fitxnew = routeDistance(data,xnew); % 计算xnew解的路线长度
xbest = xnew; % 让xbest = xnew
fitxbest = fitxnew; % 让fitxbest = fitxnew
% 循环计算
isStop = 0;
while isStop < 4 % 设置迭代次数
% 使用2-opt方式产生xnew的全部邻域解
neighbors = neighborBy2opt(xnew); % 产生xnew的邻域解
% 计算neighbors中每个解的值,并获得最小解
neighborRows = size(neighbors,1);
fitnesses = zeros(neighborRows,1);
for i = 1:neighborRows
fitnesses(i) = routeDistance(data,neighbors(i,:)); % 计算每个邻域解的路线长度
end
[~, idx] = sortrows(fitnesses); % 对邻域解进行升序排列
xnow = neighbors(idx(1),:); % 把最短路线长度的解赋给xnow
fitnow = fitnesses(idx(1)); % xnow的路线长度
% 进行解的更新和终止循环判断
if fitnow < fitxbest % 如果xnow优于xbest时将xnow赋给xbest
xbest = xnow;
fitxbest = fitnow;
isStop = 0;
else % 如果xnow不优于xbest,进行下一次的迭代
isStop = isStop + 1;
end
xnew = xnow; % 将xnow赋给xnew
% 解随机移动下
segCities = circshift(otherCities,randperm(cityQty,1)-1);
newIdx = [1 segCities];
xnew = xnew(newIdx);
end
% 输出结果
disp('------------------最短路径------------------');
disp(optX);
disp('------------------最短路径长度------------------');
disp(optFit);
用到的函数:
initData:初始化数据,各个城市之间的距离
function distData = initData()
distData = [0 15 19 30 6 11 18 14 24
15 0 34 44 14 23 29 4 38
19 34 0 16 22 15 19 32 9
30 44 16 0 35 30 18 44 7
6 14 22 35 0 9 24 11 28
11 23 15 30 9 0 24 20 23
18 29 19 18 24 24 0 30 15
14 4 32 44 11 20 30 0 37
24 38 9 7 28 23 15 37 0];
end
routeDistance:计算解的路线长度
function routeDist = routeDistance(cityDist, route)
% 根据城市间的距离计算总路径
qty = max(size(route));
sumDist = 0;
for i = 1 ; qty-1
sumDist = sumDist + cityDist(route(i),route(i+1));
end
sumDist = sumDist + cityDist(route(qty),route(1));
routeDist = sumDist;
end
neighborBy2opt:产生一个解的全部邻域解集(采用2opt方式产生)
function routes = neighborBy2opt( route )
% 根据一条路径route,采用2opt方式产生其全部邻域解集
cityQty = max(size(route));
if cityQty <= 3
disp('cityQty is too small in neighborBy2opt.....');
end
pos = 2 : cityQty;
changePos = nchoosek(pos, 2);
rows = size(changePos, 1);
routes = zeros(rows, cityQty);
% 依次对两个点进行位置互换,形成新的解
for i = 1 : rows
city1 = route(changePos(i,1));
city2 = route(changePos(i,2));
midRoute = route;
midRoute(changePos(i,1)) = city2;
midRoute(changePos(i,2)) = city1;
routes(i,:) = midRoute;
end
end
程序运行结果