diff --git a/NEWS.md b/NEWS.md index c1a3b058..4f563edf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # paradox 1.0.1-9000 * `ParamSetCollection$flatten()` now detaches `$extra_trafo` completely from original ParamSetCollection. +* Option to postfix, instead of prefix, in `ParamSetCollection`, `c()`/`ps_union()`, and `ps_replicate()`. # paradox 1.0.1 diff --git a/R/ParamSet.R b/R/ParamSet.R index 5103b965..4dcec206 100644 --- a/R/ParamSet.R +++ b/R/ParamSet.R @@ -273,8 +273,8 @@ ParamSet = R6Class("ParamSet", assert_list(x, names = "unique") trafos = private$.trafos[names(x), .(id, trafo), nomatch = 0] value = NULL # static checks - trafos[, value := x[id]] if (nrow(trafos)) { + trafos[, value := x[id]] transformed = pmap(trafos, function(id, trafo, value) trafo(value)) x = insert_named(x, set_names(transformed, trafos$id)) } diff --git a/R/ParamSetCollection.R b/R/ParamSetCollection.R index d8d2f3f6..0e18777d 100644 --- a/R/ParamSetCollection.R +++ b/R/ParamSetCollection.R @@ -34,10 +34,13 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, #' Whether to add tags of the form `"set_"` to each parameter originating from a given `ParamSet` given with name ``. #' @param tag_params (`logical(1)`)\cr #' Whether to add tags of the form `"param_"` to each parameter with original ID ``. - initialize = function(sets, tag_sets = FALSE, tag_params = FALSE) { + #' @param postfix_names (`logical(1)`)\cr + #' Whether to use the names inside `sets` as postfixes, rather than prefixes. + initialize = function(sets, tag_sets = FALSE, tag_params = FALSE, postfix_names = FALSE) { assert_list(sets, types = "ParamSet") assert_flag(tag_sets) assert_flag(tag_params) + private$.postfix = assert_flag(postfix_names) if (is.null(names(sets))) names(sets) = rep("", length(sets)) @@ -52,7 +55,11 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, set(params_child, , "original_id", params_child$id) set(params_child, , "owner_ps_index", i) set(params_child, , "owner_name", n) - if (n != "") set(params_child, , "id", sprintf("%s.%s", n, params_child$id)) + if (n != "") { + set(params_child, , "id", + private$.add_name_prefix(n, params_child$id) + ) + } params_child } }), prototype = { @@ -74,13 +81,13 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, if (tag_sets || tag_params) { ids = s$.__enclos_env__$private$.params$id newids = ids - if (n != "") newids = sprintf("%s.%s", n, ids) + if (n != "") newids = private$.add_name_prefix(n, ids) } tags_child = s$.__enclos_env__$private$.tags list( if (nrow(tags_child)) { tags_child = copy(tags_child) - if (n != "") set(tags_child, , "id", sprintf("%s.%s", n, tags_child$id)) + if (n != "") set(tags_child, , "id", private$.add_name_prefix(n, tags_child$id)) tags_child }, if (tag_sets && n != "" && length(newids)) { @@ -109,7 +116,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, trafos_child = s$.__enclos_env__$private$.trafos if (nrow(trafos_child)) { trafos_child = copy(trafos_child) - if (n != "" && nrow(trafos_child)) set(trafos_child, , "id", sprintf("%s.%s", n, trafos_child$id)) + if (n != "" && nrow(trafos_child)) set(trafos_child, , "id", private$.add_name_prefix(n, trafos_child$id)) trafos_child } }), prototype = structure(list( @@ -149,7 +156,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, } pnames = p$ids() nameclashes = intersect( - ifelse(n != "", sprintf("%s.%s", n, pnames), pnames), + ifelse(n != "", private$.add_name_prefix(n, pnames), pnames), self$ids() ) if (length(nameclashes)) { @@ -158,7 +165,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, new_index = length(private$.sets) + 1 paramtbl = p$params[, `:=`(original_id = id, owner_ps_index = new_index, owner_name = n)] - if (n != "") set(paramtbl, , "id", sprintf("%s.%s", n, paramtbl$id)) + if (n != "") set(paramtbl, , "id", private$.add_name_prefix(n, paramtbl$id)) if (!nrow(paramtbl)) { # when paramtbl is empty, use special setup to make sure information about the `.tags` column is present. @@ -225,7 +232,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, } else if (prefix == "") { info$owner_name } else { - paste0(prefix, ".", info$owner_name) + private$.add_name_prefix(prefix, info$owner_name) } if (!test_class(subset, "ParamSetCollection")) return(prefix) @@ -237,7 +244,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, xs = private$.params[list(id_), "cargo", on = "id"][[1]][[1]]$disable_in_tune prefix = full_prefix(self, id_) if (prefix == "") return(xs) - set_names(xs, paste0(full_prefix(self, id_), ".", names(xs))) + set_names(xs, private$.add_name_prefix(full_prefix(self, id_), names(xs))) })) %??% named_list() self$set_values(.values = pvs) }, @@ -274,7 +281,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, } else if (prefix == "") { info$owner_name } else { - paste0(prefix, ".", info$owner_name) + private$.add_name_prefix(prefix, info$owner_name) } subset = get_private(param_set)$.sets[[info$owner_ps_index]] if (!test_class(subset, "ParamSetCollection")) { @@ -296,17 +303,17 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, in_tune_fn = cargo$in_tune_fn - set_ids = info$ids + prefixed_set_ids = private$.add_name_prefix(prefix, info$ids) cargo$in_tune_fn = crate(function(domain, param_vals) { - param_vals = param_vals[names(param_vals) %in% paste0(prefix, ".", set_ids)] + param_vals = param_vals[names(param_vals) %in% prefixed_set_ids] names(param_vals) = gsub(sprintf("^\\Q%s.\\E", prefix), "", names(param_vals)) in_tune_fn(domain, param_vals) - }, in_tune_fn, prefix, set_ids) + }, in_tune_fn, prefix, prefixed_set_ids) if (length(cargo$disable_in_tune)) { cargo$disable_in_tune = set_names( cargo$disable_in_tune, - paste0(prefix, ".", names(cargo$disable_in_tune)) + private$.add_name_prefix(prefix, names(cargo$disable_in_tune)) ) } cargo @@ -328,7 +335,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, dd = s$deps if (id != "" && nrow(dd)) { ids_old = s$ids() - ids_new = sprintf("%s.%s", id, ids_old) + ids_new = private$.add_name_prefix(id, ids_old) dd$id = map_values(dd$id, ids_old, ids_new) dd$on = map_values(dd$on, ids_old, ids_new) } @@ -363,8 +370,23 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, ), private = list( + .postfix = FALSE, + .add_name_prefix = function(owner, id) { + if (private$.postfix) sprintf("%s.%s", id, owner) else sprintf("%s.%s", owner, id) + }, .get_values = function() { - vals = unlist(map(private$.sets, "values"), recursive = FALSE) + if (private$.postfix && !is.null(names(private$.sets))) { + vals = imap(private$.sets, function(x, n) { + vals_subset = x$values + if (nchar(n)) { + names(vals_subset) = sprintf("%s.%s", names(vals_subset), n) + } + vals_subset + }) + vals = unlist(unname(vals), recursive = FALSE) + } else { + vals = unlist(map(private$.sets, "values"), recursive = FALSE) + } if (length(vals)) vals else named_list() }, .store_values = function(xs) { @@ -393,7 +415,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, children_with_trafos = private$.children_with_trafos() sets_with_trafos = private$.sets[children_with_trafos] translation = private$.translation - psc_extra_trafo(x, children_with_trafos, sets_with_trafos, translation) + psc_extra_trafo(x, children_with_trafos, sets_with_trafos, translation, private$.postfix) }, # get an extra_trafo function that does not have any references to the PSC object or any of its contained sets. # This is used for flattening. @@ -406,7 +428,8 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, } if (!length(children_with_trafos)) return(NULL) sets_with_trafos = lapply(private$.sets[children_with_trafos], function(x) x$clone(deep = TRUE)) # get new objects that are detached from PSC - crate(function(x) psc_extra_trafo(x, children_with_trafos, sets_with_trafos, translation), children_with_trafos, sets_with_trafos, translation, psc_extra_trafo) + postfix = private$.postfix + crate(function(x) psc_extra_trafo(x, children_with_trafos, sets_with_trafos, translation, postfix), children_with_trafos, sets_with_trafos, translation, psc_extra_trafo, postfix) }, .constraint_explicit = function(x) { children_with_constraints = private$.children_with_constraints() @@ -447,7 +470,7 @@ ParamSetCollection = R6Class("ParamSetCollection", inherit = ParamSet, # We have this functoin outside of the ParamSetCollection class, because we anticipate that PSC can be "flattened", i.e. turned into # a normal ParamSet. In that case, the resulting ParamSet's extra_trafo should be a function that can stand on its own, without # referring to private$. -psc_extra_trafo = function(x, children_with_trafos, sets_with_trafos, translation) { +psc_extra_trafo = function(x, children_with_trafos, sets_with_trafos, translation, postfix) { changed = unlist(lapply(seq_along(children_with_trafos), function(i) { set_index = children_with_trafos[[i]] changing_ids = translation[J(set_index), id, on = "owner_ps_index"] @@ -464,7 +487,7 @@ psc_extra_trafo = function(x, children_with_trafos, sets_with_trafos, translatio changing_values = trafo(changing_values_in) prefix = names(sets_with_trafos)[[i]] if (prefix != "") { - names(changing_values) = sprintf("%s.%s", prefix, names(changing_values)) + names(changing_values) = if (postfix) sprintf("%s.%s", names(changing_values), prefix) else sprintf("%s.%s", prefix, names(changing_values)) } changing_values }), recursive = FALSE) diff --git a/R/ps_replicate.R b/R/ps_replicate.R index cf79919e..fb9a9497 100644 --- a/R/ps_replicate.R +++ b/R/ps_replicate.R @@ -9,13 +9,17 @@ #' [`ParamSet`] to use as template. #' @param times (`integer(1)`)\cr #' Number of times to repeat `set`. -#' Should not be given if `prefixes` is provided. -#' @param prefixes (`character`)\cr -#' A `character` vector indicating the prefixes to use for each repetition of `set`. -#' If this is given, `times` is inferred from `length(prefixes)` and should not be given separately. +#' Should not be given if `affixes` is provided. +#' @param affixes (`character`)\cr +#' A `character` vector indicating the prefixes / postfixes to use for each repetition of `set`. +#' Per default, these are prefixes; if `postfix` is `TRUE`, these values are postfixed instead. +#' If this is given, `times` is inferred from `length(affixes)` and should not be given separately. #' If `times` is given, this defaults to `"repX"`, with `X` counting up from 1. +#' @param postfix (`logical(1)`)\cr +#' Whether to use `affixes` as a postfix instead of a prefix. +#' Default `FALSE` (use prefixes). #' @param tag_sets (`logical(1)`)\cr -#' Whether to add a tag of the form `"set_"` to each parameter in the result, indicating the repetition each parameter belongs to. +#' Whether to add a tag of the form `"set_"` to each parameter in the result, indicating the repetition each parameter belongs to. #' @param tag_params (`logical(1)`)\cr #' Whether to add a tag of the form `"param_"` to each parameter in the result, indicating the original parameter ID inside `set`. #' @examples @@ -26,7 +30,9 @@ #' #' ps_replicate(pset, 3) #' -#' ps_replicate(pset, prefixes = c("first", "last")) +#' ps_replicate(pset, affixes = c("first", "last")) +#' +#' ps_replicate(pset, affixes = c("first", "last"), postfix = TRUE) #' #' pset$values = list(i = 1, z = FALSE) #' @@ -52,9 +58,10 @@ #' # get all values associated with the first repetition "rep1" #' psr$get_values(any_tags = "set_rep1") #' @export -ps_replicate = function(set, times = length(prefixes), prefixes = sprintf("rep%s", seq_len(times)), tag_sets = FALSE, tag_params = FALSE) { +ps_replicate = function(set, times = length(affixes), affixes = sprintf("rep%s", seq_len(times)), postfix = FALSE, tag_sets = FALSE, tag_params = FALSE) { assert_count(times) - assert_character(prefixes, any.missing = FALSE, unique = TRUE, len = times) + assert_character(affixes, any.missing = FALSE, unique = TRUE, len = times) + assert_flag(postfix) - ps_union(named_list(prefixes, set), tag_sets = tag_sets, tag_params = tag_params) + ps_union(named_list(affixes, set), postfix_names = postfix, tag_sets = tag_sets, tag_params = tag_params) } diff --git a/R/ps_union.R b/R/ps_union.R index a751d6f1..03684612 100644 --- a/R/ps_union.R +++ b/R/ps_union.R @@ -10,12 +10,17 @@ #' have their `` changed to `.`. This is also reflected in deps. #' #' The `c()` operator, applied to [`ParamSet`]s, is a synony for `ps_union()`. +#' The named arguments `tag_sets`, `tag_params`, and `postfix_names` are also available in the `c()` operator, but need to be +#' used with a preceding dot instead: `.tag_sets`, `.tag_params`, and `.postfix_names`. #' @param sets (`list` of [`ParamSet`])\cr #' This may be a named list, in which case non-empty names are prefixed to parameters in the corresponding [`ParamSet`]. #' @param tag_sets (`logical(1)`)\cr #' Whether to add tags of the form `"set_"` to each parameter originating from a given `ParamSet` given with name ``. #' @param tag_params (`logical(1)`)\cr #' Whether to add tags of the form `"param_"` to each parameter with original ID ``. +#' @param postfix_names (`logical(1)`)\cr +#' Whether to use names in `sets` as postfixes, instead of prefixes. +#' Default `FALSE`. #' @examples #' ps1 = ps(x = p_dbl()) #' ps1$values = list(x = 1) @@ -43,14 +48,18 @@ #' #' pu2$values #' +#' pu3 = c(one = ps1, two = ps1, ps2, .postfix_names = TRUE) +#' pu3 +#' +#' #' @export -ps_union = function(sets, tag_sets = FALSE, tag_params = FALSE) { +ps_union = function(sets, tag_sets = FALSE, tag_params = FALSE, postfix_names = FALSE) { assert_list(sets, types = "ParamSet") if (!length(sets)) return(ParamSet$new()) - ParamSetCollection$new(sets, tag_sets = tag_sets, tag_params = tag_params)$flatten() + ParamSetCollection$new(sets, tag_sets = tag_sets, tag_params = tag_params, postfix_names = postfix_names)$flatten() } #' @export -c.ParamSet = function(..., .tag_sets = FALSE, .tag_params = FALSE) { - ps_union(list(...), tag_sets = .tag_sets, tag_params = .tag_params) +c.ParamSet = function(..., .tag_sets = FALSE, .tag_params = FALSE, .postfix_names = FALSE) { + ps_union(list(...), tag_sets = .tag_sets, tag_params = .tag_params, postfix_names = .postfix_names) } diff --git a/man/ParamSetCollection.Rd b/man/ParamSetCollection.Rd index 6bf63db8..53b6223e 100644 --- a/man/ParamSetCollection.Rd +++ b/man/ParamSetCollection.Rd @@ -106,7 +106,12 @@ This field provides direct references to the \code{\link{ParamSet}} objects.} \subsection{Method \code{new()}}{ Creates a new instance of this \link[R6:R6Class]{R6} class. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ParamSetCollection$new(sets, tag_sets = FALSE, tag_params = FALSE)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{ParamSetCollection$new( + sets, + tag_sets = FALSE, + tag_params = FALSE, + postfix_names = FALSE +)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -121,6 +126,9 @@ Whether to add tags of the form \code{"set_"} to each parameter originat \item{\code{tag_params}}{(\code{logical(1)})\cr Whether to add tags of the form \code{"param_"} to each parameter with original ID \verb{}.} + +\item{\code{postfix_names}}{(\code{logical(1)})\cr +Whether to use the names inside \code{sets} as postfixes, rather than prefixes.} } \if{html}{\out{}} } diff --git a/man/ps_replicate.Rd b/man/ps_replicate.Rd index ef5aeb92..8c118e71 100644 --- a/man/ps_replicate.Rd +++ b/man/ps_replicate.Rd @@ -6,8 +6,9 @@ \usage{ ps_replicate( set, - times = length(prefixes), - prefixes = sprintf("rep\%s", seq_len(times)), + times = length(affixes), + affixes = sprintf("rep\%s", seq_len(times)), + postfix = FALSE, tag_sets = FALSE, tag_params = FALSE ) @@ -18,15 +19,20 @@ ps_replicate( \item{times}{(\code{integer(1)})\cr Number of times to repeat \code{set}. -Should not be given if \code{prefixes} is provided.} +Should not be given if \code{affixes} is provided.} -\item{prefixes}{(\code{character})\cr -A \code{character} vector indicating the prefixes to use for each repetition of \code{set}. -If this is given, \code{times} is inferred from \code{length(prefixes)} and should not be given separately. +\item{affixes}{(\code{character})\cr +A \code{character} vector indicating the prefixes / postfixes to use for each repetition of \code{set}. +Per default, these are prefixes; if \code{postfix} is \code{TRUE}, these values are postfixed instead. +If this is given, \code{times} is inferred from \code{length(affixes)} and should not be given separately. If \code{times} is given, this defaults to \code{"repX"}, with \code{X} counting up from 1.} +\item{postfix}{(\code{logical(1)})\cr +Whether to use \code{affixes} as a postfix instead of a prefix. +Default \code{FALSE} (use prefixes).} + \item{tag_sets}{(\code{logical(1)})\cr -Whether to add a tag of the form \code{"set_"} to each parameter in the result, indicating the repetition each parameter belongs to.} +Whether to add a tag of the form \code{"set_"} to each parameter in the result, indicating the repetition each parameter belongs to.} \item{tag_params}{(\code{logical(1)})\cr Whether to add a tag of the form \code{"param_"} to each parameter in the result, indicating the original parameter ID inside \code{set}.} @@ -43,7 +49,9 @@ pset = ps( ps_replicate(pset, 3) -ps_replicate(pset, prefixes = c("first", "last")) +ps_replicate(pset, affixes = c("first", "last")) + +ps_replicate(pset, affixes = c("first", "last"), postfix = TRUE) pset$values = list(i = 1, z = FALSE) diff --git a/man/ps_union.Rd b/man/ps_union.Rd index 732603e5..a4403845 100644 --- a/man/ps_union.Rd +++ b/man/ps_union.Rd @@ -4,7 +4,7 @@ \alias{ps_union} \title{Create a ParamSet from a list of ParamSets} \usage{ -ps_union(sets, tag_sets = FALSE, tag_params = FALSE) +ps_union(sets, tag_sets = FALSE, tag_params = FALSE, postfix_names = FALSE) } \arguments{ \item{sets}{(\code{list} of \code{\link{ParamSet}})\cr @@ -15,6 +15,10 @@ Whether to add tags of the form \code{"set_"} to each parameter originat \item{tag_params}{(\code{logical(1)})\cr Whether to add tags of the form \code{"param_"} to each parameter with original ID \verb{}.} + +\item{postfix_names}{(\code{logical(1)})\cr +Whether to use names in \code{sets} as postfixes, instead of prefixes. +Default \code{FALSE}.} } \description{ This emulates \code{ParamSetCollection$new(sets)}, except that the result is a flat \code{\link{ParamSet}}, not a \code{\link{ParamSetCollection}}. @@ -26,6 +30,8 @@ from the input \code{sets}, but some \verb{$id}s are changed: If the \code{\link have their \verb{} changed to \verb{.}. This is also reflected in deps. The \code{c()} operator, applied to \code{\link{ParamSet}}s, is a synony for \code{ps_union()}. +The named arguments \code{tag_sets}, \code{tag_params}, and \code{postfix_names} are also available in the \code{c()} operator, but need to be +used with a preceding dot instead: \code{.tag_sets}, \code{.tag_params}, and \code{.postfix_names}. } \examples{ ps1 = ps(x = p_dbl()) @@ -54,4 +60,8 @@ pu2 pu2$values +pu3 = c(one = ps1, two = ps1, ps2, .postfix_names = TRUE) +pu3 + + } diff --git a/tests/testthat/test_ParamSetCollection.R b/tests/testthat/test_ParamSetCollection.R index 89f7b713..50135fd5 100644 --- a/tests/testthat/test_ParamSetCollection.R +++ b/tests/testthat/test_ParamSetCollection.R @@ -369,3 +369,112 @@ test_that("disable internal tuning without set names", { param_set$disable_internal_tuning("a") expect_equal(param_set$values$b, TRUE) }) + +test_that("PSC postfix", { + ps1 = ps(x = p_int(1, 10, logscale = TRUE)) + ps2 = ps(x = p_dbl(-1, 1)) + ps3 = ps(x.y = p_fct(c("a", "b"))) + ps4 = ps(y.x = p_lgl()) + + psc = ParamSetCollection$new(list(y = ps1, z = ps2), postfix_names = TRUE) + + expect_equal(psc$ids(), c("x.y", "x.z")) + + psc$values$x.y = 1 + expect_equal(psc$values, list(x.y = 1)) + psc$values$x.z = -1 + expect_equal(psc$values, list(x.y = 1, x.z = -1)) + expect_equal(ps1$values$x, 1) + expect_equal(ps2$values$x, -1) + + ps1$extra_trafo = function(x, param_set) { + x$x.z = 99 + x + } + + expect_equal(psc$trafo(list()), list(x.z.y = 99)) + + expect_equal(psc$trafo(list(x.y = 3)), list(x.y = 10, x.z.y = 99)) + + psc$values = list() + expect_equal(psc$values, named_list()) + expect_equal(ps1$values, named_list()) + + psc$values$x.y = 1 + psc$values$x.z = -1 + psf = psc$flatten() + expect_equal(psf$ids(), c("x.y", "x.z")) + expect_equal(psf$values, list(x.y = 1, x.z = -1)) + psf$values = list(x.y = 2, x.z = -0.5) + expect_equal(psf$values, list(x.y = 2, x.z = -0.5)) + expect_equal(psc$values, list(x.y = 1, x.z = -1)) + + expect_equal(psf$trafo(list()), list(x.z.y = 99)) + expect_equal(psf$trafo(list(x.y = 3)), list(x.y = 10, x.z.y = 99)) + + ps1$extra_trafo = function(x, param_set) { + x$x.z = 999 + x + } + expect_equal(psc$trafo(list()), list(x.z.y = 999)) + expect_equal(psf$trafo(list()), list(x.z.y = 99)) + + expect_error(psc$add(ps3), "would lead to nameclashes.* x.y") + psc$add(ps4) + + expect_equal(psc$ids(), c("x.y", "x.z", "y.x")) + psc$add(ps3, n = "X.Y") + expect_equal(psc$ids(), c("x.y", "x.z", "y.x", "x.y.X.Y")) + + ps4$values = list(y.x = TRUE) + expect_equal(psc$values, list(x.y = 1, x.z = -1, y.x = TRUE)) + psc$values = list() + expect_equal(ps4$values, named_list()) + + # mixed with / without names + psc = ParamSetCollection$new(list(y = ps1, ps4), postfix_names = TRUE) + expect_equal(psc$ids(), c("x.y", "y.x")) + psc$values$x.y = 1 + expect_equal(psc$values, list(x.y = 1)) + psc$values$y.x = TRUE + expect_equal(psc$values, list(x.y = 1, y.x = TRUE)) + expect_equal(ps1$values$x, 1) + expect_equal(ps4$values$y.x, TRUE) + + ps4$extra_trafo = function(x, param_set) { + x$zzz = 888 + x + } + + expect_equal(psc$trafo(list()), list(x.z.y = 999, zzz = 888)) + + # x.y generated twice here + expect_error(ParamSetCollection$new(list(y = ps1, ps3), postfix_names = TRUE), "would contain duplicated parameter.* x.y") + + # don't get confused when no names are given + psc = ParamSetCollection$new(list(ps3, ps4), postfix_names = TRUE) + + expect_equal(psc$ids(), c("x.y", "y.x")) + psc$values$x.y = "a" + + # retains 'TRUE' from above + expect_equal(psc$values, list(x.y = "a", y.x = TRUE)) + + expect_equal(psc$trafo(list()), list(zzz = 888)) + + + expect_equal(c(y = ps1, z = ps2, .postfix_names = TRUE)$ids(), c("x.y", "x.z")) + repps = ps_replicate(ps1, affixes = letters[1:3], postfix = TRUE) + expect_equal(repps$ids(), + c("x.a", "x.b", "x.c")) + + expect_equal(repps$trafo(list(x.a = 1, x.b = 2)), + list( + x.a = 2, + x.z.a = 999, + x.b = 7, + x.z.b = 999, + x.z.c = 999 + ) + ) +}) diff --git a/vignettes/indepth.Rmd b/vignettes/indepth.Rmd index 8fbf474c..b2275115 100644 --- a/vignettes/indepth.Rmd +++ b/vignettes/indepth.Rmd @@ -17,7 +17,7 @@ The `paradox` package offers a language for the description of *parameter spaces A parameter space is often useful when describing: * A set of sensible input values for an R function -* The set of possible values that slots of a configuration object can take +* The set of possible values that fields of a configuration object can take * The search space of an optimization process The tools provided by `paradox` therefore relate to: @@ -105,13 +105,13 @@ The `ParamSet` should be considered immutable, except for some fields such as `$ Bounds and levels should not be changed after construction. Instead, a new `ParamSet` should be constructed. -Besides the possible values that can be given to a constructor, there are also the `$class`, `$nlevels`, `$is_bounded`, `$has_default`, `$storage_type`, `$is_number` and `$is_categ` slots that give information about a parameter. +Besides the possible values that can be given to a constructor, there are also the `$class`, `$nlevels`, `$is_bounded`, `$has_default`, `$storage_type`, `$is_number` and `$is_categ` fields that give information about a parameter. -A list of all slots can be found in `?Param`. +A list of all fields can be found in `?ParamSet`. ```{r} param_set$lower -param_set$parD$levels +param_set$levels$parD param_set$class ``` @@ -164,10 +164,10 @@ as.data.table(ps_all) ##### Values in a `ParamSet` -Although a `ParamSet` fundamentally represents a value space, it also has a slot `$values` that can contain a point within that space. +Although a `ParamSet` fundamentally represents a value space, it also has a field `$values` that can contain a point within that space. This is useful because many things that define a parameter space need similar operations (like parameter checking) that can be simplified. -The `$values` slot contains a named list that is always checked against parameter constraints. -When trying to set parameter values, e.g. for `mlr3` `Learner`s, it is the `$values` slot of its `$param_set` that needs to be used. +The `$values` field contains a named list that is always checked against parameter constraints. +When trying to set parameter values, e.g. for `mlr3` `Learner`s, it is the `$values` field of its `$param_set` that needs to be used. ```{r} ps1$values = list(x = 1, y = 1.5) @@ -222,9 +222,9 @@ p$check(list(A = TRUE, D = "x", B = 1), check_strict = TRUE) # D's dependency p$check(list(A = TRUE, B = 1), check_strict = TRUE) # B's dependency is not met ``` -Internally, the dependencies are represented as a `data.table`, which can be accessed listed in the **`$deps`** slot. +Internally, the dependencies are represented as a `data.table`, which can be accessed listed in the **`$deps`** field. This `data.table` can even be mutated, to e.g. remove dependencies. -There are no sanity checks done when the `$deps` slot is changed this way. +There are no sanity checks done when the `$deps` field is changed this way. Therefore it is advised to be cautious. ```{r} @@ -267,7 +267,7 @@ Furthermore, for most samplers `p_int()` and `p_dbl()` must have finite lower an #### Parameter Designs Functions that sample the parameter space fundamentally return an object of the `Design` class. -These objects contain the sampled data as a `data.table` under the `$data` slot, and also offer conversion to a list of parameter-values using the **`$transpose()`** function. +These objects contain the sampled data as a `data.table` under the `$data` field, and also offer conversion to a list of parameter-values using the **`$transpose()`** function. #### Grid Design