Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Binder

This case study develops a spatial predator–prey model on a two-dimensional lattice. The ecosystem contains two types of agents: Prey, which move and reproduce, and predators, which move, die, consume neighbouring prey and reproduce following successful predation.

Topics:

  • Agent-Based Modelling

Objectives:

  • Which difficulties are involved in agent-based models with spatial structure?

  • Why is it important to update agents simultaneously in models with discrete time steps?

  • Why is it tricky to remove agents from an agent-based model?

Modelling Purpose

In principle, the model in this case study could be motivated analogous to the model in Simulation Circle. I.e. we want to help a farmer decising for an intervention into an existing predator-prey system, however, this time we found that consideration of spatial effects is crucial for the model’s validity. Therefore a microscopic modelling strategy was chosen in favour of the macroscopic System Dynamics approach.

However, the agent-based model(s) derived/used in this case-study are primarily used to teach about features and problems of spatially-discrete agent-based models. Therefore the focus lies more on clarity and computational simplicity than on validity compared with the real system. We will discuss the biological implications of the model(s) in the final section of this notebook.

Conceptual Modelling

We define an agent-based model (ABM) on the following modelling assumptions:

  1. Each agent in the model represents either prey or a predator.

  2. All agents inhabit a commin environment in form of a finite rectangular lattice. Each cell can contain no more than one agent.

  3. Agents interact through a spatial neighborhood.

  4. The model is updated in discrete time steps and consists of agent movement, where agents update their positions, and population dynamics, where agents die, reproduce and interact with each other.

  5. Movement is random within the agent’s neighourhood and is not influenced by e.g. food availability, predator avoidance or habitat quality.

  6. Predator have a fixed probability of dying at the end of each timestep.

  7. A predator may consume up to one neighbouring prey agent each timestep with a fixed probability.

  8. Following successful predation, the prey is removed and a new predator is placed in its former location.

  9. Each prey agent may reproduce into an empty neighbouring cell with a fixed probability.

  10. All probabilities remain constant throughout a simulation.

We discuss conceptual details later on together with the implementation.

Model Parameters - Conceptual

The model has five parameters: the height m∈Nm\in \mathbb{N} and width n∈Nn\in \mathbb{N} of the grid, the initial numbers of prey Nprey∈NN_{prey}\in \mathbb{N} and predators Npred∈NN_{pred}\in \mathbb{N} with m⋅n<Nprey+Npredm\cdot n<N_{prey}+N_{pred}, and three probabilities for predator death pd∈[0,1]p_d\in [0,1], prey birth pb∈[0,1]p_b\in [0,1] and predation success ph∈[0,1]p_h\in [0,1].

Model Parameters - Implemented

For the implemented version, the actual conceptual model parameters often fall together with other experiment specific parameters. In this case, we must also define the seed for generation of the random numbers. Note that running the notebook with the same software environment and seed produces the same sequence of movement and interaction events. Changing the seed does not modify the model itself, but it generates a different realisation of the same stochastic process.

Agents - Conceptual

Each model agent represents either a prey or a predator animal. Since the model does not require any specific agent states apart from each position on the grid, this is, conceptually, its only state.

Agents - Implemented

In the implemented model, we would extend this by a second attribute for technical reasons:

  • agent_id: a unique identifier used to track removal, reproduction and conflict resolution.

  • position: a (row, column) tuple specifying the occupied lattice cell.

Adding a unique agent id helps to identify agents in the implemented model. However, in particular in population-dynamic agent-based models it is not always simple to assign such ids (see later). To differentiate optimally between predator and prey animals, we may use class ineritance to derive a Prey and a Predator class from the same Agent class. Addig a copy method is often a good strategy to help making things reproducible. Also some serialization method like the defined to_dict method is useful to create something object-independent to save.

Agent Initialisation - Conceptual

To initialise the agent population we need to create the defined number of prey and predator agents and assign random unique grid-points to them.

Agent Initialisation - Implemented

As seen above, the initial numbers of prey and predator agents are defined by N_PREY_INITIAL and N_PREDATORS_INITIAL and the size of the grid is defined by GRID_SIZE. Since positions must be unique, it is not possible to simply draw a random position for each agent, because this would not prevent different agents to get the same assigned gridpoint. In our implementation the task is solved by rng.choice without replacement together with the divmod function to map the unique 1D position onto a 2D grid. Using shuffling would be another viable strategy.

We furthermore write some utility functions to help with the analysis and visualisation of the agent-population and test our initialisation routine.

Update Rules - Conceptual

As mentioned, we update the model in discrete time-step, whereas each time-step should be divided into two sequential phases:

  1. Movement phase Agents (may) move to an empty neighbouring cell

  2. Population-dynamics phase Predators may die or consume neighbouring prey, while prey may reproduce into an empty neighbouring cell.

Hereby, phase 2 is started as soon as phase 1 is finished for all agents.

Neighbourhood - Conceptual

