1. 概述
混合蛙跳(SFL)算法是由M.Eusuff 和其他一些作者在2003年提出的。该算法结合了模因算法和粒子群算法的原理,其设计灵感来自一群青蛙在觅食过程中的行为。
SFL算法最初是作为一种求解组合优化问题的元启发式方法而开发的。它是基于数学函数和启发式搜索的使用。
SFL算法由几个相互作用的虚拟青蛙种群组成,称为模因复合体。虚拟青蛙是模因的宿主或载体,模因代表了文化进化的一个单元。每个模因复合体都使用类似于粒子群优化的方法进行独立的局部搜索,但重点是局部搜索。
为了支持全局探索,虚拟青蛙被周期性地混洗,并使用类似于混洗复杂进化(Shuffled Complex Evolution,SCE)算法的方法重组为新的模因。此外,随机虚拟青蛙在种群中被生成和替换,以允许随机生成改进的信息。
混合蛙跳是解决复杂优化问题的一种有效方法,它可以在各种应用领域实现最佳解决方案。在本文中,我们将介绍该算法的基本原理和应用,以及它的优点和局限性。
2. 算法
模因学(Memetics)是一种基于模因概念的进化信息传递模型的方法。模因(Memes)是基因的类似物,通过模仿、学习和其他方式在人与人之间传播文化信息。模因的概念和模因学的基础是由C.R. Dawkins 在1976年提出的。模因可以垂直传播——来自前辈、父母、教育者、书籍、文化文物等。模因在人与人之间、文化与文化之间的横向传播也是可能的。尽管模因是纯粹的信息,但它们的功能会导致人类行为的重大变化。
模因算法(M-算法,M-algorithms)是基于模因概念和新达尔文主义进化原理的混合种群元启发式搜索引擎优化算法。在M-算法的上下文中,模因是局部优化算法的实现,该算法在每次迭代或一定次数的迭代后细化当前解。M-算法可以被视为一种基于群体的全局搜索算法和一种或多种经典的或基于群体的局部优化算法的混合。最初,M-算法被提出作为提高遗传算法效率的选项之一。
M-算法的效率很大程度上取决于其自由参数的值。大量研究表明,所用模因的选择对这些算法的效率有很大影响。因此,这个问题在专门研究M-算法的工作中占据了中心位置之一。
模因代表了革命性的思想之一,暗示了基因进化与人类文化进化之间的相似性。Dawkins 认为,模因是文化交流的一个单位,相当于文化中的基因。模因可以是一个手势、一个单词或一个想法。任何可以通过模仿学习在人与人之间传递的文化信息单位都是模因。
模因算法与遗传算法不同,它模仿文化进化的过程。莫斯卡托的方法使用了模因进化的类比。模因算法包括以下几个阶段:局部搜索、合作、竞争和搜索终止准则。模因类是一类广泛的算法,由一个共同的想法统一起来:将个体的个体学习纳入遗传算法,并使用关于可能解的空间结构的信息。平衡总体和局部搜索的问题可以被视为在搜索空间的广泛和密集探索之间保持平衡的一般问题。
SFL优化算法的逻辑单元是青蛙。它可以用 S_Frog 结构来描述,该结构表示搜索空间中的代理。
S_Frog 结构包含以下字段:
c - 青蛙当前位置的坐标数组。
cPrev - 青蛙先前位置的坐标数组。
f - 青蛙当前位置的适应度函数。
fPrev - 青蛙先前位置的适应度函数。
frogStep - 青蛙所在步骤的编号。
//——————————————————————————————————————————————————————————————————————————————
struct S_Frog
{
void Init (int coords)
{
ArrayResize (c, coords);
ArrayResize (cPrev, coords);
f = -DBL_MAX;
fPrev = -DBL_MAX;
frogStep = 0;
}
double c []; //coordinates
double cPrev []; //previous coordinates
double f; //fitness
double fPrev; //previous fitness
int frogStep; //frog step
};
//——————————————————————————————————————————————————————————————————————————————
S_Memeplex结构描述了算法中的模因复合体。它包含以下字段:
frogs - 组成模因复合体的青蛙数组。
fBest - 模因复合体中所有青蛙的适应度函数的最佳值。
cBest - 与模因复合体中的适应度函数的最佳值相对应的坐标数组。
//——————————————————————————————————————————————————————————————————————————————
struct S_Memeplex
{
S_Frog frogs [];
double fBest; //best fitness
double cBest []; //best coordinates
};
//——————————————————————————————————————————————————————————————————————————————
C_AO_SFL类提供了初始化算法、移动蛙类和修改种群的方法。它还包含用于转换值和生成随机数的辅助方法。
让我们编写包含以下字段的SFL算法类:
cB - 存储最佳坐标的数组;
fB - 存储最佳坐标的适应度函数值的变量;
frogs - 存储种群中所有青蛙的数组;
mems - 存储模因(青蛙组)的数组;
rangeMax - 存储每个搜索坐标的最大值的数组;
rangeMin - 存储每个搜索坐标的最小值的数组;
rangeStep - 存储每个坐标的搜索步骤。
公有类方法:
Init - 用于初始化算法参数的方法,接受以下参数:
coordinatesNumberP - 搜索坐标的数量;
populationSizeP - 种群规模(青蛙数量);
numbMemsP - 模因的数量(青蛙群);
numbCyclesP - 模因复合体中的循环数;
frogStepsToLocalMaxP - 蛙步数达到局部最大值;
movConstantP - 青蛙的位移常数(搜索步长)。
Moving - 实现青蛙在搜索空间中移动的方法。
Revision - 实现对青蛙种群的修改并更新最佳坐标的方法。
SeInDiSp - 通过给定步骤将值从一个范围转换为另一个范围的辅助方法。
RNDfromCI - 在给定间隔内生成随机数的辅助方法。
私有类字段的描述:
coordinatesNumber - 搜索坐标的数量;
frogsNumber - 种群中青蛙的数量;
numbMems - 模因的数量(青蛙群);
numbCycles - 模因复合体中的循环数;
frogStepsToLocalMax - 蛙步数达到局部最大值;
movConstant - 蛙类的位移常数(搜索步长);
memsFrogs - 每个模因复合体中的青蛙数量;
numbCyclesCNT - 循环计数器;
vect - 存储向量的数组;
indexes - 存储索引的数组;
revision - 指示需要进行总体修订的标志。
//——————————————————————————————————————————————————————————————————————————————
class C_AO_SFL
{
//----------------------------------------------------------------------------
public: double cB []; //best coordinates
public: double fB; //FF of the best coordinates
public: S_Frog frogs []; //all frogs
public: S_Memeplex mems []; //memeplexes
public: double rangeMax []; //maximum search range
public: double rangeMin []; //manimum search range
public: double rangeStep []; //step search
public: void Init (const int coordinatesNumberP, //coordinates number
const int populationSizeP, //population size
const int numbMemsP, //number of memeplexes
const int numbCyclesP, //number of cycles in the memeplex
const int frogStepsToLocalMaxP, //frog steps to the local maximum
const double movConstantP); //movement step (0.0 .. 1.0)
public: void Moving ();
public: void Revision ();
//----------------------------------------------------------------------------
private: int coordinatesNumber; //coordinates number
private: int frogsNumber; //frogs number
private: int numbMems; //number of memeplexes
private: int numbCycles; //number of cycles in the memeplex
private: int frogStepsToLocalMax; //frog steps to the local maximum
private: double movConstant; //movement step (0.0 .. 1.0)
private: int memsFrogs; //number of frogs in the memplex
private: int numbCyclesCNT; //cycle counter
private: double vect []; //vector
private: int indexes []; //indexes
private: bool revision;
private: double SeInDiSp (double In, double InMin, double InMax, double Step);
private: double RNDfromCI (double min, double max);
};
//——————————————————————————————————————————————————————————————————————————————
要初始化算法,我们将使用Init初始化方法,该方法有几个参数:
coordinatesNumberP - 坐标数量
populationSizeP - 种群规模
numbMemsP - 模因复合体数量
numbCyclesP - 模因复合体中的循环数
frogStepsToLocalMaxP - 局部最大蛙步数
movConstantP - 移动步长(从0.0到1.0)
首先,该方法重置随机数生成器,并设置fB(-DBL_MAX)和revision(false)变量的初始值
接下来,该方法创建具有所需大小的rangeMax、rangeMin、rangeStep、vect、indexes、cB、frogs和mems数组。该方法使用传递坐标数的Init方法初始化frogs数组中的每个青蛙和mems数组中每个模因复合体中的每个青蛙。
然后,该方法在-DBL_MAX中设置每个模因复合体的fBest变量的初始值,并为每个具有所需大小的模因复合体创建cBest数组。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_SFL::Init (const int coordinatesNumberP, //coordinates number
const int populationSizeP, //population size
const int numbMemsP, //number of memeplexes
const int numbCyclesP, //number of cycles in the memeplex
const int frogStepsToLocalMaxP, //frog steps to the local maximum
const double movConstantP) //movement step (0.0 .. 1.0)
{
MathSrand ((int)GetMicrosecondCount ()); // reset of the generator
fB = -DBL_MAX;
revision = false;
coordinatesNumber = coordinatesNumberP;
frogsNumber = populationSizeP;
numbMems = numbMemsP;
numbCycles = numbCyclesP;
frogStepsToLocalMax = frogStepsToLocalMaxP;
movConstant = movConstantP;
memsFrogs = frogsNumber / numbMems;
numbCyclesCNT = 0;
ArrayResize (rangeMax, coordinatesNumber);
ArrayResize (rangeMin, coordinatesNumber);
ArrayResize (rangeStep, coordinatesNumber);
ArrayResize (vect, coordinatesNumber);
ArrayResize (indexes, frogsNumber);
ArrayResize (cB, coordinatesNumber);
ArrayResize (frogs, frogsNumber);
for (int i = 0; i < frogsNumber; i++)
{
frogs .Init (coordinatesNumber);
}
ArrayResize (mems, numbMems);
for (int i = 0; i < numbMems; i++)
{
ArrayResize (mems .frogs, memsFrogs);
for (int frgs = 0; frgs < memsFrogs; frgs++)
{
mems .frogs [frgs].Init (coordinatesNumber);
}
mems .fBest = -DBL_MAX;
ArrayResize (mems .cBest, coordinatesNumber);
}
}
//——————————————————————— |