确定性振荡搜索(DOS)
内容
引言
优化算法在不断发展,旨在克服传统方法的根本性局限。大多数元启发式优化算法高度依赖随机过程与随机数。尽管这类方法在避免局部最优解上表现出色,但其非确定性特性,在需要结果精确可复现的领域会带来问题。
本文介绍确定性振荡搜索(DOS)—— 这是一种新型元启发式算法,它结合了传统基于梯度方法的优势与群体算法的高效性,同时完全不使用随机数。
DOS由Archana于2017年提出,用于求解复杂的全局优化问题。其核心思想是:在搜索空间中模拟粒子的振荡运动,并采用确定性初始位置分布。该算法的关键特点是能够处理高维问题,同时保持完全可复现性:在相同初始条件下,算法每次运行都能得到完全一致的结果。
与大多数元启发式算法不同,DOS引入了“适应度斜率”概念。通过这一机制,粒子可以判断当前移动方向是否在提升解的质量,并自适应调整搜索策略。粒子可处于三种斜率状态之一:正向(移动使解更优)、负向(移动使解变差)、未知。
该信息用于控制粒子的振荡行为。传统梯度法一旦到达所有方向都会使目标函数变差的位置,就会停止搜索。而DOS通过群体机制突破了这一限制:当振荡运动无法带来改进时,群体机制便会启动。此时,粒子会朝着当前已知的全局最优解的方向移动。
本文将详细阐述DOS算法的数学基础,分析其特性与实现要点,并通过若干测试问题验证其优化效率。
算法实现
现在,让我们来研究DOS算法的工作原理。它不采用随机游走,而是基于几条简单规则的系统性搜索,完全不依赖随机性。算法首先将若干个“探索者”(粒子)放置在搜索空间中的不同位置。这些位置并非随机,而是由特定公式确定,以实现对区域的均匀覆盖。每个探索者都有初始方向和移动速度。当探索者向前移动时,它会记录周围地形是变高(更优)还是变低(更差)。我们称之为“斜率” —— 这是一种简单判断是否在朝正确方向前进的方式。
下面进入算法的关键环节。当一个探索者发现自己不再上升、反而开始下降(适应度变差)时,它不会直接停下或原路返回。相反,它会进行一次“反弹” —— 掉头向相反方向继续移动,但速度减半。就像网球撞到墙壁后反弹,只是能量减弱。
这种反弹形成了振荡运动,算法也因此得名。每一次反弹,探索者都会更精确地逼近极值点。但如果探索者陷入了局部陷阱 —— 比如一座小山丘,周围全是更低的区域,这时DOS会启用另一套机制。如果探索者尝试各个方向,发现全都是下坡,它就会切换到另一种模式 —— “群集机制”。在此模式下,它会朝着所有探索者目前找到的最优点移动。
与随机搜索或试错法不同,DOS利用改进方向信息和全体探索者的集体经验,系统性地探索解空间。同时,它不需要复杂的导数计算,也不需要存储大量搜索历史。因此,通过移动、反弹、聚集这几条简单规则,DOS便能逐步为复杂问题找到最优解。
下图展示了该算法的以下关键特征:一个包含全局最优与多个局部最优的二维搜索空间(以等高线表示),以及从起点到全局最优的路径,体现出DOS算法特有的行为:
- 粒子确定性的初始位置,
- 搜索空间中的振荡(锯齿形)运动,
- 向全局最优的自适应移动
算法的核心组件包括:确定性粒子初始化、适应度斜率概念、振荡运动以及群体机制(向已知最优解移动)。
斜率状态可以是:
- 正向(+1):当前移动使适应度提升,
- 负向(-1):当前移动使适应度下降,
- 未知(0):初始化阶段或策略切换后的状态。

