Skip to content

Commit

Permalink
doc: constructing graph from grid and local processes deterministic/s…
Browse files Browse the repository at this point in the history
…tochastic
  • Loading branch information
Becheler committed Jun 30, 2024
1 parent 261a3b3 commit 8fc57c6
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 62 deletions.
66 changes: 62 additions & 4 deletions docs/4-tutorials.md
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ This approach enables the creation of spatial graphs that not only capture the t
---

[//]: # (----------------------------------------------------------------------)
@page spatial_graph_local_parameters Local Parameters and Ecological Niche Modeling
@page spatial_graph_local_parameters Local Parameters
@tableofcontents

# Environmental Niche Models
Expand Down Expand Up @@ -971,13 +971,12 @@ The general idea is to define lambda expressions that embed stochastic aspects o
---
[//]: # (----------------------------------------------------------------------)
@page spatial_graph_local_process Local processes
@page spatial_graph_local_process Local autoregressive processes
@tableofcontents
## Background
Local processes on a spatial graph encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph.
These processes can entail interactions, transformations, and behaviors that unfold at a granular level, influencing the spatial dynamics and characteristics of the graph. Understanding local processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and trends.
While local parameters describe a static relationship to the environment, local processes on a spatial graph are dynamic in nature. They encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph, including interactions, transformations, and behaviors unfolding at a granular level. Understanding these processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and their temporal trends.
In the realm of ecology and evolution, these local processes encompass the intricate dynamics unfolding within specific ecological niches or habitats delineated by the vertices of the graph. These processes encapsulate ecological interactions, evolutionary adaptations, and population dynamics occurring at localized scales, shaping the distribution, abundance, and genetic diversity of species within the spatial landscape.
Expand All @@ -987,28 +986,87 @@ Local population growth models, integral to ecological and evolutionary studies,
This page provides examples of how to combine **Quetzal** components to construct the local simulation process corresponding to your hypotheses.
## Autoregressive Models
A process in which the value at time \f$ t \f$ depends on its value at time \f$ t−1 \f$ (like population growth over time)
is commonly referred to as an autoregressive process or a first-order autoregressive process (\f$AR(1)\f$).
These are widely used in time series analysis and modeling to capture temporal dependencies and patterns in data.
In mathematical terms, it can be represented as:
\f[
X_t =​ \phi X_{t-1} + \epsilon_t
\f]
where:
- \f$ X_t \f$ is the value of the process at time \f$ t \f$
- \f$ X_{t-1} \f$ is the value of the process at time \f$ t-1 \f$
- \f$ \phi \f$ is the autoregressive parameter,
- \f$ \epsilon_t \f$ is a random error term.
Users can represent first-order (or even p-order) autoregressive processes using **Quetzal** components. Although flexible, the general approach will be to represent time series as `std::vector` structures embedded in each vertex or edges they relate to, where a quantity \f$q\f$ a time \f$t\f$ at vertex \f$x\f$ is described by `graph[x][q][t]`.
---
## Deterministic Models
Deterministic models describe population growth based on precise mathematical equations that govern population dynamics. These models typically assume constant parameters and predictable relationships between population variables, such as birth rates, death rates, and carrying capacity. While deterministic models provide valuable insights into long-term population trends, they may oversimplify real-world complexities and fail to account for stochastic fluctuations or environmental variability.
In this example, we store a time-series vector at each vertex of the graph to monitor the population dynamics. After initializing one vertex with a non-zero value, we iterate through time to update the series. It's important to note that, since we defined no migration along the graph's edges, all time-series except one remain at zero.
**Input**
@include{lineno} geography_graph_local_process_1.cpp
**Output**
@include{lineno} geography_graph_local_process_1.txt
---
## Stochastic Models
Stochastic models introduce randomness and variability into population growth processes, acknowledging the inherent uncertainty in ecological systems. These models incorporate probabilistic elements, such as random fluctuations in birth and death rates, environmental variability, and demographic stochasticity. Stochastic models are particularly useful for capturing the effects of environmental variability and demographic stochasticity on population dynamics, allowing researchers to assess the likelihood of rare events and population extinctions.
We build up on the previous example by adding some stochasticity in the process. We store a time-series vector at each vertex of the graph to monitor the population dynamics. After initializing one vertex with a non-zero value, we iterate through time to update the series. It's important to note that, since we defined no migration along the graph's edges, some time-series remain at zero.
**Input**
@include{lineno} geography_graph_local_process_2.cpp
**Output**
@include{lineno} geography_graph_local_process_2.txt
---
## Environmental Niche Models
Environmental niche models focus on how environmental factors influence the distribution and abundance of species within specific habitats. These models integrate ecological niche theory and environmental data to predict species' occurrence probabilities and population densities across spatial gradients. By quantifying the relationships between environmental variables (e.g., temperature, precipitation, habitat quality) and species' ecological requirements, environmental niche models help elucidate how environmental factors shape local population growth and species distributions.
**Input**
@include{lineno} geography_graph_local_process_3.cpp
**Output**
@include{lineno} geography_graph_local_process_3.txt
---
## Species Competition Models
Species competition models explore how interspecific interactions, such as competition for resources or interactions with predators, influence population dynamics and species coexistence within local communities. These models typically incorporate competition coefficients, representing the strength of interspecific interactions, into population equations to simulate the effects of species interactions on population growth rates and carrying capacities. Species competition models provide insights into the mechanisms driving species coexistence, competitive exclusion, and community dynamics within ecological communities.
**Input**
@include{lineno} geography_graph_local_process_4.cpp
**Output**
@include{lineno} geography_graph_local_process_4.txt
---
[//]: # (----------------------------------------------------------------------)
Expand Down
2 changes: 1 addition & 1 deletion example/expressive_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ int main()

// We need to make choices here concerning how NA are handled
auto f1 = raster.to_view(); // lightweight functor returning empty optionals for NA
auto f2 = [f1](location_type x, time_type t) {
auto f2 = [&](location_type x, time_type t) {
return f1(x, t).value_or(0.0);
}; // remap empty optionals (NA) to 0.0 suitability value
auto f3 = expressive::use(f2); // f3 has now access to math operators
Expand Down
8 changes: 4 additions & 4 deletions example/expressive_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ int main()
auto e_view = landscape["DEM"].to_view();

// We need to make choices here concerning how NA are handled
auto suit = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
auto elev = expressive::use([e_view](location_type x, time_type t) { return e_view(x, t).value_or(0.0); });
auto suit = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
auto elev = expressive::use([&](location_type x, time_type t) { return e_view(x, t).value_or(0.0); });

std::random_device rd; // a seed source for the random number engine
std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()

// 1) hostile environment above an isoline: particularly useful if 123.0 is a randomly sampled parameter to be
// estimated
auto isoline_suitability = [suit, elev](location_type x, time_type t) {
auto isoline_suitability = [&](location_type x, time_type t) {
return (elev(x, t) >= 123.0) ? 0.0 : suit(x, t);
};

// 2) small-scale suitable ice-free shelters randomly popping above the snow cover at high-altitude
auto nunatak_suitability = [suit, elev, &gen](location_type x, time_type t) {
auto nunatak_suitability = [&](location_type x, time_type t) {
std::bernoulli_distribution d(0.1); // give "false" 9/10 of the time
bool is_nunatak = d(gen);
return (elev(x, t) >= 123.0) ? static_cast<double>(is_nunatak) * suit(x, t) : suit(x, t);
Expand Down
8 changes: 4 additions & 4 deletions example/expressive_4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ int main()
auto e_view = landscape["DEM"].to_view();

// We need to make choices here concerning how NA are handled
auto suit = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
auto elev = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
auto suit = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
auto elev = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });

std::random_device rd; // a seed source for the random number engine
std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()

auto rafting_capacity = [suit, elev, &gen](location_type x, time_type t) {
auto rafting_capacity = [&](location_type x, time_type t) {
std::bernoulli_distribution d(0.1); // give "false" 9/10 of the time
if (suit(x, t) == 0.0 and elev(x, t) == 0.0) // ocean cell case
return static_cast<double>(d(gen)) * 2; // will (rarely) allow 2 individuals to survive in the ocean cell
Expand All @@ -45,7 +45,7 @@ int main()
return 100. * suit(x, 0); // simple rescaling by the max number of individuals in a cell
};

auto rafting_friction = [suit, elev](location_type x, time_type t) {
auto rafting_friction = [&](location_type x, time_type t) {
if (suit(x, t) == 0.0 and elev(x, t) == 0.0) // ocean cell case
return 0.0; // the raft should move freely
else if (suit(x, 0) == 0.0 and elev(x, t) > 0.0) // hostile continental cell case
Expand Down
4 changes: 2 additions & 2 deletions example/geography_graph_4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace geo = quetzal::geography;
struct MySpatialGrid
{
// it is just required to define these two functions
constexpr int width() const { return 300; }
constexpr int height() const { return 100; }
constexpr int width() const { return 30; }
constexpr int height() const { return 10; }
};

int main()
Expand Down
44 changes: 0 additions & 44 deletions example/geography_graph_local_1.cpp

This file was deleted.

17 changes: 14 additions & 3 deletions src/include/quetzal/geography/graph/from_grid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace quetzal::geography
/// @param v An example of information to be stored on vertices
/// @param e An example of information to be stored on edges
/// @param vicinity A policy class giving the connectivity method to be applied
/// @param directionality A policy class giving the directionality (isotropy or anistropy)
/// @param directionality A policy class giving the directionality (isotropy or anisotropy)
/// @param bound A BoundPolicy
/// @return A graph with the desired level of connectivity
template <two_dimensional SpatialGrid, class VertexProperty, class EdgeProperty, class Vicinity,
Expand All @@ -31,10 +31,21 @@ auto from_grid(SpatialGrid const &grid, VertexProperty const &v, EdgeProperty co
Directionality dir, Policy const &bounding_policy)
{
using graph_type = quetzal::geography::graph<VertexProperty, EdgeProperty, typename Vicinity::connectedness, Directionality>;
// using graph_type = typename Vicinity::graph_type<Directionality, VertexProperty, EdgeProperty>;
// Graph size has to be static in dense graphs :/
graph_type graph( grid.width() * grid.height() + bounding_policy.num_extra_vertices() ) ;
vicinity.connect(graph, grid, bounding_policy);

if constexpr ( ! std::is_same_v<VertexProperty, no_property>) {
for( auto vertex : graph.vertices() ){
graph[vertex] = v;
}
}

if constexpr ( ! std::is_same_v<EdgeProperty, no_property>) {
for(auto edge : graph.edges()){
graph[edge] = e;
}
}

return graph;
}

Expand Down

0 comments on commit 8fc57c6

Please sign in to comment.