在自然界中各种生物群体显现出来的智能近几十年来得到了学者们的广泛关注,学者们通过对简单生物体的群体行为进行模拟,进而提出了群智能算法。其中,模拟蚁群觅食过程的蚁群优化算法(Ant Colony Optimization, ACO)和模拟鸟群运动方式的粒子群算法是两种最主要的群体智能算法。本文介绍蚁群优化算法(简称蚁群算法)。
蚁群算法是一种源于大自然生物世界的新的仿生进化算法,是由意大利学者M.Dorigo等人于20世纪90年代初期通过模拟自然界中蚂蚁集体寻经行为而提出的一种基于种群的启发式随机搜索算法。蚂蚁有能力在其走过的路径上释放一种特殊的分泌物——信息素,随着时间的推移该物质会逐渐挥发,后来的蚂蚁选择该路径的概率与当时这条路经上的信息素强度成正比。当一条路径上通过的蚂蚁越来越多时,其留下的信息素越来越多,后来蚂蚁选择该路径的概率也就越高,从而更增加了该路径上的信息素强度。而强度大的信息素会吸引更多蚂蚁,从而形成一种正反馈机制。通过这种正反馈机制,蚂蚁最终可以发现最短路径。
蚁群算法是对自然界蚂蚁的寻径方式进行模拟而得出的一种仿生算法。蚂蚁在运动过程中,能够在它所在的路径上留下信息素进行信息传递,而且蚂蚁在运动过程中能够感知这种物质,并以此来指导自己的运动方向。因此,由大量蚂蚁组成的蚁群的集体行为便表现出一种信息正反馈现象:某一路径上走过的蚂蚁越多,则后来者选择该路径的概率就越大。
为了说明蚁群算法的原理,先简要介绍一下蚂蚁搜寻食物的具体过程。在自然界中,蚁群在寻找食物时,它们总能找到一条从食物到巢穴之间的最优路径。这是因为蚂蚁在寻找路径时会在路径上释放出一种特殊的信息素。蚁群算法的信息素交互主要是通过信息素来完成的。蚂蚁在运动过程中,能够感知到这种物质的存在和强度。初始阶段,环境中并没有信息素的遗留,蚂蚁寻找食物完全是随机选择路径,随后寻找该食物源的过程中就会受到先前蚂蚁所残留的信息素的影响,其表现为蚂蚁在选择路径时趋向于选择信息素浓度高的路径。同时,信息素是一种挥发性化学物质,会随着时间的推移而慢慢地消逝。如果每只蚂蚁在单位距离留下的信息素相同,那对较短路径上残留的信息素浓度就相对较高,这被后来的蚂蚁选择的概率就大,从而导致这条路径上走的蚂蚁就越多。而经过的蚂蚁越多,该路径上残留的信息素就将更多,这样使得整个蚂蚁的集体欣慰构成了信息素的正反馈过程,最终整个蚁群会找出最优路径。
基于以上真实蚁群寻找食物时的最优路径选择问题,可以构造人工蚁群解决最优化问题,如旅行商问题(TSP)。人工蚁群中把具体简单功能的工作单元看作蚂蚁。二者的相似之处在于都是优化选择信息素浓度大的路径。较短路径的信息素浓度高,所以能够最终被所有蚂蚁选择,也就是最终的优化结果。两者的区别在于人工蚁群有一定的记忆能力,能够记忆已经访问过的节点。同时,人工蚁群再选择下一条路径的时候是按照一定算法规律有意识地寻找最优路径,而不是盲目的。例如在TSP中,可以预先知道当前城市到下一个目的地的距离。
在TSP的人工蚁群算法中,假设m只蚂蚁在图的相邻节点间移动,从而协作异步地得到问题的解。每只蚂蚁的一步转移概率由图中的每条边上的两类参数决定:一是信息素值,也称信息素痕迹;二是可见度,即经验值。
信息素的更新方式有两种:
蚂蚁向下一个目标的运动是通过一个随机原则来实现的,也就是运用当前节点存储的信息,计算出下一步可达节点的概率,并按此概率实现一步移动。如此往复,越来越接近最优解。
蚂蚁在寻径过程中,或在找到一个解之后,会评估该解或解的一部分的优化程度,并把评价信息保存在相关连接的信息素中。
蚁群算法是一种基于群体的、用于求解复杂优化问题的通用搜索技术。与真实蚂蚁通过外信息的留存、跟随行为进行间接通信相似,蚁群算法中一群见到那的人工蚂蚁通过信息素进行间接通信,并利用该信息和与问题相关的启发式信息逐步构造问题的解。
人工蚂蚁具有双重特性:
人工蚂蚁与真实蚂蚁的相同点为:
人工蚂蚁和真实蚂蚁的不同点:
蚁群算法是通过对生物特征的模拟得到的一种优化算法,它本身具有很多优点:
这里以旅行商问题(TSP)为例介绍基本蚁群算法及其流程。基本蚁群算法可以表述如下:
在算法的初始时刻,将m只蚂蚁随机地放到n个城市中,同时,将每只蚂蚁的禁忌表tabu的第一个元素设置为它当前所在的城市。此时各路径上的信息素量相等,设\(\tau_{ij} (0) = c\)(c为一个较小的常数),接下来,每只蚂蚁根据路径上残留的信息素量和启发式信息(两个城市的距离)独立地选择下一个城市,在时刻t,蚂蚁k从城市i转移到城市j的概率为\(p_{ij}^k (t)\)为

