library(plotly)
#> Loading required package: ggplot2
#>
#> Attaching package: 'plotly'
#> The following object is masked from 'package:ggplot2':
#>
#> last_plot
#> The following object is masked from 'package:stats':
#>
#> filter
#> The following object is masked from 'package:graphics':
#>
#> layout
library(villager)
To create resources that have additional properties, subclass the
resource
class.
To add new members to the resource class,
initialize
functionas_table
functionTo demonstrate how to subclass and run a model with a custom
resource class, consier an example of corn and rice resources
that expire. To do this, a new variable is added to the resource class,
creation_date
which gets updated when the resource is
created. When the model runs, the date at each time step is used to
check against the creation date of each resource.
resource_expiration <- R6::R6Class("resource",
cloneable = TRUE,
public = list(
name = NA,
quantity = NA,
creation_date = NA,
#' Creates a new resource.
#'
#' @description Creates a new resource object
#' @param name The name of the resource
#' @param quantity The quantity present
#' @param creation_date The date that the resource was created
initialize = function(name = NA, quantity = 0, creation_date=NA) {
self$name <- name
self$quantity <- quantity
self$creation_date <- creation_date # New member variable to track the creation date
},
#' Returns a data.frame representation of the resource
#'
#' @return A data.frame of resources
as_table = function() {
return(data.frame(name = self$name, quantity = self$quantity))
}
)
)
The initial condition is a village that has two resource types, corn and rice.
initial_condition <- function(current_state, model_data, agent_mgr, resource_mgr) {
for (i in 1:10) {
name <- runif(1, 0.0, 100)
new_agent <- agent$new(first_name <- name, last_name <- "Smith")
agent_mgr$add_agent(new_agent)
}
# Create two new resources at the current date (The first day)
corn <- resource_expiration$new("Corn", 10, current_state$step)
rice <- resource_expiration$new("Rice", 20, current_state$step)
resource_mgr$add_resource(corn)
resource_mgr$add_resource(rice)
}
The model checks the current date against the expiration dates on each resource. When the threshold limits are reached, the quantity is set to zero.
# Create the model that, each day, checks to see whether or not any resource expire
model <- function(current_state, previous_state, model_data, agent_mgr, resource_mgr, village_mgr) {
# Loop over all of the resources and check if any expire
for (resource in resource_mgr$get_resources()) {
# Figure out how many days have passed
days_passed <- current_state$step - resource$creation_date
if (resource$name == "Corn") {
if (days_passed > 10 && resource$quantity > 0) {
print("Setting Corn quantity to 0")
resource$quantity <- 0
}
} else if (resource$name == "Rice" && resource$quantity > 0) {
if (days_passed > 20) {
print("Setting Rice quantity to 0")
resource$quantity <- 0
}
}
}
}
With the required model components complete, we can create a simulation that runs for 15 days. By the end of it, there should be no more corn left, and the rice stocks should still be full.
A timeseries of each resource type is plotted below. The rice resource has clearly not expired while the corn resource has after 10 days.
# Load in data
time_series_data <- readr::read_csv("results/Expiring_Resources/resources.csv")
#> Rows: 32 Columns: 3
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (1): name
#> dbl (2): quantity, step
#>
#> ℹ 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.
# Get unique dates
unique_step<- sort(unique(time_series_data$step))
# Get corn & rice quantities and dates
corn_date_quantities <- dplyr::filter(time_series_data, name=="Corn")
rice_date_quantities <- dplyr::filter(time_series_data, name=="Rice")
# create data frame for sorted data
reordered_time_series <- data.frame(step = unique_step, Corn = 0, Rice = 0)
for (i in 1:nrow(reordered_time_series)){
reordered_time_series[i,2] = corn_date_quantities[which(corn_date_quantities$step == reordered_time_series$step[i]),2]
reordered_time_series[i,3] = rice_date_quantities[which(rice_date_quantities$step == reordered_time_series$step[i]),2]
}
# Plot graph
plotly::plot_ly(reordered_time_series, x = ~step) %>%
plotly::add_trace(y = ~Corn, name = 'Corn', type = 'scatter', mode = 'lines') %>%
plotly::add_trace(y = ~Rice, name = 'Rice', type = 'scatter', mode = 'lines') %>%
plotly::layout(title = 'Resource Counts', xaxis = list(title = 'Time Step'),
yaxis = list(title = 'Quantity'), legend = list(title=list(text='Crop Type')))