As seen, the term neighbourhood plays a central role for the model update. In out model we will use the so called Moore neighbourhood, defined by the eight cells that share either an edge or a corner with the focal cell Moore (1962). At the edge of the lattice, torodorial boundary conditions are applied in both spatial dimensions. That means, a position extending beyond one boundary re-enters through the opposite boundary. On a two-dimensional rectangular lattice, connecting the left and right boundaries and the upper and lower boundaries produces a toroidal topology (donut) which gives these boundary conditions their name Chopard & Droz (1998),Wilensky (1999). This choice ensures that boundary cells have the same number of potential neighbours as interior cells. It therefore avoids the systematic reduction in interaction opportunities that would occur at open edges, although the toroidal geometry remains a modelling simplification rather than a literal ecological representation.

Neighbourhood - Implemented

Typically, the Moore neighourhood is implemented using the eight relative offsets {(i,j):i∈{−1,0,1},j∈{−1,0,1},i≠0∨j≠0}\{(i,j):i\in \{-1,0,1\},j\in \{-1,0,1\},i\neq 0\vee j\neq 0\}. Note that the target cell itself is not counted to its own neighbourhood (therefore i≠0∨j≠0i\neq 0\vee j\neq 0). Implementation of torodorial neighbouhood is particularly easy, because indices can be wrapped using the remainder operator (%) with the number of rows and columns. Note that this computation is marginally more complicated in programming languages in which indexing starts with 1 and not with 0

Periodic boundary conditions are applied in both spatial dimensions. The row and column indices are wrapped using the remainder operator (%), so a position extending beyond one boundary re-enters through the opposite boundary. On a two-dimensional rectangular lattice, connecting the left and right boundaries and the upper and lower boundaries produces a toroidal topology Chopard & Droz (1998),Wilensky (1999). This choice ensures that boundary cells have the same number of potential neighbours as interior cells. It therefore avoids the systematic reduction in interaction opportunities that would occur at open edges, although the toroidal geometry remains a modelling simplification rather than a literal ecological representation.

Movement Phase - Conceptual

In the movement phase, every agent should randomly move to an empty neighbouring cell.

Movement Phase - Implementation

Although the concept sounds well defined, surprisingly, it is not unproblematic. To show this we create several versions of the implementation.

Movement Phase - Implementation Version 1

In this first version, we simply update each agent’s position by randomly selecting an empty place in its neighbourhood. Note that this requires us to search for an empty site. The naive implementation would be

for agent in agents:
  pos = agent.position
  neighbour_positions = get_neighbor_positions(pos)
  for agent2 in agents:
      if agent2.position in neighbour_positions:
          neighbour_positions.pop(agent2.position)

However, since this creates a O(N2)\mathcal{O}(N^2) computational effort, we first create a mapping between positions and agents.

Just by looking at the pictures, one discovers very obvious problems with the implementation: as all agents move independently of one another, it is possible that two or more of them may, by chance, head for the same location. This violates the idea that every site can only be occupied by a single agent.

Movement Phase - Implementation Version 2

We try to resolve this problem by updating the position_agent_mapping after every single agent movement.

This solution now ensures that the location assignment is unique, but it gives rise to two further problems:

  • First, the order in which the agents are called leads to a bias in the model. The agent with index 0 can always carry out its movement first, and the one with index N always last. Although this does not yet result in any obvious advantage or disadvantage for individual agents in the current model (which involves only movement and no further interaction), it can quickly lead to such a situation when combined with other rules.

  • The second problem is that the implementation violates a fundamental law of discrete-time agent-based modelling: simultaneous update. The update for agent 1 takes into account the already updated state of agent 0, but also the states of agents 2 to N, which have not yet been updated.

Movement Phase - Implementation Version 3

An obvious solution to the first problem is to iterate through the agents in a randomised order. In many cases this approach is often used in ABMs to rule out systematic bias. However, strictly speaking, this is not a formally correct time-discrete implementation, because the second problem remains.

A correct solution that resolves both problems is actually not that easy to implement. One approach involves a two-stage iteration: the first iteration is carried out analogous to Version 1, but the randomly determined new positions are not accepted immediately. Instead, they are collected as requests. In the second iteration, the requests are resolved by randomly selecting one agent from among those requesting the same field. This agent is allowed to move whereas the other ones must remain where they are.

This version finally preserves uniqueness, does not introduce bias and updated all states at the same time. Abviously, this strategy is more complicated, but quite usual in time and spatially discrete ABMs. One example is evacuation simulation Tanimoto et al. (2010). Here modellers even make a virtue of necessity and consider e.g. heterogeneity when it comes to add deliberate bias in selecting one of the multiple requesting agents.

In any case, it is clear that this implementation involves significantly more complex processes than those simply described as “random movement” in the conceptual model. In other words, the implementation cannot be deduced from the conceptualisation. The former must therefore be carried out with greater care.

Movement Phase - Conceptual (Revisited)

In the movement phase, every agent randomly moves to an empty site in its Moore neighbourhood. In case two or more agents aim to move to the same site, one of them is randomly chosen to move whereas the other ones must stay where they are.

Population Dynamics Phase - Conceptual

After movement, local interactions are applied according to agent type.