式中,\(J_k(i)=\{ 1, 2, ..., n \} - tabu_k\)表示蚂蚁k下一步允许选择的城市集合。禁忌表\(tabu_k\)记录了蚂蚁k当前走过的城市。当所有n个城市都加入到禁忌表\(tabu_k\)中时,蚂蚁k便完成了一次周游,此时蚂蚁k所走过的路径便是TSP的一个可行解。
\(\eta_{ij}\)是通常取城市i与城市j之间距离的倒数。\(\alpha\) 与 \(\beta\)分别表示信息素和期望启发式因子的相对重要程度。当所有蚂蚁完成一次周游后,各路径上的信息素根据下面的公式更新:

式中:\(\rho (0 < \rho < 1)\)表示路径上信息素的蒸发系数,\(1-\rho\)表示信息素的持久性系数;\(\varDelta\tau_{ij}\)表示本次迭代中边\(ij\)上信息素的增量,即

其中\(\varDelta \tau _{ij}^{k}\)表示第k只蚂蚁在本次迭代中留在边\(ij\)上的信息素量,如果蚂蚁k没有经过边\(ij\),则\(\varDelta \tau _{ij}^{k}\)的值为零。\(\varDelta \tau _{ij}^{k}\)可表示为:

式中,\(Q\)为正常数,\(L_k\)表示第k只蚂蚁在本次周游中所走过的路径的长度。
蚁群算法实际上是正反馈原理和启发式算法相结合的一种算法。在选择路径时,蚂蚁不仅利用了路径上的信息素,而且用到了城市间距离的倒数作为启发式因子。
基本蚁群算法的具体实现步骤如下:
蚁群算法的运算流程图如下:

