Mutations¶
Most types of simulations must have mutations in order to do anything “interesting”.
fwdpp
allows you to define your own mutation type.
A valid mutation type publicly inherits from fwdpp::mutation_base
.
This class defines a very minimal interface.
It has no concept of an “effect size” for a mutation, etc..
To add the relevant concepts for your model, create a derived class.
For example:
#pragma once
#include <tuple>
#include <fwdpp/type_traits.hpp>
#include <fwdpp/fundamental_types/mutation_base.hpp>
/*
* The simplest mutation type, adding just a selection coefficient
* and dominance to the interface.
*/
struct mutation : public fwdpp::mutation_base
{
// selection coefficient
double s;
// dominance coefficient
double h;
mutation(const double &position, const double &sel_coeff,
const double &dominance = 0.5) noexcept
: mutation_base(position, (sel_coeff == 0)), s(sel_coeff), h(dominance)
{
}
bool
operator==(const mutation &rhs) const
{
return std::tie(this->s, this->h) == std::tie(rhs.s, rhs.h) && is_equal(rhs);
}
};
static_assert(fwdpp::traits::is_mutation_v<mutation>,
"Mutation is not a valid mutation type!");
Containers of mutations¶
In a simulation, mutation objects must be stored in random-access containers of objects.
You must not use, for example, smart pointers to fwdpp::mutation_base
.
In other words, the value_type
of your container must equal a type derived from the mutation base class.
For example:
using mutation_container = std::vector<mutation>;
By using such a container, each mutation is represented only once in a simulation. To represent individual genotypes, we need a method of tracking which mutations are present in genomes. See here for details.