本文主要是介绍《Nature-Inspired Metaheuristic Algorithms》——杜鹃搜索算法 CUCKOO SEARCH,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
杜鹃搜索算法
1.1杜鹃繁殖行为的生物现象
杜鹃鸟是一种迷人的鸟类,不仅因为它们能发出美丽的声音,还因为它们具有侵略性的繁殖策略。
杜鹃鸟的生殖策略是将自己的鸟蛋产在别的种类鸟的窝中,让别的鸟为杜鹃鸟帮忙孵化,并且等待小杜鹃鸟破壳而出的之后,小杜鹃鸟还会将别的鸟蛋推下巢穴,以保证自己一人独占食物。
雌性寄生杜鹃通常非常专门模仿一些选择的寄主卵的颜色和图案。这降低了它们的蛋被遗弃的可能性,从而提高了它们的繁殖能力。研究还表明,杜鹃鸟也可以模仿宿主雏鸟的叫声,以获得更多的进食机会。
1.2 概念引入
L´EVY FLIGHTS 列维飞行
各种研究表明,许多动物和昆虫的飞行行为已经显示出了列维飞行的典型特征。简单的来说,列维飞行更能模拟动物与人类的随机游走行为,并且具有更好的搜索能力。
Lévy flight 是随机游走的一种,它的每一步方向完全随机而各向同性,但步长的分布是重尾分布(heavy-tailed) 满足heavy tail分布函数,其特点是大多数情况下产生的随机步长都比较小,但是有很少情况下会突然增大,比如80%都是-3~3,20%情况下出现50、60这种,俗称为二八定律,也就是百分之二十的人占据百分之八十的资源,百分之八十的人只拥有百分之二十多资源。
从 • 开始的50步利维游走,图像如下
2.1 杜鹃搜索算法设计
为了简单地描述杜鹃搜索算法,我们现在使用以下三个理想化的规则:
- 每只杜鹃每次产一个蛋,然后把蛋扔在一个随机选择的巢穴里;
- 好的巢穴中的优质蛋能够顺利生存下去,直到成年繁殖下一代;
- 寄主巢的数量是固定的,杜鹃产下的卵有可能被寄主鸟发现,概率为p且p∈[0,1]。如果寄主鸟发现了杜鹃鸟的蛋不是自己的但,那么它可以毁掉蛋,或者简单地放弃巢,建立一个全新的巢。
作为进一步的近似,最后一个假设可以用n个宿主巢的一部分百分之p被新的巢所取代来近似。(这也是同一个意思,并且便于编写代码)
2.2 杜鹃搜索算法伪代码
获取目标函数f(x) 初始化n个宿主巢穴
while(t < MaxGeneration)or(stop criterion)
一只杜鹃i通过列维飞行随机生成一个解(也就是egg)并且计算其适应度函数值Fi
随机选择一个宿主巢穴j,计算其适应度函数值Fj
if(Fi > Fj)
用解i替换解j
end if
一小部分(百分之pa)较差的巢穴被遗弃并且重新生成新的解
保留最佳的解决方案(或拥有高质量解决方案的宿主巢穴)
对解决方案进行排名,并找到当前最好的解决方案
end while
后处理结果和可视化
以上2.2节依我之愚见实在不能理解,其中杜鹃蛋,宿主巢穴,杜鹃之间到底是什么,有何关系看的我一头雾水。之所以写出来是因为Yang教授在《Nature-Inspired Metaheuristic Algorithms》中就是这样写的,我只是完完整整地翻译了下来。下面是我自己根据Yang教授的例子以及代码对杜鹃算法的理解。
3.1 杜鹃搜索算法的应用
最简单情形下的一个例子:
z=(1-u(1)) ^2+100*(u(2)-u(1) ^2) ^2,求Zmin。
代码及注释:
% -------------------------------------------------------
% Cuckoo algorithm by Xin-She Yang and Suasg Deb % % Programmed by Xin-She Yang at Cambridge University % % -------------------------------------------------------
function [bestsol,fval]=cuckoo_search(Ngen)
% Here Ngen is the max number of function evaluations
if nargin<1, Ngen=1500; end%迭代次数1500次
% d-dimensions (any dimension)
d=2;%二维问题
% Number of nests (or different solutions)n=25;%巢穴数量25
% Discovery rate of alien eggs/solutions
pa=0.25;%被发现的比例0.25
% Random initial solutions
nest=randn(n,d);%最初的每个巢穴进行初始化 每个坐标都是随机数
fbest=ones(n,1)*10^(100) % minimization problems 最初的fbest极大,fbest存的是最优
Kbest=1;
%整体相当于是:每次迭代随机选择一个最优之外的巢穴k,在这个k巢穴附近生成一个新的巢穴s
%(这里使用的是随机游走生成一个步长,然后从k巢穴出发移动步长的距离*(0~1)随机数,到这个新的坐标就是生成的新巢穴s)
%计算这个新巢穴s的适应度函数值,如果他比原先的k巢穴更优,那么则在nest中更新nest[k]的坐标为s,在fbest中更新fbest[k]=s的适应度函数值
for j=1:Ngen,% Find the current bestKbest=get_best_nest(fbest);%返回值Kbest为fbest中最小的那个数的下标% Choose a random nest (avoid the current best)k=choose_a_nest(n,Kbest);%k=除了当前最佳那个巢穴之外的任意随机一个巢穴的下标(索引) bestnest=nest(Kbest,:);%bestnest中存的是最佳巢穴的坐标% Generate a new solution (but keep the current best)s=get_a_cuckoo(nest(k,:),bestnest);%s为最佳巢穴附近的一个新巢穴(由之前的k确定的)% Evaluate this solutionfnew=fobj(s);%fobj计算适应度函数值的函数:对这个最佳巢穴附近的新巢穴的适应度函数值进行计算if fnew<=fbest(k),%如果这个新巢穴比之前的最优巢穴更优秀的话 就用和这个新巢穴作为最优巢穴fbest(k)=fnew;%fbest存的是最优的巢穴的适应度函数值nest(k,:)=s;%nest中存的是每个巢穴的坐标,现在k巢穴被这个k附近的新巢穴替换掉,坐标也更新为这个附近的新巢穴end
% discovery and randomization
if rand<pa,%如果rand<pa则说明被发现了,最差的那个巢穴就被抛弃(也即是换一个新巢穴,更新位置)k=get_max_nest(fbest);%找到最差的那个巢穴,这里是求最小值,所以就是找最大值s=emptyit(nest(k,:));%以最差巢穴的位置为起点进行一次位置更新,更新方式依然是随机游走(为了简化而没有使用levy flight)nest(k,:)=s;%将更新后的位置存入nest中fbest(k)=fobj(s);%将更新后的适应度函数值存入fbest中
end
end%% Post-optimization processing
%% Find the best and display
[fval,I]=min(fbest)%fval存的是最优解的适应度函数,I中存的是最优解在nest中的下标
bestsol=nest(I,:)%bestsol即是最优解的坐标
%% Display all the nests
nest%% --------- All subfunctions are listed below -----------
%% Choose a nest randomly
function k=choose_a_nest(n,Kbest)
k=floor(rand*n)+1;
% Avoid the best
if k==Kbest,k=mod(k+1,n)+1;
end%% Get a cuckoo and generate new solutions by ramdom walk
function s=get_a_cuckoo(s,star)
% This is a random walk, which is less efficient
% than Levy flights. In addition, the step size
% should be a vector for problems with different scales.
% Here is the simplified implementation for demo only!
%这里使用的是随机游走来获取步长,这样效率更低但是只是为了简化这个demo,便于理解算法结构
stepsize=0.05;
s=star+stepsize*randn(size(s));%% Find the worse nest
function k=get_max_nest(fbest)
[fmax,k]=max(fbest);
%% Find the current best nest
function k=get_best_nest(fbest)
[fmin,k]=min(fbest);%返回值k为fbest中最小那个数的下标
%% Replace some (of the worst nests)
%% by constructing new solutions/nests
function s=emptyit(s)
% Again the step size should be varied
% Here is a simplified approach
% 同样是为了简化 使用的随机游走而非levy flight 生成一个新的步长
s=s+0.05*randn(size(s));
% d-dimensional objective function
function z=fobj(u)
% Rosenbrock’s function (in 2D)
% It has an optimal solution at (1.000,1.000)
z=(1-u(1))^2+100*(u(2)-u(1)^2)^2;
整体相当于是:
①初始化巢穴nest中存储解的坐标;fbest存储解的适应度函数值。
②每次迭代随机选择一个除最优巢穴之外的巢穴k,在这个k巢穴附近生成一个新的巢穴s(这里使用的是随机游走生成一个步长step,然后从k巢穴作为起始点,移动步长step乘一个随机数(0~1),到了这个新的坐标就是生成的新巢穴s)
③计算这个新巢穴s的适应度函数值,如果他比原先的k巢穴更优,那么则在nest中更新nest[k]的坐标为s,在fbest中更新fbest[k]=s的适应度函数值。
④有pa的概率最差的蛋会被发现,被发现之后这个最差的蛋会被更新,更新方式是使用随机游走生成一个新步长step(正确的是使用levy flight这里是为了简化而使用的随机游走),以这个最差的蛋为起点,移动step X 一个随机数(0~1)长的距离,这个新的位置就是更新之后的新坐标。
然后用新坐标更新到nest与fbest中。
继续下一次迭代
⑤迭代结束得到最优解以及最优解的坐标。
在原文中其实也提到过
从实现的角度来看,我们可以使用以下简单的表示,每个蛋代表一个解决方案,和每个杜鹃只能下一个蛋(因此代表一个解决方案),目的是使用新的和潜在的更好的解决方案(杜鹃)取代一个不太好的解决方案。显然,这个算法可以扩展到更复杂的情况,即每个巢都有多个鸡蛋代表一组解决方案。对于目前的工作,我们将使用最简单的方法,即每个巢穴只有一个蛋。在这种情况下,蛋、巢或杜鹃之间没有区别,因为每个巢对应一个蛋,也代表一个杜鹃。
也就是说,杜鹃蛋,宿主蛋,巢穴,杜鹃都是一个含义,其实都是解的意思。
个人感觉:这个杜鹃搜索算法和杜鹃的生物现象确实有点牵强附会了,很难将代码和现实联系起来。其实最主要的就是三点:
①每次在最优解之外随机找一个解进行更新
②更新方式为levy flight
③有pa的概率将最差解进行更新(更新方式依然为levy flight,也就是所说的被宿主发现了)
这篇关于《Nature-Inspired Metaheuristic Algorithms》——杜鹃搜索算法 CUCKOO SEARCH的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!