Predator agents:

  1. The agent dies with a probability pdp_d.

  2. If there is, at least, one prey-agent in any of the cells in the agent’s neighbourhood, one of them is randomly selected and consumed with probability php_h.

  3. In case 2. happens, a new predator agent is created and located on the former place of the consumed prey agent.

Prey agents:

  1. When at least one neighbouring cell is empty, one of them is selected at random. With probaility pbp_b a new prey agent is created an put at this place.

Population Dynamics Phase - Implementation

The defined rules open several places for interpretation, in particular referring to when agents are removed from the model and when new agents are added. For example, if a predator eats a certain prey animal that, in terms of update order, comes after the predator, it might already be removed before its update. If it was the other way round, the prey could potentially spawn offspring before it is eaten. However, if one adheres to the golden rule of simultaneous updates, many of these questions answer themselves: neither agents newly created nor agents removed during this time step may influence the update of agent states.

Furthermore, one encounters a common problem when implementing population-dynamic agent-based models: updating the agent list. In particular, removing agents from a list is a computationally expensive task. For each of these agents, (a) the list must be searched for the agent and (b) the list must be reconstructed without that agent - both O(N)\mathcal{O}(N) operations. There are at least three common ways to avoid this problems:

  • One idea is to use sets instead of lists, in which both finding and removing objects have a time complexity of O(1)\mathcal{O}(1). A drawback of this is that the iteration order is undefined, which might lead to problems with reproducibility when the iteration order is relevant.

  • Another idea is to simply rebuilding the agent list anew at each step. This is done, e.g. in Bicher et al. (2018).

  • Finally, it is also possible to simply leave all agents in the list, but only flag those who died. This is clearly problematic when memory is a problem, but is advantageous when it comes to unique ids: the index in the list can be used as agent-id.

It is not well visible in the plots, but the method has a rare but clear flaw in terms of uniqueness of positions. The problem lies in the creation of new prey agents. Currently, there is no guard which prevents two or more prey agents to create offsping into the same site. Note that we do not run into this problem for the creation of predator agents, because the site with the eaten prey is alway vacant.

Population Dynamics Phase - Implementation Version 2

From movement phase, version 3, we already know how to circumvent this problem, namely, by creating and resolving requests. In this case it is even easier to resolve, since it does not matter which prey agent eventually produced the offspring.

Full Model - Implementation

We can finally put all things together and create a full iterative model.

Model Analysis

The fully implemented model is now ready for deeper analysis. One way to look at the model is given by the aggregated curves of total predator and prey animals.

The model shows reasonable predator-prey behaviour, noticeable by the orange curves reacting upon the development of the blue curves. After an initial transient phase, both species reach a somewhat stable equilibrium. The lower plot shows the model without the movement phase. Here, the equilibrium state is much more sensitive to stochastic fluctuations due to the higher impact of locality.

Note that these values belong to this particular stochastic realisation and should not be interpreted as a (deterministic) forecast. A robust quantitative analysis would require repeated simulations across multiple random seeds and a summary of the resulting distributions, which is out of scope of this notebook.

The structural difference between the two versions (with and without movement) can also be seen on the visualisations of the final states of the simulation. Here the model without movement shows a much clearer clustering. However, the difference is even better visisble with an animated plot of the grid. Note that the corresponding visualisation routine was developed using Python’s Javascript bindings for plotting.

Vaidation?

The model demonstrates how population-level predator–prey dynamics can emerge from simple individual rules. No equation directly determines the number of prey or predators at the next time step. Instead, the aggregate trajectory is produced by repeated movement, mortality, predation and reproduction events.

Although the model is inspired by the predator-prey system, the modelling assumptions are very extreme and far from what can be observed in reality. For example, the assumption that a prey animal that has been eaten is instantly replaced by a new predator is a highly questionable compared to what happens in reality. Nevertheless, it is interesting to note that the results do indeed correspond with the observations from the macroscopic predator-prey model as, e.g. presented in Simulation Circle. This correlation is not by chance and can e.g. be explained using so-called mean-field analysis.

Anyhow, the model should be interpreted as a conceptual ABM rather than as a validated ecological prediction and this case-study should be interpreted in terms of methods for implementation and conceptualisation of ABMs in general.

References
  1. Moore, E. F. (1962). Machine Models of Self-Reproduction. In Mathematical Problems in the Biological Sciences (Vol. 14, pp. 17–34). American Mathematical Society.
  2. Chopard, B., & Droz, M. (1998). Cellular Automata Modeling of Physical Systems. Cambridge University Press. 10.1017/CBO9780511549755
  3. Tanimoto, J., Hagishima, A., & Tanaka, Y. (2010). Study of bottleneck effect at an emergency evacuation exit using cellular automata model, mean field approximation analysis, and game theory. Physica A: Statistical Mechanics and Its Applications, 389(24), 5611–5618. https://doi.org/10.1016/j.physa.2010.08.032
  4. Bicher, M., Urach, C., & Popper, N. (2018). Gepoc ABM: a generic agent-based population model for Austria. 2018 Winter Simulation Conference (WSC), 2656–2667. 10.1109/WSC.2018.8632170