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.
R6::R6Class("resource",
resource_expiration <-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) {
$name <- name
self$quantity <- quantity
self$creation_date <- creation_date # New member variable to track the creation date
self
},
#' 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.
function(current_state, model_data, winik_mgr, resource_mgr) {
initial_condition <-for (i in 1:10) {
runif(1, 0.0, 100)
name <- winik$new(first_name <- name, last_name <- "Smith")
new_winik <-$add_winik(new_winik)
winik_mgr
}# Create two new resources at the current date (The first day)
resource_expiration$new("Corn", 10, current_state$step)
corn <- resource_expiration$new("Rice", 20, current_state$step)
rice <-$add_resource(corn)
resource_mgr$add_resource(rice)
resource_mgr }
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
function(current_state, previous_state, model_data, winik_mgr, resource_mgr) {
model <-# 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
current_state$step - resource$creation_date
days_passed <-if (resource$name == "Corn") {
if (days_passed > 10 && resource$quantity > 0) {
print("Setting Corn quantity to 0")
$quantity <- 0
resource
}else if (resource$name == "Rice" && resource$quantity > 0) {
} if (days_passed > 20) {
print("Setting Rice quantity to 0")
$quantity <- 0
resource
}
}
} }
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.
# Create the village and simulation
village$new("Expiring_Resources", initial_condition, model, resource_class=)
coastal_village <- simulation$new(16, villages = list(coastal_village))
simulator <-$run_model()
simulator#> [1] "Setting Corn quantity to 0"
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
readr::read_csv("results/Expiring_Resources/resources.csv")
time_series_data <-#>
#> ── Column specification ────────────────────────────────────────────────────────
#> cols(
#> name = col_character(),
#> quantity = col_double(),
#> step = col_double()
#> )
# Get unique dates
sort(unique(time_series_data$step))
unique_step<-
# Get corn & rice quantities and dates
dplyr::filter(time_series_data, name=="Corn")
corn_date_quantities <- dplyr::filter(time_series_data, name=="Rice")
rice_date_quantities <-
# create data frame for sorted data
data.frame(step = unique_step, Corn = 0, Rice = 0)
reordered_time_series <-for (i in 1:nrow(reordered_time_series)){
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]
reordered_time_series[i,
}
# Plot graph
::plot_ly(reordered_time_series, x = ~step) %>%
plotly 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')))
#> Warning: `arrange_()` is deprecated as of dplyr 0.7.0.
#> Please use `arrange()` instead.
#> See vignette('programming') for more help
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_warnings()` to see where this warning was generated.