Diploids

This section builds on the information in Haploid genomes.

The simplest representation of a diploid is a pair of integers referring to the simulation’s genome container. fwdpp treats std::pair with integer types as the simplest form of diploid. At compile time, the library ensures that first_type and second_type are both integer types and that both are the same type.

For example:

#include <utility>
#include <cstdint>
#include <fwdpp/type_traits.hpp>

using diploid_size_t = std::pair<std::size_t, std::size_t>;
using diploid_int32 = std::pair<std::int32_t, std::int32_t>;

int
main(int, char **)
{
    static_assert(fwdpp::traits::is_diploid_v<diploid_size_t>,
                  "diploid_size_t is not a diploid!");
    static_assert(!fwdpp::traits::is_custom_diploid_v<diploid_size_t>,
                  "diploid_size_t is a custom diploid!");
    static_assert(fwdpp::traits::is_diploid_v<diploid_int32>,
                  "diploid_int32 is not a diploid!");
    static_assert(!fwdpp::traits::is_custom_diploid_v<diploid_int32>,
                  "diploid_size_t is a custom diploid!");
}

In the above example, the static assertions tell us that our std::pair are diploids. They also tell us that they are not custom diploids..

Diploids are more than just pairs of genomes. You may want to record other meta data along with the genome indexes. To do so, you may define your own types that duck-type the std::pair interface, adding whatever features you would like. We refer to such types as custom diploid types:

struct dip_with_fitness
{
    using first_type = std::size_t;
    using second_type = std::size_t;
    std::size_t first, second;
    double fitness;

    dip_with_fitness() : first{}, second{}, fitness{}
    {
    }
    dip_with_fitness(first_type f, second_type s) : first{f}, second{s}, fitness{0}
    {
    }
    dip_with_fitness(first_type f, second_type s, double w)
        : first{f}, second{s}, fitness{w}
    {
    }
};

static_assert(fwdpp::traits::is_diploid_v<dip_with_fitness>,
              "Error: dip with fitness is not a valid diploid type");
static_assert(fwdpp::traits::is_custom_diploid_v<dip_with_fitness>,
              "Error: dip with fitness is not a valid diploid type");

Internally, fwdpp doesn’t care much about custom diploids versus std::pair. The support for custom diploids exists to give modeling flexibility. However, the library is flexible enough to let you take other paths as well:

  • You could represent meta data as a separate array of structures.

  • You could represent the meta data as a separate structure of arrays.

Containers of diploids

In a simulation, diploid objects must be stored in random-access containers of objects.

In other words, the value_type of your container must equal a diploid type;

For example:

using diploid_container = std::vector<my_diploid_type>;