在蚁群算法中,不仅信息素和启发函数乘积以及蚂蚁之间的合作行为会严重影响到算法的收敛性,蚁群算法的参数也是影响其求解性能和效率的关键因素。信息素启发式因子\(\alpha\)、期望启发因子\(\beta\)、信息素蒸发系数\(\rho\)、信息素强度\(Q\)、蚂蚁数目\(m\)等都是非常重要的参数,其选取方法和选取原则直接影响到蚁群算法的全局收敛性和求解效率。
信息素启发式因子\(\alpha\)代表信息量对是否选择当前路径的影响程度,即反映蚂蚁在运动过程中所积累的信息量在指导蚁群搜索中的相对重要程度。\(\alpha\)的大小反映了蚁群在路径搜索中随机性因素作用的强度,其值越大,蚂蚁在选择以前走过的路径的可能性越大,搜索的随机性就会减弱;而当启发式因子\(\alpha\)的值过小时,则易使蚁群的搜索过早陷于局部最优。一般为\([1, 4]\)时,蚁群算法的综合求解性能较好。
期望启发因子\(\beta\)表示在搜索时路径上的信息素在指导蚂蚁选择路径时的向导性,它的大小反应了蚁群在搜索最优路径的过程中的先验性和确定性因素的作用强度。期望启发因子\(\beta\)的值越大,蚂蚁在某个局部点上选择局部最短路径的可能性就越大,虽然这个时候算法的收敛速度得以加快,但蚁群搜索最优路径的随机性减弱,而此时搜索易于陷入局部最优解。根据经验,期望启发因子\(\beta\)取值范围一般在\([3, 5]\),此时蚁群算法的综合求解性能较好。
实际上,信息素启发式因子\(\alpha\)和期望启发因子\(\beta\)是一对关联性很强的参数:
蚁群算法的全局寻优性能,首先要求蚁群的搜索过程必须要有很强的随机性;而蚁群算法的快速收敛性能,又要求蚁群的搜索过程必须要有较高的确定性。因此,两者对蚁群算法性能的影响和作用是相互配合、密切相关的,算法要获得最优解,就必须在这二者之间选取一个平衡点,只有正确选定它们之间的搭配关系,才能避免在搜索过程中出现过早停滞或陷入局部最优解等情况的发生。
蚁群算法中的人工蚂蚁是具有记忆功能的,随着时间的推移,以前留下的信息素将会逐渐消逝,蚁群算法与其他各种仿生进化算法一样,也存在着收敛速度慢、容易陷入局部最优解等缺陷,而信息素蒸发系数\(\rho\)大小的选择将直接影响到整个蚁群算法的收敛速度和全局搜索性能。在蚁群算法的抽象模型中,\(\rho\)表示信息素蒸发系数,\(1-\rho\)则表示信息素持久性系数。因此,\(\rho\)的取值范围应该是\([0,1]\)之间的一个数,表示信息素的蒸发程度,它实际上反映了蚂蚁群体中个体之间相互影响的强弱。\(\rho\)过小时,则表示以前搜索过的路径被再次选择的可能性过大,会影响到算法的随机性能和全局搜索能力;\(\rho\)过大时,说明路径上的信息素挥发的相对变多,虽然可以提高算法的随机搜索性能和全局搜索能力,但过多无用搜索操作势必会降低算法的收敛速度。
蚁群算法是一种随机搜索算法,与其他模拟进化算法一样,通过多个候选解组成的群体进化过程来寻求最优解,在该过程中不仅需要每个个体的自适应能力,更需要群体之间的相互协作能力。蚁群在搜索过程中之所以表现出复杂有序的行为,是因为个体之间的信息交流与相互协作起着重要的作用。
对于旅行商问题,单个蚂蚁在一次循环中所经过的路径,表现为问题可行解集中的一个解,\(m\)只蚂蚁在一次循环中所经过的路径,则表现为问题解集中的一个子集。显然,子集增大(即蚂蚁数量增多),可以提高蚁群算法的全局搜索能力以及算法的稳定性;但蚂蚁数目增大后,会使大量的曾被搜索过的解上的信息素的变化趋于平均,信息正反馈的作用不明显,虽然搜索的随机性得到了加强,但收敛速度减;反之,子集较小,特别是当要处理的问题规模比较大时,会使那些从来未被搜索到的解上的信息素减小到接近于0,搜索的随机性减弱,虽然收敛速度加快了,的那会使算法的全局性能降低,算法的稳定性差,容易出现过早停滞现象。\(m\)一般取\([10, 50]\).
在蚁群算法中,各个参数的作用实际上是紧密联系的,其中对算法性能起到主要作用的是信息启发式因子\(\alpha\)、期望启发式因子\(\beta\)和信息素挥发因子\(\rho\)这三个参数,总信息量\(Q\)对算法性能的影响有依赖于上述三个参数的选取,以及算法模型的选取。
在算法参数的选择上,对参数\(Q\)不必进行特别的考虑,可以任意选取。
最大进化代数\(G\)是表示蚁群算法运行结束条件的一个参数,表示蚁群算法运行到指定的进化代数之后就停止运行,并将当前群体中的最佳个体作为所求问题的最优解输出。一般\(G\)取\([100,500]\).
旅行商问题(TSP)。假设有一个旅行商人要拜访柳州20个景点,他需要选择所要走的路径,路径的限制是每个景点只能拜访一次,而且最后要回到原来出发的景点。路径的选择要求是:所选路径的路径为所有路径中最小的。
柳州20个景点的坐标为
citys =
109.4177 24.3085
109.4443 24.3086
109.4394 24.3089
109.4226 24.3090
109.4471 24.3092
109.4277 24.3093
109.4347 24.3101
109.4168 24.3102
109.4470 24.3167
109.4175 24.3186
109.4469 24.3230
109.4197 24.3240
109.4467 24.3285
109.4218 24.3313
109.4465 24.3350
109.4205 24.3372
109.4462 24.3392
109.4209 24.3397
109.4413 24.3415
109.4356 24.3418
因为个人不喜欢猪大肠的程序,所以我把原来书上的代码拆分成结构比较清晰的多文件。
项目目录如下图所示:

