问题描述
旅行商问题(Traveling Salesman Problem,TSP)是一个著名的组合优化问题,其目标是找到一条最短路径,使得旅行商可以经过所有给定城市一次并回到起始城市。在这个问题中,假设有一位旅行商要访问多个城市,并且每两个城市之间都有确定的距离或成本。TSP的目标是找到一条路径,使得旅行商走过的总距离或总成本最小。
蚁群算法
实现步骤:
步骤1:初始化,设定相关参数:
全部城市数n
全部蚂蚁数m, m<n
循环(迭代)次数的最大值Nmax
初始时各路径信息素τi,j(0)=τ0
信息素挥发系数ρ以及α、β、Q等
建立禁忌列表Jk,并保证此时表中没有任何城市。
步骤2:将m只蚂蚁随机放在各个城市上,每个城市至多分布一个蚂蚁,并将m个蚂蚁所在城市存入禁忌列表Jk。
步骤3:所有蚂蚁依据概率选择下一城市,并将选择城市存入禁忌列表。
步骤4:所有蚂蚁都构建完一条完整的路径后,在所经过的路径上更新信息素,并记录本次迭代过程中的最优路径和最优路径长度。
步骤5:清空禁忌列表Jk,重复步骤2和步骤4直到每一只蚂蚁完成Nmax次迭代,或者出现停滞现象(所有蚂蚁都选择相同路径,路径不再变化),最后输出最优路径。
具体原理参考计算智能
代码实现
map = [18, 54; 87, 76; 74, 78; 71, 71; 25, 38; 58, 35; 04, 50; 13, 40; 18, 40; 24, 42;
71, 44; 64, 60; 68, 58; 83, 69; 58, 69; 54, 62; 51, 67; 37, 84; 41, 94; 02, 99;
07, 64; 22, 60; 25, 62; 62, 32; 87, 07; 91, 38; 83, 46; 41, 26; 45, 21; 44, 35];
n = size(map, 1); % 城市数
citys_idx = 1:n; % 城市序号
maxiter = 200; % 最大迭代次数
ant_num = 29; % 蚂蚁数量
alpha = 1; % 控制信息素权重
beta = 2; % 控制能见度权重
rho = 0.5; % 信息素挥发系数
Q = 1; % 信息素强度
Tau = ones(n, n); % 信息素矩阵,初始化为 1
% 计算每个城市之间的距离
D = zeros(n, n);
for i = 1:n
for j = 1:n
if i ~= j
D(i, j) = distance(map(i, :), map(j, :));
end
end
end
Eta = 1 ./D; % 城市之间的启发度
iter = 1;
MinRoad = zeros(maxiter, n);
MinRoad_value = zeros(maxiter, 1);
while iter <= maxiter
Table = zeros(ant_num, n); % 所有蚂蚁的路径表
% 初始化所有蚂蚁的起点城市
Table(:, 1) = randi(n, ant_num, 1);
% 遍历蚂蚁
for i = 1:ant_num
% 遍历城市
for j = 2:n % j 为下一个要访问的城市
check = Table(i, 1:(j - 1)); % 第 i 只蚂蚁已访问 j - 1 个的城市(禁忌表)
allowed = setdiff(citys_idx, check);
% 计算到达各个城市的概率
P = zeros(1, length(allowed));
for k = 1:length(P)
P(k) = Tau(check(end), allowed(k)) ^ alpha * Eta(check(end), allowed(k)) ^beta;
end
P = P / sum(P);
% 轮盘赌选择下一个访问城市
Pc = cumsum(P); % 累加概率
target_index = find(Pc >= rand);
target = allowed(target_index(1));
Table(i,j) = target;
end
end
% 计算各个蚂蚁的路径距离
Dist = calculateDistances(Table, map);
% 获得当前最短路径
[Mindist, q] = min(Dist);
MinRoad_it = Table(q, :);
MinRoad_it_value = Mindist;
% 更新信息素
Delta_Tau = zeros(n, n);
% 遍历蚂蚁
for i = 1:ant_num
% 遍历城市
for j = 1:(n -1)
Delta_Tau(Table(i, j), Table(i, j + 1)) = Delta_Tau(Table(i, j), Table(i, j +1)) + Q / Dist(i);
end
Delta_Tau(Table(i, n), Table(i, 1)) = Delta_Tau(Table(i, n), Table(i, 1)) + Q/Dist(i);
end
Tau = (1 - rho) * Tau + Delta_Tau;
% 每次更新最优解
MinRoad(iter, :) = MinRoad_it;
MinRoad_value(iter, 1) = MinRoad_it_value;
iter = iter + 1;
end
% 找出全局最优路径及其迭代次数
[MinestRoad_value, Iterindex] = min(MinRoad_value);
disp('最优路径为:');
disp(MinRoad(Iterindex, :));
disp('最优路径长度为:');
disp(MinestRoad_value);
disp('获得最佳路径的迭代次数为:');
disp(Iterindex);
% 城市路径图
figure;
% 初始路径
subplot(1, 2, 1);
draw_map = [map; map(1, :)];
plot(draw_map(:, 1), draw_map(:, 2), '*', 'DisplayName', '城市');
hold on;
plot(draw_map(:, 1), draw_map(:, 2), '-', 'LineWidth', 1, 'Color', [1, 0.5, 0],'DisplayName', '初始路径');
legend('show');
legend('Location', 'best');
for c = 1:n
text(map(c, 1), map(c, 2), [' ' num2str(c)], 'Color', 'k', 'FontWeight', 'b');
end
% 最优路径
subplot(1, 2, 2);
ordered_map = map(MinRoad(Iterindex, :), :);
ordered_map = [ordered_map; ordered_map(1, :)];
plot(ordered_map(:, 1), ordered_map(:, 2), '*', 'DisplayName', '城市');
hold on;
plot(ordered_map(:, 1), ordered_map(:, 2), '-', 'LineWidth', 1, 'Color', [1, 0.5, 0],'DisplayName', '最优路径');
legend('show');
legend('Location', 'best');
for c = 1:n
text(ordered_map(c, 1), ordered_map(c, 2), [' ' num2str(c)], 'Color', 'k','FontWeight', 'b');
end
% 迭代曲线图
figure;
plot(MinRoad_value);
title('迭代曲线');
xlabel('迭代次数');
ylabel('最短路径长度');
% 计算路径总长度
function Dist = calculateDistances(Table, map)
Popsize = size(Table, 1); % 蚂蚁数量
n = size(Table, 2); % 节点数量
Dist = zeros(Popsize, 1); % 用于存储每条路径的距离
for i = 1:Popsize
dist = 0;
for j = 1:(n - 1)
A = Table(i, j);
B = Table(i, j + 1);
A1 = map(A, :);
B1 = map(B, :);
dist = dist + distance(A1, B1);
end
A = Table(i, 1);
B = Table(i, n);
A1 = map(A, :);
B1 = map(B, :);
dist = dist + distance(A1, B1);
Dist(i, 1) = dist;
end
end
% 计算两城市之间距离
function d = distance(A, B)
d = sqrt((B(1) - A(1))^2 + (B(2) - A(2))^2);
end
输出结果
全局最优长度和对应迭代次数
初始路径与全局路径
迭代曲线