diff --git a/DESCRIPTION b/DESCRIPTION index 43c59d65..701e06ee 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -66,6 +66,7 @@ Collate: 'Individual.R' 'Household.R' 'Log.R' + 'Market.R' 'MatchingMarket.R' 'MatchingMarketOptimal.R' 'MatchingMarketStochastic.R' @@ -73,6 +74,8 @@ Collate: 'Network.R' 'Population.R' 'Pipeline.R' + 'SearchStrategy.R' + 'SelectStrategy.R' 'Transition.R' 'TransitionClassification.R' 'TransitionRegression.R' diff --git a/NAMESPACE b/NAMESPACE index e9d4ac4f..11aafa81 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -21,6 +21,7 @@ export(Generic) export(History) export(Household) export(Individual) +export(Market) export(MatchingMarket) export(MatchingMarketOptimal) export(MatchingMarketStochastic) @@ -28,6 +29,8 @@ export(Model) export(Network) export(Pipeline) export(Population) +export(SearchStrategy) +export(SelectStrategy) export(SupportedTransitionModels) export(Transition) export(TransitionClassification) diff --git a/R/Market.R b/R/Market.R new file mode 100644 index 00000000..782ab966 --- /dev/null +++ b/R/Market.R @@ -0,0 +1,41 @@ +#' Market class +#' +#' @description +#' A market class. +#' +#' @include Generic.R +#' @export +Market <- R6Class( + classname = "Market", + inherit = Generic, + public = list( + #' @description + #' Create a new market object. + #' + #' @param ... dots + #' + #' @return `NULL` + #' + #' @examples + #' + #' Mrkt <- Market$new() + initialize = function(...) { + + }, + + + #' @description + #' Match agents with choices + #' + #' @param agents a vector containing agent ids + #' @param choices a vector containing choice ids + #' @param probabilities a vector containing numerical probability values + #' + #' @return a [data.table::data.table] with two columns: `agent_id` and `choice_id`. + match = function(agents, choices, probabilities) { + + } + ), + + private = list() +) diff --git a/R/SearchStrategy.R b/R/SearchStrategy.R new file mode 100644 index 00000000..49984805 --- /dev/null +++ b/R/SearchStrategy.R @@ -0,0 +1,51 @@ +#' R6 Class Containing a search strategy for agents. +#' +#' @description +#' This is the base class for implementing a search strategy. +#' +#' @details +#' A search strategy to be adopted by agents when they are in a market. +#' +#' @include Generic.R +#' @export +SearchStrategy <- R6Class( + classname = "SearchStrategy", + inherit = dymiumCore::Generic, + public = list( + + #' @description + #' Create a search strategy object. + #' + #' @param ... dots + #' + #' @return `NULL` + #' @export + #' + #' @examples + #' + #' SS <- SearchStrategy$new() + initialize = function(...){ + self$set() + }, + + set = function() { + private$abstract() + }, + + simulate = function() { + private$abstract() + }, + + filter = function() { + private$abstract() + }, + + evaluate = function() { + private$abstract() + } + ), + + private = list( + + ) +) diff --git a/R/SelectStrategy.R b/R/SelectStrategy.R new file mode 100644 index 00000000..d73622c3 --- /dev/null +++ b/R/SelectStrategy.R @@ -0,0 +1,39 @@ +#' R6 Class Containing a select strategy for agents. +#' +#' @description +#' This is the base class for implementing a select strategy. +#' +#' @details +#' A select strategy to be adopted by agents when they are in a market. +#' +#' @include Generic.R +#' @export +SelectStrategy <- R6Class( + classname = "SelectStrategy", + inherit = dymiumCore::Generic, + public = list( + + #' @description + #' Create a select strategy object. + #' + #' @param ... dots + #' + #' @return `NULL` + #' @export + #' + #' @examples + #' + #' SS <- SearchStrategy$new() + initialize = function(...){ + + }, + + set = function() { + + } + ), + + private = list( + + ) +) diff --git a/man/Market.Rd b/man/Market.Rd new file mode 100644 index 00000000..6de9ab3b --- /dev/null +++ b/man/Market.Rd @@ -0,0 +1,110 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Market.R +\name{Market} +\alias{Market} +\title{Market class} +\description{ +A market class. +} +\examples{ + +## ------------------------------------------------ +## Method `Market$new` +## ------------------------------------------------ + + +Mrkt <- Market$new() +} +\section{Super class}{ +\code{\link[dymiumCore:Generic]{dymiumCore::Generic}} -> \code{Market} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{Market$new()}} +\item \href{#method-match}{\code{Market$match()}} +\item \href{#method-clone}{\code{Market$clone()}} +} +} +\if{html}{ +\out{
Inherited methods} +\itemize{ +\item \out{}\href{../../dymiumCore/html/Generic.html#method-class}{\code{dymiumCore::Generic$class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-debug}{\code{dymiumCore::Generic$debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-is_dymium_class}{\code{dymiumCore::Generic$is_dymium_class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-message}{\code{dymiumCore::Generic$message()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_debug}{\code{dymiumCore::Generic$msg_debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_info}{\code{dymiumCore::Generic$msg_info()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_trace}{\code{dymiumCore::Generic$msg_trace()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_warn}{\code{dymiumCore::Generic$msg_warn()}}\out{} +} +\out{
} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{new()}}{ +Create a new market object. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{Market$new(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{dots} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{NULL} +} +\subsection{Examples}{ +\if{html}{\out{
}} +\preformatted{ +Mrkt <- Market$new() +} +\if{html}{\out{
}} + +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{match()}}{ +Match agents with choices +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{Market$match(agents, choices, probabilities)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{agents}}{a vector containing agent ids} + +\item{\code{choices}}{a vector containing choice ids} + +\item{\code{probabilities}}{a vector containing numerical probability values} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +a \link[data.table:data.table]{data.table::data.table} with two columns: \code{agent_id} and \code{choice_id}. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{Market$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/SearchStrategy.Rd b/man/SearchStrategy.Rd new file mode 100644 index 00000000..181a7c30 --- /dev/null +++ b/man/SearchStrategy.Rd @@ -0,0 +1,125 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/SearchStrategy.R +\name{SearchStrategy} +\alias{SearchStrategy} +\title{R6 Class Containing a search strategy for agents.} +\description{ +This is the base class for implementing a search strategy. +} +\details{ +A search strategy to be adopted by agents when they are in a market. +} +\examples{ + +## ------------------------------------------------ +## Method `SearchStrategy$new` +## ------------------------------------------------ + + +SS <- SearchStrategy$new() +} +\section{Super class}{ +\code{\link[dymiumCore:Generic]{dymiumCore::Generic}} -> \code{SearchStrategy} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{SearchStrategy$new()}} +\item \href{#method-set}{\code{SearchStrategy$set()}} +\item \href{#method-simulate}{\code{SearchStrategy$simulate()}} +\item \href{#method-filter}{\code{SearchStrategy$filter()}} +\item \href{#method-evaluate}{\code{SearchStrategy$evaluate()}} +\item \href{#method-clone}{\code{SearchStrategy$clone()}} +} +} +\if{html}{ +\out{
Inherited methods} +\itemize{ +\item \out{}\href{../../dymiumCore/html/Generic.html#method-class}{\code{dymiumCore::Generic$class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-debug}{\code{dymiumCore::Generic$debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-is_dymium_class}{\code{dymiumCore::Generic$is_dymium_class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-message}{\code{dymiumCore::Generic$message()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_debug}{\code{dymiumCore::Generic$msg_debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_info}{\code{dymiumCore::Generic$msg_info()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_trace}{\code{dymiumCore::Generic$msg_trace()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_warn}{\code{dymiumCore::Generic$msg_warn()}}\out{} +} +\out{
} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{new()}}{ +Create a search strategy object. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$new(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{dots} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{NULL} +} +\subsection{Examples}{ +\if{html}{\out{
}} +\preformatted{ +SS <- SearchStrategy$new() +} +\if{html}{\out{
}} + +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{set()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$set()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{simulate()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$simulate()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{filter()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$filter()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{evaluate()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$evaluate()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SearchStrategy$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/SelectStrategy.Rd b/man/SelectStrategy.Rd new file mode 100644 index 00000000..c68a1368 --- /dev/null +++ b/man/SelectStrategy.Rd @@ -0,0 +1,98 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/SelectStrategy.R +\name{SelectStrategy} +\alias{SelectStrategy} +\title{R6 Class Containing a select strategy for agents.} +\description{ +This is the base class for implementing a select strategy. +} +\details{ +A select strategy to be adopted by agents when they are in a market. +} +\examples{ + +## ------------------------------------------------ +## Method `SelectStrategy$new` +## ------------------------------------------------ + + +SS <- SearchStrategy$new() +} +\section{Super class}{ +\code{\link[dymiumCore:Generic]{dymiumCore::Generic}} -> \code{SelectStrategy} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-new}{\code{SelectStrategy$new()}} +\item \href{#method-set}{\code{SelectStrategy$set()}} +\item \href{#method-clone}{\code{SelectStrategy$clone()}} +} +} +\if{html}{ +\out{
Inherited methods} +\itemize{ +\item \out{}\href{../../dymiumCore/html/Generic.html#method-class}{\code{dymiumCore::Generic$class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-debug}{\code{dymiumCore::Generic$debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-is_dymium_class}{\code{dymiumCore::Generic$is_dymium_class()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-message}{\code{dymiumCore::Generic$message()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_debug}{\code{dymiumCore::Generic$msg_debug()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_info}{\code{dymiumCore::Generic$msg_info()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_trace}{\code{dymiumCore::Generic$msg_trace()}}\out{} +\item \out{}\href{../../dymiumCore/html/Generic.html#method-msg_warn}{\code{dymiumCore::Generic$msg_warn()}}\out{} +} +\out{
} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{new()}}{ +Create a select strategy object. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SelectStrategy$new(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{dots} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{NULL} +} +\subsection{Examples}{ +\if{html}{\out{
}} +\preformatted{ +SS <- SearchStrategy$new() +} +\if{html}{\out{
}} + +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{set()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SelectStrategy$set()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{SelectStrategy$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/tests/testthat/test-Market.R b/tests/testthat/test-Market.R new file mode 100644 index 00000000..9cac233b --- /dev/null +++ b/tests/testthat/test-Market.R @@ -0,0 +1,88 @@ +test_that("initialise", { + if (FALSE) { + Mrkt <- Market$new() + + create_toy_world() + + toy_households[, .(choices = sample(toy_dwellings[zid == zid]))] + + # rough codes + library(collections) + households <- toy_households[toy_dwellings[, .(did, zid)], on = "did"] + households <- purrr::map_dfr(1:50, ~ households)[, hid := 1:.N] + dwellings <- purrr::map_dfr(1:50, ~ toy_dwellings)[, did := 1:.N] + all_hids <- as.character(households[["hid"]]) + all_zids <- households[["zid"]] + choicesets <- Dict() + + for (i in 1:nrow(households)) { + + # define variables + self_hid <- all_hids[i] + self_zid <- all_zids[i] + + # apply rules + choiceset <- sample_choice(dwellings[zid == self_zid, did], 5, replace = TRUE) + + # record choiceset + choicesets$set(key = self_hid, value = choiceset) + } + + choiceset_dt <- data.table(.key = choicesets$keys(), + .value = choicesets$values()) + choiceset_dt <- + choiceset_dt[, lapply(.SD, unlist), by = .key] + + # mental model + choicesets <- households$create_choiceset(toy_dwellings, rules) + + scores <- households$evaluate(choicesets, rules) + + matches <- market(households, choicesets, scores) + + households$update_dwelling(matches$hid, matches$did) + } + + + +}) + + +test_that("initialise2", { + + if (FALSE) { + # required data + # - household data + # - dwelling data + # - rules or models + + # rough codes + households <- + toy_households[toy_dwellings[, .(did, zid)], on = "did"] %>% + as.data.frame() + + households <- purrr::map_dfr(1:50, ~ households) %>% + setDT(.) %>% + .[, `:=`(hid = 1:.N, choiceset = list())] + + dwellings <- + purrr::map_dfr(1:50, ~ toy_dwellings)[, did := 1:.N] + + all_zids <- households[["zid"]] + + dg <- split(dwellings, dwellings$zid) + + for (i in 1:nrow(households)) { + self_zid <- all_zids[[i]] + # .choiceset <- sample(dwellings[zid == self_zid, did], size = 5, replace = FALSE) + .choiceset <- sample(dg[[self_zid]][["did"]], size = 10, replace = FALSE) + set(households, i, j = 'choiceset', value = list(.choiceset)) + } + + households <- households[, lapply(.SD, unlist), by = hid] + + households + } + + +})