竞争性学习算法(CLA)
目录
引言
在过去的几十年里,人们提出了许多受生物启发的算法,从蚁群算法、粒子群算法到灰狼算法和鲸鱼算法。然而,人类社会因其复杂的社会互动,也可以成为有效优化方法创意的丰富源泉。这一思想正是竞争性学习算法(CLA)的基础。
CLA 采用了教育过程的隐喻,其中解决方案的集合由按班级组织的学生来表示。该算法巧妙地模拟了三种学习类型:向班级中最优秀的人(老师)学习、从个人经验中学习以及通过跨班级互动学习。这种方法在探索搜索空间和利用已发现的良好解决方案之间取得了平衡,这对于有效优化至关重要。
在本文中,我们将详细研究 CLA 的原理、数学基础和实现特点,并在我们的标准测试函数上将其有效性与其他流行的元启发式算法进行比较。
算法的实现
竞争性学习算法是基于学校教育过程的隐喻而构建的。在这个隐喻中,学生代表优化问题的可能解,班级是学生群体,教师是每个班级中最优秀的学生,知识对应于搜索空间中的坐标,而分数则由适应度函数的值决定。
该算法从初始化开始,这可以与学年的开始相类比。例如,创建一个由 198 名学生组成的学生群体,并将其分为 9 个班级,每个班级 22 名学生。每个学生都被随机分配初始“知识” — 搜索空间中的坐标。
学习过程是迭代的,每次迭代时,学生都会通过三种不同的方式进行学习。第一种方法是教师主导学习,每个学生向班上表现最好的同学学习,班级表现越差,学习过程就越活跃,但随着时间的推移,每个人的学习强度都会降低。第二种方法是个人训练,仅在第四次迭代后开始。在这种模式下,学生回顾过去四“课”的最佳成绩,并尝试回到自己的历史最优位置。第三种方法是从其他班级学习,同样在第四次迭代后开始。学生有 50% 的概率向所有班级中的平均教师学习,这有助于避免陷入局部最优解。
每个训练周期结束后,都会对进度进行评估。每个班级中表现最好的学生会被选出并担任教师,同时会综合考虑所有学生的表现来计算班级的整体评分,并更新找到的全局最优解。
该算法使用五个关键参数:
- popSize — 学生总数,
- numClasses — 班级数量,
- beta — 班级所有学生对班级整体评分的影响,
- gamma — 从其他班学习的概率,
- deltaIter — 在此之后,迭代扩展学习开始,利用个人经验和班级间互动。
该算法实现了多种智能机制。自适应学习因素为学习进度较慢的班级提供更密集的学习,并随着时间的推移逐渐减缓学习进度,这与真实教育过程中的情况相符。探索与利用之间的平衡是通过在早期阶段积极探索,随后专注于已找到的最佳解决方案来实现的。记忆机制使算法能够记住每个学生的历史记录,并在必要时回顾过去的优良解。
从数学角度来看,学生的知识更新可以表示为当前知识与三个组成部分之和:来自班级教师的指导、个人历史经验以及从所有班级的平均教师那里获得的知识。这个公式在跟随领头人、利用个人经验和探索新领域之间取得了平衡。
最终,算法的有效性取决于多种因素。多样性是通过多个班级探索搜索空间中的不同方向来实现的。学生之间竞争教师职位可以促进更好的解决方案。通过班级间的知识共享进行合作,有助于防止过早趋同。自适应功能为弱势班级提供额外帮助,记忆机制存储有关良好解决方案的信息。
图1.算法运行过程
该算法运行过程的说明描述了三个主要步骤:初始化、训练阶段和更新评估。现在让我们开始编写 CLA_L 算法的伪代码。
我们需要提前准备:
- 198 名学生(我们的解决方案)
- 9 个班级(学生小组)
- 参数 β = 0.9(班级里所有学生的重要性)
- 参数 γ = 0.5(从其他班级学习的机会)
- 第四次迭代之后,增加其他类型的学习
- 用于评估解决方案质量的函数
让我们开始吧:
1.创建一所学校:
- 将 198 名学生分成 9 个班级(每班 22 人)
- 给每个学生在搜索空间中随机分配一个初始位置。
- 每个班级选出最优秀的学生 — 他们将成为老师
- 创建一个日志,记录每个学生的历史记录
2.学习过程(迭代过程):
第 1 步:确定学习强度
- 对于每一节课,我们都会计算出学生需要以多活跃的程度来学习
- 成绩较差的班级(排名较高)需要进行更强化的学习。
- 随着时间的推移,每个人的学习强度都会降低(就像在现实生活中一样)
第 2 步:找到“平均教师”
- 获取所有教师的位置
- 计算它们的平均值
- 这将成为全校范围内的知识标准
第 3 步:每个学生学习:
对于每位学生:
a) 总是向自己的老师学习:
- 看看班级教师在哪里
- 朝他们的方向移动
- 移动速度取决于课堂学习因子
b) 经过第四次迭代后,我们回顾了我们的经验:
- 查看日志:在过去的 4 次课中,我哪次最好?
- 用某种随机的力量,回到那个位置
- 这有助于保存好的解决方案。
c) 经过 4 次迭代后,向其他班级学习:
- 抛硬币(概率为 50%)
- 如果硬币反面朝上,我们就看看“平均教师”的情况。
- 向该平均位置小幅移动
- 这有助于班级之间交流经验。
第 4 阶段:对所有学生进行评估
- 每个学生都会获得一个适应度值
- 位置越好,评分越高
第 5 步:更新学校层级结构
针对每个班级:
- 找到一位新的最佳学生 — 他们将成为老师。
- 计算班级的整体水平:
* 评估教师的适应度值
* 将所有学生的平均分相加(乘以 β)
- 确定班级排名:
* 最好的班级名次较低(1、2、3……)
* 最差的班级名次较高
第 6 步:记住最佳解决方案
- 如果某个老师比我们记录的水平更高
- 将其保存为新记录
第 7 步:保存历史
- 保存所有学生的当前位置
- 这将是个人训练所必需的
3.结束:
- 返回找到的最佳解决方案
- 及其适应度值
现在我们开始编写算法代码。C_AO_CLA_l 类继承自父类 C_AO,并实现了基于竞争性学习概念的算法。该类包含多个用户可配置的参数:
- popSize — 群体规模(“代理”或“学生”的数量);
- numClasses — 代理被划分到的班级数量;
- beta — 可能影响学习或适应速度的参数;
- gamma — 另一个与学习过程相关的参数;
- deltaIter — 从第几次迭代之后开始启用扩展学习(个人经验与班级间交互)。
构造函数初始化主要参数,设置算法的名称和描述,指定变量的默认值,并设置 “params” 数组的大小,该数组用于存储有关算法参数的信息。
方法:
- SetParams() 使用 “params” 数组中的值更新类的内部变量(算法参数)的值。这样就可以更改外部设置的参数。
- Init() — 初始化算法。接受参数以定义参数更改的边界和步长。
- Moving() — “Moving” 代理的主要方法(执行算法的迭代和步骤)。
- Revision () — 方法与纠正或改进决策有关。
- Injection() — 将新知识或数据插入代理的方法。
- numClasses、beta、gamma、deltaIter — 算法参数。
- currentIter、studentsPerClass、totalIters — 用于控制算法流程的内部变量。
- teachers [] — 表示每个班级(锚点)中“教师”的 S_AO_Agent 结构数组。
- classRanks [] — 反映班级表现的班级排名。
- classTotalCosts [] — 总成本或每个类的 “cost”。
- CL [] — 用于计算教师平均知识水平的临时数组。
- UpdateTeachersAndCosts () — 用于更新教师及其成本信息的内部方法。
- UpdateClassRanks () — 用于更新班级排名的内部方法。
- UpdateStudentsKnowledge () — 用于更新知识或 “students” 参数的内部方法。
//———————————————————————————————————————————————————————————————————— class C_AO_CLA_l : public C_AO { public: //---------------------------------------------------------- ~C_AO_CLA_l () { } C_AO_CLA_l () { ao_name = "CLA_L"; ao_desc = "Competitive Learning Algorithm"; ao_link = "https://www.mql5.com/en/articles/18857"; popSize = 198; numClasses = 3; beta = 0.3; gamma = 0.8; deltaIter = 2; ArrayResize (params, 5); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "numClasses"; params [1].val = numClasses; params [2].name = "beta"; params [2].val = beta; params [3].name = "gamma"; params [3].val = gamma; params [4].name = "deltaIter"; params [4].val = deltaIter; } void SetParams () { popSize = (int)params [0].val; numClasses = (int)params [1].val; beta = params [2].val; gamma = params [3].val; deltaIter = (int)params [4].val; } bool Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0); void Moving (); void Revision (); void Injection (const int popPos, const int coordPos, const double value) { } //------------------------------------------------------------------ int numClasses; double beta; double gamma; int deltaIter; private: //--------------------------------------------------------- int currentIter; int studentsPerClass; int totalIters; // Structures for classes S_AO_Agent teachers []; double classRanks []; double classTotalCosts []; // Temporary array double CL []; // Average knowledge of teachers // Auxiliary methods void UpdateTeachersAndCosts (); void UpdateClassRanks (); void UpdateStudentsKnowledge (); }; //————————————————————————————————————————————————————————————————————
C_AO_CLA_l 类的 Init() 方法在算法开始工作之前对其进行初始化。这项工作的逻辑分为几个阶段。 标准初始化:调用 StandardInit() 方法,对优化算法执行标准初始化。它接收 rangeMinP、rangeMaxP 和 rangeStepP 这三个步长参数。如果标准初始化失败,Init() 方法将返回 “false”。
算法参数初始化:将当前迭代计数器重置为 “0”,使用 epochsP 参数中传递的值设置算法应执行的总迭代次数,通过将种群大小除以班级数量来计算每个班级中的 “学生”(代理)数量。接下来,该方法会检查每个班级是否至少有一名学生。接下来,“for” 循环初始化种群中的每个个体。在 Init() 方法中,通过数组 a 对每个代理进行初始化。
“for” 循环为每个班级初始化一个“教师”,将每个班级的排名设置为1.0,并将每个班级的初始“成本”设置为负最大值,以确保以后能找到更好的解决方案。如果所有初始化步骤都成功,该方法将返回 “true”。
//———————————————————————————————————————————————————————————————————— bool C_AO_CLA_l::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ currentIter = 0; totalIters = epochsP; studentsPerClass = popSize / numClasses; if (studentsPerClass < 1) { Print ("Error: Too few students per class"); return false; } // Adjust the population size //spopSize = studentsPerClass * numClasses; ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); // Initialize class structures ArrayResize (teachers, numClasses); ArrayResize (classRanks, numClasses); ArrayResize (classTotalCosts, numClasses); for (int i = 0; i < numClasses; i++) { teachers [i].Init (coords); classRanks [i] = 1.0; classTotalCosts [i] = -DBL_MAX; } // Temporary array ArrayResize (CL, coords); return true; } //————————————————————————————————————————————————————————————————————
C_AO_CLA_l 类的 Moving() 方法实现了主优化算法的一次迭代,检查是否是第一次迭代,如果是第一次迭代(即 “revision” 为 “false”),则该方法将种群中所有代理的位置初始化为给定范围内的随机值。它遍历种群中的所有代理,并对每个代理遍历其所有坐标。
对于每个坐标,该方法使用 u.RNDfromCI() 方法生成一个介于 rangeMin[c] 到 rangeMax[c] 之间的随机值 “val”,该方法提供了一个生成随机数的函数。它将 “val” 赋值给 “i” 代理的 a[i].c[c] 坐标,此前已对其进行“修剪”,使其在可接受的范围内,并与给定的 rangeStep[c] 步相对应。使用 u.SeInDiSp() 方法,该方法执行值检查和调整。
初始化种群后,会设置一个标志来指示初始化已完成。如果这不是第一次迭代,则当前迭代计数器加一。调用 UpdateStudentsKnowledge() 方法来实现根据 CLA_L 算法中使用的竞争性学习原则训练或调整代理的主要机制。该方法的逻辑决定了代理如何交互、交换信息以及在解决方案搜索空间中如何改善自身位置。
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::Moving () { // Initial population setup if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { double val = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } currentIter++; // Update students' knowledge UpdateStudentsKnowledge (); } //————————————————————————————————————————————————————————————————————
UpdateStudentsKnowledge() 方法负责在优化过程中更新每个学生(代理)的位置。计算当前优化进度。计算两个关键学习因子:
- TF(教学因子)— 显示学生从老师那里学到了多少东西。
- CF(参照学习因子)— 显示学生在多大程度上考虑了教师的平均知识水平。这些因子取决于学生的学习进度和班级排名。
接下来,计算所有“活跃”教师(结果有效的教师)坐标的平均值。这些平均知识值存储在一个临时数组中。对于每个学生(代理),确定该学生所属的班级,并为每个学生的坐标,通过将当前坐标与“知识来源”相加来计算新的学生位置。学生通过调整自己的位置来向老师学习,调整的幅度与老师的坐标和自己的坐标之差成正比,再乘以 TF。如果经过了足够的迭代(currentIter > deltaIter),并且学生得到了“最佳解决方案”,那么学生就会从之前的成功经验中学习,将自己的位置调整到最佳坐标,并乘以一个随机因子。
如果迭代次数足够且教师数量有效,学生将从所有教师的平均知识中学习,以一定的概率(1-gamma)朝着平均坐标乘以 CF 的方向调整其位置。对每个学生的坐标施加边界(约束),以确保其值在可接受范围内。根据搜索抽样步骤,调整该值以匹配可接受的值。
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::UpdateStudentsKnowledge () { // Calculate learning factors for the current iteration double progress = (double)currentIter / (double)MathMax (totalIters, 100); // Calculate the average knowledge of all teachers (CL) ArrayInitialize (CL, 0.0); int validTeachers = 0; for (int k = 0; k < numClasses; k++) { // Make sure the teacher is initialized if (teachers [k].f > -DBL_MAX) { for (int c = 0; c < coords; c++) { CL [c] += teachers [k].c [c]; } validTeachers++; } } if (validTeachers > 0) { for (int c = 0; c < coords; c++) { CL [c] /= validTeachers; } } // Update each student for (int i = 0; i < popSize; i++) { int classIdx = i / studentsPerClass; // Teaching Factor - decreases with progress double TF = MathExp (-0.6 * progress * classRanks [classIdx]); TF = MathMax (0.1, MathMin (1.0, TF)); // Confirmatory Factor double CF = MathExp (-0.5 * progress * classRanks [classIdx]); CF = MathMax (0.1, MathMin (1.0, CF)); // Update the student position for (int c = 0; c < coords; c++) { double newPos = a [i].c [c]; // a) Teacher Learning - learn from the class teacher if (teachers [classIdx].f > -DBL_MAX) { newPos += TF * (teachers [classIdx].c [c] - a [i].c [c]); } // b) Personal Learning - learn from your best solution if (currentIter > deltaIter && a [i].fB > -DBL_MAX) { double PF = u.RNDprobab (); newPos += PF * (a [i].cB [c] - a [i].c [c]); } // c) Confirmatory Learning - learn from the average of all teachers if (currentIter > deltaIter && validTeachers > 0) { double rnd = u.RNDprobab (); if (rnd >= gamma) // Participate with probability (1-gamma) { newPos += CF * (CL [c] - a [i].c [c]); } } // Apply borders a [i].c [c] = u.SeInDiSp (newPos, rangeMin [c], rangeMax [c], rangeStep [c]); } } } //————————————————————————————————————————————————————————————————————
C_AO_CLA_l 类中的 Revision() 方法用于更新每个代理的最佳解决方案的信息,以及更新全局最佳解决方案和相应的参数。
对于每个代理,检查其当前目标函数(a[i].f)是否比其记忆中的最佳值(a[i].fB)有所改进。如果符合条件,则保存最佳值并复制相应的坐标。检查所有代理后,如果其中任何一个代理的函数值优于当前全局最大值(fB),则更新全局参数:fB 为全局最佳函数值,cB 为该最佳解的坐标。
接下来,调用 UpdateTeachersAndCosts() 方法,该方法会更新有关最佳教师的信息。最后,调用 UpdateClassRanks() 来重新计算班级排名,这会影响后续迭代中选择某些解决方案的优先级。
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::Revision () { for (int i = 0; i < popSize; i++) { // Update personal best positions if (a [i].f > a [i].fB) { a [i].fB = a [i].f; ArrayCopy (a [i].cB, a [i].c); } // Update the global best one if (a [i].f > fB) { fB = a [i].f; ArrayCopy (cB, a [i].c); } } // Update teachers UpdateTeachersAndCosts (); // Update class ranks UpdateClassRanks (); } //————————————————————————————————————————————————————————————————————
UpdateTeachersAndCosts() 方法用于更新每个班级中教师的信息,并计算班级的总“成本”。该方法会遍历系统中定义的所有班级。对于每个班级,确定该班级中包含的学生(代理)的初始索引和最终索引。
为了找出班上最好的学生,初始化变量来存储最佳函数值、最佳学生的索引、班上所有学生的函数值之和以及有效学生的数量。该循环会遍及当前班级的所有学生。对于每个学生,检查其解决方案是否有效,如果解决方案有效,则:将该学生的适应度值添加到 sumFitness 中,有效学生的计数器加一,如果当前学生的特征值优于当前最佳值 bestFitness,则更新 bestFitness 并更新 bestIdx。
在找到班上最好的学生后,检查班上是否至少有一名有效学生(validStudents > 0)。如果条件满足,则将最优秀学生的坐标复制到相应班级教师的坐标中,并将最优秀学生的函数值赋给该教师的函数值。
计算 avgFitness 类中所有学生的函数平均值。班级的总“成本”计算方法是:将成绩最好的学生的函数值与所有学生的函数平均值乘以 “beta” 系数,然后求和。这是教师表现与班级平均适应度的组合指标。
//———————————————————————————————————————————————————————————————————— void C_AO_CLA::UpdateTeachersAndCosts () { for (int k = 0; k < numClasses; k++) { int startIdx = k * studentsPerClass; int endIdx = startIdx + studentsPerClass; double bestFitness = -DBL_MAX; int bestIdx = startIdx; double sumFitness = 0.0; int validStudents = 0; // Find the best student (teacher) in the class for (int i = startIdx; i < endIdx; i++) { if (a[i].f > -DBL_MAX) // Validity check { sumFitness += a[i].f; validStudents++; if (a[i].f > bestFitness) { bestFitness = a[i].f; bestIdx = i; } } } // Update the teacher if (validStudents > 0) { ArrayCopy (teachers[k].c, a[bestIdx].c); teachers[k].f = bestFitness; // Calculate the class total cost double avgFitness = sumFitness / validStudents; classTotalCosts[k] = bestFitness + beta * avgFitness; } } } //————————————————————————————————————————————————————————————————————
UpdateClassRanks() 方法用于根据班级的总体“成本”来确定班级的排名,该成本表征了类的有效性。这个过程首先要找出所有有效班级中的最低成本和最高成本。如果所有班级的值都相同,或者没有有效的班级,则所有班级的排名都设置为 1。
如果成本存在差异,则将这些值标准化 — 每个成本都调整到 0 到 1 的范围内。之后,进行反转:成本较高的班级获得较低的排名,接近 1,而成本较低的班级获得等于班级数的最高排名。
然后,每个排名值都被限制在最小值和最大值之间,以避免超出范围的值。最终,根据这种方法的结果,班级会根据其表现进行排名。
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::UpdateClassRanks () { // Find the min and max costs among valid classes double minCost = DBL_MAX; double maxCost = -DBL_MAX; int validClasses = 0; for (int k = 0; k < numClasses; k++) { if (classTotalCosts [k] > -DBL_MAX) { if (classTotalCosts [k] < minCost) minCost = classTotalCosts [k]; if (classTotalCosts [k] > maxCost) maxCost = classTotalCosts [k]; validClasses++; } } if (validClasses == 0 || maxCost - minCost < 1e-10) { // All classes have the same score for (int k = 0; k < numClasses; k++) classRanks [k] = 1.0; } else { // Ranking: best classes (high cost) get low rank for (int k = 0; k < numClasses; k++) { if (classTotalCosts [k] > -DBL_MAX) { // Normalize from 0 to 1 double normalized = (classTotalCosts [k] - minCost) / (maxCost - minCost); // Inversion: the best get a rank close to 1 classRanks [k] = 1.0 + (1.0 - normalized) * (numClasses - 1.0); // Limitation classRanks [k] = MathMax (1.0, MathMin ((double)numClasses, classRanks [k])); } else { classRanks [k] = numClasses; // Worst rank for uninitialized } } } } //————————————————————————————————————————————————————————————————————
测试结果
根据测试结果,CLA_L 算法取得了相当不错的结果。CLA_L|Competitive Learning Algorithm|198.0|3.0|0.3|0.8|2.0|
=============================
5 Hilly's; Func runs:10000; result:0.6482993681242128
25 Hilly's;Func runs:10000; result:0.5535249826770444
500 Hilly's; Func runs:10000; result:0.2584959913710746
=============================
5 Forest's; Func runs:10000; result:0.8027208362980616
25 Forest's; Func runs:10000; result:0.49540442971179494
500 Forest's; Func runs:10000; result:0.20048686632188017
=============================
5 Megacity's; Func runs:10000; result:0.6353846153846153
25 Megacity's; Func runs:10000; result:0.2716923076923076
500 Megacity's;Func runs:10000; result:0.10086153846153936
=============================
All score:3.96687 (44.08%)
可视化结果显示,该算法最初具有良好的搜索能力,但由于局部陷阱而恶化,导致算法运行的后半段陷入停滞。

Hilly 测试函数上的 CLA_L

Forest 测试函数上的 CLA_L

Megacity 测试函数上的 CLA_L
根据算法的运行结果,现列出 CLA_L 排名表,供参考。
| # | 算法 | 描述 | Hilly | Hilly Final | Forest | Forest Final | Megacity (discrete) | Megacity Final | Final 结果 | % 的 最大限度 | ||||||
| 10 p(5 F) | 50 p(25 F) | 1000 p(500 F) | 10 p(5 F) | 50 p(25 F) | 1000 p(500 F) | 10 p(5 F) | 50 p(25 F) | 1000 p(500 F) | ||||||||
| 1 | ANS | 跨邻里搜索(across neighbourhood search) | 0.94948 | 0.84776 | 0.43857 | 2.23581 | 1.00000 | 0.92334 | 0.39988 | 2.32323 | 0.70923 | 0.63477 | 0.23091 | 1.57491 | 6.134 | 68.15 |
| 2 | CLA | 密码锁算法(joo) | 0.95345 | 0.87107 | 0.37590 | 2.20042 | 0.98942 | 0.91709 | 0.31642 | 2.22294 | 0.79692 | 0.69385 | 0.19303 | 1.68380 | 6.107 | 67.86 |
| 3 | AMOm | 动物迁徙优化 M(animal migration optimization M) | 0.90358 | 0.84317 | 0.46284 | 2.20959 | 0.99001 | 0.92436 | 0.46598 | 2.38034 | 0.56769 | 0.59132 | 0.23773 | 1.39675 | 5.987 | 66.52 |
| 4 | (P+O)ES | (P+O) 演进战略((P+O) evolution strategies) | 0.92256 | 0.88101 | 0.40021 | 2.20379 | 0.97750 | 0.87490 | 0.31945 | 2.17185 | 0.67385 | 0.62985 | 0.18634 | 1.49003 | 5.866 | 65.17 |
| 5 | CTA | 彗尾算法(joo) | 0.95346 | 0.86319 | 0.27770 | 2.09435 | 0.99794 | 0.85740 | 0.33949 | 2.19484 | 0.88769 | 0.56431 | 0.10512 | 1.55712 | 5.846 | 64.96 |
| 6 | TETA | 时间演化旅行算法(joo) | 0.91362 | 0.82349 | 0.31990 | 2.05701 | 0.97096 | 0.89532 | 0.29324 | 2.15952 | 0.73462 | 0.68569 | 0.16021 | 1.58052 | 5.797 | 64.41 |
| 7 | SDSm | 随机扩散搜索 M(stochastic diffusion search M) | 0.93066 | 0.85445 | 0.39476 | 2.17988 | 0.99983 | 0.89244 | 0.19619 | 2.08846 | 0.72333 | 0.61100 | 0.10670 | 1.44103 | 5.709 | 63.44 |
| 8 | BOAm | 台球优化算法 M | 0.95757 | 0.82599 | 0.25235 | 2.03590 | 1.00000 | 0.90036 | 0.30502 | 2.20538 | 0.73538 | 0.52523 | 0.09563 | 1.35625 | 5.598 | 62.19 |
| 9 | AAm | 射箭算法 M(archery algorithm M) | 0.91744 | 0.70876 | 0.42160 | 2.04780 | 0.92527 | 0.75802 | 0.35328 | 2.03657 | 0.67385 | 0.55200 | 0.23738 | 1.46323 | 5.548 | 61.64 |
| 10 | ESG | 社会群体的进化(joo) | 0.99906 | 0.79654 | 0.35056 | 2.14616 | 1.00000 | 0.82863 | 0.13102 | 1.95965 | 0.82333 | 0.55300 | 0.04725 | 1.42358 | 5.529 | 61.44 |
| 11 | SIA | 模拟各向同性退火(joo) | 0.95784 | 0.84264 | 0.41465 | 2.21513 | 0.98239 | 0.79586 | 0.20507 | 1.98332 | 0.68667 | 0.49300 | 0.09053 | 1.27020 | 5.469 | 60.76 |
| 12 | EOm | 极端优化 M | 0.76166 | 0.77242 | 0.31747 | 1.85155 | 0.99999 | 0.76751 | 0.23527 | 2.00277 | 0.74769 | 0.53969 | 0.14249 | 1.42987 | 5.284 | 58.71 |
| 13 | BBO | 基于生物地理学的优化 | 0.94912 | 0.69456 | 0.35031 | 1.99399 | 0.93820 | 0.67365 | 0.25682 | 1.86867 | 0.74615 | 0.48277 | 0.17369 | 1.40261 | 5.265 | 58.50 |
| 14 | ACS | 人工协同搜索(artificial cooperative search) | 0.75547 | 0.74744 | 0.30407 | 1.80698 | 1.00000 | 0.88861 | 0.22413 | 2.11274 | 0.69077 | 0.48185 | 0.13322 | 1.30583 | 5.226 | 58.06 |
| 15 | DA | 辩证算法 | 0.86183 | 0.70033 | 0.33724 | 1.89940 | 0.98163 | 0.72772 | 0.28718 | 1.99653 | 0.70308 | 0.45292 | 0.16367 | 1.31967 | 5.216 | 57.95 |
| 16 | BHAm | 黑洞算法 M | 0.75236 | 0.76675 | 0.34583 | 1.86493 | 0.93593 | 0.80152 | 0.27177 | 2.00923 | 0.65077 | 0.51646 | 0.15472 | 1.32195 | 5.196 | 57.73 |
| 17 | ASO | 无政府社会优化(anarchy society optimization) | 0.84872 | 0.74646 | 0.31465 | 1.90983 | 0.96148 | 0.79150 | 0.23803 | 1.99101 | 0.57077 | 0.54062 | 0.16614 | 1.27752 | 5.178 | 57.54 |
| 18 | RFO | 皇家同花顺优化(joo) | 0.83361 | 0.73742 | 0.34629 | 1.91733 | 0.89424 | 0.73824 | 0.24098 | 1.87346 | 0.63154 | 0.50292 | 0.16421 | 1.29867 | 5.089 | 56.55 |
| 19 | AOSm | 原子轨道搜索 M | 0.80232 | 0.70449 | 0.31021 | 1.81702 | 0.85660 | 0.69451 | 0.21996 | 1.77107 | 0.74615 | 0.52862 | 0.14358 | 1.41835 | 5.006 | 55.63 |
| 20 | TSEA | 龟壳进化算法(joo) | 0.96798 | 0.64480 | 0.29672 | 1.90949 | 0.99449 | 0.61981 | 0.22708 | 1.84139 | 0.69077 | 0.42646 | 0.13598 | 1.25322 | 5.004 | 55.60 |
| 21 | BSA | 回溯搜索算法 | 0.97309 | 0.54534 | 0.29098 | 1.80941 | 0.99999 | 0.58543 | 0.21747 | 1.80289 | 0.84769 | 0.36953 | 0.12978 | 1.34700 | 4.959 | 55.10 |
| 22 | DE | 差分进化(differential evolution) | 0.95044 | 0.61674 | 0.30308 | 1.87026 | 0.95317 | 0.78896 | 0.16652 | 1.90865 | 0.78667 | 0.36033 | 0.02953 | 1.17653 | 4.955 | 55.06 |
| 23 | SRA | 成功餐馆算法(joo) | 0.96883 | 0.63455 | 0.29217 | 1.89555 | 0.94637 | 0.55506 | 0.19124 | 1.69267 | 0.74923 | 0.44031 | 0.12526 | 1.31480 | 4.903 | 54.48 |
| 24 | CRO | 化学反应优化(chemical reaction optimization) | 0.94629 | 0.66112 | 0.29853 | 1.90593 | 0.87906 | 0.58422 | 0.21146 | 1.67473 | 0.75846 | 0.42646 | 0.12686 | 1.31178 | 4.892 | 54.36 |
| 25 | BIO | 血液遗传优化(joo) | 0.81568 | 0.65336 | 0.30877 | 1.77781 | 0.89937 | 0.65319 | 0.21760 | 1.77016 | 0.67846 | 0.47631 | 0.13902 | 1.29378 | 4.842 | 53.80 |
| 26 | BSA | 鸟群算法(bird swarm algorithm) | 0.89306 | 0.64900 | 0.26250 | 1.80455 | 0.92420 | 0.71121 | 0.24939 | 1.88479 | 0.69385 | 0.32615 | 0.10012 | 1.12012 | 4.809 | 53.44 |
| 27 | DEA | 海豚回声定位算法 | 0.75995 | 0.67572 | 0.34171 | 1.77738 | 0.89582 | 0.64223 | 0.23941 | 1.77746 | 0.61538 | 0.44031 | 0.15115 | 1.20684 | 4.762 | 52.91 |
| 28 | HS | 和声搜索(harmony search) | 0.86509 | 0.68782 | 0.32527 | 1.87818 | 0.99999 | 0.68002 | 0.09590 | 1.77592 | 0.62000 | 0.42267 | 0.05458 | 1.09725 | 4.751 | 52.79 |
| 29 | SSG | 树苗播种和生长(saplings sowing and growing) | 0.77839 | 0.64925 | 0.39543 | 1.82308 | 0.85973 | 0.62467 | 0.17429 | 1.65869 | 0.64667 | 0.44133 | 0.10598 | 1.19398 | 4.676 | 51.95 |
| 30 | BCOm | 细菌趋化性优化 M(bacterial chemotaxis optimization M) | 0.75953 | 0.62268 | 0.31483 | 1.69704 | 0.89378 | 0.61339 | 0.22542 | 1.73259 | 0.65385 | 0.42092 | 0.14435 | 1.21912 | 4.649 | 51.65 |
| 31 | ABO | 非洲水牛优化 | 0.83337 | 0.62247 | 0.29964 | 1.75548 | 0.92170 | 0.58618 | 0.19723 | 1.70511 | 0.61000 | 0.43154 | 0.13225 | 1.17378 | 4.634 | 51.49 |
| 32 | (PO)ES | (PO) 进化策略((PO) evolution strategies) | 0.79025 | 0.62647 | 0.42935 | 1.84606 | 0.87616 | 0.60943 | 0.19591 | 1.68151 | 0.59000 | 0.37933 | 0.11322 | 1.08255 | 4.610 | 51.22 |
| 33 | FBA | 基于分形的算法 | 0.79000 | 0.65134 | 0.28965 | 1.73099 | 0.87158 | 0.56823 | 0.18877 | 1.62858 | 0.61077 | 0.46062 | 0.12398 | 1.19537 | 4.555 | 50.61 |
| 34 | TSm | 禁忌搜索 M(tabu search M) | 0.87795 | 0.61431 | 0.29104 | 1.78330 | 0.92885 | 0.51844 | 0.19054 | 1.63783 | 0.61077 | 0.38215 | 0.12157 | 1.11449 | 4.536 | 50.40 |
| 35 | BSO | 头脑风暴优化(brain storm optimization) | 0.93736 | 0.57616 | 0.29688 | 1.81041 | 0.93131 | 0.55866 | 0.23537 | 1.72534 | 0.55231 | 0.29077 | 0.11914 | 0.96222 | 4.498 | 49.98 |
| 36 | WOAm | Wale 优化算法 M(wale optimization algorithm M) | 0.84521 | 0.56298 | 0.26263 | 1.67081 | 0.93100 | 0.52278 | 0.16365 | 1.61743 | 0.66308 | 0.41138 | 0.11357 | 1.18803 | 4.476 | 49.74 |
| 37 | AEFA | 人工电场算法(artificial electric field algorithm) | 0.87700 | 0.61753 | 0.25235 | 1.74688 | 0.92729 | 0.72698 | 0.18064 | 1.83490 | 0.66615 | 0.11631 | 0.09508 | 0.87754 | 4.459 | 49.55 |
| 38 | AEO | 基于人工生态系统的优化算法 | 0.91380 | 0.46713 | 0.26470 | 1.64563 | 0.90223 | 0.43705 | 0.21400 | 1.55327 | 0.66154 | 0.30800 | 0.28563 | 1.25517 | 4.454 | 49.49 |
| 39 | CAm | 骆驼算法 M | 0.78684 | 0.56042 | 0.35133 | 1.69859 | 0.82772 | 0.56041 | 0.24336 | 1.63149 | 0.64846 | 0.33092 | 0.13418 | 1.11356 | 4.444 | 49.37 |
| 40 | ACOm | 蚁群优化M(ant colony optimization M) | 0.88190 | 0.66127 | 0.30377 | 1.84693 | 0.85873 | 0.58680 | 0.15051 | 1.59604 | 0.59667 | 0.37333 | 0.02472 | 0.99472 | 4.438 | 49.31 |
| 41 | CMAES | 协方差矩阵自适应演化策略 | 0.76258 | 0.72089 | 0.00000 | 1.48347 | 0.82056 | 0.79616 | 0.00000 | 1.61672 | 0.75846 | 0.49077 | 0.00000 | 1.24923 | 4.349 | 48.33 |
| 42 | BFO-GA | 细菌觅食优化 - ga(bacterial foraging optimization - ga) | 0.89150 | 0.55111 | 0.31529 | 1.75790 | 0.96982 | 0.39612 | 0.06305 | 1.42899 | 0.72667 | 0.27500 | 0.03525 | 1.03692 | 4.224 | 46.93 |
| 43 | SOA | 简单优化算法 | 0.91520 | 0.46976 | 0.27089 | 1.65585 | 0.89675 | 0.37401 | 0.16984 | 1.44060 | 0.69538 | 0.28031 | 0.10852 | 1.08422 | 4.181 | 46.45 |
| 44 | ABHA | 人工蜂巢算法(artificial bee hive algorithm) | 0.84131 | 0.54227 | 0.26304 | 1.64663 | 0.87858 | 0.47779 | 0.17181 | 1.52818 | 0.50923 | 0.33877 | 0.10397 | 0.95197 | 4.127 | 45.85 |
| 45 | ACMO | 大气云模型优化(atmospheric cloud model optimization) | 0.90321 | 0.48546 | 0.30403 | 1.69270 | 0.80268 | 0.37857 | 0.19178 | 1.37303 | 0.62308 | 0.24400 | 0.10795 | 0.97503 | 4.041 | 44.90 |
| CLA_L | 竞争性学习算法 | 0.64829 | 0.55352 | 0.25849 | 1.46030 | 0.80272 | 0.49540 | 0.20048 | 1.49860 | 0.63538 | 0.27169 | 0.10086 | 1.00793 | 3.967 | 44.08 | |
| RW | 随机游走 | 0.48754 | 0.32159 | 0.25781 | 1.06694 | 0.37554 | 0.21944 | 0.15877 | 0.75375 | 0.27969 | 0.14917 | 0.09847 | 0.52734 | 2.348 | 26.09 | |
总结
竞争性学习算法(CLA_L)在解决标准优化问题时表现平平。对该算法运行过程的分析揭示了一种典型的两阶段动态:初始迭代阶段为活跃的探索阶段,优化过程后半段为过早停滞阶段。
将种群划分为不同的班级,可以确保在早期阶段对搜索空间进行良好的覆盖。每个班级探索自己的领域,从而为全局搜索做出贡献。这种教育隐喻使算法结构清晰,也更易于解释。教师、学生和不同类型学习的概念很容易理解。理论上,依赖于班级排名的学习因素应在探索与利用之间取得平衡。三种学习类型(教师学习、个人学习和参照学习)的结合,有可能避免陷入局部最优解。尽管采用了多样化机制,该算法仍容易陷入局部最优解。
CLA 算法提出了一种将教育隐喻应用于优化问题的有趣概念。尽管该算法采用了创新的方法且初始表现良好,但要想与现代元启发式算法相竞争,仍需进行重大修改。主要挑战仍然是在整个优化过程中确保探索与利用之间的平衡。

图2.测试算法的颜色编码

图 3.算法测试结果直方图(范围从 0 到 100,越高越好,其中 100 是可能的最大理论结果,存档中有一个用于计算评级表的脚本)
CLA_L 的优缺点:
优点:
- 快速。
缺点:
- 大量外部参数。
- 容易陷入局部最优解。
这篇文章附有一个归档,其中包含当前版本的算法代码。文章作者不对规范算法描述的绝对准确性负责。为提高搜索能力,已对其中多项功能进行了修改。文章中提出的结论和判断都是基于实验结果。
本文中用到的程序
| # | 名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | #C_AO.mqh | 包含文件 | 种群优化算法的父类 |
| 2 | #C_AO_enum.mqh | 包含文件 | 种群优化算法的枚举 |
| 3 | TestFunctions.mqh | 包含文件 | 测试函数库 |
| 4 | TestStandFunctions.mqh | 包含文件 | 测试平台函数库 |
| 5 | Utilities.mqh | 包含文件 | 辅助函数库 |
| 6 | CalculationTestResults.mqh | 包含文件 | 用于计算比较表中结果的脚本 |
| 7 | Testing AOs.mq5 | 脚本 | 所有种群优化算法的统一测试平台 |
| 8 | Simple use of population optimization algorithms.mq5 | 脚本 | 使用不带可视化的种群优化算法的简单示例 |
| 9 | Test_AO_CLA_L.mq5 | 脚本 | CLA_L 测试平台 |
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18857
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
使用MQL5实现Firebase数据的增删改查
新手在交易中的10个基本错误