图例1. 算法运行过程
上图清晰地展示了DOS如何结合传统梯度法(通过振荡进行局部搜索)与群体算法的优势,同时保持完全确定性的运行特性。在了解运行原理之后,让我们接下来开始编写算法的伪代码。
步骤1:初始化准备
- 创建数组,用于存储每个粒子的位置、速度、上一代适应度值和斜率状态
- 将当前找到的最优解初始化为最小适应度值
步骤2:确定性粒子初始化
- 对于每个粒子:
- 通过确定性公式在搜索空间中定位,确保均匀覆盖
- 将初始速度设为0
- 将初始斜率状态设置为“未知”(0)
- 将上一代适应度值设为最小可能值
步骤3:主优化循环
- 重复执行,直到达到最大迭代次数:第一部分:粒子移动
- 对于每个粒子:
- 将当前适应度值保存为上一代适应度值
- 通过叠加当前速度更新粒子位置
- 如果新位置超出搜索边界,将其限制在合理范围内
- 对于每个粒子:
- 计算新的适应度值
- 如果新适应度优于当前最优解,则更新最优解
- 情况1:斜率状态为“未知”(0)
- 如果新适应度更优,则将斜率设置为“正向”(1)
- 如果新适应度更差,则将斜率设置为“负向”(-1)
- 如果适应度无变化,则保持斜率为“未知”。
- 情况2:斜率状态为“正向”(1)
- 如果新适应度变差:
- 将运动方向反转
- 速度减半
- 将斜率设置为“负向”(-1)
- 如果新适应度变差:
- 情况3:斜率状态为“负向”(-1)
- 如果新适应度变差:
- 启用群体机制:在当前速度上叠加指向最优解的向量(乘以移动系数)
- 将斜率设置为“未知 ”(0)
- 如果新适应度变差:
- 检查速度是否为0或接近0:
- 如果速度几乎为0:
- 将速度设置为指向最优解的方向(乘以移动系数)
- 将斜率设置为“未知 ”(0)
- 如果速度几乎为0:
- 对于每个粒子:
步骤4:结束
- 返回找到的最优解及其适应度值
现在我们可以开始编写DOS算法代码。首先创建一个结构体,用于存储优化过程中粒子的状态。该结构体包含这些字段:速度斜率状态(正向、负向、未知)和各维度速度分量数组,这样可以方便地存储和处理粒子的运动参数。
为初始化该结构体,提供一个方法:将斜率设置为默认值,并且创建指定大小的速度数组,全部填充为0,确保算法启动前的初始状态正确。
此外,还实现了零速度检测方法:检查所有速度分量,如果在指定精度内全部接近0,返回"true",否则返回"false"。该方法用于判断粒子是否已达到稳定状态,还是需要继续移动。
// Structure for storing particle velocity struct S_DOS_Velocity { int slope; // Particle slope (-1: negative, 0: unknown, 1: positive) double v []; // Velocity components for each dimension void Init (int dims) { slope = 0; ArrayResize (v, dims); ArrayInitialize (v, 0.0); // Quick initialization of the entire array to zeros } // Check for zero velocity bool IsZero (double epsilon = 1e-10) { for (int i = 0; i < ArraySize (v); i++) if (MathAbs (v [i]) > epsilon) return false; return true; } }; //——————————————————————————————————————————————————————————————————————————————
C_AO_DOS类代表本算法的具体实现。该类继承自基类C_AO的通用功能,并额外添加了DOS算法专属逻辑。该类的主要特性:构造函数初始化默认参数,包括种群大小、向最优解移动的系数,并创建参数数组。SetParams()方法用设置并校验参数(如种群大小popSize和移动系数movementFactor),确保符合约束条件。Init()方法负责初始化所有前置条件:搜索区间、变化步长以及迭代次数。
粒子运动逻辑(方法):- Moving()实现粒子在搜索空间中的基础移动机制,基于当前速度与评估值运行。
- Revision()用于在每一步迭代后调整粒子的位置或速度。
类内部定义了S_DOS_Velocity速度结构体,用于存储每个粒子在所有维度上的速度分量,并包含初始化与零速度检测的方法。
内部辅助方法:- InitializeParticles()作为粒子初始化的辅助函数,ProcessParticleMovement()作为粒子位置更新的辅助函数。二者共同实现算法的核心逻辑。
整体而言,该类以结构化方式实现了DOS算法,通过粒子的位置、速度与搜索方向,系统性地引导解空间的搜索过程。
//—————————————————————————————————————————————————————————————————————————————— class C_AO_DOS : public C_AO { public: //-------------------------------------------------------------------- ~C_AO_DOS () { } C_AO_DOS () { ao_name = "DOS"; ao_desc = "Deterministic Oscillatory Search"; ao_link = "https://www.mql5.com/en/articles/18154"; // Set default parameters popSize = 30; // population size movementFactor = 0.95; // movement factor towards the best solution // Create and initialize the parameters array ArrayResize (params, 2); params [0].name = "Population Size"; params [0].val = popSize; params [1].name = "Movement Factor"; params [1].val = movementFactor; } void SetParams () { // Set parameter values with validation popSize = (int)MathMax (5, params [0].val); // Minimum 5 particles for efficiency movementFactor = MathMax (0.1, MathMin (1.0, params [1].val)); // Limit from 0.1 to 1.0 } bool Init (const double &rangeMinP [], // minimum values const double &rangeMaxP [], // maximum values const double &rangeStepP [], // step change const int epochsP = 0); void Moving (); void Revision (); //---------------------------------------------------------------------------- double movementFactor; // movement factor towards the best solution S_DOS_Velocity velocities []; // Array of particle velocity structures private: //------------------------------------------------------------------- void InitializeParticles (); void ProcessParticleMovement (int particleIndex); }; //——————————————————————————————————————————————————————————————————————————————
Init方法负责为算法执行做好初始化准备。首先,它调用基类初始化方法,完成算法运行所需的初始搜索区间与步长设置。基础初始化成功后,为数组分配内存,用于存储所有粒子的速度信息。
针对种群中的每个粒子,初始化各维度的速度数组,为后续运动过程建立初始状态。最后,调用方法以确定性方式将粒子放置到初始位置,明确它们在搜索空间中的起始点。
该方法的结果:生成一组具备完整初始条件的粒子种群,准备就绪,可开始迭代搜索过程。
//—————————————————————————————————————————————————————————————————————————————— bool C_AO_DOS::Init (const double &rangeMinP [], // minimum values const double &rangeMaxP [], // maximum values const double &rangeStepP [], // step change const int epochsP = 0) // number of epochs { // Standard C_AO initialization if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //---------------------------------------------------------------------------- // Allocating memory for arrays ArrayResize (velocities, popSize); // Initialize the velocities for each dimension for (int i = 0; i < popSize; i++) velocities [i].Init (coords); // Initialize particle positions deterministically InitializeParticles (); return true; } //——————————————————————————————————————————————————————————————————————————————
Moving方法实现DOS算法中粒子在搜索空间内的移动逻辑,并按顺序处理种群中的每一个粒子(从第一个到最后一个)。对于每个粒子,先保存其当前适应度函数值"f"。这一步是为了后续对比,判断粒子位置是更优还是变差。
针对粒子的每一个坐标(维度),通过将当前坐标加上对应速度分量计算出新的坐标值。新坐标会根据步长限制在设定的区间rangeMin[d]和rangeMax[d]内,确保粒子不会超出允许的搜索范围。
最终,Moving方法完成粒子在搜索空间中的位置更新,保留上一状态信息,并在约束与离散化条件下,确保新坐标的有效性。
//+----------------------------------------------------------------------------+ //| Basic method of particle movement | //+----------------------------------------------------------------------------+ void C_AO_DOS::Moving () { // Handle all particles for (int i = 0; i < popSize; i++) { // Save the fitness value a [i].fP = a [i].f; // Calculate new coordinates based on velocity for (int d = 0; d < coords; d++) { // Update position a [i].c [d] += velocities [i].v [d]; // Round to the nearest acceptable step a [i].c [d] = u.SeInDiSp (a [i].c [d], rangeMin [d], rangeMax [d], rangeStep [d]); } } } //——————————————————————————————————————————————————————————————————————————————
Revision方法负责更新最优解信息,并在搜索过程中处理粒子的运动调整。该方法会依次处理种群中的所有粒子。对于每个粒子,都会检查其当前解是否优于全局最优适应度值fB。如果满足,则更新全局最优值,并保存对应的最优坐标。针对每个粒子,会调用一个独立的方法,根据适应度函数的变化重新计算并调整其位置与速度。
该方法的运行结果:完成最优解更新,并让系统准备好进入下一阶段搜索,使粒子能够基于最新信息继续移动。
//+----------------------------------------------------------------------------+ //| Fitness function update method | //+----------------------------------------------------------------------------+ void C_AO_DOS::Revision () { // Handle each particle for (int i = 0; i < popSize; i++) { // Update the best solution if the current solution is better if (a [i].f > fB) { fB = a [i].f; ArrayCopy (cB, a [i].c, 0, 0, WHOLE_ARRAY); } // Handle particle motion based on fitness change ProcessParticleMovement (i); } } //——————————————————————————————————————————————————————————————————————————————
ProcessParticleMovement方法负责根据适应度函数变化与当前方向,调整单个粒子在搜索空间中的运动状态。如果粒子索引无效,则方法直接终止。为加速访问,系统会缓存粒子的当前适应度、上一代适应度值以及当前运动斜率。算法会根据当前与历史适应度差值以及当前斜率,决定粒子下一步的移动方向,规则如下:
- 如果斜率未知,则根据适应度变化重新确定方向(正向、负向或保持未知);
- 如果斜率原本为正向但适应度变差,则将斜率切换为负向,并将所有轴上的速度减半,促使粒子改变运动方向;
- 如果斜率原本为负向且适应度持续变差,则触发“群集机制” —— 粒子向全局最优解方向移动,各轴速度朝最优解方向递增。
如果所有方向的速度均为0,则根据当前坐标与全局最优解坐标的差值(结合移动系数)设置速度,启动向全局最优解的移动。最终,系统会根据实时状态调整速度的方向与大小,使粒子对适应度变化做出合理响应,并“学习”向最优方向移动。
该方法的最终目标:为粒子提供动态自适应运动,同时结合局部解与全局解的变化,实现高效的最优值搜索。
//+----------------------------------------------------------------------------+ //| Handle particle motion after fitness update | //+----------------------------------------------------------------------------+ void C_AO_DOS::ProcessParticleMovement (int particleIndex) { // Local variables for access optimization double currentFitness = a [particleIndex].f; double previousFitness = a [particleIndex].fP; int currentSlope = velocities [particleIndex].slope; // Comparison of fitnesses to determine the movement direction double fitnessDiff = currentFitness - previousFitness; // Handle a slope according to the current state if (currentSlope == 0) // Unknown slope { // Determine the slope based on the change in fitness velocities [particleIndex].slope = (fitnessDiff > 0) ? 1 : (fitnessDiff < 0) ? -1 : 0; } else if (currentSlope == 1 && fitnessDiff < 0) // Positive slope and deterioration of fitness { // Change direction and decrease velocity for (int d = 0; d < coords; d++) velocities [particleIndex].v [d] *= -0.5; // Optimized form of division by 2 velocities [particleIndex].slope = -1; // Change the slope to negative } else if (currentSlope == -1 && fitnessDiff < 0) // Negative slope and fitness degradation { // Apply the swarming mechanism - movement towards the global optimum for (int d = 0; d < coords; d++) velocities [particleIndex].v [d] += (cB [d] - a [particleIndex].c [d]) * movementFactor; velocities [particleIndex].slope = 0; // Reset the slope as unknown } // Check for zero velocity using the structure method if (velocities [particleIndex].IsZero ()) { // Initialize the velocity by moving towards the global optimum for (int d = 0; d < coords; d++) velocities [particleIndex].v [d] = (cB [d] - a [particleIndex].c [d]) * movementFactor; // Reset the slope velocities [particleIndex].slope = 0; } } //——————————————————————————————————————————————————————————————————————————————
测试结果
现在,让我们来看一下结果。可见,这款内置群体效应的梯度型算法,在处理优化任务时,表现优于传统的常规梯度法。
=============================
5 Hilly's; Func runs: 10000; result: 0.3422040822277234
25 Hilly's; Func runs: 10000; result: 0.3421751631202356
500 Hilly's; Func runs: 10000; result: 0.3421605659711745
=============================
5 Forest's; Func runs: 10000; result: 0.5708601371368296
25 Forest's; Func runs: 10000; result: 0.34628707444514434
500 Forest's; Func runs: 10000; result: 0.32879379664917996
=============================
5 Megacity's; Func runs: 10000; result: 0.19999999999999998
25 Megacity's; Func runs: 10000; result: 0.20923076923076928
500 Megacity's; Func runs: 10000; result: 0.23076923076922945
=============================
总分: 2.91248 (32.36%)
可视化结果显示,在低维函数上,算法的结果存在较大离散性。

