Program Listing for File generate_offspring.hpp¶
↰ Return to documentation for file (fwdpp/ts/generate_offspring.hpp)
#ifndef FWDPP_TS_GENERATE_OFFSPRING_HPP
#define FWDPP_TS_GENERATE_OFFSPRING_HPP
#include <tuple>
#include <vector>
#include <utility>
#include <type_traits>
#include <gsl/gsl_rng.h>
#include <fwdpp/debug.hpp>
#include <fwdpp/util/wrapped_range.hpp>
#include <fwdpp/forward_types.hpp>
#include <fwdpp/mutate_recombine.hpp>
#include <fwdpp/internal/mutation_internal.hpp>
namespace fwdpp
{
namespace ts
{
struct mut_rec_intermediates
{
int swapped;
std::vector<double> breakpoints;
std::vector<uint_t> mutation_keys;
template <typename B, typename M>
mut_rec_intermediates(int s, B&& b, M&& m)
: swapped{s}, breakpoints{std::forward<B>(b)}, mutation_keys{
std::forward<M>(m)}
{
}
};
struct all_mutations
{
};
struct selected_variants_only
{
};
namespace detail
{
template <typename key_vector, typename MutationContainerType>
inline wrapped_range<typename key_vector::iterator>
process_new_mutations(key_vector& new_mutation_keys,
const MutationContainerType&, all_mutations)
{
return make_wrapped_range(begin(new_mutation_keys),
end(new_mutation_keys));
}
template <typename key_vector, typename MutationContainerType>
inline wrapped_range<typename key_vector::iterator>
process_new_mutations(key_vector& new_mutation_keys,
MutationContainerType& mutations,
selected_variants_only)
{
auto itr = std::stable_partition(
begin(new_mutation_keys), end(new_mutation_keys),
[&mutations](typename key_vector::value_type k) {
return mutations[k].neutral == false;
});
return make_wrapped_range(begin(new_mutation_keys), itr);
}
template <typename poptype, typename recmodel, typename mutmodel>
inline mut_rec_intermediates
generate_mutations_and_breakpoints(
std::size_t parent, std::size_t parental_haploid_genome, int swapped,
const recmodel& generate_breakpoints, const mutmodel& generate_mutations,
flagged_mutation_queue& mutation_recycling_bin, poptype& pop)
{
auto breakpoints = generate_breakpoints();
auto new_mutation_keys = fwdpp_internal::mmodel_dispatcher(
generate_mutations, pop.diploids[parent],
pop.haploid_genomes[parental_haploid_genome], pop.mutations,
mutation_recycling_bin);
return mut_rec_intermediates(swapped, std::move(breakpoints),
std::move(new_mutation_keys));
}
struct parental_data
{
std::size_t index, haploid_genome1, haploid_genome2;
int swapped;
};
template <typename poptype, typename recmodel, typename mutmodel,
typename mutation_key_container, typename mutation_handling_policy>
inline std::pair<std::size_t, mut_rec_intermediates>
generate_offspring_haploid_genome(
const parental_data parent, const recmodel& generate_breakpoints,
const mutmodel& generate_mutations,
const mutation_handling_policy& mutation_policy,
flagged_mutation_queue& mutation_recycling_bin,
flagged_haploid_genome_queue& haploid_genome_recycling_bin,
mutation_key_container& neutral, mutation_key_container& selected,
poptype& pop)
{
auto haploid_genome_data = generate_mutations_and_breakpoints(
parent.index, parent.haploid_genome1, parent.swapped,
generate_breakpoints, generate_mutations, mutation_recycling_bin,
pop);
auto range_ = process_new_mutations(haploid_genome_data.mutation_keys,
pop.mutations, mutation_policy);
std::size_t offspring_haploid_genome = mutate_recombine(
range_, haploid_genome_data.breakpoints, parent.haploid_genome1,
parent.haploid_genome2, pop.haploid_genomes, pop.mutations,
haploid_genome_recycling_bin, neutral, selected);
return std::make_pair(offspring_haploid_genome,
std::move(haploid_genome_data));
}
template <typename genetic_param_holder, typename mutation_handling_policy,
typename poptype>
inline std::pair<mut_rec_intermediates, mut_rec_intermediates>
generate_offspring_details(fwdpp::poptypes::DIPLOID_TAG, const gsl_rng* r,
const std::pair<std::size_t, std::size_t> parents,
const mutation_handling_policy& mutation_policy,
poptype& pop, genetic_param_holder& genetics,
typename poptype::diploid_type& offspring)
{
auto p1g1 = pop.diploids[parents.first].first;
auto p1g2 = pop.diploids[parents.first].second;
auto p2g1 = pop.diploids[parents.second].first;
auto p2g2 = pop.diploids[parents.second].second;
int swap1 = genetics.haploid_genome_swapper(r, p1g1, p1g2);
int swap2 = genetics.haploid_genome_swapper(r, p2g1, p2g2);
if (swap1)
{
std::swap(p1g1, p1g2);
}
if (swap2)
{
std::swap(p2g1, p2g2);
}
auto offspring_first_haploid_genome_data
= generate_offspring_haploid_genome(
parental_data{parents.first, p1g1, p1g2, swap1},
genetics.generate_breakpoints, genetics.generate_mutations,
mutation_policy, genetics.mutation_recycling_bin,
genetics.haploid_genome_recycling_bin, genetics.neutral,
genetics.selected, pop);
auto offspring_second_haploid_genome_data
= generate_offspring_haploid_genome(
parental_data{parents.second, p2g1, p2g2, swap2},
genetics.generate_breakpoints, genetics.generate_mutations,
mutation_policy, genetics.mutation_recycling_bin,
genetics.haploid_genome_recycling_bin, genetics.neutral,
genetics.selected, pop);
// Update the offspring's haploid_genomes.
offspring.first = offspring_first_haploid_genome_data.first;
offspring.second = offspring_second_haploid_genome_data.first;
pop.haploid_genomes[offspring.first].n++;
pop.haploid_genomes[offspring.second].n++;
return std::make_pair(
std::move(offspring_first_haploid_genome_data.second),
std::move(offspring_second_haploid_genome_data.second));
}
} // namespace detail
template <typename genetic_param_holder, typename mutation_handling_policy,
typename poptype>
std::pair<mut_rec_intermediates, mut_rec_intermediates>
generate_offspring(const gsl_rng* r,
const std::pair<std::size_t, std::size_t> parents,
const mutation_handling_policy& mutation_policy, poptype& pop,
genetic_param_holder& genetics,
typename poptype::diploid_type& offspring)
{
return detail::generate_offspring_details(typename poptype::popmodel_t(), r,
parents, mutation_policy, pop,
genetics, offspring);
}
} // namespace ts
} // namespace fwdpp
#endif