<commit_before>#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/helper/random.hpp"
#include <cmath> // std::pow

pass::particle_swarm_optimisation::particle_swarm_optimisation() noexcept
    : optimiser(),
      swarm_size(40),
      inertia(1.0 / (2.0 * std::log(2.0))),
      cognitive_acceleration(0.5 + std::log(2.0)),
      social_acceleration(cognitive_acceleration),
      neighbourhood_probability(1.0 -
                                std::pow(1.0 - 1.0 / static_cast<double>(swarm_size), 3.0)) {}

pass::optimise_result pass::particle_swarm_optimisation::optimise(
    const pass::problem &problem)
{
  assert(inertia >= 0.0);
  assert(cognitive_acceleration >= 0.0);
  assert(social_acceleration >= 0.0);
  assert(neighbourhood_probability > 0.0 && neighbourhood_probability <= 1.0);

  pass::stopwatch stopwatch;
  stopwatch.start();

  // initialise the memory for the result
  pass::optimise_result result(problem.dimension(), acceptable_fitness_value);

  // Initialise the positions and the velocities
  // Particle data, stored column-wise.
  arma::mat positions = problem.random_agents(swarm_size);
  arma::mat velocities(problem.dimension(), swarm_size);

  for (arma::uword col = 0; col < swarm_size; ++col)
  {
    for (arma::uword row = 0; row < problem.dimension(); ++row)
    {
      velocities(row, col) = random_uniform_in_range(problem.lower_bounds.at(row) - positions(row, col), problem.upper_bounds.at(row) - positions(row, col));
    }
  }

  // Memory containing the previous/personal best and its fitness value
  arma::mat personal_best_positions = positions;
  arma::rowvec personal_best_fitness_values(swarm_size);

  // Evaluate the initial positions.
  // Compute the fitness.
  // Begin with the previous best set to this initial position
  for (arma::uword n = 0; n < swarm_size; ++n)
  {
    const double fitness_value = problem.evaluate(positions.col(n));
    personal_best_fitness_values(n) = fitness_value;

    if (fitness_value <= result.fitness_value)
    {
      result.agent = positions.col(n);
      result.fitness_value = fitness_value;
    }
  }
  ++result.iterations;
  result.duration = stopwatch.get_elapsed();

  // check termination criteria
  if (result.duration == maximal_duration ||
      result.iterations == maximal_iterations || result.solved())
  {
    return result;
  }
  //end initialisation

  arma::umat topology(swarm_size, swarm_size);
  bool randomize_topology = true;

  // termination criteria.
  while (result.duration < maximal_duration &&
         result.iterations < maximal_iterations && !result.solved())
  {
    if (randomize_topology)
    {
      topology = (arma::mat(swarm_size, swarm_size,
                            arma::fill::randu) < neighbourhood_probability);
      // When searching for the best neighbour, we begin with the particles
      // personal best value; We don't need to visit it twice.
      topology.diag().fill(0);
    }
    randomize_topology = true;

    // iterate over the particles
    for (arma::uword n = 0; n < swarm_size; ++n)
    {
      // l_i^t
      arma::vec local_best_position = personal_best_positions.col(n);
      double local_best_fitness_value = personal_best_fitness_values(n);

      // check the topology to identify with which particle you communicate
      for (arma::uword i = 0; i < swarm_size; i++)
      {
        if (topology(n, i) && personal_best_fitness_values(i) < local_best_fitness_value)
        {
          local_best_fitness_value = personal_best_fitness_values(i);
          local_best_position = personal_best_positions.col(i);
        }
      }

      /**
       * Compute the new velocity 
       */

      //p_i
      const arma::vec weighted_personal_attraction = positions.col(n) +
                                                     random_uniform_in_range(0.0, cognitive_acceleration) *
                                                         (personal_best_positions.col(n) - positions.col(n));

      // l_i
      const arma::vec weighted_local_attraction = positions.col(n) +
                                                  random_uniform_in_range(0.0, social_acceleration) *
                                                      (local_best_position - positions.col(n));

      // G
      arma::vec attraction_center;
<commit_msg>Remove unnecessary termination criteria check (it's redundant with the following loop condition)<commit_after>#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/helper/random.hpp"
#include <cmath> // std::pow

pass::particle_swarm_optimisation::particle_swarm_optimisation() noexcept
    : optimiser(),
      swarm_size(40),
      inertia(1.0 / (2.0 * std::log(2.0))),
      cognitive_acceleration(0.5 + std::log(2.0)),
      social_acceleration(cognitive_acceleration),
      neighbourhood_probability(1.0 -
                                std::pow(1.0 - 1.0 / static_cast<double>(swarm_size), 3.0)) {}

pass::optimise_result pass::particle_swarm_optimisation::optimise(
    const pass::problem &problem)
{
  assert(inertia >= 0.0);
  assert(cognitive_acceleration >= 0.0);
  assert(social_acceleration >= 0.0);
  assert(neighbourhood_probability > 0.0 && neighbourhood_probability <= 1.0);

  pass::stopwatch stopwatch;
  stopwatch.start();

  // initialise the memory for the result
  pass::optimise_result result(problem.dimension(), acceptable_fitness_value);

  // Initialise the positions and the velocities
  // Particle data, stored column-wise.
  arma::mat positions = problem.random_agents(swarm_size);
  arma::mat velocities(problem.dimension(), swarm_size);

  for (arma::uword col = 0; col < swarm_size; ++col)
  {
    for (arma::uword row = 0; row < problem.dimension(); ++row)
    {
      velocities(row, col) = random_uniform_in_range(problem.lower_bounds.at(row) - positions(row, col), problem.upper_bounds.at(row) - positions(row, col));
    }
  }

  // Memory containing the previous/personal best and its fitness value
  arma::mat personal_best_positions = positions;
  arma::rowvec personal_best_fitness_values(swarm_size);

  // Evaluate the initial positions.
  // Compute the fitness.
  // Begin with the previous best set to this initial position
  for (arma::uword n = 0; n < swarm_size; ++n)
  {
    const double fitness_value = problem.evaluate(positions.col(n));
    personal_best_fitness_values(n) = fitness_value;

    if (fitness_value <= result.fitness_value)
    {
      result.agent = positions.col(n);
      result.fitness_value = fitness_value;
    }
  }
  ++result.iterations;
  result.duration = stopwatch.get_elapsed();
  //end initialisation

  arma::umat topology(swarm_size, swarm_size);
  bool randomize_topology = true;

  // termination criteria.
  while (result.duration < maximal_duration &&
         result.iterations < maximal_iterations && !result.solved())
  {
    if (randomize_topology)
    {
      topology = (arma::mat(swarm_size, swarm_size,
                            arma::fill::randu) < neighbourhood_probability);
      // When searching for the best neighbour, we begin with the particles
      // personal best value; We don't need to visit it twice.
      topology.diag().fill(0);
    }
    randomize_topology = true;

    // iterate over the particles
    for (arma::uword n = 0; n < swarm_size; ++n)
    {
      // l_i^t
      arma::vec local_best_position = personal_best_positions.col(n);
      double local_best_fitness_value = personal_best_fitness_values(n);

      // check the topology to identify with which particle you communicate
      for (arma::uword i = 0; i < swarm_size; i++)
      {
        if (topology(n, i) && personal_best_fitness_values(i) < local_best_fitness_value)
        {
          local_best_fitness_value = personal_best_fitness_values(i);
          local_best_position = personal_best_positions.col(i);
        }
      }

      /**
       * Compute the new velocity
       */

      //p_i
      const arma::vec weighted_personal_attraction = positions.col(n) +
                                                     random_uniform_in_range(0.0, cognitive_acceleration) *
                                                         (personal_best_positions.col(n) - positions.col(n));

      // l_i
      const arma::vec weighted_local_attraction = positions.col(n) +
                                                  random_uniform_in_range(0.0, social_acceleration) *
                                                      (local_best_position - positions.col(n));

      // G
      arma::vec attraction_center;

{'fraction_non_alphanumeric': 0.11150029188558085, 'fraction_numerical': 0.009340338587273789, 'mean_word_length': 2.795303500221533, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3391860', 'n_tokens_mistral': 2724, 'n_tokens_neox': 2525, 'n_words': 536}