1. 概述
自然界一直是许多元启发式算法的灵感来源。 它设法在没有提示的情况下,基于个体经验找到问题的解决方案。 自然选择和适者生存是创建早期元启发式算法的主要动机。 在自然界中,动物以多种方式相互交流。 萤火虫则是利用眨眼的能力进行交流。 大约有 2000 种萤火虫,都拥有自己特殊的闪烁图案。 它们通常会产生具有特定图案的短闪烁。 光亮及其强度成为称为生物发光的生化过程的成果。 据信,这种闪烁的主要功能是求偶和吸引潜在的受害者。 一些热带萤火虫可以同步它们的闪烁,从而展示了生物自组织的一个例子。 光亮的强度作为与其光源距离的函数,遵循平方反比定律,因此来自萤火虫的闪烁光线会导致它周围的萤火虫在闪烁的视线范围内做出反应。
受萤火虫行为启发的种群优化算法有两种变体:萤火虫算法,和萤火虫群优化(GSO)算法。 萤火虫(firefly)和发光甲虫(glowworms)的主要区别在于后者是无翅的。 在本文中,我们将研究前一种类的优化算法。
2. 算法说明
萤火虫算法(F-算法)由 X-Sh. Yang 于 2007 年在英国剑桥大学提出,并立即引起了优化研究人员的注意。 萤火虫算法是群体智能算法家族的一部分,最近在解决优化问题方面取得了令人印象深刻的成果。 特别是,萤火虫算法在求解连续和离散优化问题的能力。 萤火虫算法基于真实萤火虫的闪烁特性,有三条规则。 规则如下:
-
所有萤火虫都会朝着更有吸引力和更明亮的对应物移动。
-
萤火虫的吸引力程度与其亮度成正比,由于空气吸收光线的事实,随着与另一只萤火虫的距离增加,亮度会降低。 故此,在任何两只闪烁的萤火虫之间,不太亮的萤火虫会向较亮的萤火虫移动。 如果没有更亮或更具吸引力的对应物,则萤火虫将随机移动。
-
萤火虫的亮度或光线强度由问题的目标函数的值决定。
最初,在算法开始时,所有萤火虫都随机分散在整个搜索空间当中。 然后,该算法根据两个阶段判定最佳分区:
-
光线强度的变化 — 萤火虫在其当前位置的亮度反映在其适应性值中,朝着有吸引力的萤火虫移动。
-
萤火虫通过观察邻近萤火虫的光线强度来改变其位置。
现在,我们可以更详尽地深入了解萤火虫优化的复杂性。 该算法本质上如图例 1 所示。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
图例 1. 搜索空间中的萤火虫。 能见度随着距离的增加而降低
搜索原理背后的主要思路是随着萤火虫之间距离的增加,能见度呈非线性降低。 如果没有这种非线性关系,每只萤火虫都会确定性地向更明亮的光源移动。 然而,正如我们在图例 1 中看到的,萤火虫不会选择其最亮的近邻,因为由于环境对光线的吸收,它发出的光线很难被注意到。 取而代之,它选择了一个不太明亮的对应物(尽管是其环境中最亮的)。 此特征解释了算法划分为较小群落的良好能力。 由于远距离光吸收的非线性函数,这现象会很自然地发生。 在下面的图例 2 中,我们可以看到具有不同 gamma 介质吸收系数值的算法的可见性与距离的函数,这是算法参数之一。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
图例 2. 介质透明度与距离f(x) 的函数,其中 gamma 透明度系数分别等于 1.0、0.2、0.05、0.01。
当 gamma 趋于无穷大时,环境变得不透明;当 gamma 为零时,环境是完全透明的;每只萤火虫在搜索空间中的任何距离都能看到对方。 如果 gamma = 0.0 会发生什么? 所有的萤火虫都会飞到最明亮的相对位置,汇聚到某个非最佳点。 如此,算法不会收敛停留在某个局部极值。 如果环境完全不透明,会发生什么情况? 萤火虫不会看到比自己更有吸引力的同类。 根据算法作者提出的概念,看不到比自己更好的同类,那么萤火虫就会随机移动。 该算法将退化为随机搜索。 在我们的算法分类评级表格中,随机搜索算法排在最后。
我们来深入分析算法,并考虑描述萤火虫运动的方程。 能见度与距离的函数是计算所谓吸引力指数的基础:
attractiveness = fireflies [k].f / (1.0 + gamma * distance * distance);
其中: attractiveness - 吸引力,不言自明 gamma - 环境不透明度系数 distance - 萤火虫之间的欧氏距离 fireflies [k].f - 第 k 只萤火虫的光线强度
该方程清楚地表明,吸引力函数直接取决于问题的维度和距离值的限制,因此该算法的作者建议为特定的优化问题选择透明度系数。 我认为,在事先不知算法将如何表现的情况下就这样做,既不方便又耗时;因此我认为有必要对 0 到 20 范围内的距离值进行规范化。 为达此目的,应用我们在其它算法中反复使用的 Scale() 函数。 在计算吸引力之前,“distance” 的转换如下所示:
distance = Scale (distance, 0.0, maxDist, 0.0, 20.0, false);
其中:
maxDist — 在一对萤火虫之间的最大欧几里得距离
在这种情况下,萤火虫的吸引力将不取决于问题的维度,也无需为特定的优化问题选择 gamma 系数。 吸引力函数判定每只萤火虫将做出什么样的配偶选择。 这个选择是有严格判定的。 萤火虫相互吸引力的影响决定了 beta 系数(算法的第二个参数)。 如果在每次迭代中萤火虫已经提前确定了相应的选择,如何确保算法的搜索能力? 为此,引入了随机向量分量,和第三个算法参数(alpha)。 萤火虫的复杂行为关系如下所示:
fireflies [i].c [c] = Xj + beta * (Xi - Xj) + alpha * r * v [c];
其中: fireflies [i].c [c] - 第 i 个萤火虫的第 c 个坐标 beta - 萤火虫吸引力影响系数 alpha - 当萤火虫移动时影响随机分量的系数,给出与移动目标的偏差 r - 范围 [-1.0;1.0] 内的随机数 v[c] - 向量分量,通过第 c 个坐标表征搜索范围极点之间的距离 Хj - 萤火虫对中的对应坐标,其将有运动 Xi - 计算运动的萤火虫的对应坐标
现在是时候讲述算法代码了。 它相对简单。 我们来研究细节。
萤火虫将用一个简单的结构来描述 S_Firefly,该结构具有两个组成部分,即 c[] - 坐标,f - 萤火虫的亮度(适应度函数)。 鉴于对于每只萤火虫,在相应的迭代中只有单一个体,它移动后会形成新的配对,因此在计算下一次移动时,我们不会冒覆盖坐标的风险。 为此目的,我将引入下面研究的特殊结构。
//—————————————————————————————————————————————————————————————————————————————— struct S_Firefly { double c []; //coordinates double f; //the value of the fitness function }; //——————————————————————————————————————————————————————————————————————————————
S_Attractiveness 结构的用意是存储成对的吸引力值和相应萤火虫的数量。 每只萤火虫不会朝向最吸引人的萤火虫的坐标移动,而是朝向其伙伴已经移动的坐标。 这与作者描述的算法版本存在一些差异,但这就是它能更好地工作的方式。
//—————————————————————————————————————————————————————————————————————————————— struct S_Attractiveness { double a; //attractiveness int i; //index of the most attractive firefly }; //——————————————————————————————————————————————————————————————————————————————
萤火虫算法由 C_AO_FA 类进行定义。 这里有三个公开方法,其中一个是用于初始初始化的 Init(),两个需要在每次迭代时调用的公开方法 — Flight() 和 Luminosity(),私密帮助方法,和存储参数常量的成员。
//—————————————————————————————————————————————————————————————————————————————— class C_AO_FA { //---------------------------------------------------------------------------- public: S_Firefly fireflies []; //fireflies public: double rangeMax []; //maximum search range public: double rangeMin []; //minimum search range public: double rangeStep []; //step search public: double cB []; //best coordinates public: double fB; //FF of the best coordinates public: void Init (const int paramsP, //number of opt. parameters const int sizeP, //swarm size const double alphaP, //alpha, randomness in motion const double betaP, //beta, effect of attractiveness const double gammaP); //gamma, transparency of the environment public: void Flight (); public: void Luminosity (); //---------------------------------------------------------------------------- private: S_Attractiveness att []; private: int swarmSize; private: int params; private: double maxDist; private: double v []; private: double alpha; //randomness in motion private: double beta; //effect of attractiveness private: double gamma; //transparency of the environment private: bool luminosity; private: double SeInDiSp (double In, double inMin, double inMax, double step); private: double RNDfromCI (double min, double max); protected: double Scale (double In, double InMIN, double InMAX, double OutMIN, double OutMAX, bool revers); }; //——————————————————————————————————————————————————————————————————————————————
Init() 公开方法用于初始化,应在每次优化开始之前调用。 其参数是算法的补充参数。 该方法将为数组分配内存,并重置全局和每个单独萤火虫的光线亮度值。