Русский Português
preview
Competitive Learning Algorithm (CLA)

Competitive Learning Algorithm (CLA)

MetaTrader 5Trading |
372 0
Andrey Dik
Andrey Dik

Contents

  1. Introduction
  2. Implementation of the algorithm
  3. Test results


Introduction

Over the past decades, many bioinspired algorithms have been proposed, from ant colonies and particle swarms to gray wolves and whales. However, human society, with its complex social interactions, can also serve as a rich source of ideas for effective optimization methods. This idea is the basis for the Competitive Learning Algorithm (CLA).

CLA uses a metaphor of the educational process, where the population of solutions is represented by students organized into classes. The algorithm elegantly models three types of learning: from the best in the class (teacher), from personal experience, and through cross-class interaction. This approach provides a balance between exploring the search space and exploiting the good solutions found, which is critical for effective optimization.

In this article, we will examine in detail the principles of CLA, its mathematical basis, implementation features, and compare its effectiveness with other popular metaheuristics on our standard test functions.


Implementation of the algorithm

The Competitive Learning Algorithm is based on a metaphor of the educational process in school. In this metaphor, students represent possible solutions to the optimization problem, classes are groups of students, teachers are the best students in each class, knowledge corresponds to coordinates in the search space, and the score is determined by the value of the fitness function.

The algorithm starts with an initialization, which can be compared to the beginning of the school year. A population of, for example, 198 students is created, which are divided into 9 classes of 22 students each. Each student is randomly assigned initial "knowledge" - coordinates in the search space.

The learning process is iterative, and at each iteration, students learn in three different ways. The first method is teacher-led learning, where each student learns from the best in their class, and the worse the class's performance, the more active the learning process, but over time the intensity of learning decreases for everyone. The second method is personal training, which begins only after the fourth iteration. In this mode, the student recalls his best results over the last four "lessons" and tries to return to his personal best. The third method is learning from other classes, which also begins after the fourth iteration. With a 50% probability, a student learns from the average teacher computed across all classes, which helps avoid getting stuck in local optima.

After each training cycle, progress is assessed. The best student in each class is identified and becomes the teacher, the overall class rating is calculated taking into account the performance of all students, and the globally best solution found is updated.

The algorithm uses five key parameters:

  • popSize - total number of students,
  • numClasses — number of classes,
  • beta - influence of all students in a class on its overall rating,
  • gamma — probability of learning from other classes,
  • deltaIter — after which iteration extended learning begins using personal experience and inter-class interactions.

The algorithm implements several smart mechanisms. Adaptive learning factors provide more intensive learning for weaker classes and a gradual slowdown of learning over time, as happens in the real educational process. The balance between exploration and exploitation is achieved through active exploration in the early stages, followed by a focus on the best solutions found. The memory mechanism allows the algorithm to remember the history of each student and, if necessary, return to good decisions from the past.

Mathematically, a student’s knowledge update can be represented as the sum of the current knowledge and three components: instruction from the class teacher, personal historical experience, and knowledge obtained from the average teacher across all classes. This formula provides a balance between following the leader, using personal experience and exploring new areas.

Ultimately, the algorithm's effectiveness is determined by several factors. Diversity is achieved through multiple classes exploring different directions in the search space. Competition between students for a teaching position encourages better solutions. Cooperation through knowledge sharing between classes helps prevent premature convergence. Adaptivity provides additional help for weak classes, and the memory mechanism stores information about good solutions.

CLA_L

Figure 1. Algorithm operation

The illustration of the algorithm's operation describes three main steps: initialization, training phase, and evaluation with updating. Now let's start writing pseudocode for the CLA_L algorithm.

WHAT WE NEED IN ADVANCE:
- 198 students (our solutions)
- 9 classes (student groups)
- Parameter β = 0.9 (how important are all students in the class)
- Parameter γ = 0.5 (chance to learn from other classes)
- After the 4th iteration, include additional types of learning
- Function for evaluating the quality of the solution

LET'S START:

1. CREATE A SCHOOL:
   - Distribute 198 students into 9 classes (22 in each)
   - Give each student a random initial position in the search space
   - In each class, choose the best student - they become a teacher
- Create a journal to record each student's history

2. LEARNING PROCESS (iterative process):
   
   Step 1: Determine the learning intensity
