English Русский Español Deutsch 日本語 Português
preview
无政府社会优化(ASO)算法

无政府社会优化(ASO)算法

MetaTrader 5示例 | 17 三月 2025, 12:15
350 0
Andrey Dik
Andrey Dik

内容
  1. 概述
  2. 算法实现
  3. 测试结果


1. 概述

我一直对社会关系的话题以及在社会联系概念中构建算法的可能性深感兴趣,因为这是社会发展中最有趣的现象之一,并且为系统化描述关系体系的结构以及实施相应的优化算法提供了广阔的领域。

在之前的文章中,我们已经探讨过社会行为的算法,包括社会群体的演化人工合作搜索。在本文中,我们将尝试理解无序社会的概念——一个没有中央权力和层级结构的社交互动系统,在这个系统中,人们可以基于自由协商来组织生活和进行互动。

无政府社会基于自主和自由的原则,每个人都可以独立自主地做出关于自己生活的决定,不受外界干涉;基于自愿合作的原则,人们在没有强迫的情况下,基于所有参与者的同意进行互动;还基于权利和平等机会的原则,以及团结、互助和合作的原则。从算法实现的角度来看,这个概念非常有趣。有人已经尝试将这种社会结构融入到无政府社会优化(Anarchic Society Optimization,ASO)算法中。该算法由Ahmadi-Javid提出,并于2011年发表。

主要思想是开发一种受无政府社会中个体行为启发的优化方法。与基于昆虫或动物群体开发的现有群体智能方法(如粒子群优化算法(PSO)蚁群优化算法(ACO))不同,基于研究标准人类社会构建来开发算法可能只会取得有限的成功,因为组织良好的社会无法仅通过个体决策来实现其愿望。此外,社会中的任何成员都不是真正独立自主的,也无法在给定时间段内彻底改善自己的处境。这一认识促使算法创建者从基于异常结构的社会中借鉴基本概念进行开发。 

无政府社会优化(ASO)的核心是一群善变、爱冒险、不喜欢稳定且经常表现出非理性行为的个体,他们在探索阶段会移动到之前访问过的最差位置。成员间无政府行为的程度随着他们处境差异的增大而增加。利用这些参与者,ASO探索解空间,并试图避免陷入局部最优陷阱。因此,ASO的创建者试图传达这样一个观点:研究并应用基于异常社群行为的原则,可以创建出能够解决复杂优化问题的有效算法。我们将考虑一个统一的ASO框架,该框架可以轻松地用于连续和离散问题。


2. 算法实现

在编写算法代码之前,我们需要了解其结构以及作者融入其中的基本机制。ASO(Anarchic Social Optimization)算法是一种优化方法,它结合了粒子群优化(Particle Swarm Optimization, PSO)算法的优点以及无政府状态社会行为的特征机制。该算法的自适应性以及在不同运动策略之间保持平衡的能力是其主要特点。

让我们从ASO算法的详细描述开始:

1. 初始化:

  • 从社会成员中创建一个种群(popSize)。
  • 每个成员在搜索空间中被初始化到一个随机位置。
  • 每个成员保留其个人最佳位置和前一个位置。

2. 基本优化循环:

   在每次迭代中,算法对每个社会成员执行以下步骤:

   a) 指数计算:

  • 反复无常指数(FI) — 该指数反映了社会成员的不稳定性,并衡量了他与其他个体相比的不满程度。   
  • 外部不规则指数(EI) — 该指数评估社会中位置的多样性,并显示与全局最佳解的偏差。
  • 内部不规则指数(II) — 该指数评估个体在迭代过程中的位置变化,并反映与个人最佳解的偏差。

   b) 选择移动策略:

      根据比较FIEIII指数,选择以下三种移动策略之一:

  • 当前移动策略(CurrentMP) 使用带有惯性和加速度比率的PSO方程。
  • 社会移动策略(SocietyMP) 对社会中随机选择的成员应用交叉操作。
  • 过去移动策略(PastMP) 使用有关个体前一个位置的信息。

   c) 无政府行为: 以anarchyProb的概率完全随机化个体的位置。

   d) 位置更新: 检查新位置是否符合搜索空间的约束。

   e) 更新最佳位置:

  • 如果当前位置更好,则更新pBest个人最佳位置。
  • 如果找到新的更好解,则更新gBest全局最佳位置。

3. 参数调整:

  • anarchyProb无政府行为的概率逐渐降低。
  • 计算FIalpha参数逐渐增加。
  • omega惯性权重逐渐降低。

4. 算法参数:

  • popSize - 种群规模。
  • omegalambda1lambda2 — 在CurrentMP中计算速度的参数(与PSO相同)。
  • anarchyProb — 无政府行为的概率。
  • alphathetadelta — 分别用于计算FIEIII指数的参数。