DOS在Hilly测试函数上

DOSForest测试函数上

DOSMegacity测试函数上
在种群优化算法的评级表中,DOS算法仅作为参考示例列出。
| # | AO | 描述 | Hilly值 | Hilly 最终 | Forest值 | Forest 最终 | Megacity (离散) | Megacity 最终 | 最终 结果 | % of 最大 | ||||||
| 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 | 跨邻域搜索 | 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 | 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) 进化策略 | 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 | 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 | 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 | ACS | 人工协同搜索 | 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 |
| 13 | 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 |
| 14 | 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 |
| 15 | ASO | 无序社会优化 | 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 |
| 16 | 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 |
| 17 | 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 |
| 18 | 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 |
| 19 | DE | 差分进化 | 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 |
| 20 | 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 |
| 21 | CRO | 化学反应优化 | 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 |
| 22 | 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 |
| 23 | BSA | 鸟群算法 | 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 |
| 24 | HS | 和声搜索 | 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 |
| 25 | SSG | 树苗播种和生长 | 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 |
| 26 | BCOm | 细菌趋化性优化算法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 |
| 27 | 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 |
| 28 | (PO)ES | (PO) 进化策略 | 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 |
| 29 | 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 |
| 30 | TSm | 禁忌搜索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 |
| 31 | BSO | 头脑风暴优化 | 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 |
| 32 | WOAm | 鲸鱼优化算法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 |
| 33 | AEFA | 人工电场算法 | 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 |
| 34 | 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 |
| 35 | 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 |
| 36 | ACOm | 蚁群优化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 |
| 37 | BFO-GA | 细菌觅食优化 - 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 |
| 38 | 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 |
| 39 | ABHA | 人工蜂巢算法 | 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 |
| 40 | ACMO | 大气云模型优化 | 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 |
| 41 | ADAMm | 群体自适应矩估计M | 0.88635 | 0.44766 | 0.26613 | 1.60014 | 0.84497 | 0.38493 | 0.16889 | 1.39880 | 0.66154 | 0.27046 | 0.10594 | 1.03794 | 4.037 | 44.85 |
| 42 | CGO | 混沌博弈优化 | 0.57256 | 0.37158 | 0.32018 | 1.26432 | 0.61176 | 0.61931 | 0.62161 | 1.85267 | 0.37538 | 0.21923 | 0.19028 | 0.78490 | 3.902 | 43.35 |
| 43 | ATAm | 人工部落算法M | 0.71771 | 0.55304 | 0.25235 | 1.52310 | 0.82491 | 0.55904 | 0.20473 | 1.58867 | 0.44000 | 0.18615 | 0.09411 | 0.72026 | 3.832 | 42.58 |
| 44 | CROm | 珊瑚礁优化算法M | 0.78512 | 0.46032 | 0.25958 | 1.50502 | 0.86688 | 0.35297 | 0.16267 | 1.38252 | 0.63231 | 0.26738 | 0.10734 | 1.00703 | 3.895 | 43.27 |
| 45 | CFO | 中央力优化 | 0.60961 | 0.54958 | 0.27831 | 1.43750 | 0.63418 | 0.46833 | 0.22541 | 1.32792 | 0.57231 | 0.23477 | 0.09586 | 0.90294 | 3.668 | 40.76 |
| DOS | 确定性振荡搜索 | 0.34220 | 0.34218 | 0.34216 | 1.02654 | 0.57086 | 0.34629 | 0.32879 | 1.24594 | 0.20000 | 0.20923 | 0.23077 | 0.64000 | 2.912 | 32.36 | |
| RW | 神经Boid优化算法2(joo) | 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 | |
总结
算法所需配置的参数极少(仅种群大小和移动系数),这简化了实际应用,并降低了参数设置不当的风险。
其三态斜率机制(正向、负向、未知)允许粒子根据当前搜索方向的质量自适应调整行为,这正是该算法的核心创新点。算法不涉及复杂数学运算,因此计算效率很高。
其主要优势在于将群体算法的高效性与确定性方法的稳定性、可复现性相结合,尽管总体上确定性算法略逊于随机算法,但在解决某些特定问题时,此类方法依然具备实用价值。

图例2. 算法在相应测试中的颜色渐变表示

图例3. 算法测试结果的直方图(评分范围为0到100,越高越好,其中100为理论上的最高可能得分,档案中附有计算排名表的脚本)
DOS的优缺点:
优点:
- 快速。
- 实现简单。
缺点:
- 低维函数结果分散。
文章附有一个包含当前版本算法代码的归档文件。本文作者对标准算法描述的绝对准确性不承担责任。为提升搜索能力,已经对其中的许多算法进行了修改。文章中表述的结论和论断都是基于实验的结果。
文中所用的程序
| # | 名称 | 类型 | 描述 |
|---|---|---|---|
| 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_DOS.mq5 | 脚本 | DOS测试 |
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18154
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
你应该了解的 MQL5 向导技巧(第67部分):使用 TRIX 和威廉百分比范围的形态
您应该了解的MQL5向导技巧(第六十六部分):结合点积核使用FrAMA与强力指数形态
神经网络在交易中的应用:多元时间序列的双重聚类(DUET)