Skip to content

Commit

Permalink
Store MigrationMatrix as an object rather than unique_ptr (#785)
Browse files Browse the repository at this point in the history
Closes #781
  • Loading branch information
molpopgen committed Jul 5, 2021
1 parent 5029a84 commit 03933eb
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 69 deletions.
6 changes: 3 additions & 3 deletions cpptests/discrete_demography_fixtures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct mock_population_fixture
set_migration_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_selfing_rates_vector
set_selfing_rates;
std::unique_ptr<fwdpy11::discrete_demography::MigrationMatrix> migmatrix;
fwdpy11::discrete_demography::MigrationMatrix migmatrix;

struct gsl_matrix_deleter
{
Expand All @@ -34,7 +34,7 @@ struct mock_population_fixture

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

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

Expand Down
8 changes: 4 additions & 4 deletions cpptests/make_DiscreteDemography.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ struct demographic_events
set_migration_rates;
fwdpy11::discrete_demography::DiscreteDemography::set_selfing_rates_vector
set_selfing_rates;
std::unique_ptr<fwdpy11::discrete_demography::MigrationMatrix> migmatrix;
fwdpy11::discrete_demography::MigrationMatrix migmatrix;

demographic_events()
: mass_migrations{}, set_growth_rates{}, set_deme_sizes{}, set_migration_rates{},
set_selfing_rates{}, migmatrix{nullptr}
set_selfing_rates{}, migmatrix{}
{
}
};
Expand Down Expand Up @@ -107,10 +107,10 @@ add_events(demographic_events& events,
template <typename... Args>
inline void
add_events(demographic_events& events,
std::unique_ptr<fwdpy11::discrete_demography::MigrationMatrix> migmatrix,
fwdpy11::discrete_demography::MigrationMatrix migmatrix,
Args&&... args)
{
if (events.migmatrix != nullptr)
if (!events.migmatrix.empty())
{
throw std::invalid_argument("multiple migration matrices");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct demographic_event_stable_sorting_fixture
return fwdpy11::discrete_demography::DiscreteDemography(
std::move(massmigs), std::move(growth), std::move(sizechanges),
std::move(selfing),
std::make_unique<fwdpy11::discrete_demography::MigrationMatrix>(
fwdpy11::discrete_demography::MigrationMatrix(
std::move(migmatrix), 5, false),
std::move(migration));
}
Expand Down
3 changes: 3 additions & 0 deletions doc/misc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ C++ back-end

* A population can now be checked that it is- or is not- being simulated.
{pr}`762`
* {class}`fwdpy11.discrete_demography.DiscreteDemography` now stores the migration matrix as a stack-allocated object and not a `unique_ptr`.
{pr}`785`
{issue}`781`

Build system

Expand Down
24 changes: 12 additions & 12 deletions fwdpy11/headers/fwdpy11/discrete_demography/DiscreteDemography.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ namespace fwdpy11
// If there are no nonzero off-diagonal elements,
// and no migration rate changes during a sim,
// then there is no migration. Thus, reset
// migmatrix to nullptr.
// migmatrix to empty.
{
if (migmatrix == nullptr)
if (migmatrix.empty())
{
return;
}
Expand All @@ -218,14 +218,14 @@ namespace fwdpy11
return;
}
gsl_matrix_const_view v = gsl_matrix_const_view_array(
migmatrix->M.data(), migmatrix->npops, migmatrix->npops);
migmatrix.M.data(), migmatrix.npops, migmatrix.npops);
gsl_vector_const_view diag = gsl_matrix_const_diagonal(&v.matrix);
bool allequal = true;
for (std::size_t i = 0; allequal == true && i < migmatrix->npops; ++i)
for (std::size_t i = 0; allequal == true && i < migmatrix.npops; ++i)
{
gsl_vector_const_view rv = gsl_matrix_const_row(&v.matrix, i);
double rsum = 0.0;
for (std::size_t j = 0; j < migmatrix->npops; ++j)
for (std::size_t j = 0; j < migmatrix.npops; ++j)
{
rsum += gsl_vector_get(&rv.vector, j);
}
Expand All @@ -236,14 +236,14 @@ namespace fwdpy11
}
if (allequal)
{
migmatrix.reset(nullptr);
migmatrix.M.clear();
}
}

void
validate_change_migration_events()
{
if (migmatrix == nullptr)
if (migmatrix.empty())
{
if (!set_migration_rates.empty())
{
Expand All @@ -255,9 +255,9 @@ namespace fwdpy11
}
for (auto& event : set_migration_rates)
{
if (event.migrates.size() == migmatrix->npops)
if (event.migrates.size() == migmatrix.npops)
{
if (migmatrix->scaled == true)
if (migmatrix.scaled == true)
{
auto sum
= std::accumulate(begin(event.migrates),
Expand All @@ -272,7 +272,7 @@ namespace fwdpy11
}
}
else if (event.migrates.size()
!= migmatrix->npops * migmatrix->npops)
!= migmatrix.npops * migmatrix.npops)
{
throw std::invalid_argument("invalid matrix size");
}
Expand All @@ -292,7 +292,7 @@ namespace fwdpy11
set_growth_rates_vector set_growth_rates;
set_deme_sizes_vector set_deme_sizes;
set_selfing_rates_vector set_selfing_rates;
std::unique_ptr<const MigrationMatrix> migmatrix;
MigrationMatrix migmatrix;
set_migration_rates_vector set_migration_rates;

// pairs of iterators over the events
Expand All @@ -305,7 +305,7 @@ namespace fwdpy11
DiscreteDemography(mass_migration_vector mmig, set_growth_rates_vector sg,
set_deme_sizes_vector size_changes,
set_selfing_rates_vector ssr,
std::unique_ptr<MigrationMatrix> m,
MigrationMatrix m,
set_migration_rates_vector smr)
: model_state(nullptr),
mass_migrations(init_events_vector(std::move(mmig))),
Expand Down
13 changes: 11 additions & 2 deletions fwdpy11/headers/fwdpy11/discrete_demography/MigrationMatrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ namespace fwdpy11

public:
std::vector<double> M;
const std::size_t npops;
const bool scaled;
std::size_t npops;
bool scaled;

MigrationMatrix(): M{}, npops{0}, scaled{false} {}

template <typename T>
MigrationMatrix(T&& matrix, std::size_t nrows,
Expand Down Expand Up @@ -132,6 +134,13 @@ namespace fwdpy11
std::copy(begin(migrates), end(migrates), M.begin());
}
}

bool
empty() const
{
return M.empty();
}

};
} // namespace discrete_demography
} // namespace fwdpy11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ namespace fwdpy11
namespace discrete_demography
{
inline void
build_migration_lookup(const std::unique_ptr<MigrationMatrix>& M,
build_migration_lookup(const MigrationMatrix& M,
const current_deme_sizes_vector& current_deme_sizes,
migration_lookup& ml)
{
if (M != nullptr)
if (!M.empty())
{
std::vector<double> temp;
std::size_t npops = ml.lookups.size();
Expand All @@ -57,11 +57,11 @@ namespace fwdpy11
// But if the deme size is zero, we make
// sure it is removed as a possible source
// of a parent.
if (M->scaled == false && ref[source] != 0)
if (M.scaled == false && ref[source] != 0)
{
scaling_factor = 1.0;
}
double rate_in = M->M[dest * npops + source];
double rate_in = M.M[dest * npops + source];
if (rate_in > 0.
&& (ref[source] == 0 || ref[dest] == 0))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,13 @@ namespace fwdpy11
/// the relevant data structures.
{
private:
std::unique_ptr<MigrationMatrix>
init_migmatrix(const std::unique_ptr<const MigrationMatrix>& Minput)
{
if (Minput == nullptr)
{
return nullptr;
}
return std::unique_ptr<MigrationMatrix>(new MigrationMatrix(*Minput));
}

std::uint32_t next_global_N;

public:
const std::int32_t maxdemes;
multideme_fitness_lookups<std::uint32_t> fitnesses;
deme_properties sizes_rates;
std::unique_ptr<MigrationMatrix> M;
MigrationMatrix M;
migration_lookup miglookup;

// NOTE: demography.update_event_times() needs to have been
Expand All @@ -66,34 +56,33 @@ namespace fwdpy11
: next_global_N(0),
maxdemes(get_max_number_of_demes()(metadata, demography)),
fitnesses(maxdemes), sizes_rates(maxdemes, metadata),
M(init_migmatrix(demography.migmatrix)),
miglookup(maxdemes, M == nullptr)
M(demography.migmatrix), miglookup(maxdemes, M.empty())
{
}

demographic_model_state(const demographic_model_state& other)
: next_global_N{other.next_global_N}, maxdemes{other.maxdemes},
fitnesses{other.fitnesses}, sizes_rates{other.sizes_rates},
M{other.M},
miglookup{maxdemes, M.empty()}
{
build_migration_lookup(M, sizes_rates.current_deme_sizes, miglookup);
}

// This constructor is only used when resetting
// the state from an event like pickling a DiscreteDemography
// instance.
demographic_model_state(std::int32_t maxdemes_, deme_properties sizes_rates_,
std::unique_ptr<MigrationMatrix> M_)
MigrationMatrix M_)
: next_global_N(0), maxdemes(maxdemes_), fitnesses(maxdemes),
sizes_rates(std::move(sizes_rates_)), M(std::move(M_)),
miglookup(maxdemes, M == nullptr)
miglookup(maxdemes, M.empty())
{
next_global_N
= std::accumulate(begin(sizes_rates.next_deme_sizes.get()),
end(sizes_rates.next_deme_sizes.get()), 0u);
}

demographic_model_state(const demographic_model_state& other)
: next_global_N{other.next_global_N}, maxdemes{other.maxdemes},
fitnesses{other.fitnesses}, sizes_rates{other.sizes_rates},
M{other.M == nullptr ? nullptr : new MigrationMatrix(*other.M)},
miglookup{maxdemes, M == nullptr}
{
build_migration_lookup(M, sizes_rates.current_deme_sizes, miglookup);
}

void
set_next_global_N(std::uint32_t N)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ namespace fwdpy11
update_migration_matrix(
const std::uint32_t t,
migration_rate_change_range& migration_rate_change_tracker,
std::unique_ptr<MigrationMatrix>& M)
MigrationMatrix& M)

{
auto& range = migration_rate_change_tracker.get();
Expand All @@ -167,7 +167,7 @@ namespace fwdpy11
for (; range.first < range.second && range.first->when == t;
++range.first)
{
M->set_migration_rates(range.first->deme,
M.set_migration_rates(range.first->deme,
range.first->migrates);
}
}
Expand Down Expand Up @@ -217,7 +217,7 @@ namespace fwdpy11
inline std::uint32_t
apply_demographic_events(std::uint32_t t,
DiscreteDemography& demography,
std::unique_ptr<MigrationMatrix>& M,
MigrationMatrix& M,
deme_properties& sizes_rates)
{
std::copy(begin(sizes_rates.current_deme_sizes.get()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,25 @@ namespace fwdpy11
auto temp
= std::max(maxdeme_from_metadata, maxdeme_from_demography)
+ 1;
if (demography.migmatrix == nullptr)
if (demography.migmatrix.empty())
{
// There is no migration, so we are done
return temp;
}
if (static_cast<std::size_t>(temp)
> demography.migmatrix->npops)
> demography.migmatrix.npops)
{
throw std::invalid_argument(
"MigrationMatrix contains too few demes");
}
if (static_cast<std::size_t>(temp)
< demography.migmatrix->npops)
< demography.migmatrix.npops)
{
throw std::invalid_argument(
"MigrationMatrix contains too many demes");
}
return std::max(temp, static_cast<std::int32_t>(
demography.migmatrix->npops));
demography.migmatrix.npops));
}
};
} // namespace discrete_demography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ namespace fwdpy11

inline void
check_migration_in(std::size_t i, std::uint32_t generation,
const std::unique_ptr<MigrationMatrix> &M)
const MigrationMatrix &M)
{
if (M->M[i * M->npops + i] > 0)
if (M.M[i * M.npops + i] > 0)
{
std::ostringstream o;
o << "deme " << i << " at time " << generation
Expand All @@ -70,7 +70,7 @@ namespace fwdpy11
if (next_N_deme[i] > 0
&& current_demographic_state.fitnesses.lookups[i] == nullptr)
{
if (current_demographic_state.M == nullptr)
if (current_demographic_state.M.empty())
{
no_valid_parents(i, generation, next_N_deme[i]);
}
Expand Down

0 comments on commit 03933eb

Please sign in to comment.