这一算法相当复杂。我将尝试以一种非常清晰且有条理的方式来描述其运行机制,以便于理解。下一步是分析算法中使用的方程。

ASO算法中的基本方程继承自PSO算法。它执行速度更新的计算:V_i (k+1) = ω * V_i (k) + λ1 * r1 * (P_i (k) - X_i (k)) + λ2 * r2 * (G (k) - X_i (k)),其中:

  • V_i (k)i粒子在k次迭代中的速度。
  • X_i (k)i粒子在k次迭代中的位置。
  • P_i (k)i粒子在k次迭代之前找到的最佳位置。
  • G (k) — 所有粒子在k次迭代之前找到的全局最佳位置。
  • ω — 惯性比率。
  • λ1λ2 — 加速度比率。
  • r1r2 — 区间(0, 1)内的随机数。

作者指出,当定义了相应的移动策略和组合规则时,PSO方程是ASO结构的一个特例。在原始版本中,智能体的先前速度被纳入计算中。我通过仅保留当前速度值来改变方法,这使得算法性能有了显著提升。

方程(1)和(2)定义了ASO算法中i社区成员在k次迭代中的反复无常指数FI。这些方程有助于评估个体对其当前位置与其他位置相比的不满程度。让我们详细看看它们:

1. 计算反复无常指数的方程(1):(kFI)i = α - α (f (Xi (k)) - f (Pi (k))) / (f (Xi (k*)) - f (Xi (k)))

这个方程展示了i个体的当前位置与其最佳个人位置以及其最佳全局位置的差异,差异由α(alpha)参数加权。

2. 计算i个体在k次迭代中的反复无常指数的方程(2):(kFI)i = α - α (f (Xi (k)) - f (Pi (k))) / (f (G (k)) - f (Xi (k)))

这个方程与第一个类似,但用于不同的目的,其中比较了当前位置、最佳个人位置和最佳全局位置。

这两个方程都用于评估社会成员的不满程度,这使他们能够更明智地决定如何改变他们的位置,以寻找最优解。

方程(3)和(4)描述了算法中社会成员的外部不规则指数内部不规则指数

3. 方程(3) — k次迭代中i个体的外部不规则指数:(kEI)i = exp (-(θi) (f (G) - f (Xi (k))))

4. 方程(4) — k次迭代中i个体的内部不规则指数:(kEI)i = 1 - exp (-δi (kD))

其中:

  • (kFI)ik次迭代中i个体的反复无常指数。
  • α — [0,1]区间内的非负“alpha”数值。
  • f (Xi (k))k次迭代中i个体的目标函数值。
  • f (Pi (k))i个体之前访问的最佳位置的目标函数值。
  • f (Xi (k))k次迭代中最佳个体位置的目标函数值。
  • f (G (k)) — 社会全体在k次迭代之前访问的全局最佳位置的目标函数值。
  • (kEI)ik次迭代中i个体的外部不规则指数。
  • θi — 正数theta值。
  • kD — 社会多样性的一个合适度量,例如个体目标函数值的变化率。
  • δi — 正数delta值。

这些方程表明,如果社会中的多样性增加(即个体的目标函数值更加不同),个体更有可能表现出不规则的行为。这些方程用于评估ASO算法中社会成员行为的变异性,使他们能够在寻找最优解的过程中做出更多样化和适应性强的决策。

FI200

图例1. 如果智能体的当前最佳解(200)比全体智能体的最佳解(1000)的值小得多,那么图表上的线条几乎呈线性变化。

FI800

图例 2. 智能体的当前最佳解与全体智能体的最佳解(1000)之间的差异越小,图表上的线条就越呈非线性。

theta

图例 3. 外部不规则指数与内部不规则指数随“theta”和“delta”比率变化的依赖关系图(以0.01到0.9的值为例)

因此,社会成员可以利用其他成员的信息来决定他们的移动方式,以及他们的行为如何根据社会多样性水平的不同而变化。

现在我们对ASO算法有了更多的了解,并且基于我们获得的理论,我们可以进入实践部分。我们将编写算法的伪代码,以便在代码中实现它。ASO算法伪代码:

初始化:
1. 设置参数:popSize、omega、lambda1、lambda2、anarchyProb、alpha、theta、delta、rangeMin[]、rangeMax[]、rangeStep[]
2. 创建一个包含popSize成员的种群:对每个成员i从0到popSize-1,对每个坐标c从0到coords-1:
position[i].[c] = rangeMin[c]与rangeMax[c]之间的随机数
    pBest [i].[c] = position [i].[c]
    prevPosition [i].[c] = position [i].[c]
pBestFitness [i] = -无穷大
3. 设置gBest为初始种群中的最佳位置
4. 设置gBestFitness为gBest的适应度值

主循环:
5. 直到达到停止条件:对每个成员i从0到popSize-1:
5.1 计算索引
    FI = CalculateFI (i)
    EI = CalculateEI (i)
    II = CalculateII (i)   