- For each class we calculate how actively students need to study
- Weak classes (with a bad rank) study more intensively
- Over time, everyone studies less intensively (like in real life)
   
   Step 2: Find the "average teacher"
- Take the positions of all teachers
- Calculate their average value
   - This will be a school-wide standard of knowledge
   
   Step 3: Each student learns:
   
   For each student:
   
   a) ALWAYS learn from their own teacher:
      - Look where the class teacher is
      - Move in their direction
      - The speed of movement depends on the class learning factor
   
   b) After the 4th iteration, we recall our experience:
      - Look at the journal: where was I best in the last 4 lessons?
      - With some random force, return to that position
      - This helps preserve good solutions
   
   c) After the 4th iteration, learn from other classes:
      - Toss a coin (with a 50% probability)
- If it lands on tails, we look at the "average teacher"
      - Move a little towards it
      - This helps to exchange experiences between classes
   
   Step 4: Evaluate all students
   - Each student receives a fitness value
   - The better the position, the higher the rating
   
   Step 5: Update the school hierarchy
   
   For each class:
   - Find a new best student - they become a teacher
   - Calculate the general level of the class:
     * Take the teacher's fitness value
     * Add the average score of all students (multiplied by β)
   - Determine the class rank:
     * The best classes get a low rank (1, 2, 3...)
     * Worst classes get a high rank
   
   Step 6: Remember the best solution
   - If some teacher is better than our record value
   - Save it as a new record
   
   Step 7: Saving history
   - Save the current positions of all student
   - This will be needed for personal training

3. FINISHING:
   - Return the best solution found
   - And its fitness value

Now let's start writing the algorithm code. The C_AO_CLA_l class inherits from the parent class C_AO and implements an algorithm based on the concept of competitive learning. The class contains a number of user-configurable parameters:

  • popSize — population size (number of "agents" or "students");
  • numClasses — number of classes agents are divided into;
  • beta — parameter that likely influences the speed of learning or adaptation;
  • gamma — another parameter related to the learning process;
  • deltaIter — the iteration number after which certain stages of the algorithm are activated.

The constructor initializes the main parameters, sets the name and description of the algorithm, specifies default values for variables, and sizes the "params" array, which is used to store information about the algorithm parameters.

Methods:

  • SetParams ()  updates the values of the class's internal variables (algorithm parameters) using the values from the "params" array. This allows you to change externally set parameters.
  • Init () — initialize the algorithm. Accepts parameters to define the boundaries and step of changing the parameters.
  • Moving () — main method for "moving" agents (performing iterations and steps of the algorithm).
  • Revision () — method is associated with the correction or improvement of decisions.
  • Injection () — method for inserting new knowledge or data into an agent.
Class fields:
  • numClasses, beta, gamma, deltaIter — algorithm parameters.
  • currentIter, studentsPerClass, totalIters — internal variables for controlling the algorithm flow.
  • teachers [] — array of S_AO_Agent structures representing the "teachers" in each class (anchor points).
  • classRanks [] — class ranks reflecting their performance.
  • classTotalCosts [] — total costs or "cost" of each class.
  • CL [] — temporary array for calculating the average knowledge of teachers.
  • UpdateTeachersAndCosts () — internal method to update information about teachers and their costs.
  • UpdateClassRanks () — internal method for updating class ranks.
  • UpdateStudentsKnowledge () — internal method for updating knowledge or "students" parameters.
//————————————————————————————————————————————————————————————————————
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 ();
};
//————————————————————————————————————————————————————————————————————

The Init() method of the C_AO_CLA_l class initializes the algorithm before it starts working. The logic of the work is divided into several stages. Standard Initialization: the StandardInit () method is called and performs standard initialization for the optimization algorithm. It receives the rangeMinP, rangeMaxP and the rangeStepP step parameters. If standard initialization fails, the Init() method returns 'false'.

Initialization of Algorithm Parameters: resets the current iteration counter to "0", sets the total number of iterations the algorithm should perform using the value passed in the epochsP argument, calculates the number of "students" (agents) in each class by dividing the population size by the number of classes. Next, the method checks that there is at least one student in each class. Next, the "for" loop initializes each agent in the population. The 'a' array the Init() method is called for each agent to initialize its coordinate array.

The "for" loop initializes a "teacher" for each class, sets the rank of each class to 1.0, and sets the initial "cost" of each class to a negative maximum value to ensure that a better solution is found later. If all initialization steps are successful, the method returns '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;
}
//————————————————————————————————————————————————————————————————————