效果如下图所示:

主函数:
%% 旅行商问题(TSP)优化
%% 清空环境变量
clear; clc
%% 导入数据
% load citys_data.mat
load data.mat
citys = data;
%% 计算城市间相互距离
n = size(citys, 1);
D = distance(citys, n);
%% 初始化参数
m = 20; % 蚂蚁数量
alpha = 1; % 信息素重要程度因子
beta = 5; % 启发函数重要程度因子
rho = 0.2; % 信息素挥发因子
Q = 10; % 常系数
Eta = 1./D; % 启发函数
Tau = ones(n, n); % 信息素矩阵
Table = zeros(m, n); % 路径记录表
it = 1; % 迭代次数初值
G = 150; % 最大迭代次数
Route_best = zeros(G, n); % 各代最佳路径
Length_best = zeros(G, 1); % 各代最佳路径的长度
Length_ave = zeros(G, 1); % 各代路径的平均长度
citys_index = 1:n; % 给城市编号
%% 迭代寻找最佳路径
while it <= G
% 随机产生各个蚂蚁的起点城市
Table(:, 1) = randi([1 n], m, 1);
for i = 1:m
for j = 2:n
tabu = Table(i, 1:(j - 1)); % 已访问的城市集合(禁忌表)
allow = citys_index(~ismember(citys_index, tabu)); % 待访问的城市集合
P = allow;
% 计算城市间转移概率
for k = 1:length(allow)
P(k) = Tau(tabu(end), allow(k))^alpha * Eta(tabu(end), allow(k))^beta;
end
% 轮盘赌法选择下一个访问城市
Table(i,j) = allow(find(cumsum(P/sum(P)) >= rand, 1));
end
end
% 计算各个蚂蚁的路径距离
Length = getPathLength(m, n, Table, D);
% 计算最短路径距离及平均距离
[min_Length, min_index] = min(Length);
Length_ave(it) = mean(Length);
Route_best(it, :) = Table(min_index, :);
if it == 1
Length_best(it) = min_Length;
else
Length_best(it) = min(Length_best(it - 1), min_Length);
if Length_best(it) ~= min_Length
Route_best(it, :) = Route_best((it - 1), :);
end
end
% 更新信息素
Tau = updateTau(Tau, rho, m, n, Table, Q, Length);
it = it + 1;
end
%% 结果显示
[Shortest_Length, index] = min(Length_best);
Shortest_Route = Route_best(index, :);
disp(['最短距离:' num2str(Shortest_Length)]);
disp(['最短路径:' num2str([Shortest_Route Shortest_Route(1)])]);
%% 绘图
figure(1)
plot([citys(Shortest_Route, 1); citys(Shortest_Route(1), 1)],...
[citys(Shortest_Route, 2); citys(Shortest_Route(1), 2)], 'o-');
for i = 1:size(citys,1)
text(citys(i, 1), citys(i, 2), [' ' num2str(i)]);
end
text(citys(Shortest_Route(1), 1), citys(Shortest_Route(1), 2), ' 起点');
text(citys(Shortest_Route(end), 1), citys(Shortest_Route(end), 2), ' 终点');
xlabel('城市位置横坐标')
ylabel('城市位置纵坐标')
title(['蚁群算法优化路径(最短距离:' num2str(Shortest_Length) ')'])
figure(2)
plot(1:G, Length_best, 'b', 1:G, Length_ave, 'r-')
legend('最短距离','平均距离')
xlabel('迭代次数')
ylabel('距离')
title('各代最短距离与平均距离对比')
主函数调用的子函数如下所示:
function D = distance(citys, n)
%distance - 获取城市距离矩阵
%
% Syntax: D = distance(citys, n)
%
% Long description
D = zeros(n, n);
for i = 1:n
for j = 1:n
if i ~= j
D(i, j) = sqrt(sum((citys(i, :) - citys(j, :)).^2));
else
D(i,j) = 1e-4;
end
end
end
end
function Length = getPathLength(m, n, Table, D)
%getPathLength - Description
%
% Syntax: Length = getPathLength(m, n, Table, D)
%
% Long description
Length = zeros(m, 1);
for i = 1:m
Route = Table(i, :);
for j = 1:(n - 1)
Length(i) = Length(i) + D(Route(j), Route(j + 1));
end
Length(i) = Length(i) + D(Route(n),Route(1));
end
end
function Tau = updateTau(Tau, rho, m, n, Table, Q, Length)
%updateTau - 更新信息素
%
% Syntax: Tau = updateTau(Tau, rho, m, n, Table, Q, Length)
%
% Long description
Delta_Tau = zeros(n, n);
for i = 1:m
for j = 1:(n - 1)
Delta_Tau(Table(i, j),Table(i, j+1)) = Delta_Tau(Table(i, j),Table(i, j + 1)) + Q/Length(i);
end
Delta_Tau(Table(i, n),Table(i, 1)) = Delta_Tau(Table(i, n),Table(i, 1)) + Q/Length(i);
end
Tau = (1-rho) * Tau + Delta_Tau;
end
智能优化算法及其MATLAB实例 / 包子阳,余继周,杨杉编著.
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s
下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen
为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti
我正在开发一个类似微论坛的项目,其中一个特殊用户发布一条快速(接近推文大小)的主题消息,订阅者可以用他们自己的类似大小的消息来响应。直截了当,没有任何形式的“挖掘”或投票,只是每个主题消息的响应按时间顺序排列。但预计会有很高的流量。我们想根据它们引起的响应嗡嗡声来标记主题消息,使用0到10的等级。在谷歌上搜索了一段时间的趋势算法和开源社区应用示例,到目前为止已经收集到两个有趣的引用资料,但我还没有完全理解它们:Understandingalgorithmsformeasuringtrends,关于使用基线趋势算法比较维基百科页面浏览量的讨论,在SO上。TheBritneySpearsP
我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts
文章目录一.Dijkstra算法想解决的问题二.Dijkstra算法理论三.java代码实现一.Dijkstra算法想解决的问题解决的问题:求解单源最短路径,即各个节点到达源点的最短路径或权值考察其他所有节点到源点的最短路径和长度局限性:无法解决权值为负数的情况二.Dijkstra算法理论参数:S记录当前已经处理过的源点到最短节点U记录还未处理的节点dist[]记录各个节点到起始节点的最短权值path[]记录各个节点的上一级节点(用来联系该节点到起始节点的路径)Dijkstra算法步骤:(1)初始化:顶点集S:节点A到自已的最短路径长度为0。只包含源点,即S={A}顶点集U:包含除A外的其他顶
对于体育新闻中文文本的关键字提取,常用的算法包括TF-IDF、TextRank和LDA等。它们的基本步骤如下:1.TF-IDF算法: -将文本进行分词和词性标注处理。-统计每个词在文本中的词频(TF)。-计算每个词在整个语料库中出现的文档频率(DF)和逆文档频率(IDF)。-计算每个词的TF-IDF值,并按照值的大小进行排序,选择排名前几的词作为关键字。2.TextRank算法:-将文本进行分词和词性标注处理。-将分词结果转化成图模型,每个词语为节点,根据词语之间的共现关系建立边。-对图模型进行迭代计算,计算每个节点的PageRank值,表示该节点的重要性。-选择排名前几的节点作为关键字。3.
我正在尝试计算由二进制形式的1和0的P数表示的数字的数量。如果P=2,则表示的数字为0011、1100、0110、0101、1001、1010,所以计数为6。我试过:[0,0,1,1].permutation.to_a.uniq但这不是大数的最佳解决方案(P可以什么可能是最好的排列技术,或者我们是否有任何直接的数学来做到这一点? 最佳答案 Numberofpermutationcanbecalculatedusingfactorial.a=[0,0,1,1](1..a.size).inject(:*)#=>4!=>24要计算重复项,