diff --git a/Project.toml b/Project.toml index 7ac59798e0..5ad0223c67 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Agents" uuid = "46ada45e-f475-11e8-01d0-f70cc89e6671" authors = ["Tim DuBois", "George Datseris", "Ali Vahdati"] -version = "4.1.4" +version = "4.1.5" [deps] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" diff --git a/docs/src/tutorial.md b/docs/src/tutorial.md index 1fdade49e5..d9822e2da6 100644 --- a/docs/src/tutorial.md +++ b/docs/src/tutorial.md @@ -8,10 +8,9 @@ In the spirit of simple design, all of this is done by defining simple Julia dat To set up an ABM simulation in Agents.jl, a user only needs to follow these steps: 1. Choose in what kind of space the agents will live in, for example a graph, a grid, etc. Several spaces are provided by Agents.jl and can be initialized immediately. -1. Define the agent type (or types, for mixed models) that will populate the ABM. This is defined as a standard Julia Type and contains two mandatory fields `id, pos`, with the position field being appropriate for the chosen space. -3. The created agent type, the chosen space, and optional additional model level properties (typically in the form of a dictionary) are provided in our universal structure [`AgentBasedModel`](@ref). This instance defines the model within an Agents.jl simulation. -4. Provide functions that govern the time evolution of the ABM. -A user can provide an agent-stepping function, that acts on each agent one by one, and/or model-stepping function, that steps the entire model as a whole. These functions are standard Julia functions that take advantage of the Agents.jl [API](@ref). +1. Define the agent type (or types, for mixed models) that will populate the ABM. This is defined as a standard Julia `struct` and contains two mandatory fields `id, pos`, with the position field being appropriate for the chosen space. +3. The created agent type, the chosen space, and optional additional model level properties (typically in the form of a dictionary) are provided in our universal structure [`AgentBasedModel`](@ref). This instance defines the model within an Agents.jl simulation. Further options are also available, regarding schedulers and random number generation. +4. Provide functions that govern the time evolution of the ABM. A user can provide an agent-stepping function, that acts on each agent one by one, and/or model-stepping function, that steps the entire model as a whole. These functions are standard Julia functions that take advantage of the Agents.jl [API](@ref). 5. Collect data. To do this, specify which data should be collected, by providing one standard Julia `Vector` of data-to-collect for agents, and another one for the model, for example `[:mood, :wealth]`. The outputted data are in the form of a `DataFrame`. diff --git a/examples/schelling.jl b/examples/schelling.jl index eea34bbf73..cc45e73291 100644 --- a/examples/schelling.jl +++ b/examples/schelling.jl @@ -11,31 +11,38 @@ # the following definition of Schelling's segregation model: # * Agents belong to one of two groups (0 or 1). -# * The agents live in a two-dimensional Chebyshev grid (8 neighbors per position). -# * If an agent is in the same group with at least three neighbors, then it is happy. +# * The agents live in a two-dimensional grid with a Chebyshev metric. +# This leads to 8 neighboring positions per position (except at the edges of the grid). +# * Each position of the grid can be occupied by at most one agent. +# * If an agent has at least `3` neighbors belonging to the same group, then it is happy. # * If an agent is unhappy, it keeps moving to new locations until it is happy. # Schelling's model shows that even small preferences of agents to have neighbors -# belonging to the same group (e.g. preferring that at least 30% of neighbors to +# belonging to the same group (e.g. preferring that at least 3/8 of neighbors to # be in the same group) could lead to total segregation of neighborhoods. # This model is also available as [`Models.schelling`](@ref). +# ## Creating a space + +# For this example, we will be using a Chebyshev 2D grid, e.g. + +space = GridSpace((10, 10); periodic = false) + +# Agents belonging in this type of space must have a position field that is a +# `NTuple{2, Int}`. We ensure this below. + # ## Defining the agent type using Agents -using StatsBase: mean mutable struct SchellingAgent <: AbstractAgent - id::Int # The identifier number of the agent - pos::Dims{2} # The x, y location of the agent on a 2D grid - mood::Bool # whether the agent is happy in its position. (true = happy) - group::Int # The group of the agent, determines mood as it interacts with neighbors + id::Int # The identifier number of the agent + pos::NTuple{2, Int} # The x, y location of the agent on a 2D grid + mood::Bool # whether the agent is happy in its position. (true = happy) + group::Int # The group of the agent, determines mood as it interacts with neighbors end -# Notice that the position of this Agent type is a `Dims{2}`, equivalent to -# `NTuple{2,Int}`, because we will use a 2-dimensional `GridSpace`. - # We added two more fields for this model, namely a `mood` field which will # store `true` for a happy agent and `false` for an unhappy one, and an `group` # field which stores `0` or `1` representing two groups. @@ -49,12 +56,6 @@ end # end # ``` -# ## Creating a space - -# For this example, we will be using a Chebyshev 2D grid, e.g. - -space = GridSpace((10, 10), periodic = false) - # ## Creating an ABM # To make our model we follow the instructions of [`AgentBasedModel`](@ref). @@ -106,7 +107,6 @@ function initialize(; numagents = 320, griddims = (20, 20), min_to_be_happy = 3, end return model end -nothing # hide # Notice that the position that an agent is initialized does not matter # in this example. @@ -120,10 +120,11 @@ nothing # hide function agent_step!(agent, model) minhappy = model.min_to_be_happy - neighbor_positions = nearby_positions(agent, model) count_neighbors_same_group = 0 ## For each neighbor, get group and compare to current agent's group ## and increment count_neighbors_same_group as appropriately. + ## Here `nearby_agents` (with default arguments) will provide an iterator + ## over the nearby agents one grid point away, which are at most 8. for neighbor in nearby_agents(agent, model) if agent.group == neighbor.group count_neighbors_same_group += 1 @@ -139,7 +140,6 @@ function agent_step!(agent, model) end return end -nothing # hide # For the purpose of this implementation of Schelling's segregation model, # we only need an agent step function. @@ -226,7 +226,7 @@ abm_video( framerate = 4, frames = 20, title = "Schelling's segregation model" ) -nothing # hide + # ```@raw html #