Program Listing for File transpose_invert_mutate.hpp

Return to documentation for file (include/sgpl/mutate/transpose_invert_mutate.hpp)

#pragma once
#ifndef SGPL_MUTATE_TRANSPOSE_INVERT_MUTATE_HPP_INCLUDE
#define SGPL_MUTATE_TRANSPOSE_INVERT_MUTATE_HPP_INCLUDE

#include <algorithm>
#include <iterator>

#include "../algorithm/transpose_window.hpp"
#include "../program/Program.hpp"
#include "../utility/MemoizeCtor.hpp"
#include "../utility/random_between.hpp"
#include "../utility/ThreadLocalRandom.hpp"

namespace sgpl {

template<typename Config, typename Spec>
size_t transpose_invert_mutate(
  sgpl::Program<Spec> & program,
  const Config& cfg
) {

  // ideally, we would draw from the binomial distn,
  // but that's expensive with varying n...
  // so approximate with the poisson distribution instead
  // they're similar-ish, e.g., https://www.researchgate.net/figure/Poisson-versus-binomial-distribution-from-number-of-heads-in-a-coin-toss-The-Poisson_fig3_255717571
  // (they become more similar for large n)
  const size_t num_transpositions = sgpl::tlrand.Get().GetRandPoisson(
    program.size(),
    cfg.SGPL_SEQMUTATE_INST_TRANSPOSE_RATE()
  );
  const sgpl::TransposeWindowDisplacementGenerator_Default disp_gen(cfg);
  const sgpl::TransposeWindowSizeGenerator_Default size_gen(cfg);

  size_t num_rearranged_sites{};
  for (size_t i{}; i < num_transpositions; ++i) {
    const auto [
      transposedfrom_window_first,
      transposedto_window_first,
      transposedto_window_last
    ] = sgpl::transpose_window(
      std::begin(program),
      std::end(program),
      disp_gen,
      size_gen
    );

    const auto displacement = std::abs(
      std::distance(transposedfrom_window_first, transposedto_window_first)
    );
    const auto window_size = std::distance(
      transposedto_window_first, transposedto_window_last
    );

    num_rearranged_sites += std::min(displacement, window_size);

    if (sgpl::tlrand.Get().P(
      cfg.SGPL_SEQMUTATE_INST_TRANSPOSE_INVERSION_RATE()
    )) {
      std::reverse(transposedto_window_first, transposedto_window_first);
      num_rearranged_sites += window_size;
    }
  }

  return num_rearranged_sites;
}

} // namespace sgpl

#endif // #ifndef SGPL_MUTATE_TRANSPOSE_INVERT_MUTATE_HPP_INCLUDE