The Moving() method of the C_AO_CLA_l class implements one iteration of the main optimization algorithm, checks whether it is the first iteration, and if it is the first iteration (i.e., "revision" is 'false'), the method initializes the positions of all agents in the population to random values in the given range. It iterates over all agents in the population and for each agent iterates over all its coordinates.

For each coordinate, the method generates a random value "val" in the range from rangeMin[c] to rangeMax[c] using the u.RNDfromCI() method, which provides a function for generating random numbers. It assigns "val" to the a[i].c[c] coordinate of 'i' agent, having previously "trimmed" it so that it is within the acceptable range and corresponds to the given rangeStep[c] step. The u.SeInDiSp() method is used, which performs value checking and adjustment.

After initializing the population, a flag is set to indicate that initialization has been performed. If this is not the first iteration, the current iteration counter is incremented. The UpdateStudentsKnowledge() method is called to implement the main mechanism for training or adapting agents in accordance with the principles of competitive learning used in the CLA_L algorithm. The logic of this method determines how agents interact, exchange information, and improve their positions in the solution search space.

//————————————————————————————————————————————————————————————————————
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 ();
}
//————————————————————————————————————————————————————————————————————

The UpdateStudentsKnowledge() method is responsible for updating the position of each student (agent) during the optimization. The current optimization progress is calculated. Two key learning factors are calculated:

  • TF (Teaching Factor) - shows how much a student learns from a teacher.
  • CF (Confirmatory Factor) - shows the extent to which a student takes into account the average knowledge of teachers. These factors depend on the student's progress and class rank.

Next, the average value of the coordinates of all "active" teachers (teachers whose results are valid) is calculated. This average knowledge is stored in a temporary array. For each student (agent), the class to which the student belongs is determined, and for each student's coordinate, a new student position is calculated by summing the current coordinate with the "knowledge sources". The student learns from his teacher by adjusting his position by an amount proportional to the difference between the teacher's coordinate and his own, multiplied by TF. If enough iterations have passed (currentIter > deltaIter) and the student has a "best solution", then the student learns from its previous successful experience by adjusting its position towards the best coordinate, multiplied by a random factor.

If enough iterations have passed and the number of teachers is valid, the student learns from the average knowledge of all teachers, adjusting its position in the direction of the average coordinate multiplied by CF with a certain probability (1-gamma). Boundaries (constraints) are applied to each student coordinate to ensure that the value is within the acceptable range. The value is adjusted to match the acceptable values given the search sampling step.

//————————————————————————————————————————————————————————————————————
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]);
    }
  }
}
//————————————————————————————————————————————————————————————————————

The Revision() method in the C_AO_CLA_l class is used to update information about the best solutions of each agent, as well as to update the global best solution and the corresponding parameters.

For each agent, it is checked whether its current objective function (a[i].f) has improved compared to its remembered best value (a[i].fB). If so, the best value is saved and the corresponding coordinates are copied. After checking all agents, if any of them got a better function value than the current global maximum (fB), the global parameters are updated: fB is the global best function value and cB are the coordinates of this best solution.

Next, the UpdateTeachersAndCosts() method is called, which updates information about the best teachers. At the end, UpdateClassRanks() is called to recalculate the class ranks, which affects the priority of choosing certain solutions in subsequent iterations.

//————————————————————————————————————————————————————————————————————
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 ();
}
//————————————————————————————————————————————————————————————————————

The UpdateTeachersAndCosts() method is used to update information about teachers in each class and calculate the total "cost" of the class. The method loops through all classes defined in the system. For each class, the initial and final indices of students (agents) included in this class are determined.

To find the best student in the class, variables are initialized to store the best function value, the index of the best student, the sum of the function values of all students in the class, and the number of valid students. The cycle goes through all students in the current class. For each student, it is checked whether their solution is valid, and if the solution is valid, then: the student's fitness value is added to sumFitness, the counter of valid students is incremented, and if the current student's feature value is better than the current best value bestFitness, then it is updated and bestIdx is updated.

After finding the best student in the class, it is checked that there was at least one valid student in the class (validStudents > 0). If the condition is met, then the coordinates of the best student are copied to the coordinates of the teacher of the corresponding class, and the value of the best student's function is assigned to the value of the teacher's function.

