1.蚁群算法来源
蚁群算法(Ant Colony Optimization,简称ACO)是一种模拟自然界中蚂蚁寻找食物路径行为的优化算法,主要用于解决组合优化问题。它的灵感来源于意大利学者Marco Dorigo在1992年提出的蚂蚁系统模型。
蚁群算法的灵感来源于自然界中蚂蚁寻找食物的行为。蚂蚁在寻找食物的过程中会释放一种称为信息素的化学物质,这种物质会在蚂蚁走过的路径上留下痕迹,后续的蚂蚁会根据这些信息素的浓度来选择路径,从而形成一条从蚁巢到食物源的最短路径。蚂蚁觅食的过程是一个正反馈的过程,该路段经过的蚂蚁越多,信息素留下的就越多,浓度越高,更多的蚂蚁都会选择这个路段。
这种行为模式启发了科学家们设计出蚁群算法,用于解决复杂的优化问题。
2.蚁群算法基本原理
蚁群算法的基本原理可以概括为以下几个步骤:
(1)初始化:设定每个解(相当于蚂蚁可能行走的路径)的信息素初始值,通常设置为一个较小的正数。
(2)蚂蚁构建解:每只蚂蚁根据当前的信息素浓度和启发式信息(如距离的倒数)来选择下一步要走的路径。这个过程是概率性的,信息素浓度越高,被选中的概率越大。
(3)信息素更新:一轮搜索结束后,根据蚂蚁找到的解的质量来更新信息素。通常情况下,较优的解对应的路径上的信息素会被加强,而较差解对应的信息素则会减少或蒸发。
(4)循环迭代:重复上述过程,直到满足停止条件(如达到最大迭代次数或解的质量不再明显提高)。
通过这样的机制,蚁群算法能够在解空间中逐渐逼近最优解。需要注意的是,蚁群算法是一种随机优化算法,每次运行可能会得到不同的结果,但多次运行后往往能够找到接近最优的解。
数学原理:
3.蚁群算法的应用
蚁群算法的应用非常广泛,包括旅行商问题(TSP)、图着色问题、网络路由优化、调度问题等。它特别适合于解决大规模的、复杂的优化问题,尤其是那些难以用传统数学方法求解的问题。
下面简单介绍一些经典的应用:
(1)旅行商问题(TSP):最初被用于解决TSP问题,即在给定一组城市中找到最短的巡回路径。
(2)物流和交通:用于优化物流配送路径、车辆路径规划和交通信号控制等问题。
(3)网络路由:在计算机网络和通信网络中,用于动态路由选择以提高网络效率。
(4)生产调度:在制造业中,用于优化生产计划和调度,减少生产成本和时间。
(5)图像处理:用于图像分割、边缘检测等图像处理任务。
(6)图着色问题:
4.蚁群算法解决TSP问题
旅行商问题(Traveling saleman problem, TSP)是物流配送的典型问题,其求解有十分重要的理论和现实意义。
旅行商问题传统的解决方法都是遗传算法,但是遗传算法的收敛速度慢,具有一定的缺陷。
在求解TSP蚁群算法中,每只蚂蚁相互独立,用于构造不同的路线,蚂蚁之间通过信息素进行交流,合作求解。
动图展示TSP问题求解过程:
下面介绍一下具体流程:
(1)初始化参数:epochs表示迭代次数,ants表示蚂蚁数量,alpha和beta是信息素重要程度的参数,rho是信息素挥发速度,Q是信息素强度常数。
(2)计算城市之间的距离矩阵:使用numpy的linalg.norm函数计算每对城市之间的欧几里得距离,并将结果存储在Distance矩阵中。
(3)初始化信息素矩阵Tau:将所有元素设置为1.0。
(4)初始化每只蚂蚁的路线图Route:创建一个ants x cities的零矩阵,表示每只蚂蚁访问过的城市。
(5)进行迭代:对于每次迭代,首先为每只蚂蚁随机选择一个起始城市,然后根据概率选择下一个要访问的城市。概率由信息素浓度和启发式信息共同决定。
(6)计算每只蚂蚁的总距离:遍历每只蚂蚁的路线,累加经过的城市之间的距离。
(7)更新最优解:如果当前迭代中找到了一条更短的路径,就更新最优距离和最优路线。
(8)更新信息素:根据蚂蚁走过的路径,更新信息素矩阵Tau。
(9)输出结果:打印出找到的最短路径和对应的距离。
程序中各符号说明如下表格:
变量/矩阵名称 | 维度 | 描述 |
position | (cities, 2) | 城市坐标数组,每行代表一个城市的x和y坐标。 |
Distance | (cities, cities) | 城市之间的距离矩阵,存储每两个城市之间的欧几里得距离。 |
Eta | (cities, cities) | 启发式信息矩阵,是Distance矩阵的倒数,用于指导蚂蚁选择路径。 |
Tau | (cities, cities) | 信息素矩阵,表示在每两个城市之间的路径上的信息素浓度。 |
Route | (ants, cities) | 蚂蚁路径矩阵,存储每一只蚂蚁在当前迭代中的路径。 |
best_distance | 1 | 变量,存储迄今为止找到的最短路径的长度。 |
best_route | (cities,) | 数组,存储迄今为止找到的最短路径的城市顺序。 |
epochs | 1 | 算法运行的迭代次数。 |
ants | 1 | 蚁群中蚂蚁的数量。 |
alpha | 1 | 信息素重要性的影响因子。 |
beta | 1 | 启发式信息重要性的影响因子。 |
rho | 1 | 信息素蒸发率。 |
Q | 1 | 信息素强度,用于在每次迭代后更新信息素矩阵。 |
最终结果展示:
完整python代码如下:
import numpy as np
import random
# 城市坐标
x = np.array([51, 27, 56, 21, 4, 6, 58, 71, 54, 40, 94, 18, 89, 33, 12, 25, 24, 58, 71, 94, 17, 38, 13, 82, 12, 58, 45, 11, 47, 4])
y = np.array([14, 81, 67, 92, 64, 19, 98, 18, 62, 69, 30, 54, 10, 46, 34, 18, 42, 69, 61, 78, 16, 40, 10, 7, 32, 17, 21, 26, 35, 90])
position = np.column_stack((x, y))
epochs = 50
ants = 50
alpha = 1.4
beta = 2.2
rho = 0.15
Q = 10**6
cities = position.shape[0]
# 城市之间的距离矩阵
Distance = np.ones((cities, cities))
for i in range(cities):
for j in range(cities):
if i != j:
Distance[i, j] = np.linalg.norm(position[i] - position[j])
else:
Distance[i, j] = np.finfo(float).eps
Eta = 1.0 / Distance
Tau = np.ones((cities, cities))
# 每只蚂蚁的路线图
Route = np.zeros((ants, cities))
best_distance = np.inf
best_route = np.zeros(cities)
for epoch in range(epochs):
# 为每只蚂蚁随机选择一个唯一的起始城市
start_cities = np.random.permutation(cities).tolist()
for i in range(ants):
Route[i, 0] = start_cities[i % cities]
for j in range(1, cities):
for i in range(ants):
Visited = Route[i, :j]
NoVisited = np.setdiff1d(np.arange(cities), Visited)
P = np.zeros(len(NoVisited))
for k in range(len(NoVisited)):
P[k] = (Tau[int(Visited[-1]), int(NoVisited[k])] ** alpha) * (Eta[int(Visited[-1]), int(NoVisited[k])] ** beta)
P = P / P.sum()
Pcum = np.cumsum(P)
select = np.where(Pcum >= random.random())[0][0]
to_visit = NoVisited[select]
Route[i, j] = to_visit
Distance_epoch = np.zeros(ants)
for i in range(ants):
R = Route[i, :]
for j in range(cities - 1):
Distance_epoch[i] += Distance[int(R[j]), int(R[j + 1])]
Distance_epoch[i] += Distance[int(R[0]), int(R[-1])]
best_distance_epoch = np.min(Distance_epoch)
best_index_epoch = np.argmin(Distance_epoch)
if best_distance_epoch < best_distance:
best_distance = best_distance_epoch
best_route = Route[best_index_epoch, :]
Delta_Tau = np.zeros((cities, cities))
for i in range(ants):
for j in range(cities - 1):
Delta_Tau[int(Route[i, j]), int(Route[i, j + 1])] += Q / Distance_epoch[i]
Delta_Tau[int(Route[i, 0]), int(Route[i, -1])] += Q / Distance_epoch[i]
Tau = (1 - rho) * Tau + Delta_Tau
print("最短路径:", best_route)
print("最短距离:", best_distance)
MATLAB代码如下:
动图显示路径部分
function DrawRoute(C, R)
N = length(R);
scatter(C(:, 1), C(:, 2));
hold on
plot([C(R(1), 1), C(R(N), 1)], [C(R(1), 2), C(R(N), 2)], 'g');
for ii = 2: N
hold on
plot([C(R(ii - 1), 1), C(R(ii), 1)], [C(R(ii - 1), 2), C(R(ii), 2)], 'g');
pause(0.1)
frame = getframe(gcf);
imind = frame2im(frame);
[imind, cm] = rgb2ind(imind, 256);
if ii == 2
imwrite(imind, cm, 'test.gif', 'gif', 'Loopcount', inf, 'DelayTime', 1e-4);
else
imwrite(imind, cm, 'test.gif', 'gif', 'WriteMode', 'append', 'DelayTime', 1e-4);
end
end
title('旅行商规划');
蚁群算法部分:
clear;
clc;
x=[51 27 56 21 4 6 58 71 54 40 94 18 89 33 12 25 24 58 71 94 17 38 13 82 12 58 45 11 47 4]';
y=[14 81 67 92 64 19 98 18 62 69 30 54 10 46 34 18 42 69 61 78 16 40 10 7 32 17 21 26 35 90]';
position = 100 * randn(40, 2);
% position = [x, y];
epochs = 50;
ants = 50;
alpha = 1.4;
beta = 2.2;
rho = 0.15;Q = 10^6;
cities = size(position, 1);
% 城市之间的距离矩阵
Distance = ones(cities, cities);
for i = 1: cities
for j = 1: cities
if i ~= j
Distance(i, j) = ((position(i, 1) - position(j, 1))^2 + (position(i, 2) - position(j, 2))^2)^0.5;
else
Distance(i, j) = eps;
end
Distance(j, i) = Distance(i, j);
end
end
Eta = 1./Distance;
Tau = ones(cities, cities);
% 每只蚂蚁的路线图
Route = zeros(ants, cities);
epoch = 1;
% 记录每回合最优城市
R_best = zeros(epochs, cities);
L_best = inf .* ones(epochs, 1);
L_ave = zeros(epochs, 1);
% 开始迭代
while epoch <= epochs
% 随机位置
RandPos = [];
for i = 1: ceil(ants / cities)
RandPos = [RandPos, randperm(cities)];
end
Route(:, 1) = (RandPos(1, 1:ants))';
for j = 2:cities
for i = 1: ants
Visited = Route(i, 1:j-1);
NoVisited = zeros(1, (cities - j + 1));
P = NoVisited;
num = 1;
for k = 1: cities
if length(find(Visited == k)) == 0
NoVisited(num) = k;
num = num + 1;
end
end
for k = 1: length(NoVisited)
P(k) = (Tau(Visited(end), NoVisited(k))^alpha) * (Eta(Visited(end), NoVisited(k))^beta);
end
P = P / sum(P);
Pcum = cumsum(P);
select = find(Pcum >= rand);
to_visit = NoVisited(select(1));
Route(i, j) = to_visit;
end
end
if epoch >= 2
Route(1, :) = R_best(epoch - 1, :);
end
Distance_epoch = zeros(ants, 1);
for i = 1: ants
R = Route(i, :);
for j = 1: cities - 1
Distance_epoch(i) = Distance_epoch(i) + Distance(R(j), R(j + 1));
end
Distance_epoch(i) = Distance_epoch(i) + Distance(R(1), R(cities));
end
L_best(epoch) = min(Distance_epoch);
pos = find(Distance_epoch == L_best(epoch));
R_best(epoch, :) = Route(pos(1), :);
L_ave(epoch) = mean(Distance_epoch);
epoch = epoch + 1;
Delta_Tau = zeros(cities, cities);
for i = 1: ants
for j = 1: (cities - 1)
Delta_Tau(Route(i, j), Route(i, j + 1)) = Delta_Tau(Route(i, j), Route(i, j + 1)) + Q / Distance_epoch(i);
end
Delta_Tau(Route(i, 1), Route(i, cities)) = Delta_Tau(Route(i, 1), Route(i, cities)) + Q / Distance_epoch(i);
end
Tau = (1 - rho) .* Tau + Delta_Tau;
Route = zeros(ants, cities);
end
%% 结果展示
Pos = find(L_best == min(L_best));
Short_Route = R_best(Pos(1), :);
Short_Length = L_best(Pos(1), :);
figure
% subplot(121);
DrawRoute(position, Short_Route);
% subplot(122);
% plot(L_best);
% hold on
% plot(L_ave, 'r');
% title('平均距离和最短距离');