禁忌搜索算法求解TSP旅行商问题Matlab实现

一. 禁忌搜索算法

禁忌搜索算法是一种全局性邻域搜索算法,模拟人类具有记忆功能的寻优特征。它通过局部邻域搜索机制和相应的禁忌准则来避免迂回搜索,并通过破禁水平来释放一些被禁忌的优良状态,进而保证多样化的有效搜索,以实现全局优化。

二. 禁忌搜索计算流程以及Matlab实现

1. 算法流程图

在这里插入图片描述

2. 代码实现

主程序

%% 禁忌搜索算法求解TSP问题程序


clear
clc

data = initData();                                          % 存放城市之间距离的矩阵
cityQty = size(data,1);                                     % 城市总数
otherCities = 2:cityQty;       
tabuTimes = 3;                                              % 禁忌次数

% 随机产生初始解
randCities = otherCities(randperm(cityQty - 1));
xnew = [1 randCities];                                      % 产生xnew
fitxnew = routeDistance(data,xnew);                         % 计算xnew解的路线长度
xbest = xnew;                                               % 让xbest = xnew     
fitxbest = fitxnew;                                         % 让fitxbest = fitxnew

% 定义禁忌表,12为置换的两点符号,3为禁忌剩余代数
tabuTable = zeros(0,3);

% 循环计算
isStop = 0;
while isStop < 4                                            % 设置迭代次数
    % 使用2-opt方式产生xnew的全部邻域解
    [neighbors,changePos] = neighborBy2opt(xnew);                       % 产生xnew的邻域解
    
    % 计算neighbors中每个解的值,并获取最小值
    neighborRows = size(neighbors,1);
    fitnesses = zeros(neighborRows, 2);
    for i = 1 : neighborRows
        fitnesses(i,1) = routeDistance(data, neighbors(i,:));
        minC = min(changePos(i,:));
        maxC = max(changePos(i,:));
        for j = 1 : size(tabuTable,1)
            if tabuTable(j,1) == minC && tabuTable(j,2) == maxC
                fitnesses(i,2) = 1;
                % 特赦准则
                if fitnesses(i, 1) < fitxbest 
                    fitnesses(i,2) = 0;
                end
            end
        end
    end
    
    [~, idx] = sortrows(fitnesses, [2,1]);
    xnow = neighbors(idx(1),:);
    fitnow = fitnesses(idx(1),1);               
    tabuObj = changePos(idx(1), :);                                         % 禁忌对象
    tabuTable = updataTabuTable(tabuTable, tabuObj, tabuTimes);             % 更新禁忌表
    
    % 进行解的更新和终止循环判断
    
    if fitnow < fitxbest
        xbest  = xnow;
        fitxbest = fitnow;
        isStop = 0;
    else
        isStop = isStop + 1;
    end
    xnew = xnow;
end

% 输出结果
disp('----------------------最短路径------------------------');
disp(xbest);
disp('---------------------最短路径长度---------------------');
disp(fitxbest);
    
    
    

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()函数
两点邻域法产生xnow的邻域解集

function [routes, changePos] = 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


updataTabuTable()函数
更新禁忌表里的对象和禁忌次数

function newTabuTable = updataTabuTable( tabuTable, tabuObj, tabuTimes )
% 更新禁忌表

oldRows = size(tabuTable,1);

% 先排序
if tabuObj(1) > tabuObj(2)
    midV = tabuObj(1);
    tabuObj(1) = tabuObj(2);
    tabuObj(2) = midV;
end

if oldRows == 0
    tabuTable = [tabuObj tabuTimes];
else
    % 将以前禁忌表中的禁忌次数-1
    for i = 1 : oldRows
        tabuTable(i, 3) = tabuTable(i,3) - 1;
    end
    
    % 查看当前禁忌对象是否存在于原有禁忌表中
    isExist = 0;
    for i = 1 : oldRows
        if tabuTable(i, 1) == tabuObj(1) && tabuTable(i, 2) == tabuObj(2)
            isExist = i;
            break;
        end
    end
    
    if isExist == 0
        midTabu = [tabuObj tabuTimes];
        tabuTable = [tabuTable; midTabu];
    else
        tabuTable(isExist, 3) = tabuTimes;
    end
    a = tabuTable(:, 3) == 0;
    tabuTable(a, :) = [];               % 删除禁忌次数为0的替换对
end
newTabuTable = tabuTable;
end

3. 实现结果

在这里插入图片描述

  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
蚁群算法可以用来解决TSP问题,其基本思路是将蚂蚁的行走路径表示为待优化问题的可行解,整个蚂蚁群体的所有路径构成待优化问题的解空间。路径较短的蚂蚁释放的信息素量较多,随着时间的推移,较短的路径上累积的信息素浓度逐渐增高,选择该路径的蚂蚁数量也越来越多。最终,整个蚂蚁会在正反馈的作用下集中到最佳的路径上,此时对应的便是待优化问题的最优解。 蚁群算法解决TSP问题的基本步骤如下: 1. 初始化信息素和蚂蚁的位置。 2. 蚂蚁按照一定的策略选择下一个城市,并更新信息素。 3. 计算每只蚂蚁的路径长度,并记录最短路径。 4. 更新信息素,使得路径较短的蚂蚁释放的信息素量较多。 5. 重复步骤2-4,直到满足停止条件。 下面是一个Python实现的例子: ```python import numpy as np # 城市数量 num_cities = 10 # 蚂蚁数量 num_ants = 20 # 信息素重要程度 alpha = 1 # 启发式因子重要程度 beta = 5 # 信息素挥发速度 rho = 0.1 # 初始信息素浓度 tau0 = 1 # 最大迭代次数 max_iter = 100 # 城市坐标 cities = np.random.rand(num_cities, 2) # 计算城市之间的距离 distances = np.zeros((num_cities, num_cities)) for i in range(num_cities): for j in range(num_cities): distances[i][j] = np.sqrt((cities[i][0] - cities[j][0]) ** 2 + (cities[i][1] - cities[j][1]) ** 2) # 初始化信息素 pheromones = np.ones((num_cities, num_cities)) * tau0 # 迭代 for iter in range(max_iter): # 初始化蚂蚁位置 ants = np.zeros((num_ants, num_cities), dtype=int) for i in range(num_ants): ants[i][0] = np.random.randint(num_cities) # 蚂蚁选择下一个城市 for i in range(num_ants): for j in range(1, num_cities): # 计算城市之间的启发式信息 eta = 1.0 / distances[ants[i][j - 1]][:] # 计算城市之间的信息素浓度 tau = pheromones[ants[i][j - 1]][:] # 计算城市之间的转移概率 p = np.power(tau, alpha) * np.power(eta, beta) p[ants[i]] = 0 p = p / np.sum(p) # 选择下一个城市 ants[i][j] = np.random.choice(num_cities, p=p) # 计算每只蚂蚁的路径长度 lengths = np.zeros(num_ants) for i in range(num_ants): for j in range(num_cities - 1): lengths[i] += distances[ants[i][j]][ants[i][j + 1]] lengths[i] += distances[ants[i][num_cities - 1]][ants[i][0]] # 记录最短路径 best_ant = np.argmin(lengths) best_path = ants[best_ant] best_length = lengths[best_ant] # 更新信息素 pheromones *= (1 - rho) for i in range(num_ants): for j in range(num_cities - 1): pheromones[ants[i][j]][ants[i][j + 1]] += 1.0 / lengths[i] pheromones[ants[i][num_cities - 1]][ants[i][0]] += 1.0 / lengths[i] # 输出结果 print("最短路径:", best_path) print("最短路径长度:", best_length) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值