The average value of the function of all students in the avgFitness class is calculated. The total "cost" of the class is calculated as the sum of the value of the best student's function and the product of the "beta" coefficient by the average value of the function of all students. It is a combination of teacher effectiveness and average class wealth.

//————————————————————————————————————————————————————————————————————
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;
    }
  }
}
//————————————————————————————————————————————————————————————————————

The UpdateClassRanks() method is used to determine the ranks of classes based on their overall "cost", which characterizes how effective the class is. The process starts by finding the minimum and maximum cost among all valid classes. If all classes have the same value, or there are no valid classes, then the same rank of 1 is set for all.

If there are differences in cost, then these values are normalized - each cost is brought to a range from 0 to 1. After this, an inversion is performed: classes with a higher cost receive a lower rank, close to 1, and those with a lower cost receive a maximum rank equal to the number of classes.

Each rank value is then constrained to a minimum and maximum value to avoid out-of-bounds values. Ultimately, based on the results of this method, classes are given ranks based on their performance.

//————————————————————————————————————————————————————————————————————
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
      }
    }
  }
}
//————————————————————————————————————————————————————————————————————


Test results

According to the test, the CLA_L algorithm delivers fairly good results.

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%)

The visualization shows that the algorithm initially has good search capabilities, which deteriorate due to local traps, leading to stagnation in the second half of the algorithm's operation.

Hilly

CLA_L on the Hilly test function

Forest

CLA_L on the Forest test function

Megacity

CLA_L on the Megacity test function

Based on the results of the algorithm's work, the CLA_L ranking table is presented for informational purposes.

