panga
Chromosome.h
1 //-------------------------------------------------------------------------------------------------------
2 // Copyright (C) Taylor Woll and panga contributors. All rights reserved.
3 // Licensed under the MIT license. See LICENSE.txt file in the project root for
4 // full license information.
5 //-------------------------------------------------------------------------------------------------------
6 
7 #ifndef CHROMOSOME_H__
8 #define CHROMOSOME_H__
9 
10 #include <cassert>
11 #include <cstdint>
12 
13 #include "BitVector.h"
14 #include "Genome.h"
15 
16 namespace panga {
17 
18 class RandomWrapper;
19 
28 class Chromosome : public BitVector {
29  public:
30  explicit Chromosome(const Genome& genome);
31  Chromosome(const Chromosome& rhs) = delete;
32  Chromosome(Chromosome&& rhs) = default;
33  Chromosome& operator=(const Chromosome& rhs) = delete;
34  ~Chromosome() = default;
35 
39  const Genome& GetGenome() const;
40 
44  void Randomize(RandomWrapper* random);
45 
57  template <typename IntegerType = uint64_t, bool use_gray_encoding = true>
58  IntegerType DecodeIntegerGene(
59  size_t gene_index, IntegerType min = 0,
60  IntegerType max = std::numeric_limits<IntegerType>::max()) const {
61  if (min == max) {
62  return min;
63  }
64 
65  const size_t gene_bit_index = genome_.GetGeneStartBitIndex(gene_index);
66  const size_t gene_width = genome_.GetGeneBitWitdh(gene_index);
67  assert(sizeof(IntegerType) * CHAR_BIT >= gene_width);
68 
69  auto value = GetInt<IntegerType>(gene_bit_index, gene_width);
70  if (use_gray_encoding) {
71  value = DecodeGray<IntegerType>(value);
72  }
73 
74  // Clamp into range.
75  return (value % (max - min)) + min;
76  }
77 
86  template <typename IntegerType = uint64_t, bool use_gray_encoding = true>
87  void EncodeIntegerGene(size_t gene_index, IntegerType value) {
88  const size_t gene_bit_index = genome_.GetGeneStartBitIndex(gene_index);
89  const size_t gene_width = genome_.GetGeneBitWitdh(gene_index);
90  assert(sizeof(IntegerType) * CHAR_BIT >= gene_width);
91 
92  if (use_gray_encoding) {
93  value = EncodeGray<IntegerType>(value);
94  }
95  SetInt<IntegerType>(value, gene_bit_index, gene_width);
96  }
97 
109  template <typename FloatType = double, bool use_gray_encoding = true>
110  FloatType DecodeFloatGene(size_t gene_index, FloatType min,
111  FloatType max) const {
112  const uint64_t int_value =
113  DecodeIntegerGene<uint64_t, use_gray_encoding>(gene_index);
114  const size_t gene_width = genome_.GetGeneBitWitdh(gene_index);
115  return DecodeFloat<FloatType, uint64_t>(int_value, gene_width, min, max);
116  }
117 
127  template <typename FloatType = double, bool use_gray_encoding = true>
128  void EncodeFloatGene(size_t gene_index, FloatType value, FloatType min,
129  FloatType max) {
130  const size_t gene_width = genome_.GetGeneBitWitdh(gene_index);
131  const uint64_t int_value =
132  EncodeFloat<FloatType, uint64_t>(value, gene_width, min, max);
133  EncodeIntegerGene<uint64_t, use_gray_encoding>(gene_index, int_value);
134  }
135 
142  bool DecodeBooleanGene(size_t gene_index) const;
143 
151  void EncodeBooleanGene(size_t gene_index, bool value);
152 
159  std::byte* GetRawGene(size_t gene_index, size_t* gene_bit_width);
160 
166  template <typename IntegerType = uint64_t>
167  static IntegerType DecodeGray(IntegerType gray_value) {
168  IntegerType binary_value = gray_value;
169  while (gray_value >>= 1) {
170  binary_value ^= gray_value;
171  }
172  return binary_value;
173  }
174 
180  template <typename IntegerType = uint64_t>
181  static IntegerType EncodeGray(IntegerType binary_value) {
182  return binary_value ^ (binary_value >> 1);
183  }
184 
193  template <typename FloatType = double, typename IntegerType = uint64_t>
194  static FloatType DecodeFloat(IntegerType int_value, size_t bit_width,
195  FloatType min, FloatType max) {
196  constexpr size_t bits_per_byte = 8;
197  const IntegerType local_max =
198  std::numeric_limits<IntegerType>::max() >>
199  (sizeof(IntegerType) * bits_per_byte - bit_width);
200  const FloatType factor =
201  static_cast<FloatType>(int_value) / static_cast<FloatType>(local_max);
202  return factor * (max - min) + min;
203  }
204 
214  template <typename FloatType = double, typename IntegerType = uint64_t>
215  static IntegerType EncodeFloat(FloatType float_value, size_t bit_width,
216  FloatType min, FloatType max) {
217  constexpr size_t bits_per_byte = 8;
218  const IntegerType local_max =
219  std::numeric_limits<IntegerType>::max() >>
220  (sizeof(IntegerType) * bits_per_byte - bit_width);
221  const FloatType factor = (float_value - min) / (max - min);
222  return factor > 1.0 ? local_max
223  : static_cast<IntegerType>(factor * local_max);
224  }
225 
236  static void UniformCrossover(const Chromosome& parent1,
237  const Chromosome& parent2, Chromosome* offspring,
238  RandomWrapper* random,
239  bool ignore_gene_boundaries = true);
240 
252  static void KPointCrossover(size_t k, const Chromosome& parent1,
253  const Chromosome& parent2, Chromosome* offspring,
254  RandomWrapper* random,
255  bool ignore_gene_boundaries = true);
256 
262  static void FlipMutator(Chromosome* chromosome, double mutation_percentage,
263  RandomWrapper* random);
264 
265  private:
266  const Genome& genome_;
267 };
268 
269 } // namespace panga
270 
271 #endif // CHROMOSOME_H__
panga::Chromosome::DecodeGray
static IntegerType DecodeGray(IntegerType gray_value)
Definition: Chromosome.h:167
panga::Chromosome
Definition: Chromosome.h:28
panga::Chromosome::EncodeGray
static IntegerType EncodeGray(IntegerType binary_value)
Definition: Chromosome.h:181
panga::Chromosome::UniformCrossover
static void UniformCrossover(const Chromosome &parent1, const Chromosome &parent2, Chromosome *offspring, RandomWrapper *random, bool ignore_gene_boundaries=true)
Definition: Chromosome.cc:71
panga::Chromosome::GetRawGene
std::byte * GetRawGene(size_t gene_index, size_t *gene_bit_width)
Definition: Chromosome.cc:56
panga::Chromosome::GetGenome
const Genome & GetGenome() const
Definition: Chromosome.cc:26
panga::Chromosome::EncodeFloatGene
void EncodeFloatGene(size_t gene_index, FloatType value, FloatType min, FloatType max)
Definition: Chromosome.h:128
panga::Chromosome::Randomize
void Randomize(RandomWrapper *random)
Definition: Chromosome.cc:28
panga::Chromosome::EncodeFloat
static IntegerType EncodeFloat(FloatType float_value, size_t bit_width, FloatType min, FloatType max)
Definition: Chromosome.h:215
panga::Chromosome::KPointCrossover
static void KPointCrossover(size_t k, const Chromosome &parent1, const Chromosome &parent2, Chromosome *offspring, RandomWrapper *random, bool ignore_gene_boundaries=true)
Definition: Chromosome.cc:133
panga::Chromosome::DecodeFloatGene
FloatType DecodeFloatGene(size_t gene_index, FloatType min, FloatType max) const
Definition: Chromosome.h:110
panga::Genome
Definition: Genome.h:31
panga::Chromosome::DecodeFloat
static FloatType DecodeFloat(IntegerType int_value, size_t bit_width, FloatType min, FloatType max)
Definition: Chromosome.h:194
panga::Genome::GetGeneBitWitdh
size_t GetGeneBitWitdh(size_t gene_index) const
Definition: Genome.cc:44
panga::RandomWrapper
Definition: RandomWrapper.h:20
panga::Chromosome::DecodeBooleanGene
bool DecodeBooleanGene(size_t gene_index) const
Definition: Chromosome.cc:34
panga::Chromosome::EncodeIntegerGene
void EncodeIntegerGene(size_t gene_index, IntegerType value)
Definition: Chromosome.h:87
panga::BitVector
Definition: BitVector.h:19
panga::Genome::GetGeneStartBitIndex
size_t GetGeneStartBitIndex(size_t gene_index) const
Definition: Genome.cc:36
panga::Chromosome::EncodeBooleanGene
void EncodeBooleanGene(size_t gene_index, bool value)
Definition: Chromosome.cc:43
panga::Chromosome::DecodeIntegerGene
IntegerType DecodeIntegerGene(size_t gene_index, IntegerType min=0, IntegerType max=std::numeric_limits< IntegerType >::max()) const
Definition: Chromosome.h:58
panga::Chromosome::FlipMutator
static void FlipMutator(Chromosome *chromosome, double mutation_percentage, RandomWrapper *random)
Definition: Chromosome.cc:214