2opt邻域搜索算法—以旅行商问题为例

一. 旅行商问题描述

一位商人要到若干城市去推销商品,已知城市个数和各城市间的路程(或者旅费),要求找到一条从城市1出发,经过所有城市且每个城市只能访问一次,最后回到城市1的路线,使总的路程(或者旅费)最小
结点数为 N N N的TSP问题,其路径组合数量为 ( N − 1 ) ! (N-1)! (N1)!

二. 邻域搜索算法

1. 邻域的概念

在这里插入图片描述
字面意思理解,如上面的表格所示,如果红色表格代表解,那么它旁边的绿色部分表格就是它的邻域。
对应到旅行商问题中,假如有七个城市,那么它的一个解可以如下表示:
1 → 2 → 3 → 4 → 5 → 6 → 7 1\to2\to3\to4\to5\to6\to7 1234567
即:
在这里插入图片描述
则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


程序运行结果
在这里插入图片描述

  • 6
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值