💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.9 KiB

  1. /*
  2. * Copyright (C) 2020 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_GENETIC_OPERATORS_HPP
  20. #define ANTKEEPER_GENETIC_OPERATORS_HPP
  21. #include <cstdlib>
  22. #include <iterator>
  23. namespace dna
  24. {
  25. /**
  26. * Performs a genetic crossover on a range of interleaved allele blocks defined by `[first1, last1)`.
  27. *
  28. * @param[in] first1,last1 First range of interleaved allele blocks to crossover.
  29. * @param[in] first2 Beginning of the the second range of interleaved allele blocks to crossover.
  30. * @param[out] d_first Beginning of the destination range.
  31. * @param[in,out] g A uniform random bit generator.
  32. * @return Output iterator to the block past the last block crossed over.
  33. */
  34. template <class InputIt1, class InputIt2, class OutputIt, class URBG>
  35. OutputIt crossover(InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, URBG&& g)
  36. {
  37. typedef typename std::iterator_traits<OutputIt>::value_type block_t;
  38. static constexpr std::size_t bits_per_block = sizeof(block_t) << 3;
  39. while (first1 != last1)
  40. {
  41. block_t block = 0;
  42. for (std::size_t i = 0; i < bits_per_block;)
  43. {
  44. block_t allele1 = ((*first1) >> (i + (g() % 2))) & 1;
  45. block_t allele2 = ((*first2) >> (i + (g() % 2))) & 1;
  46. block |= allele1 << i++;
  47. block |= allele2 << i++;
  48. }
  49. *d_first++ = block;
  50. ++first1;
  51. ++first2;
  52. }
  53. return d_first;
  54. }
  55. /**
  56. * Performs a genetic mutation by flipping the bit of a single allele in a range of interleaved allele blocks defined by `[first1, last1)`.
  57. *
  58. * @param[in,out] first,last Range of interleaved allele blocks to mutate.
  59. * @param[in,out] g A uniform random bit generator.
  60. * @return Locus of the mutated allele.
  61. */
  62. template <class RandomIt, class URBG>
  63. typename std::iterator_traits<RandomIt>::difference_type mutate(RandomIt first, RandomIt last, URBG&& g)
  64. {
  65. typedef typename std::iterator_traits<RandomIt>::value_type block_t;
  66. typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
  67. static constexpr diff_t bits_per_block = sizeof(block_t) << 3;
  68. diff_t i = g() % ((last - first) * bits_per_block);
  69. first[i / bits_per_block] ^= block_t(1) << (i % bits_per_block);
  70. return i;
  71. }
  72. } // namespace dna
  73. #endif // ANTKEEPER_GENETIC_OPERATORS_HPP