To create agents (agents) that have more properties than the ones
provided by villager, subclass the agent
class
into a new R6 class. Once sub-classed, additional properties can be
added to the agent which can be used in the subsequent model. The new
agent class can be tied to individual villages. This gives flexibility
to model populations differently when running under the same
simulation.
To add new members to the agent class,
initialize
functionas_table
functionTo give a complete example of the sublclassing process, consider an
extended agent. In this case the agent has an additional property,
gps_coordinates
, that’s a named list of latitude and
longitude coordinates: [lat=1234, long=1234]. Each coordinate gets
updated by the model each day by a random number.
To start the base class off, the original class was copied to save time with the member variable definitions.
gps_agent <- R6::R6Class("agent",
inherit = villager::agent,
public = list(
age = NULL,
alive = NULL,
children = NULL,
father_id = NULL,
first_name = NULL,
gender = NULL,
health = NULL,
identifier = NULL,
last_name = NULL,
mother_id = NULL,
partner = NULL,
profession = NULL,
latitude = NULL,
longitude = NULL,
initialize = function(identifier = NA,
first_name = NA,
last_name = NA,
age = 0,
mother_id = NA,
father_id = NA,
partner = NA,
children = vector(mode = "character"),
gender = NA,
profession = NA,
alive = TRUE,
health = 100,
latitude = 0,
longitude = 0) {
super$initialize(identifier,
first_name,
last_name,
age,
mother_id,
father_id,
partner,
children,
gender,
profession,
alive,
health)
self$latitude <- latitude
self$longitude <- longitude
},
as_table = function() {
agent_table <- data.frame(
age = self$age,
alive = self$alive,
father_id = self$father_id,
first_name = self$first_name,
gender = self$gender,
health = self$health,
identifier = self$identifier,
last_name = self$last_name,
mother_id = self$mother_id,
partner = self$partner,
profession = self$profession,
latitude = self$latitude,
longitude = self$longitude
)
return(agent_table)
}
)
)
We’ll create the initial population of one Agent in the
initial_condition
function, which gets run before the model
starts. The initial starting location is in Los Angeles, Ca. Note that
the new gps_agent
class is used to instantiate the agent
rather than the library provided agent
class.
Each day, the model picks a number between 0.0000001 and 0.0000003
and increments gps_coordinate
on the agent.
test_model <- function(current_state, previous_state, model_data, agent_mgr, resource_mgr, village_mgr) {
# Loop over all the agents (just one at the moment)
for (agent in agent_mgr$get_living_agents()) {
# Generate new coordinates
latitude <- agent$latitude + runif(1, 0.01, 0.03)
longitude <- agent$longitude + runif(1, 0.01, 0.03)
agent$latitude <- latitude
agent$longitude <- longitude
}
}
Finally, we’ll create and run a simulation with a duration of 10 days.
# Load in data
agent_data <- readr::read_csv("results/Test_Village/agents.csv")
#> Rows: 10 Columns: 14
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (3): first_name, identifier, last_name
#> dbl (5): age, health, latitude, longitude, step
#> lgl (6): alive, father_id, gender, mother_id, partner, profession
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Grab just the location data
agent_location <- data.frame(latitude = agent_data$latitude, longitude = agent_data$longitude)
# create a map
leaflet::leaflet() %>%
leaflet::addTiles() %>% # Add default OpenStreetMap map tiles
leaflet::addMarkers (data = agent_location) # Add agent locations