/* * 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 . */ #ifndef ANTKEEPER_CHROMOSOME_HPP #define ANTKEEPER_CHROMOSOME_HPP #include "bit-math.hpp" #include 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 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 T desegregate(T x) { return interleave(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 T replicate(T x) { x = bit_expand(x); return x | (x << 1); } /** * Performs */ template std::array 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 T reproduce(T a, T b, URBG&& g) { auto gametes_a = meiosis(a, static_cast(g())); auto gametes_b = meiosis(b, static_cast(g())); T i = static_cast(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 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 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 T mutate(T x, int i); template inline constexpr T crossover(T a, T b, int i) noexcept { T mask = (T(1) << i) - 1; return bit_merge(b, a, mask); } template 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 inline T mutate(T x, int i) { return x ^ (T(1) << i); } } // namespace dna #endif // ANTKEEPER_CHROMOSOME_HPP