@ -0,0 +1,169 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_CHROMOSOME_HPP | |||
#define ANTKEEPER_CHROMOSOME_HPP | |||
#include "bit-math.hpp" | |||
#include <array> | |||
namespace dna | |||
{ | |||
/** | |||
* Segregates the odd and even bits of a value. | |||
* | |||
* @param x Value to segregate. | |||
* @return Value with even bits of @p x in the lower half, and odd bits in the upper half. | |||
*/ | |||
template <class T> | |||
T segregate(T x) | |||
{ | |||
T odd = deinterleave(x); | |||
T even = deinterleave(x >> 1); | |||
return odd | (even << (sizeof(T) << 2)); | |||
} | |||
/** | |||
* Interleaves bits of the lower and upper halves of a value. | |||
* | |||
* @param x Value to desegregate. | |||
* @return Value with bits from the upper half of @p x interleaved with bits from the lower half. | |||
*/ | |||
template <class T> | |||
T desegregate(T x) | |||
{ | |||
return interleave<T>(x, x >> (sizeof(T) << 2)); | |||
} | |||
/** | |||
* Replicates each bit in the lower half of a value. | |||
* | |||
* @param x Value to replicate. | |||
* @return Value of @p x interleaved with itself. | |||
*/ | |||
template <class T> | |||
T replicate(T x) | |||
{ | |||
x = bit_expand(x); | |||
return x | (x << 1); | |||
} | |||
/** | |||
* Performs | |||
*/ | |||
template <class T> | |||
std::array<T, 4> meiosis(T x, T mask) | |||
{ | |||
x = segregate(x); | |||
T xl = x & (sizeof(T) << 2); | |||
T xh = x >> (sizeof(T) << 2); | |||
T a = xl; | |||
T b = crossover_n(xl, xh, mask); | |||
T c = crossover_n(xh, xl, mask); | |||
T d = xh; | |||
return {a, b, c, d}; | |||
} | |||
/** | |||
* | |||
* | |||
* @param a 2c chromosome of first parent. | |||
* @param b 2c chromosome of second parent. | |||
* @param g Uniform random bit generator. `g()` will be called three times. | |||
* @return 2c chromosome of child. | |||
*/ | |||
template <class T, class URBG> | |||
T reproduce(T a, T b, URBG&& g) | |||
{ | |||
auto gametes_a = meiosis(a, static_cast<T>(g())); | |||
auto gametes_b = meiosis(b, static_cast<T>(g())); | |||
T i = static_cast<T>(g()); | |||
T ca = gametes_a[i & 3]; | |||
T cb = gametes_b[(i >> 2) & 3]; | |||
return interleave(ca, cb); | |||
} | |||
/** | |||
* Performs a single-point crossover between two values. | |||
* | |||
* @param a First value. | |||
* @param b Second value. | |||
* @param i Index of the crossover point. | |||
* @return Crossed over value. | |||
*/ | |||
template <class T> | |||
constexpr T crossover(T a, T b, int i) noexcept; | |||
/** | |||
* Performs an n-point crossover between two values. | |||
* | |||
* @param a First value. | |||
* @param b Second value. | |||
* @param mask Bit mask with set bits marking crossover points. | |||
* @return Crossed over value. | |||
*/ | |||
template <class T> | |||
constexpr T crossover_n(T a, T b, T mask) noexcept; | |||
/** | |||
* Mutates a value by flipping a single bit. | |||
* | |||
* @param x Value to mutate. | |||
* @param i Index of the bit to flip. | |||
* @return Mutated copy of @p x. | |||
*/ | |||
template <class T> | |||
T mutate(T x, int i); | |||
template <class T> | |||
inline constexpr T crossover(T a, T b, int i) noexcept | |||
{ | |||
T mask = (T(1) << i) - 1; | |||
return bit_merge(b, a, mask); | |||
} | |||
template <class T> | |||
constexpr T crossover_n(T a, T b, T mask) noexcept | |||
{ | |||
T merge = ~T(0) * parity(mask); | |||
while (mask) | |||
{ | |||
merge ^= (mask ^ (mask - 1)) >> 1; | |||
mask &= mask - 1; | |||
} | |||
return bit_merge(a, b, merge); | |||
} | |||
template <class T> | |||
inline T mutate(T x, int i) | |||
{ | |||
return x ^ (T(1) << i); | |||
} | |||
} // namespace dna | |||
#endif // ANTKEEPER_CHROMOSOME_HPP |
@ -1,74 +0,0 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_CROSSOVER_HPP | |||
#define ANTKEEPER_CROSSOVER_HPP | |||
#include "bit-math.hpp" | |||
namespace dna | |||
{ | |||
/** | |||
* Performs a single-point crossover between two values. | |||
* | |||
* @param a First value. | |||
* @param b Second value. | |||
* @parma pos Position of the crossover point. | |||
*/ | |||
template <class T> | |||
constexpr T crossover(T a, T b, int pos) noexcept; | |||
/** | |||
* Performs an n-point crossover between two values. | |||
* | |||
* @param a First value. | |||
* @param b Second value. | |||
* @param mask Bit mask with set bits marking crossover points. | |||
*/ | |||
template <class T> | |||
constexpr T crossover_n(T a, T b, T mask) noexcept; | |||
template <class T> | |||
inline constexpr T crossover(T a, T b, int pos) noexcept | |||
{ | |||
T mask = (T(1) << pos) - 1; | |||
return bit_merge(b, a, mask); | |||
} | |||
template <class T> | |||
constexpr T crossover_n(T a, T b, T mask) noexcept | |||
{ | |||
T merge = 0, i = 0; | |||
while (mask) | |||
{ | |||
merge ^= (mask ^ (mask - 1)) >> 1; | |||
mask &= mask - 1; | |||
i = !i; | |||
} | |||
merge ^= ~T(0) * i; | |||
return bit_merge<T>(a, b, merge); | |||
} | |||
} // namespace dna | |||
#endif // ANTKEEPER_CROSSOVER_HPP |
@ -0,0 +1,56 @@ | |||
/* | |||
* Copyright (C) 2020 Christopher J. Howard | |||
* | |||
* This file is part of Antkeeper source code. | |||
* | |||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* Antkeeper source code is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef ANTKEEPER_GENE_HPP | |||
#define ANTKEEPER_GENE_HPP | |||
namespace dna | |||
{ | |||
/** | |||
* Isolates a pair of bits and returns them in the two least significant bits. | |||
* | |||
* @param x Diploid chromosome with interleaved alleles. | |||
* @param i Index of the pair to isolate. | |||
* @return Isolated pair of bits in the two least significant bits. | |||
*/ | |||
template <class T> | |||
T isolate(T x, int i) | |||
{ | |||
return (x >> (i << 1)) & 0b11; | |||
} | |||
/** | |||
* Isolates a sequence of genes and returns their alleles in the least significant bits. | |||
* | |||
* @param x Diploid chromosome with interleaed alleles. | |||
* @param i Index of the first gene in the sequence. | |||
* @param n Length of the sequence, in genes. | |||
* @return Alleles of the sequeuence in the least significant bits. | |||
*/ | |||
template <class T> | |||
T isolate_n(T x, int i, int n) | |||
{ | |||
T mask = (T(1) << (n << 1)) - 1; | |||
return (x >> (i << 1)) & mask; | |||
} | |||
} // namespace dna | |||
#endif // ANTKEEPER_GENE_HPP |