Skip to content

Commit

Permalink
Refactor the class handling the state of a discrete demographic model.
Browse files Browse the repository at this point in the history
The new class is completely independent of DiscreteDemography.

Closes #782
Closes #783

This PR also affects the implementation of changes made in
PRs #773 and #774
  • Loading branch information
molpopgen committed Jul 19, 2021
1 parent 4ba08a7 commit 5b313b6
Show file tree
Hide file tree
Showing 25 changed files with 1,046 additions and 984 deletions.
26 changes: 11 additions & 15 deletions cpptests/discrete_demography_fixtures.hpp
Expand Up @@ -2,23 +2,19 @@

#include <memory>
#include <fwdpy11/rng.hpp>
#include "fwdpy11/discrete_demography/SetDemeSize.hpp"
#include "make_DiscreteDemography.hpp"
#include "discrete_demography_roundtrips.hpp"

struct mock_population_fixture
{
fwdpy11::GSLrng_t rng;
MockPopulation pop;
fwdpy11::discrete_demography::DiscreteDemography::mass_migration_vector
mass_migrations;
fwdpy11::discrete_demography::DiscreteDemography::set_growth_rates_vector
set_growth_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_deme_sizes_vector
set_deme_sizes;
fwdpy11::discrete_demography::DiscreteDemography::set_migration_rates_vector
set_migration_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_selfing_rates_vector
set_selfing_rates;
fwdpy11::DiploidPopulation pop;
std::vector<fwdpy11::discrete_demography::MassMigration> mass_migrations;
std::vector<fwdpy11::discrete_demography::SetExponentialGrowth> set_growth_rates;
std::vector<fwdpy11::discrete_demography::SetDemeSize> set_deme_sizes;
std::vector<fwdpy11::discrete_demography::SetMigrationRates> set_migration_rates;
std::vector<fwdpy11::discrete_demography::SetSelfingRate> set_selfing_rates;
fwdpy11::discrete_demography::MigrationMatrix migmatrix;

struct gsl_matrix_deleter
Expand All @@ -33,8 +29,8 @@ struct mock_population_fixture
using gsl_matrix_ptr = std::unique_ptr<gsl_matrix, gsl_matrix_deleter>;

mock_population_fixture()
: rng{416134}, pop(100), mass_migrations{}, set_growth_rates{}, set_deme_sizes{},
set_migration_rates{}, set_selfing_rates{}, migmatrix{}
: rng{416134}, pop(100, 1.0), mass_migrations{}, set_growth_rates{},
set_deme_sizes{}, set_migration_rates{}, set_selfing_rates{}, migmatrix{}
{
}

Expand All @@ -51,8 +47,8 @@ struct mock_population_fixture
inline void
set_migmatrix(Args &&...args)
{
migmatrix = fwdpy11::discrete_demography::MigrationMatrix(
std::forward<Args>(args)...);
migmatrix
= fwdpy11::discrete_demography::MigrationMatrix(std::forward<Args>(args)...);
}

auto
Expand Down
102 changes: 47 additions & 55 deletions cpptests/discrete_demography_roundtrips.cc
Expand Up @@ -10,33 +10,8 @@ MatingEventRecord::MatingEventRecord(std::uint32_t g, std::int32_t pd, std::int3
{
}

MockMetadata::MockMetadata(std::size_t parent1_, std::size_t parent2_,
std::size_t label_, std::int32_t deme_, double w_)
: parent1{parent1_}, parent2{parent2_}, label{label_}, deme{deme_}, w{w_}
{
}

MockPopulation::MockPopulation(std::uint32_t popsize)

: N{popsize}, generation{0}, diploid_metadata{init_metadata(popsize)}
{
}

std::vector<MockMetadata>
MockPopulation::init_metadata(std::uint32_t popsize)
{
std::vector<MockMetadata> rv;
for (decltype(popsize) i = 0; i < popsize; ++i)
{
rv.emplace_back(std::numeric_limits<std::size_t>::max(),
std::numeric_limits<std::size_t>::max(), static_cast<int>(i),
0, 1.0);
}
return rv;
}

std::unordered_map<int, int>
get_deme_sizes(const std::vector<MockMetadata>& metadata)
get_deme_sizes(const std::vector<fwdpy11::DiploidMetadata>& metadata)
{
std::unordered_map<int, int> rv;
for (auto&& md : metadata)
Expand All @@ -48,27 +23,29 @@ get_deme_sizes(const std::vector<MockMetadata>& metadata)

std::vector<MatingEventRecord>
DiscreteDemography_roundtrip(
const fwdpy11::GSLrng_t& rng, MockPopulation& pop,
const fwdpy11::GSLrng_t& rng, fwdpy11::DiploidPopulation& pop,
fwdpy11::discrete_demography::DiscreteDemography& demography, std::uint32_t ngens)
// Assumptions:
// 1. Initial deme labels are set by the user. NOTE: validated by manager object
//
{
bool demographic_model_needs_updating = true;
auto current_demographic_state
= fwdpy11::discrete_demography::initialize_model_state(
pop.generation, pop.diploid_metadata, demography,
&demographic_model_needs_updating);
auto current_demographic_state = demography.get_model_state();

decltype(pop.diploid_metadata) offspring_metadata;
offspring_metadata.reserve(pop.N);
std::vector<MatingEventRecord> rv;
if (demographic_model_needs_updating)
{
fwdpy11::discrete_demography::update_demography_manager(
rng, pop.generation, pop.diploid_metadata, demography,
*current_demographic_state);
}
if (current_demographic_state->will_go_globally_extinct() == true)
current_demographic_state.initialize(pop);
fwdpy11::discrete_demography::multideme_fitness_lookups<std::uint32_t>
fitness_lookup{current_demographic_state.maxdemes};
fwdpy11::discrete_demography::migration_lookup miglookup{
current_demographic_state.maxdemes, current_demographic_state.M.empty()};
current_demographic_state.early(rng, pop.generation, pop.diploid_metadata);
current_demographic_state.late(pop.generation, miglookup, pop.diploid_metadata);
fitness_lookup.update(current_demographic_state.fitness_bookmark);
fwdpy11::discrete_demography::validate_parental_state(
pop.generation, fitness_lookup,
current_demographic_state.current_deme_parameters, current_demographic_state.M);
if (current_demographic_state.will_go_globally_extinct() == true)
{
std::ostringstream o;
o << "extinction at time " << pop.generation;
Expand All @@ -78,19 +55,22 @@ DiscreteDemography_roundtrip(
{
++pop.generation;
// Generate the offspring
for (std::int32_t deme = 0; deme < current_demographic_state->maxdemes;
for (std::int32_t deme = 0; deme < current_demographic_state.maxdemes;
++deme)
{
for (unsigned ind = 0; ind < current_demographic_state->sizes_rates
.next_deme_sizes.get()[deme];
for (unsigned ind = 0;
ind < current_demographic_state.current_deme_parameters
.next_deme_sizes.get()[deme];
++ind)
{
auto pdata = fwdpy11::discrete_demography::pick_parents(
rng, deme, current_demographic_state->miglookup,
current_demographic_state->sizes_rates
rng, deme, miglookup,
current_demographic_state.current_deme_parameters
.current_deme_sizes,
current_demographic_state->sizes_rates.selfing_rates,
current_demographic_state->fitnesses);
current_demographic_state.current_deme_parameters
.selfing_rates,
current_demographic_state.fitness_bookmark,
fitness_lookup);
if (pdata.deme1 != deme)
{
rv.emplace_back(pop.generation + 1, pdata.deme1,
Expand All @@ -101,18 +81,31 @@ DiscreteDemography_roundtrip(
rv.emplace_back(pop.generation + 1, pdata.deme2,
deme, pdata.mating);
}
offspring_metadata.emplace_back(pdata.parent1, pdata.parent2,
offspring_metadata.size(),
deme, 1.);
offspring_metadata.emplace_back(
fwdpy11::DiploidMetadata{0.,
0.,
1.,
{0., 0., 0.},
offspring_metadata.size(),
{pdata.parent1, pdata.parent2},
deme,
0,
{-1, -1}});
}
}
pop.diploid_metadata.swap(offspring_metadata);
offspring_metadata.clear();

fwdpy11::discrete_demography::update_demography_manager(
rng, pop.generation, pop.diploid_metadata, demography,
*current_demographic_state);
if (current_demographic_state->will_go_globally_extinct() == true)
current_demographic_state.early(rng, pop.generation, pop.diploid_metadata);
current_demographic_state.late(pop.generation, miglookup,
pop.diploid_metadata);
fitness_lookup.update(current_demographic_state.fitness_bookmark);
fwdpy11::discrete_demography::validate_parental_state(
pop.generation, fitness_lookup,
current_demographic_state.current_deme_parameters,
current_demographic_state.M);

if (current_demographic_state.will_go_globally_extinct() == true)
{
std::ostringstream o;
o << "extinction at time " << pop.generation;
Expand All @@ -123,8 +116,7 @@ DiscreteDemography_roundtrip(
// from what we do in a "real" simulation.
pop.N = static_cast<std::uint32_t>(pop.diploid_metadata.size());
}
fwdpy11::discrete_demography::save_model_state(std::move(current_demographic_state),
demography);
demography.set_model_state(std::move(current_demographic_state));
return rv;
}

34 changes: 6 additions & 28 deletions cpptests/discrete_demography_roundtrips.hpp
Expand Up @@ -22,8 +22,8 @@
#include <unordered_map>
#include <vector>
#include <fwdpy11/rng.hpp>
#include <fwdpy11/types/DiploidPopulation.hpp>
#include <fwdpy11/discrete_demography/DiscreteDemography.hpp>
#include <fwdpy11/discrete_demography/simulation/demographic_model_state.hpp>
#include <fwdpy11/discrete_demography/simulation/mating_event_type.hpp>

struct MatingEventRecord
Expand All @@ -36,31 +36,9 @@ struct MatingEventRecord
fwdpy11::discrete_demography::mating_event_type mt);
};

struct MockMetadata
{
std::size_t parent1, parent2, label;
std::int32_t deme;
double w;

MockMetadata(std::size_t parent1_, std::size_t parent2_, std::size_t label_,
std::int32_t deme_, double w_);
};

class MockPopulation
{
private:
std::vector<MockMetadata> init_metadata(std::uint32_t popsize);

public:
std::uint32_t N, generation;
std::vector<MockMetadata> diploid_metadata;

MockPopulation(std::uint32_t popsize);
};

std::unordered_map<int, int> get_deme_sizes(const std::vector<MockMetadata>&);
std::unordered_map<int, int>
get_deme_sizes(const std::vector<fwdpy11::DiploidMetadata>&);

std::vector<MatingEventRecord>
DiscreteDemography_roundtrip(const fwdpy11::GSLrng_t& rng, MockPopulation& pop,
fwdpy11::discrete_demography::DiscreteDemography& demography,
std::uint32_t ngens);
std::vector<MatingEventRecord> DiscreteDemography_roundtrip(
const fwdpy11::GSLrng_t& rng, fwdpy11::DiploidPopulation& pop,
fwdpy11::discrete_demography::DiscreteDemography& demography, std::uint32_t ngens);
47 changes: 20 additions & 27 deletions cpptests/make_DiscreteDemography.hpp
@@ -1,20 +1,17 @@
#pragma once

#include "fwdpy11/discrete_demography/SetDemeSize.hpp"
#include "fwdpy11/discrete_demography/SetExponentialGrowth.hpp"
#include "fwdpy11/discrete_demography/SetSelfingRate.hpp"
#include <fwdpy11/discrete_demography/DiscreteDemography.hpp>
#include <fwdpy11/discrete_demography/simulation/demographic_model_state.hpp>

struct demographic_events
{
fwdpy11::discrete_demography::DiscreteDemography::mass_migration_vector
mass_migrations;
fwdpy11::discrete_demography::DiscreteDemography::set_growth_rates_vector
set_growth_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_deme_sizes_vector
set_deme_sizes;
fwdpy11::discrete_demography::DiscreteDemography::set_migration_rates_vector
set_migration_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_selfing_rates_vector
set_selfing_rates;
std::vector<fwdpy11::discrete_demography::MassMigration> mass_migrations;
std::vector<fwdpy11::discrete_demography::SetExponentialGrowth> set_growth_rates;
std::vector<fwdpy11::discrete_demography::SetDemeSize> set_deme_sizes;
std::vector<fwdpy11::discrete_demography::SetMigrationRates> set_migration_rates;
std::vector<fwdpy11::discrete_demography::SetSelfingRate> set_selfing_rates;
fwdpy11::discrete_demography::MigrationMatrix migmatrix;

demographic_events()
Expand All @@ -32,8 +29,7 @@ add_events(demographic_events&)
template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::DiscreteDemography::mass_migration_vector
mass_migrations,
std::vector<fwdpy11::discrete_demography::MassMigration> mass_migrations,
Args&&... args)
{
if (!events.mass_migrations.empty())
Expand All @@ -47,8 +43,7 @@ add_events(demographic_events& events,
template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::DiscreteDemography::set_deme_sizes_vector
set_deme_sizes,
std::vector<fwdpy11::discrete_demography::SetDemeSize> set_deme_sizes,
Args&&... args)
{
if (!events.set_deme_sizes.empty())
Expand All @@ -61,10 +56,10 @@ add_events(demographic_events& events,

template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::DiscreteDemography::set_growth_rates_vector
set_growth_rates,
Args&&... args)
add_events(
demographic_events& events,
std::vector<fwdpy11::discrete_demography::SetExponentialGrowth> set_growth_rates,
Args&&... args)
{
if (!events.set_growth_rates.empty())
{
Expand All @@ -76,10 +71,10 @@ add_events(demographic_events& events,

template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::DiscreteDemography::set_migration_rates_vector
set_migration_rates,
Args&&... args)
add_events(
demographic_events& events,
std::vector<fwdpy11::discrete_demography::SetMigrationRates> set_migration_rates,
Args&&... args)
{
if (!events.set_migration_rates.empty())
{
Expand All @@ -92,8 +87,7 @@ add_events(demographic_events& events,
template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::DiscreteDemography::set_selfing_rates_vector
set_selfing_rates,
std::vector<fwdpy11::discrete_demography::SetSelfingRate> set_selfing_rates,
Args&&... args)
{
if (!events.set_selfing_rates.empty())
Expand All @@ -107,8 +101,7 @@ add_events(demographic_events& events,
template <typename... Args>
inline void
add_events(demographic_events& events,
fwdpy11::discrete_demography::MigrationMatrix migmatrix,
Args&&... args)
fwdpy11::discrete_demography::MigrationMatrix migmatrix, Args&&... args)
{
if (!events.migmatrix.empty())
{
Expand Down

0 comments on commit 5b313b6

Please sign in to comment.