5.2 选择移动策略
如果 FI > EI 且 FI > II: newPosition = CurrentMP(i)
否则,如果 EI > FI 且 EI > II: newPosition = SocietyMP (i)
否则: newPosition = PastMP(i)
5.3 应用无政府行为
如果随机数 < anarchyProb: 对每个坐标c从0到coords-1:
newPosition[c] = rangeMin[c]与rangeMax[c]之间的随机数
5.4 更新位置:对每个坐标c从0到coords-1:
    prevPosition [i].[c] = position [i].[c]
    position [i].[c] = limit (newPosition [c], rangeMin [c], rangeMax [c], rangeStep [c])
5.5 评估新的“适应度”位置 = rate_fitness(position[i])
5.6 如果“适应度” > pBestFitness[i]: 更新个人“最佳”
    pBestFitness [i] = fitness
    pBest [i] = position [i]
5.7 如果“适应度” > gBestFitness: 更新全局“最佳”
    gBestFitness = fitness
    gBest = position [i]
5.8 调整参数 AdaptParameters()
5.9 CalculateFI(i)函数: 返回 1 - alpha * (fitness[i] - pBestFitness[i]) / (gBestFitness - fitness[i])
5.10 CalculateEI(i)函数: 返回 1 - exp(-(gBestFitness - fitness[i]) / theta)
5.11 CalculateII(i)函数: 返回 1 - exp(-(pBestFitness[i] - fitness[i]) / delta)
5.12 CurrentMP(i)函数: 对每个坐标c从0到coords-1
r1 = 0到1之间的随机数
r1 = 0到1之间的随机数
velocity = omega * (position [i].[c] - pBest [i].[c]) + lambda1 * r1 * (pBest [i].[c] - position [i].[c]) + lambda2 * r2 * (gBest [c] - position [i].[c])
    newPosition [c] = position [i].[c] + velocity
返回newPosition
5.13 SocietyMP(i)函数: j = 种群中不等于i的随机成员,对每个坐标c从0到coords-1:
如果随机数 < 0.5:
        newPosition [c] = position [i].[c]
    否则:newPosition [c] = position [j].[c]
返回newPosition
5.14 PastMP(i)函数: 对每个坐标c从0到coords-1:
如果随机数 < 0.5:
        newPosition [c] = position [i].[c]
    否则:newPosition [c] = prevPosition [i].[c]