# AO Description Hilly Hilly
Final
Forest Forest
Final
Megacity (discrete) Megacity
Final
Final
Result
% of
MAX
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)
1ANSacross neighbourhood search0.949480.847760.438572.235811.000000.923340.399882.323230.709230.634770.230911.574916.13468.15
2CLAcode lock algorithm (joo)0.953450.871070.375902.200420.989420.917090.316422.222940.796920.693850.193031.683806.10767.86
3AMOmanimal migration ptimization M0.903580.843170.462842.209590.990010.924360.465982.380340.567690.591320.237731.396755.98766.52
4(P+O)ES(P+O) evolution strategies0.922560.881010.400212.203790.977500.874900.319452.171850.673850.629850.186341.490035.86665.17
5CTAcomet tail algorithm (joo)0.953460.863190.277702.094350.997940.857400.339492.194840.887690.564310.105121.557125.84664.96
6TETAtime evolution travel algorithm (joo)0.913620.823490.319902.057010.970960.895320.293242.159520.734620.685690.160211.580525.79764.41
7SDSmstochastic diffusion search M0.930660.854450.394762.179880.999830.892440.196192.088460.723330.611000.106701.441035.70963.44
8BOAmbilliards optimization algorithm M0.957570.825990.252352.035901.000000.900360.305022.205380.735380.525230.095631.356255.59862.19
9AAmarchery algorithm M0.917440.708760.421602.047800.925270.758020.353282.036570.673850.552000.237381.463235.54861.64
10ESGevolution of social groups (joo)0.999060.796540.350562.146161.000000.828630.131021.959650.823330.553000.047251.423585.52961.44
11SIAsimulated isotropic annealing (joo)0.957840.842640.414652.215130.982390.795860.205071.983320.686670.493000.090531.270205.46960.76
12EOmextremal_optimization_M0.761660.772420.317471.851550.999990.767510.235272.002770.747690.539690.142491.429875.28458.71
13BBObiogeography based optimization0.949120.694560.350311.993990.938200.673650.256821.868670.746150.482770.173691.402615.26558.50
14ACSartificial cooperative search0.755470.747440.304071.806981.000000.888610.224132.112740.690770.481850.133221.305835.22658.06
15DAdialectical algorithm0.861830.700330.337241.899400.981630.727720.287181.996530.703080.452920.163671.319675.21657.95
16BHAmblack hole algorithm M0.752360.766750.345831.864930.935930.801520.271772.009230.650770.516460.154721.321955.19657.73
17ASOanarchy society optimization0.848720.746460.314651.909830.961480.791500.238031.991010.570770.540620.166141.277525.17857.54
18RFOroyal flush optimization (joo)0.833610.737420.346291.917330.894240.738240.240981.873460.631540.502920.164211.298675.08956.55
19AOSmatomic orbital search M0.802320.704490.310211.817020.856600.694510.219961.771070.746150.528620.143581.418355.00655.63
20TSEAturtle shell evolution algorithm (joo)0.967980.644800.296721.909490.994490.619810.227081.841390.690770.426460.135981.253225.00455.60
21BSAbacktracking_search_algorithm0.973090.545340.290981.809410.999990.585430.217471.802890.847690.369530.129781.347004.95955.10
22DEdifferential evolution0.950440.616740.303081.870260.953170.788960.166521.908650.786670.360330.029531.176534.95555.06
23SRAsuccessful restaurateur algorithm (joo)0.968830.634550.292171.895550.946370.555060.191241.692670.749230.440310.125261.314804.90354.48
24CROchemical reaction optimization0.946290.661120.298531.905930.879060.584220.211461.674730.758460.426460.126861.311784.89254.36
25BIOblood inheritance optimization (joo)0.815680.653360.308771.777810.899370.653190.217601.770160.678460.476310.139021.293784.84253.80
26BSAbird swarm algorithm0.893060.649000.262501.804550.924200.711210.249391.884790.693850.326150.100121.120124.80953.44
27DEAdolphin_echolocation_algorithm0.759950.675720.341711.777380.895820.642230.239411.777460.615380.440310.151151.206844.76252.91
28HSharmony search0.865090.687820.325271.878180.999990.680020.095901.775920.620000.422670.054581.097254.75152.79
29SSGsaplings sowing and growing0.778390.649250.395431.823080.859730.624670.174291.658690.646670.441330.105981.193984.67651.95
30BCOmbacterial chemotaxis optimization M0.759530.622680.314831.697040.893780.613390.225421.732590.653850.420920.144351.219124.64951.65
31ABOafrican buffalo optimization0.833370.622470.299641.755480.921700.586180.197231.705110.610000.431540.132251.173784.63451.49
32(PO)ES(PO) evolution strategies0.790250.626470.429351.846060.876160.609430.195911.681510.590000.379330.113221.082554.61051.22
33FBAFractal-Based Algorithm0.790000.651340.289651.730990.871580.568230.188771.628580.610770.460620.123981.195374.55550.61
34TSmtabu search M0.877950.614310.291041.783300.928850.518440.190541.637830.610770.382150.121571.114494.53650.40
35BSObrain storm optimization0.937360.576160.296881.810410.931310.558660.235371.725340.552310.290770.119140.962224.49849.98
36WOAmwale optimization algorithm M0.845210.562980.262631.670810.931000.522780.163651.617430.663080.411380.113571.188034.47649.74
37AEFAartificial electric field algorithm0.877000.617530.252351.746880.927290.726980.180641.834900.666150.116310.095080.877544.45949.55
38AEOartificial ecosystem-based optimization algorithm0.913800.467130.264701.645630.902230.437050.214001.553270.661540.308000.285631.255174.45449.49
39CAmcamel algorithm M0.786840.560420.351331.698590.827720.560410.243361.631490.648460.330920.134181.113564.44449.37
40ACOmant colony optimization M0.881900.661270.303771.846930.858730.586800.150511.596040.596670.373330.024720.994724.43849.31
41CMAEScovariance_matrix_adaptation_evolution_strategy0.762580.720890.000001.483470.820560.796160.000001.616720.758460.490770.000001.249234.34948.33
42BFO-GAbacterial foraging optimization - ga0.891500.551110.315291.757900.969820.396120.063051.428990.726670.275000.035251.036924.22446.93
43SOAsimple optimization algorithm0.915200.469760.270891.655850.896750.374010.169841.440600.695380.280310.108521.084224.18146.45
44ABHAartificial bee hive algorithm0.841310.542270.263041.646630.878580.477790.171811.528180.509230.338770.103970.951974.12745.85
45ACMOatmospheric cloud model optimization0.903210.485460.304031.692700.802680.378570.191781.373030.623080.244000.107950.975034.04144.90
CLA_Lcompetitivelearningalgorithm0.648290.553520.258491.460300.802720.495400.200481.498600.635380.271690.100861.007933.96744.08
RWrandom walk0.487540.321590.257811.066940.375540.219440.158770.753750.279690.149170.098470.527342.34826.09


Summary

