Agent based models
This page describes functions that can be used in conjunction with Agents.jl to animate and interact with agent based models.
The animation at the start of this page was done by running the examples/daisyworld.jl
file, and see also an example application in Agents.jl docs.
InteractiveDynamics.abm_plot
— Functionabm_plot(model::ABM; kwargs...) → fig, abmstepper
Plot an agent based model by plotting each individual agent as a marker and using the agent's position field as its location on the plot. Requires Agents
.
Return the overarching fig
object, as well as a struct abmstepper
that can be used to interactively animate the evolution of the ABM and combine it with other subplots. The figure is not displayed by default, you need to either return fig
as a last statement in your functions or simply call display(fig)
. Notice that models with DiscreteSpace
are plotted starting from 0 to n, with n the space size along each dimension.
To progress the ABM plot n
steps simply do:
Agents.step!(abmstepper, model, agent_step!, model_step!, n)
You can still call this function with n=0
to update the plot for a new model
, without doing any stepping. From fig
you can obtain the plotted axis (to e.g. turn off ticks, etc.) using ax = content(fig[1, 1])
. See Sugarscape for an example of using abmstepper
to make an animation of evolving the ABM and a heatmap in parallel with only a few lines of code.
Agent related keywords
ac, as, am
: These three keywords decided the color, size, and marker, that each agent will be plotted as. They can each be either a constant or a function, which takes as an input a single argument and ouputs the corresponding value. For example:
Notice that# ac = "#338c54" ac(a) = a.status == :S ? "#2b2b33" : a.status == :I ? "#bf2642" : "#338c54" # as = 10 as(a) = 10*randn() + 1 # am = :diamond am(a) = a.status == :S ? :circle : a.status == :I ? :diamond : :rect
am
can be/return aPolygon
instance, which plots each agent as an arbitrary polygon. It is assumed that the origin (0, 0) is the agent's position when creating the polygon. In this case, the keywordas
is meaningless, as each polygon has its own size. Use the functionsscale, rotate2D
to transform this polygon.scheduler = model.scheduler
: decides the plotting order of agents (which matters only if there is overlap).offset = nothing
: If notnothing
, it must be a function taking as an input an agent and outputting an offset position vector to be added to the agent's position (which matters only if there is overlap).scatterkwargs = ()
: Additional keyword arguments propagated to the scatter plot. Ifam
is/returns Polygons, then these arguments are propagated to apoly
plot.
Model and figure related keywords
heatarray = nothing
: A keyword that plots a heatmap over the space. Its values can be standard data accessors given to functions likerun!
, i.e. either a symbol (directly obtain model property) or a function of the model. The returned data must be a matrix of the same size as the underlying space. For exampleheatarray = :temperature
is used in the Daisyworld example. But you could also definef(model) = create_some_matrix_from_model...
and setheatarray = f
. The heatmap will be updated automatically during model evolution in videos and interactive applications.heatkwargs = (colormap=:tokyo,)
: Keyowrds given toMakie.heatmap
function ifheatarray
is not nothing.aspect = DataAspect()
: The aspect ratio behavior of the axis.resolution = (600, 600)
: Resolution of the figugre.static_preplot!
: A functionf(ax, model)
that plots something after the heatmap but before the agents. Notice that you can still make objects of this plot be visible above the agents using a translation in the third dimension like below:function static_preplot!(ax, model) obj = CairoMakie.scatter!([50 50]; color = :red) # Show position of teacher CairoMakie.hidedecorations!(ax) # hide tick labels etc. CairoMakie.translate!(obj, 0, 0, 5) # be sure that the teacher will be above students end
InteractiveDynamics.abm_play
— Functionabm_play(model, agent_step!, model_step!; kwargs...) → fig, abmstepper
Launch an interactive application that plots an agent based model and can animate its evolution in real time. Requires Agents
.
The agents are plotted exactly like in abm_plot
, while the two functions agent_step!, model_step!
decide how the model will evolve, as in the standard approach of Agents.jl and its step!
function.
The application has two buttons: "run" and "reset" which starts/stops the time evolution and resets the model to its original configuration. Two sliders control the animation speed: "spu" decides how many model steps should be done before the plot is updated, and "sleep" the sleep()
time between updates.
Keywords
ac, am, as, scheduler, offset, aspect, scatterkwargs
: propagated toabm_plot
.spu = 1:100
: The values of the "spu" slider.
InteractiveDynamics.abm_video
— Functionabm_video(file, model, agent_step! [, model_step!]; kwargs...)
This function exports the animated time evolution of an agent based model into a video saved at given path file
, by recording the behavior of abm_play
(without sliders). The plotting is identical as in abm_plot
.
Keywords
spf = 1
: Steps-per-frame, i.e. how many times to step the model before recording a new frame.framerate = 30
: The frame rate of the exported video.frames = 300
: How many frames to record in total, including the starting frame.resolution = (600, 600)
: Resolution of the fig.axiskwargs = NamedTuple()
: Keyword arguments given to the main axis creation for e.g. settingxticksvisible = false
.kwargs...
: All other keywords are propagated toabm_plot
.
InteractiveDynamics.abm_data_exploration
— Functionabm_data_exploration(model::ABM, agent_step!, model_step!, params=Dict(); kwargs...)
Open an interactive application for exploring an agent based model and the impact of changing parameters on the time evolution. Requires Agents
.
The application evolves an ABM interactively and plots its evolution, while allowing changing any of the model parameters interactively and also showing the evolution of collected data over time (if any are asked for, see below). The agent based model is plotted and animated exactly as in abm_play
, and the arguments model, agent_step!, model_step!
are propagated there as-is.
Calling abm_data_exploration
returns: figure, agent_df, model_df
. So you can save the figure, but you can also access the collected data (if any).
Interaction
Besides the basic time evolution interaction of abm_play
, additional functionality here allows changing model parameters in real time, based on the provided fourth argument params
. This is a dictionary which decides which parameters of the model will be configurable from the interactive application. Each entry of params
is a pair of Symbol
to an AbstractVector
, and provides a range of possible values for the parameter named after the given symbol (see example online). Changing a value in the parameter slides is only updated into the actual model when pressing the "update" button.
The "reset" button resets the model to its original agent and space state but it updates it to the currently selected parameter values. A red vertical line is displayed in the data plots when resetting, for visual guidance.
Keywords
ac, am, as, scheduler, offset, aspect, scatterkwargs
: propagated toabm_plot
.adata, mdata
: Same as the keyword arguments ofAgents.run!
, and decide which data of the model/agents will be collected and plotted below the interactive plot. Notice that data collection can only occur on plotted steps (and thus steps not plotted due to "spu" are also not data-collected).alabels, mlabels
: If data are collected from agents or the model withadata, mdata
, the corresponding plots have a y-label named after the collected data. Instead, you can givealabels, mlabels
(vectors of strings with exactly same length asadata, mdata
), and these labels will be used instead.when = true
: When to perform data collection, as inAgents.run!
.spu = 1:100
: Values that the "spu" slider will obtain.