蚁群优化算法(ACO)求解旅行商问题(TSP)
前言
提醒:
文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。
其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展及意见建议,欢迎评论区讨论交流。
内容由AI辅助生成,仅经笔者审核整理,请甄别食用。
文章目录
- 前言
- matlab代码
- 代码分析
- **一、算法核心原理与数学基础**
- **二、代码模块解析**
- **1. 参数设置(对应算法核心参数)**
- **2. 初始化(问题建模与变量初始化)**
- (1)城市坐标与距离矩阵
- (2)信息素与启发信息初始化
- **3. 主循环:蚂蚁构建路径与信息素更新**
- (1)蚂蚁构建路径(基于转移概率)
- (2)更新最优路径
- (3)信息素更新(挥发+沉积)
- **4. 动态可视化**
- **三、算法逻辑总结**
matlab代码
function [bestPath, bestDistance, convergence] = antColonyTSP_Animated()%% 参数设置% 蚁群优化算法(ACO),用于求解旅行商问题(TSP)% 即寻找一条访问所有城市并返回起点的最短闭合路径cityNum = 100; % 城市数量antNum = 50; % 蚂蚁数量maxIter = 200; % 最大迭代次数alpha = 1; % 信息素重要程度因子beta = 5; % 启发函数重要程度因子rho = 0.1; % 信息素挥发因子Q = 100; % 信息素增强系数pauseTime = 0; % 动画播放速度(单位:秒)%% 初始化城市坐标(随机生成)cities = rand(cityNum, 2) * 100;% 计算距离矩阵distMatrix = inf(cityNum);for i = 1:cityNumfor j = i+1:cityNumd = norm(cities(i,:) - cities(j,:));distMatrix(i,j) = d;distMatrix(j,i) = d;endend% 初始化信息素矩阵pheromone = ones(cityNum);%代码中 pheromone = ones(cityNum); % 实际创建的是 cityNum×cityNum 的二维矩阵,% 用于存储每对城市之间的信息素浓度。% 启发信息eta = 1 ./ distMatrix;eta(distMatrix == inf) = 0;% 初始化记录bestDistance = inf;bestPath = [];convergence = zeros(maxIter, 1);%% 初始化图像窗口figure('Name', '蚁群算法动态路径演化', 'Position', [100, 100, 1200, 500]);subplot(1, 2, 1);pathPlot = plot(0,0,'b-','LineWidth',2); hold on;cityPlot = plot(cities(:,1), cities(:,2), 'ro', 'MarkerSize', 8, 'MarkerFaceColor', 'r');title('TSP路径演化');xlabel('X坐标'); ylabel('Y坐标');textHandles = gobjects(cityNum,1);for i = 1:cityNumtextHandles(i) = text(cities(i,1)+1, cities(i,2)+1, num2str(i), 'FontSize', 9);enditerTitle = title('');grid on;subplot(1, 2, 2);convPlot = plot(0,0,'b-','LineWidth',2);title('收敛曲线'); xlabel('迭代次数'); ylabel('最优距离'); grid on;%% 主循环for iter = 1:maxIterantPaths = zeros(antNum, cityNum);antDistances = zeros(antNum, 1);for ant = 1:antNumcurrentCity = randi(cityNum);path = currentCity;unvisited = setdiff(1:cityNum, currentCity);while ~isempty(unvisited)prob = zeros(length(unvisited),1);for i = 1:length(unvisited)nc = unvisited(i);prob(i) = pheromone(currentCity,nc)^alpha * eta(currentCity,nc)^beta;endprob = prob / sum(prob);nextCity = unvisited(find(rand() <= cumsum(prob),1));path(end+1) = nextCity;currentCity = nextCity;unvisited(unvisited==nextCity) = [];end% 路径长度dist = sum(arrayfun(@(i) distMatrix(path(i),path(i+1)), 1:cityNum-1)) ...+ distMatrix(path(end), path(1));antPaths(ant,:) = path;antDistances(ant) = dist;end% 更新最优路径[iterBestDist, bestAnt] = min(antDistances);if iterBestDist < bestDistancebestDistance = iterBestDist;bestPath = antPaths(bestAnt,:);endconvergence(iter) = bestDistance;% 信息素挥发pheromone = (1 - rho) * pheromone;% 信息素更新for ant = 1:antNump = antPaths(ant,:);delta = Q / antDistances(ant);for i = 1:cityNum-1pheromone(p(i),p(i+1)) = pheromone(p(i),p(i+1)) + delta;pheromone(p(i+1),p(i)) = pheromone(p(i+1),p(i)) + delta;endpheromone(p(end),p(1)) = pheromone(p(end),p(1)) + delta;pheromone(p(1),p(end)) = pheromone(p(1),p(end)) + delta;end% 动态更新图像subplot(1,2,1);bpX = [cities(bestPath,1); cities(bestPath(1),1)];bpY = [cities(bestPath,2); cities(bestPath(1),2)];set(pathPlot, 'XData', bpX, 'YData', bpY);set(iterTitle, 'String', sprintf('迭代 %d / %d:当前最优距离 = %.2f', iter, maxIter, bestDistance));subplot(1,2,2);set(convPlot, 'XData', 1:iter, 'YData', convergence(1:iter));drawnow;pause(pauseTime); % 控制动画速度end%% 输出结果fprintf('\n=== 蚁群算法TSP求解结果 ===\n');fprintf('城市数量: %d\n', cityNum);fprintf('最优路径长度: %.2f\n', bestDistance);fprintf('最优路径: ');fprintf('%d -> ', bestPath);fprintf('%d\n', bestPath(1));
end% 调用函数
[bestPath, bestDistance, convergence] = antColonyTSP_Animated();
运行结果
这段MATLAB代码实现了一个带动态可视化的蚁群优化算法(ACO),用于求解旅行商问题(TSP)——即寻找一条访问所有城市并返回起点的最短闭合路径。
代码分析
一、算法核心原理与数学基础
蚁群算法解决TSP的核心是模拟蚂蚁通过信息素(pheromone) 传递路径信息的机制,其数学框架包括:
- 转移概率:蚂蚁根据信息素浓度和路径距离选择下一个城市;
- 信息素更新:路径越短,信息素积累越多,同时信息素会随时间挥发;
- 正反馈机制:优质路径(短路径)的信息素浓度更高,吸引更多蚂蚁选择,形成“越短路径→信息素越浓→更多蚂蚁选择”的循环。
二、代码模块解析
1. 参数设置(对应算法核心参数)
cityNum = 100; % 城市数量(TSP问题规模)
antNum = 50; % 蚂蚁数量(群体规模,影响搜索多样性)
maxIter = 200; % 最大迭代次数(算法终止条件)
alpha = 1; % 信息素重要程度因子(τ的权重)
beta = 5; % 启发函数重要程度因子(η的权重)
rho = 0.1; % 信息素挥发因子(控制挥发速度)
Q = 100; % 信息素增强系数(控制沉积量)
- 参数作用:
alpha
和beta
平衡“信息素引导”与“距离启发”(距离越短,启发信息越强);rho
防止信息素无限积累,避免算法早熟;Q
控制信息素沉积的总量,路径越短,单位长度沉积的信息素越多。
2. 初始化(问题建模与变量初始化)
(1)城市坐标与距离矩阵
% 生成随机城市坐标(范围[0,100])
cities = rand(cityNum, 2) * 100;% 计算距离矩阵(城市i到j的欧氏距离)
distMatrix = inf(cityNum);
for i = 1:cityNumfor j = i+1:cityNumd = norm(cities(i,:) - cities(j,:)); % 欧氏距离公式distMatrix(i,j) = d;distMatrix(j,i) = d; % 距离矩阵对称(TSP路径双向距离相同)end
end
- 数学公式:城市i(xi,yi)i(x_i,y_i)i(xi,yi)与城市j(xj,yj)j(x_j,y_j)j(xj,yj)的欧氏距离:
dij=(xi−xj)2+(yi−yj)2d_{ij} = \sqrt{(x_i - x_j)^2 + (y_i - y_j)^2} dij=(xi−xj)2+(yi−yj)2
代码中通过norm
函数实现该计算,距离矩阵distMatrix
存储所有城市间的距离。
(2)信息素与启发信息初始化
% 信息素矩阵(τ_ij:城市i到j的信息素浓度)
pheromone = ones(cityNum); % 初始信息素浓度相同(均为1)% 启发信息(η_ij:距离的倒数,距离越近,启发信息越强)
eta = 1 ./ distMatrix;
eta(distMatrix == inf) = 0; % 避免除零(自身到自身的距离为inf)
- 启发信息公式:启发信息与距离成反比(距离越近,蚂蚁越倾向选择):
ηij=1dij\eta_{ij} = \frac{1}{d_{ij}} ηij=dij1
初始信息素矩阵pheromone
设为全1,确保所有路径初始时公平竞争。
3. 主循环:蚂蚁构建路径与信息素更新
这是算法的核心,对应蚁群算法“解的构建→信息素更新”的迭代过程。
(1)蚂蚁构建路径(基于转移概率)
for ant = 1:antNum % 每个蚂蚁独立构建路径currentCity = randi(cityNum); % 随机选择起点城市path = currentCity; % 记录路径unvisited = setdiff(1:cityNum, currentCity); % 未访问城市集合while ~isempty(unvisited) % 直到访问所有城市% 计算转移概率:选择下一个城市的概率prob = zeros(length(unvisited),1);for i = 1:length(unvisited)nc = unvisited(i); % 候选城市% 转移概率公式:τ_ij^α · η_ij^β 的归一化prob(i) = pheromone(currentCity,nc)^alpha * eta(currentCity,nc)^beta;endprob = prob / sum(prob); % 归一化概率(总和为1)% 轮盘赌选择:按概率选择下一个城市nextCity = unvisited(find(rand() <= cumsum(prob),1));% 更新路径与未访问城市path(end+1) = nextCity;currentCity = nextCity;unvisited(unvisited==nextCity) = [];end% 计算路径长度(TSP目标函数:闭合路径总距离)dist = sum(arrayfun(@(i) distMatrix(path(i),path(i+1)), 1:cityNum-1)) ...+ distMatrix(path(end), path(1)); % 最后返回起点antPaths(ant,:) = path; % 记录第ant只蚂蚁的路径antDistances(ant) = dist; % 记录路径长度
end
setdiff(A, B)
:这是MATLAB中的一个内置函数,用于计算集合A中存在但集合B中不存在的元素,即返回A与B的差集。
-
核心公式:转移概率
蚂蚁kkk从当前城市iii选择未访问城市jjj的概率为:
Pijk=τijα⋅ηijβ∑l∈allowedkτilα⋅ηilβP_{ij}^k = \frac{\tau_{ij}^\alpha \cdot \eta_{ij}^\beta}{\sum_{l \in \text{allowed}_k} \tau_{il}^\alpha \cdot \eta_{il}^\beta} Pijk=∑l∈allowedkτilα⋅ηilβτijα⋅ηijβ
其中:
-τij\tau_{ij}τij:城市iii到jjj的信息素浓度;
-allowedk\text{allowed}_kallowedk:蚂蚁kkk未访问的城市集合;
-α,β\alpha, \betaα,β:平衡信息素(历史经验)与启发信息(局部距离)的权重。代码中通过
prob(i) = pheromone(...)^alpha * eta(...)^beta
计算分子,再归一化得到概率,最后用轮盘赌(cumsum(prob)
)实现随机选择。
轮盘赌选择机制
的核心思想是:根据概率分布随机选择下一个城市,而不是直接选择概率最大的城市。这样可以增加算法的随机性和探索性,避免陷入局部最优解。
具体来说,假设我们有以下概率分布:
P=[P1,P2,P3,…,Pn]P = [P_1, P_2, P_3, \ldots, P_n] P=[P1,P2,P3,…,Pn]
其中PiP_iPi表示选择第iii个城市的概率。为了实现随机选择,我们通常会将这些概率值累加起来,形成一个累积概率分布:
cumsum(P)=[P1,P1+P2,P1+P2+P3,…,∑i=1nPi]\text{cumsum}(P) = [P_1, P_1 + P_2, P_1 + P_2 + P_3, \ldots, \sum_{i=1}^{n} P_i] cumsum(P)=[P1,P1+P2,P1+P2+P3,…,i=1∑nPi]
然后,生成一个随机数r∈[0,1]r \in [0, 1]r∈[0,1],并找到第一个满足r≤cumsum(Pi)r \leq \text{cumsum}(P_i)r≤cumsum(Pi)的索引iii。这个索引iii就是我们选择的城市。
这样做的意义:
- 平衡利用和探索:
- 如果直接选择概率最大的城市,算法会很快收敛到局部最优解,缺乏探索性。
- 轮盘赌选择机制允许蚂蚁以一定概率选择非最优路径,增加了算法的随机性和全局搜索能力。
- 概率分布的随机性:
- 轮盘赌选择机制确保了每个城市都有被选择的机会,即使它的概率不是最大。
- 这种随机性有助于避免算法陷入局部最优解,提高全局优化能力。
- 小结:
- 直接选择最大概率的城市:会导致算法过早收敛,缺乏探索性。
- 轮盘赌选择机制:通过随机选择,平衡了利用和探索,增加了算法的全局搜索能力。
(2)更新最优路径
% 找到当前迭代的最优路径(最短距离)
[iterBestDist, bestAnt] = min(antDistances);
if iterBestDist < bestDistance % 更新全局最优bestDistance = iterBestDist;bestPath = antPaths(bestAnt,:);
end
convergence(iter) = bestDistance; % 记录收敛过程
每次迭代后,比较所有蚂蚁的路径长度,保留全局最优路径,convergence
数组记录每代最优距离,用于后续绘制收敛曲线。
(3)信息素更新(挥发+沉积)
信息素更新分两步:挥发(所有路径信息素减少)和沉积(优质路径信息素增加)。
% 1. 信息素挥发:所有路径的信息素按比例减少
pheromone = (1 - rho) * pheromone;% 2. 信息素沉积:蚂蚁在自己的路径上添加信息素
for ant = 1:antNump = antPaths(ant,:); % 第ant只蚂蚁的路径delta = Q / antDistances(ant); % 信息素增量(路径越短,增量越大)% 对路径上的每段边更新信息素for i = 1:cityNum-1pheromone(p(i),p(i+1)) = pheromone(p(i),p(i+1)) + delta;pheromone(p(i+1),p(i)) = pheromone(p(i+1),p(i)) + delta; % 对称更新end% 闭合路径:最后一个城市到起点pheromone(p(end),p(1)) = pheromone(p(end),p(1)) + delta;pheromone(p(1),p(end)) = pheromone(p(1),p(end)) + delta;
end
- 数学公式:
- 挥发过程:τij←(1−ρ)⋅τij\tau_{ij} \leftarrow (1 - \rho) \cdot \tau_{ij}τij←(1−ρ)⋅τij(ρ\rhoρ为挥发因子,0<ρ<10 < \rho < 10<ρ<1)
- 沉积过程:每只蚂蚁在路径上的信息素增量与路径长度成反比:
Δτijk=QLk\Delta \tau_{ij}^k = \frac{Q}{L_k} Δτijk=LkQ
其中LkL_kLk是第kkk只蚂蚁的路径长度,QQQ是信息素总量常数。 - 总更新:τij←(1−ρ)⋅τij+∑k=1mΔτijk\tau_{ij} \leftarrow (1 - \rho) \cdot \tau_{ij} + \sum_{k=1}^{m} \Delta \tau_{ij}^kτij←(1−ρ)⋅τij+∑k=1mΔτijk(mmm为蚂蚁数量)
4. 动态可视化
代码通过subplot
分两部分可视化:
- 左侧:实时展示当前最优路径(蓝色线条)和城市分布(红色圆点);
- 右侧:展示最优路径长度随迭代的收敛曲线(蓝色线条)。
drawnow
和pause
函数实现动画效果,直观展示算法从随机路径逐步逼近最优路径的过程。
三、算法逻辑总结
- 初始化:生成城市坐标、距离矩阵、初始信息素和启发信息;
- 迭代优化:
- 蚂蚁根据转移概率构建路径(短距离+高信息素的路径被优先选择);
- 信息素挥发(防止信息素无限积累)+ 沉积(优质路径获得更多信息素);
- 更新全局最优路径并记录收敛过程;
- 终止与输出:达到最大迭代次数后,输出最优路径和长度。
该代码完整实现了蚁群算法解决TSP的核心机制,通过信息素的正反馈和挥发平衡“探索”(尝试新路径)与“利用”(强化优质路径),最终找到近似最优解。动态可视化则直观展示了算法的优化过程。