The competitive learning algorithm (CLA_L) demonstrates average performance in solving standard optimization problems. Analysis of the algorithm's operation revealed a characteristic two-phase dynamic: an active research phase in the initial iterations and a premature stagnation phase in the second half of the optimization process.

Dividing the population into classes ensures good coverage of the search space in the early stages. Each class explores its own area, which contributes to a global search. The educational model makes the algorithm clear and easy to interpret. The concepts of teachers, students and different types of learning are natural to understand. Learning factors that depend on class rank should theoretically provide a balance between exploration and exploitation. The combination of three types of learning (teacher learning, personal learning, and confirmatory learning) creates the potential to avoid local optima. Despite the diversification mechanisms, the algorithm is prone to getting stuck in local optima. 

The CLA algorithm presents an interesting concept of applying an educational metaphor to optimization problems. Despite the innovative approach and good initial performance, the algorithm requires significant modifications to be competitive with modern metaheuristics. The main challenge remains to ensure a balance between exploration and exploitation throughout the optimization process.

tab

Figure 2. Color coding of the algorithms by test

chart

Figure 3. Histogram of algorithm testing results (scale from 0 to 100, the higher the better, where 100 is the maximum possible theoretical result, in the archive there is a script for calculating the rating table)

CLA_L pros and cons:

Pros:

  1. Fast.

Cons:

  1. A large number of external parameters.
  2. Prone to getting stuck in local optima.

The article is accompanied by an archive with the current versions of the algorithm codes. The author of the article is not responsible for the absolute accuracy in the description of canonical algorithms. Changes have been made to many of them to improve search capabilities. The conclusions and judgments presented in the articles are based on the results of the experiments.


Programs used in the article

#NameTypeDescription
1#C_AO.mqh
Include
Parent class of population optimization algorithms
2#C_AO_enum.mqh
Include
Enumeration of population optimization algorithms
3TestFunctions.mqh
Include
Library of test functions
4
TestStandFunctions.mqh
Include
Test stand function library
5
Utilities.mqh
Include
Library of auxiliary functions
6
CalculationTestResults.mqh
Include
Script for calculating results in the comparison table
7
Testing AOs.mq5
ScriptThe unified test stand for all population optimization algorithms
8
Simple use of population optimization algorithms.mq5
Script
A simple example of using population optimization algorithms without visualization
9
Test_AO_CLA_L.mq5
ScriptCLA_L test stand

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/18857

Attached files |
CLA_I.zip (250.43 KB)
The Repository Pattern in MQL5: Abstracting Trade History Access for Testable EA Logic The Repository Pattern in MQL5: Abstracting Trade History Access for Testable EA Logic
Direct calls to the MQL5 History API inside analytics components create hidden terminal dependencies that make isolated testing structurally impossible. This article constructs an ITradeRepository abstraction layer with CLiveTradeRepository and CMockTradeRepository implementations, enabling the same analytics engine and equity curve panel to operate identically against live account data or a deterministic in-memory dataset. Repository injection eliminates direct API coupling, supports offline validation, and confines data source changes to a single implementation class.
Gaussian Processes in Machine Learning (Part 1): Classification Model in MQL5 Gaussian Processes in Machine Learning (Part 1): Classification Model in MQL5
The article considers the classification model of Gaussian processes. We will start by studying its theoretical principles moving on to the practical development of the GP library in MQL5.
MQL5 Wizard Techniques you should know (Part 96): Using Wavelet Thresholding and LSTM Network in a Custom Money Management Class MQL5 Wizard Techniques you should know (Part 96): Using Wavelet Thresholding and LSTM Network in a Custom Money Management Class
In this article we consider a custom MQL5 Wizard class that processes Money Management. Our custom class is labelled ‘CMoneyWaveletLSTM’, and is developed by combining the Wavelet Thresholding algorithm with an LSTM network. As has been the case throughout these series, the developed model is testable with MQL5 Wizard-Assembled Expert Advisors that can be tuned with different trailing stops and entry Signals classes. We maintain our entry Signal, as in past articles as the built-in 'Envelopes' class and the RSI class.
Neural Networks in Trading: Actor—Director—Critic (Final Part) Neural Networks in Trading: Actor—Director—Critic (Final Part)
The Actor–Director–Critic framework is an evolution of the classic agent learning architecture. The article presents practical experience of its implementation and adaptation to financial market conditions.