返回newPosition

    现在我们有了伪代码,可以开始根据它编写算法代码了。让我们描述一下用于表示算法中的参与者(智能体)S_ASO_Member的结构。

    1. 结构字段:    

    • pPrev [] — 参与者之前的坐标位置数组。 
    • pBest [] — 参与者已知的最佳位置数组(个人最佳位置)。 
    • pBestFitness — 该变量存储已知最佳位置的适应度值(质量)。

    2. Init 方法根据传递的坐标数量(或搜索空间的维度)初始化 pPrevpBest 数组。ArrayResize(pBest, coords)ArrayResize(pPrev, coords) — 这些调用将数组大小调整为 coords 的值。pBestFitness = -DBL_MAX — 将最佳位置的初始适应度值设置为一个极小值,以确保任何找到的值都会比这个值更好。

    S_ASO_Member 结构用于存储优化算法中每个参与者的信息。它允许我们跟踪参与者的当前位置和最佳位置,以及它们的适应度。 

    //——————————————————————————————————————————————————————————————————————————————
    struct S_ASO_Member
    {
        double pPrev [];     // Previous position
        double pBest  [];    // Personal best position
        double pBestFitness; // Personal best fitness
    
    
        void Init (int coords)
        {
          ArrayResize (pBest, coords);
          ArrayResize (pPrev, coords);
          pBestFitness = -DBL_MAX;
        }
    };
    //——————————————————————————————————————————————————————————————————————————————
    
    

    定义从C_AO基类继承的C_AO_ASO类。让我们更详细地看看它:

    1. 参数包括:

    • popSize — 种群大小(社会成员的数量)。
    • anarchyProb — 无政府行为的可能性,一些参与者可能会独立于其他成员行动。
    • omegalambda1lambda2 — 与惯性和加速度相关的参数,用于控制参与者的行为。
    • alphathetadelta — 用于计算指标(FI、EI、II)的参数。

    2. params — 参数数组,其中每个元素包含一个名称和一个值。 

    3. SetParams() — 该方法从params数组中更新参数值,这允许在算法初始化后更改其参数。

    4. Init() — 该方法使用给定的范围和步长初始化算法。它接受rangeMinPrangeMaxPrangeStepP数组,以及epochsP迭代次数。

    5. Moving()Revision() — 这些方法实现了参与者在优化过程中的基本移动逻辑及其修订(更新)。 

    6. 类字段:

     S_ASO_Member member[] — 社会成员数组,存储算法中每个参与者的信息。

    7. 私有方法:

    • CalculateFI — 计算特定参与者的FI(适应度指标)值的方法。
    • CalculateEI — 计算EI(探索指标)的方法。
    • CalculateII — 计算II(惯性指标)值的方法。
    • CurrentMPSocietyMPPastMP — 这些方法实现了参与者与其当前位置、社会位置和过去位置的交互逻辑。

    C_AO_ASO类实现了“无政府社会”的概念,其中参与者既可以联合行动,也可以独立于彼此行动,并且包括控制参与者行为的参数以及用于其初始化和更新的方法。 

    //——————————————————————————————————————————————————————————————————————————————
    class C_AO_ASO : public C_AO
    {
      public: //--------------------------------------------------------------------
      ~C_AO_ASO () { }
      C_AO_ASO ()
      {
        ao_name = "ASO";
        ao_desc = "Anarchy Society Optimization";
        ao_link = "https://www.mql5.com/en/articles/15511";
    
        popSize     = 50;     // Population size
        anarchyProb = 0.1;    // Probability of anarchic behavior
    
        omega       = 0.7;    // Inertia weight
        lambda1     = 1.5;    // Acceleration coefficient for P-best
        lambda2     = 1.5;    // Acceleration coefficient for G-best
    
        alpha       = 0.5;    // Parameter for FI calculation
        theta       = 1.0;    // Parameter for EI calculation
        delta       = 1.0;    // Parameter for II calculation
    
        ArrayResize (params, 8);
    
        params [0].name = "popSize";     params [0].val = popSize;
        params [1].name = "anarchyProb"; params [1].val = anarchyProb;
    
        params [2].name = "omega";       params [2].val = omega;
        params [3].name = "lambda1";     params [3].val = lambda1;
        params [4].name = "lambda2";     params [4].val = lambda2;
    
        params [5].name = "alpha";       params [5].val = alpha;
        params [6].name = "theta";       params [6].val = theta;
        params [7].name = "delta";       params [7].val = delta;
      }
    
      void SetParams ()
      {
        popSize     = (int)params [0].val;
        anarchyProb = params      [1].val;
    
        omega       = params      [2].val;
        lambda1     = params      [3].val;
        lambda2     = params      [4].val;
    
        alpha       = params      [5].val;
        theta       = params      [6].val;
        delta       = params      [7].val;
      }
    
      bool Init (const double &rangeMinP  [],
                 const double &rangeMaxP  [],
                 const double &rangeStepP [],
                 const int     epochsP = 0);
    
      void Moving   ();
      void Revision ();
    
      //----------------------------------------------------------------------------
      double anarchyProb; // Probability of anarchic behavior
      double omega;       // Inertia weight
      double lambda1;     // Acceleration coefficient for P-best
      double lambda2;     // Acceleration coefficient for G-best
      double alpha;       // Parameter for FI calculation
      double theta;       // Parameter for EI calculation
      double delta;       // Parameter for II calculation
    
      S_ASO_Member member []; // Vector of society members
    
      private: //-------------------------------------------------------------------
    
      double CalculateFI (int memberIndex);
      double CalculateEI (int memberIndex);
      double CalculateII (int memberIndex);
      void   CurrentMP   (S_AO_Agent &agent, S_ASO_Member &memb, int coordInd);
      void   SocietyMP   (S_AO_Agent &agent, int coordInd);
      void   PastMP      (S_AO_Agent &agent, S_ASO_Member &memb, int coordInd);
    };
    //——————————————————————————————————————————————————————————————————————————————
    

    让我们看看C_AO_ASO类的以下Init方法。方法逻辑:

    • StandardInit — 调用此方法以使用传递的范围执行标准初始化。如果此方法返回false,则表示发生了错误。
    • ArrayResize — 此方法将member数组的大小调整为popSize,这决定了算法中的参与者数量(社会成员)。
    接下来,循环初始化member数组的每个成员。每个成员的Init方法设置在coords数组中定义的初始坐标。Init方法旨在初始化算法。它设置参数的值范围,调整成员数组的大小,并初始化每个成员。 

    //——————————————————————————————————————————————————————————————————————————————
    
    bool C_AO_ASO::Init (const double &rangeMinP  [],
                         const double &rangeMaxP  [],
                         const double &rangeStepP [],
                         const int     epochsP = 0)
    {
    
      if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;
    
      //----------------------------------------------------------------------------
      ArrayResize (member, popSize);
    
      for (int i = 0; i < popSize; i++) member [i].Init (coords);
    
      return true;
    
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    让我们看看C_AO_ASO类的Moving方法代码。方法结构和逻辑:

    1. 首次调用检查:

    • 如果revisionfalse,则该方法使用指定范围内的随机值初始化a数组,范围为rangeMinrangeMax
    • 对于每个i种群成员的每个c坐标,调用u.RNDfromCI方法。它生成一个随机值,然后使用u.SeInDiSp对该值进行归一化。
    • 这些值被保存在member[i].pPrev[c]中,以便后续使用。
    • 之后,将revision设置为true,方法执行完成。

    2. 基本移动逻辑:

    • 对于每个i种群成员,计算三个指数:fieiii。这些是描述种群成员状态的指标。
    • 对于每个c坐标,执行以下操作:
      • 将当前值保存到member[i].pPrev[c]
      • 使用u.RNDprobab()生成一个rnd随机数。
      • 如果随机数小于anarchyProb(这意味着行为表现出无政府状态的概率满足),则i成员的c坐标将从范围内随机初始化。
      • 否则,根据fieiii的值,调用CurrentMPSocietyMPPastMP方法。
      • 在所有更改之后,使用u.SeInDiSp调整每个c坐标的值。

    Moving方法实现了基于当前状态和指标在解空间中移动种群成员的逻辑。 

    //——————————————————————————————————————————————————————————————————————————————
    void C_AO_ASO::Moving ()
    {
      //----------------------------------------------------------------------------
      if (!revision)
      {
        for (int i = 0; i < popSize; i++)
        {
          for (int c = 0; c < coords; c++)
          {
            a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
    
            a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    
            member [i].pPrev [c] = a [i].c [c];
          }
        }
    
        revision = true;
        return;
      }
    
      //----------------------------------------------------------------------------
    
      double fi  = 0.0; //fickleness index
      double ei  = 0.0; //external irregularity index
      double ii  = 0.0; //internal irregularity index
      double rnd = 0.0;
    
      for (int i = 0; i < popSize; i++)
      {
        fi = CalculateFI (i);
        ei = CalculateEI (i);
        ii = CalculateII (i);
    
        for (int c = 0; c < coords; c++)
        {
          member [i].pPrev [c] = a [i].c [c];
    
          rnd = u.RNDprobab ();
    
          if (u.RNDprobab () < anarchyProb) a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
          else
          {
            if (rnd > fi) CurrentMP (a [i], member [i], c);
            else
            {
              if (rnd < ei) SocietyMP (a [i], c);
              else
              {
                if (rnd < ii) PastMP (a [i], member [i], c);
              }
            }
          }
        }
    
        for (int c = 0; c < coords; c++)
        {
          a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
        }
      }
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    让我们从Moving方法转向Revision方法。总体结构和逻辑:

    1. 将ind变量初始化为-1。它将用于存储具有最佳f函数值的种群成员的索引。

    2. 该方法遍历种群中的所有成员,从0popSize - 1

    3. 寻找最佳函数值:对于种群中的每个成员,检查a[i],即其f函数值是否超过了当前的最佳值fB。如果满足条件,则用a[i].f更新fB,同时将ind索引设置为i

    4. 更新个人最佳值:该方法还检查a[i].f函数值是否大于种群成员的member[i].pBestFitness值。如果是,则更新该值,并使用ArrayCopy函数将当前坐标a[i].c复制到member[i].pBest

    5. 复制最佳解:循环完成后,如果找到ind索引(即至少有一个种群成员的函数值大于fB),则使用ArrayCopy将该种群成员的坐标复制到cB

    Revision方法负责更新种群中找到的最佳解,以及更新种群中每个成员的个人最佳值。它使用简单的逻辑比较函数值,以确定哪些解是最佳的,并将它们存储起来以供后续使用。 

    //——————————————————————————————————————————————————————————————————————————————
    void C_AO_ASO::Revision ()
    {
      int ind = -1;
    
      for (int i = 0; i < popSize; i++)
      {
        if (a [i].f > fB)
        {
          fB = a [i].f;
          ind = i;
        }
    
        if (a [i].f > member [i].pBestFitness)
        {
          member [i].pBestFitness = a [i].f;
    
          ArrayCopy (member [i].pBest, a [i].c, 0, 0, WHOLE_ARRAY);
        }
      }
    
      if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    接下来是C_AO_ASO类的CalculateFI方法。方法描述:

    1. 该方法接收种群成员的索引memberIndex,用于计算其适应度值。

    2. 获取适应度值:

    • currentFitness — 通过memberIndex索引从a数组中获取种群成员的当前适应度值。
    • personalBestFitness — 从member数组中获取该成员的个人最佳适应度值。
    • globalBestFitness — 获取存储在fB变量中的全局最佳适应度值。

    3. 适应度指数(FI)计算 — 该方法返回通过公式计算出的值。

    该公式通过将个人适应度与当前适应度的差值除以全局适应度与当前适应度的差值来归一化,从而计算适应度指数。CalculateFI方法为种群成员计算适应度指数,用于评估其相对于个人最佳和全局最佳适应度值的质量。 

    //——————————————————————————————————————————————————————————————————————————————
    double C_AO_ASO::CalculateFI (int memberIndex)
    {
      double currentFitness      = a      [memberIndex].f;
      double personalBestFitness = member [memberIndex].pBestFitness;
      double globalBestFitness   = fB;
    
      //1 - 0.9 * (800-x)/(1000-x)
      return 1 - alpha * (personalBestFitness - currentFitness) / (globalBestFitness - currentFitness);
    }
    //——————————————————————————————————————————————————————————————————————————————
    
    

    接下来是C_AO_ASO类的CalculateEI方法。该方法与前一个方法几乎相同,但使用全局最佳和当前个人适应度值来进行计算。

    最终,该方法返回一个介于01之间的值,其中1表示最大预期改进,而0表示没有改进。CalculateEI方法根据给定种群成员的当前适应度值和全局最佳适应度值计算预期改进率。 

    //——————————————————————————————————————————————————————————————————————————————
    double C_AO_ASO::CalculateEI (int memberIndex)
    {
      double currentFitness    = a [memberIndex].f;
      double globalBestFitness = fB;
    
      //1-exp(-(10000-x)/(10000*0.9))
      return 1 - MathExp (-(globalBestFitness - currentFitness) / (globalBestFitness * theta));
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    C_AO_ASO类的CalculateII方法与前一个方法完全相同,但它使用最佳和当前自身的适应度。

    指数函数有助于平滑变化并提供值之间的平滑过渡。CalculateII方法为种群成员计算一个改进指数,该指数考虑了当前适应度状态与个人成就的对比情况。

    //——————————————————————————————————————————————————————————————————————————————
    double C_AO_ASO::CalculateII (int memberIndex)
    {
      double currentFitness      = a      [memberIndex].f;
      double personalBestFitness = member [memberIndex].pBestFitness;
    
      //1-exp(-(10000-x)/(10000*0.9))
      return 1 - MathExp (-(personalBestFitness - currentFitness) / (personalBestFitness * delta));
    }
    //——————————————————————————————————————————————————————————————————————————————
    
    

    让我们继续探讨C_AO_ASO类的CurrentMP方法。描述:

    1. 随机数生成:

    • r1 = u.RNDprobab() — 生成范围在 [0, 1] 内的随机数 r1
    • r2 = u.RNDprobab() — 生成范围在 [0, 1] 内的随机数 r2

    2. 计算 velocity — 方程包含三个组成部分:

    • omega * (agent.c[coordInd] - memb.pBest[coordInd]) — 惯性分量,考虑智能体的前一个位置来移动智能体。
    • lambda1 * r1 * (memb.pBest[coordInd] - agent.c[coordInd]) — 考虑个人最佳位置来引导智能体。
    • lambda2 * r2 * (cB[coordInd] - agent.c[coordInd]) — 考虑种群的最佳位置来引导智能体。

    3. 通过将速度加到当前坐标值来更新智能体的位置。

    CurrentMP 方法基于智能体的当前位置、个人最佳位置以及种群的最佳位置来实现智能体在空间中的位置更新。

    //——————————————————————————————————————————————————————————————————————————————
    void C_AO_ASO::CurrentMP (S_AO_Agent &agent, S_ASO_Member &memb, int coordInd)
    {
      double r1 = u.RNDprobab ();
      double r2 = u.RNDprobab ();
    
      double velocity = omega   *      (agent.c    [coordInd] - memb.pBest [coordInd]) +
                        lambda1 * r1 * (memb.pBest [coordInd] - agent.c    [coordInd]) +
                        lambda2 * r2 * (cB         [coordInd] - agent.c    [coordInd]);
    
      agent.c [coordInd] += velocity;
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    C_AO_ASO类的SocietyMP方法根据群体和个体信息之间的随机选择来更新智能体的坐标。这使得智能体处于既能够适应整个种群又能够适应个体的状态。

    //——————————————————————————————————————————————————————————————————————————————
    void C_AO_ASO::SocietyMP (S_AO_Agent &agent, int coordInd)
    {
      int otherMember = u.RNDminusOne (popSize);
    
      agent.c [coordInd] = u.RNDprobab () < 0.5 ? cB [coordInd] : member [otherMember].pBest [coordInd];
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    C_AO_ASO类的PastMP方法根据种群成员当前最佳状态和其前一个状态之间的随机选择来更新智能体的坐标。这使得智能体能够同时考虑种群成员的当前成就及其过去的成果。这种方法改善了算法的组合特性。

    //——————————————————————————————————————————————————————————————————————————————
    void C_AO_ASO::PastMP (S_AO_Agent &agent, S_ASO_Member &memb, int coordInd)
    {
      agent.c [coordInd] = u.RNDprobab () < 0.5 ? memb.pBest [coordInd] : memb.pPrev [coordInd];
    }
    //——————————————————————————————————————————————————————————————————————————————
    


    3. 测试结果

    ASO测试的标准结果:

    ASO|Anarchy Society Optimization|50.0|0.01|0.7|1.5|1.5|0.5|0.1|0.1|
    =============================
    5 Hilly's; Func runs: 10000; result: 0.8487202680440514
    25 Hilly's; Func runs: 10000; result: 0.746458607174428
    500 Hilly's; Func runs: 10000; result: 0.31465494017509904
    =============================
    5 Forest's; Func runs: 10000; result: 0.9614752193694915
    25 Forest's; Func runs: 10000; result: 0.7915027321897546
    500 Forest's; Func runs: 10000; result: 0.23802894131144553
    =============================
    5 Megacity's; Func runs: 10000; result: 0.5707692307692309
    25 Megacity's; Func runs: 10000; result: 0.5406153846153848
    500 Megacity's; Func runs: 10000; result: 0.16613846153846298
    =============================
    总分:5.17836 (57.54%)

    通过观察算法运行的可视化结果,我们可以得出一些结论:结果存在一定的分散性。然而,该算法在处理高维函数时表现出良好的搜索能力,这一特点也得到了其结果的验证。 

    Hilly值

      ASO在Hilly函数上

    Forest值

    ASO在Forest函数上

    Megacity

    ASO在Megacity函数上

    种群优化算法排名表:经过测试,ASO算法进入前十名,并在排名表中位列第9名。

    # AO 说明 Hilly值 Hilly最终值 Forest值 Forest最终值 Megacity (离散) Megacity最终值 最终结果 最大百分比
    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 密码锁算法 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 (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
    4 CTA 彗星尾算法 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
    5 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
    6 ESG 社会群体的进化 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
    7 SIA 模拟各向同性退火 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
    8 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
    9 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
    10 TSEA 龟壳演化算法 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
    11 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
    12 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
    13 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
    14 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
    15 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
    16 (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
    17 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
    18 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
    19 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
    20 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
    21 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
    22 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
    23 ASBO 适应性社会行为优化 0.76331 0.49253 0.32619 1.58202 0.79546 0.40035 0.26097 1.45677 0.26462 0.17169 0.18200 0.61831 3.657 40.63
    24 MEC 思维进化计算 0.69533 0.53376 0.32661 1.55569 0.72464 0.33036 0.07198 1.12698 0.52500 0.22000 0.04198 0.78698 3.470 38.55
    25 IWO 入侵杂草优化 0.72679 0.52256 0.33123 1.58058 0.70756 0.33955 0.07484 1.12196 0.42333 0.23067 0.04617 0.70017 3.403 37.81
    26 Micro-AIS 微型人工免疫系统 0.79547 0.51922 0.30861 1.62330 0.72956 0.36879 0.09398 1.19233 0.37667 0.15867 0.02802 0.56335 3.379 37.54
    27 COAm 布谷鸟优化算法 M 0.75820 0.48652 0.31369 1.55841 0.74054 0.28051 0.05599 1.07704 0.50500 0.17467 0.03380 0.71347 3.349 37.21
    28 SDOm 螺旋动力学优化 M 0.74601 0.44623 0.29687 1.48912 0.70204 0.34678 0.10944 1.15826 0.42833 0.16767 0.03663 0.63263 3.280 36.44
    29 NMm Nelder-Mead方法 M 0.73807 0.50598 0.31342 1.55747 0.63674 0.28302 0.08221 1.00197 0.44667 0.18667 0.04028 0.67362 3.233 35.92
    30 FAm 萤火虫算法 M 0.58634 0.47228 0.32276 1.38138 0.68467 0.37439 0.10908 1.16814 0.28667 0.16467 0.04722 0.49855 3.048 33.87
    31 GSA 引力搜索算法 0.64757 0.49197 0.30062 1.44016 0.53962 0.36353 0.09945 1.00260 0.32667 0.12200 0.01917 0.46783 2.911 32.34
    32 BFO 细菌觅食优化 0.61171 0.43270 0.31318 1.35759 0.54410 0.21511 0.05676 0.81597 0.42167 0.13800 0.03195 0.59162 2.765 30.72
    33 ABC 人工蜂群 0.63377 0.42402 0.30892 1.36671 0.55103 0.21874 0.05623 0.82600 0.34000 0.14200 0.03102 0.51302 2.706 30.06
    34 BA 蝙蝠算法 0.59761 0.45911 0.35242 1.40915 0.40321 0.19313 0.07175 0.66810 0.21000 0.10100 0.03517 0.34617 2.423 26.93
    35 SA 模拟退火 0.55787 0.42177 0.31549 1.29513 0.34998 0.15259 0.05023 0.55280 0.31167 0.10033 0.02883 0.44083 2.289 25.43
    36 IWDm 智能水滴 M 0.54501 0.37897 0.30124 1.22522 0.46104 0.14704 0.04369 0.65177 0.25833 0.09700 0.02308 0.37842 2.255 25.06
    37 PSO 粒子群优化 0.59726 0.36923 0.29928 1.26577 0.37237 0.16324 0.07010 0.60572 0.25667 0.08000 0.02157 0.35823 2.230 24.77
    38 Boids算法 虚拟生物算法 0.43340 0.30581 0.25425 0.99346 0.35718 0.20160 0.15708 0.71586 0.27846 0.14277 0.09834 0.51957 2.229 24.77
    39 MA 猴群算法 0.59107 0.42681 0.31816 1.33604 0.31138 0.14069 0.06612 0.51819 0.22833 0.08567 0.02790 0.34190 2.196 24.40
    40 SFL 混合蛙跳算法 0.53925 0.35816 0.29809 1.19551 0.37141 0.11427 0.04051 0.52618 0.27167 0.08667 0.02402 0.38235 2.104 23.38
    41 FSS 鱼群搜索 0.55669 0.39992 0.31172 1.26833 0.31009 0.11889 0.04569 0.47467 0.21167 0.07633 0.02488 0.31288 2.056 22.84
    42 RND 随机 0.52033 0.36068 0.30133 1.18234 0.31335 0.11787 0.04354 0.47476 0.25333 0.07933 0.02382 0.35648 2.014 22.37
    43 GWO 灰狼优化算法 0.59169 0.36561 0.29595 1.25326 0.24499 0.09047 0.03612 0.37158 0.27667 0.08567 0.02170 0.38403 2.009 22.32
    44 CSS 人工电场算法 0.44252 0.35454 0.35201 1.14907 0.24140 0.11345 0.06814 0.42299 0.18333 0.06300 0.02322 0.26955 1.842 20.46
    45 EM 类电磁算法 0.46250 0.34594 0.32285 1.13129 0.21245 0.09783 0.10057 0.41085 0.15667 0.06033 0.02712 0.24412 1.786 19.85



    总结

    根据算法在不同维度测试函数上的运行结果,可以得出以下结论:与表中其最近的邻居相比,ASO在平滑的丘陵函数上表现中规中矩,但在“尖锐”的森林函数上表现相当不错,尤其是在离散的大都市函数上表现出色。总体最终得分为5.17836(57.54%)。该算法在处理高维函数时表现出良好的搜索能力。换句话说,它具有良好的可扩展性。该算法可以推荐用于解决离散优化问题,这对于交易者来说是一个优先考虑的方向。

    tab

    图例 4. 根据相关测试,将算法的颜色等级大于或等于0.99的结果以白色突出显示。

    图表

    图例 5. 算法测试结果的直方图(标尺从 0 到 100,数字越大结果越好,

    其中 100 是理论上的最大可能结果,将计算评级表格的脚本存档)


    ASO算法的优缺点:

    优势:

    1. 在各种函数上表现出良好的收敛性。
    2. 在离散函数上表现出色。

    缺点:

    1. 参数数量众多(配置非常困难)。
    2. 低维函数结果分散。
    3. 复杂的实现难度。

    文章附有一个包含当前版本算法代码的归档文件。本文作者对标准算法描述的绝对准确性不承担责任。为提升搜索能力,已经对其中的许多算法进行了修改。文章中表述的结论和论断都是基于实验的结果。

    本文由MetaQuotes Ltd译自俄文
    原文地址: https://www.mql5.com/ru/articles/15511

    附加的文件 |
    ASO.zip (27.77 KB)
    将 MQL5 与数据处理包集成(第 1 部分):高级数据分析和统计处理 将 MQL5 与数据处理包集成(第 1 部分):高级数据分析和统计处理
    集成实现了无缝的工作流程,来自 MQL5 的原始金融数据可以导入到 Jupyter Lab 等数据处理包中,用于包括统计测试在内的高级分析。
    您应当知道的 MQL5 向导技术(第 26 部分):移动平均和赫斯特(Hurst)指数 您应当知道的 MQL5 向导技术(第 26 部分):移动平均和赫斯特(Hurst)指数
    赫斯特(Hurst)指数是时间序列长期自相关度的衡量度。据了解,它捕获时间序列的长期属性,故在时间序列分析中也具有一定的分量,即使在财经/金融时间序列之外亦然。然而,我们专注于其对交易者的潜在益处,研究如何将该计量度与移动平均线配对,从而构建潜在的稳健信号。
    交易中的混沌理论(第二部分):深入探索 交易中的混沌理论(第二部分):深入探索
    我们继续深入探讨金融市场的混沌理论,这一次我将考虑其对货币和其他资产分析的适用性。
    交易中的神经网络:时间序列的分段线性表示 交易中的神经网络:时间序列的分段线性表示
    这篇文章与我以前发表的有些不同。在本文中,我们将谈谈时间序列的另类表示。时间序列的分段线性表示是一种利用涵盖小间隔的线性函数逼近时间序列的方法。