Skip to content

Commit

Permalink
S3 params (#350)
Browse files Browse the repository at this point in the history
* faster

* extend tests a little

* minor improvements

* document

* more efficient deps handling in PSC

* fix ps_union

* transparent tags

* dynamic tags shadow

* avoid some instantiation of tags

* renaming param  to prevent misuse

* trying to make R 4 tests work

* testing shadow tags

* tag shadows work with adds / removes

* Towards S3 Params
tuning sets and ParamSetCollection still missing

* some fixes

* a few fixes

* a few fixes

* quality of life stuff: set6 cache, domain class propreties, init values

* some reorg

* PSC & PSC trafos

* relatively done with PSC

* psc should be feature complete now

* remove 'describe_error'

* minor fixes

* experiments

* solution demo

* progress

* condition as S3

* Param.R -> Domain_methods.R

* S6ObjectCache is pretty cool but we don't need it

* domain -> Domain

* for domain methods: default -> Domain

* cleaning up

* "feature complete"

* more efficient tags

* rename package

* some bugfixes

* qiute some progress

* commit message

* tests pass

* S3 consistency

* tests pass

* trafo info flags

* news and docs

* rename back to 'paradox'

* vignette progress

* vignette builds

* rd_info repair

* work with bbotk

* PSC

* bugfix

* checking strict now

* handle requirements as in current paradox

* documentation

* small correction in doc

* document

* fix in examples

* fix in examples II

* document domain_-functions

* document()

* clean up documentation

* document()

* some more small doc fixes

* document()

---------

Co-authored-by: mb706 <mlr.developer@mb706.com>
  • Loading branch information
mllg and mb706 authored Feb 28, 2024
1 parent 9738e56 commit 5a353d9
Show file tree
Hide file tree
Showing 111 changed files with 4,210 additions and 3,936 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,12 @@ $RECYCLE.BIN/
!.vscode/extensions.json
*.code-workspace
.vscode

# Autosaves and Temp files
.#*
*~
\#*#
*.swp

README.html
cran-comments\.md
14 changes: 8 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ Type: Package
Package: paradox
Title: Define and Work with Parameter Spaces for Complex
Algorithms
Version: 0.11.1-9000
Version: 1.0.0
Authors@R:
c(person(given = "Michel",
family = "Lang",
role = c("cre", "aut"),
role = "aut",
email = "michellang@gmail.com",
comment = c(ORCID = "0000-0001-9754-0393")),
person(given = "Bernd",
Expand All @@ -26,7 +26,7 @@ Authors@R:
comment = c(ORCID = "0000-0003-3269-2307")),
person(given = "Martin",
family = "Binder",
role = "aut",
role = c("aut", "cre"),
email = "mlr.developer@mb706.com"),
person(given = "Marc",
family = "Becker",
Expand Down Expand Up @@ -66,8 +66,9 @@ VignetteBuilder: knitr
Collate:
'Condition.R'
'Design.R'
'Domain.R'
'Domain_methods.R'
'NoDefault.R'
'Param.R'
'ParamDbl.R'
'ParamFct.R'
'ParamInt.R'
Expand All @@ -82,13 +83,14 @@ Collate:
'SamplerUnif.R'
'asserts.R'
'default_values.R'
'helper.R'
'domain.R'
'generate_design_grid.R'
'generate_design_lhs.R'
'generate_design_random.R'
'generate_design_sobol.R'
'helper.R'
'ps.R'
'ps_replicate.R'
'ps_union.R'
'reexports.R'
'to_tune.R'
'zzz.R'
66 changes: 57 additions & 9 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,8 +1,52 @@
# Generated by roxygen2: do not edit by hand

S3method(as.data.table,Param)
S3method("$",Constructor)
S3method(as.data.table,ParamSet)
S3method(c,ParamSet)
S3method(condition_as_string,Condition)
S3method(condition_test,CondAnyOf)
S3method(condition_test,CondEqual)
S3method(default_values,ParamSet)
S3method(domain_check,ParamDbl)
S3method(domain_check,ParamFct)
S3method(domain_check,ParamInt)
S3method(domain_check,ParamLgl)
S3method(domain_check,ParamUty)
S3method(domain_is_bounded,Domain)
S3method(domain_is_bounded,ParamDbl)
S3method(domain_is_bounded,ParamFct)
S3method(domain_is_bounded,ParamInt)
S3method(domain_is_bounded,ParamLgl)
S3method(domain_is_bounded,ParamUty)
S3method(domain_is_categ,Domain)
S3method(domain_is_categ,ParamDbl)
S3method(domain_is_categ,ParamFct)
S3method(domain_is_categ,ParamInt)
S3method(domain_is_categ,ParamLgl)
S3method(domain_is_categ,ParamUty)
S3method(domain_is_number,Domain)
S3method(domain_is_number,ParamDbl)
S3method(domain_is_number,ParamFct)
S3method(domain_is_number,ParamInt)
S3method(domain_is_number,ParamLgl)
S3method(domain_is_number,ParamUty)
S3method(domain_nlevels,Domain)
S3method(domain_nlevels,ParamDbl)
S3method(domain_nlevels,ParamFct)
S3method(domain_nlevels,ParamInt)
S3method(domain_nlevels,ParamLgl)
S3method(domain_nlevels,ParamUty)
S3method(domain_qunif,Domain)
S3method(domain_qunif,ParamDbl)
S3method(domain_qunif,ParamFct)
S3method(domain_qunif,ParamInt)
S3method(domain_qunif,ParamLgl)
S3method(domain_qunif,ParamUty)
S3method(domain_sanitize,Domain)
S3method(domain_sanitize,ParamDbl)
S3method(domain_sanitize,ParamInt)
S3method(format,Condition)
S3method(print,Condition)
S3method(print,Domain)
S3method(print,FullTuneToken)
S3method(print,ObjectTuneToken)
Expand All @@ -13,15 +57,8 @@ export(CondEqual)
export(Condition)
export(Design)
export(NO_DEF)
export(NoDefault)
export(Param)
export(ParamDbl)
export(ParamFct)
export(ParamInt)
export(ParamLgl)
export(ParamSet)
export(ParamSetCollection)
export(ParamUty)
export(Sampler)
export(Sampler1D)
export(Sampler1DCateg)
Expand All @@ -32,9 +69,18 @@ export(SamplerHierarchical)
export(SamplerJointIndep)
export(SamplerUnif)
export(as.data.table)
export(assert_param)
export(assert_param_set)
export(condition_as_string)
export(default_values)
export(domain_assert)
export(domain_check)
export(domain_is_bounded)
export(domain_is_categ)
export(domain_is_number)
export(domain_nlevels)
export(domain_qunif)
export(domain_sanitize)
export(domain_test)
export(generate_design_grid)
export(generate_design_lhs)
export(generate_design_random)
Expand All @@ -45,6 +91,8 @@ export(p_int)
export(p_lgl)
export(p_uty)
export(ps)
export(ps_replicate)
export(ps_union)
export(psc)
export(to_tune)
import(checkmate)
Expand Down
10 changes: 8 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# paradox 0.11.1-9000

# paradox 0.12.0
* Removed `Param` objects. `ParamSet` now uses a `data.table` internally; individual parameters are more like `Domain` objects now. `ParamSets` should be constructed using the `ps()` shorthand and `Domain` objects. This entails the following major changes:
* `ParamSet` now supports `extra_trafo` natively; it behaves like `.extra_trafo` of the `ps()` call.
* `ParamSet` has `$constraint`
* `ParamSet` objects are now less mutable. The only properties that can be changed are `values`, `tags`, `deps`, `constraint` and `extra_trafo`.
* `ParamSet$is_bounded` is a vector with an entry for each parameter. Use `$all_bounded` for the previous behavior.
* `Condition` objects are now S3 objects and can be constructed with `CondEqual()` and `CondAnyOf()`, instead of `CondXyz$new()`. (It is recommended to use the `Domain` interface for conditions, which has not changed)
* `ParamSet` has new fields `$is_logscale`, `$has_trafo_param` (per-param), and `$has_trafo_param` (scalar for the whole set).
* Added a vignette which was previously a chapter in the `mlr3book`

# paradox 0.11.1
Expand Down
167 changes: 96 additions & 71 deletions R/Condition.R
Original file line number Diff line number Diff line change
@@ -1,88 +1,113 @@
# -- class methods

#' @describeIn Condition
#'
#' Used internally. Tests whether a value satisfies a given condition.
#' Vectorizes when `x` is atomic.
#'
#' @param cond (`Condition`)\cr
#' `Condition` to use
#' @param x (`any`)\cr
#' Value to test
condition_test = function(cond, x) {
UseMethod("condition_test")
}

#' @describeIn Condition
#'
#' Used internally. Returns a string that represents the condition for pretty
#' printing, in the form `"<lhs> <relation> <rhs>"`, e.g. `"x == 3"` or
#' `"param %in% {1, 2, 10}"`.
#'
#' @param cond (`Condition`)\cr
#' `Condition` to use
#' @param lhs_chr (`character(1)`)\cr
#' Symbolic representation to use for `<lhs>` in the returned string.
#' @export
condition_as_string = function(cond, lhs_chr = "x") {
assert_string(lhs_chr)
UseMethod("condition_as_string")
}

# -- Condition

#' @title Dependency Condition
#'
#' @description
#' Condition object, to specify the condition in a dependency.
#'
#' @param rhs (`any`)\cr
#' Right-hand-side of the condition.
#' @param condition_format_string (`character(1)`)\cr
#' Format-string for representing the condition when pretty-printing
#' in [`condition_as_string()`].
#' Should contain two `%s`, as it is used in an `sprintf()`-call with
#' two further string values.
#'
#' @section Currently implemented simple conditions:
#' * `CondEqual$new(rhs)` \cr
#' Parent must be equal to `rhs`.
#' * `CondAnyOf$new(rhs)` \cr
#' Parent must be any value of `rhs`.
#' * `CondEqual(rhs)` \cr
#' Value must be equal to `rhs`.
#' * `CondAnyOf(rhs)` \cr
#' Value must be any value of `rhs`.
#'
#' @aliases CondEqual CondAnyOf
#' @export
Condition = R6Class("Condition",
public = list(
#' @field type (`character(1)`)\cr
#' Name / type of the condition.
type = NULL,
#' @field rhs (`any`)\cr
#' Right-hand-side of the condition.
rhs = NULL,
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
#'
#' @param type (`character(1)`)\cr
#' Name / type of the condition.
#' @param rhs (`any`)\cr
#' Right-hand-side of the condition.
initialize = function(type, rhs) {
self$type = assert_string(type)
self$rhs = rhs
},
Condition = function(rhs, condition_format_string) {
assert_string(condition_format_string)
structure(list(rhs = rhs, condition_format_string = condition_format_string), class = "Condition")
}

#' @description
#' Checks if condition is satisfied.
#' Called on a vector of parent param values.
#'
#' @param x (`vector()`).
#' @return `logical(1)`.
test = function(x) stop("abstract"),
#' @export
condition_as_string.Condition = function(cond, lhs_chr = "x") {
sprintf(cond$condition_format_string, lhs_chr, str_collapse(cond$rhs))
}

#' @export
format.Condition = function(x, ...) {
sprintf("<Condition:%s>", class(x)[[1L]])
}

#' @export
print.Condition = function(x, ...) {
catf("%s: %s", class(x)[[1L]], condition_as_string(x))
}

#' @description
#' Conversion helper for print outputs.
#' @param lhs_chr (`character(1)`)
as_string = function(lhs_chr = "x") {
sprintf("%s %s %s", lhs_chr, self$type, str_collapse(self$rhs))
},
# -- CondEqual

#' @description
#' Helper for print outputs.
#' @param ... (ignored).
format = function(...) {
sprintf("<%s:%s>", class(self)[1L], self$type)
},
#' @export
CondEqual = function(rhs) {
assert_atomic(rhs, any.missing = FALSE, len = 1)
cond = Condition(rhs, "%s == %s")
set_class(cond, c("CondEqual", class(cond)))
}

#' @description
#' Printer.
#'
#' @param ... (ignored).
print = function(...) {
catf("%s: %s", class(self)[1L], self$as_string())
}
),
)
#' @export
condition_test.CondEqual = function(cond, x) {
!is.na(x) & x == cond$rhs
}

#' @export
CondEqual = R6Class("CondEqual", inherit = Condition,
public = list(
initialize = function(rhs) {
assert_atomic(rhs, any.missing = FALSE, len = 1)
super$initialize("equal", rhs)
},
test = function(x) !is.na(x) & x == self$rhs,
as_string = function(lhs_chr = "x") sprintf("%s = %s", lhs_chr, as.character(self$rhs))
)
)
CondAnyOf = function(rhs) {
assert_atomic(rhs, any.missing = FALSE, min.len = 1, unique = TRUE)
cond = Condition(rhs, "%s %%in%% {%s}")
set_class(cond, c("CondAnyOf", class(cond)))
}

#' @export
CondAnyOf = R6Class("CondAnyOf", inherit = Condition,
public = list(
initialize = function(rhs) {
assert_atomic(rhs, any.missing = FALSE, min.len = 1, unique = TRUE)
super$initialize("anyof", rhs)
},
test = function(x) !is.na(x) & x %in% self$rhs,
as_string = function(lhs_chr = "x") sprintf("%s \u2208 {%s}", lhs_chr, str_collapse(self$rhs))
)
)
condition_test.CondAnyOf = function(cond, x) {
!is.na(x) & x %in% cond$rhs
}

# FIXME: the following makes `condition$new()` possible for paradox transition
# should give a deprecated warning at some point.
#' @export
`$.Constructor` = function(e1, e2) {
if (!identical(e2, "new")) {
stop("only 'new' element can be accessed.")
} else {
e1
}
}

CondEqual = structure(CondEqual, class = c("Constructor", "function"))
CondAnyOf = structure(CondAnyOf, class = c("Constructor", "function"))
8 changes: 4 additions & 4 deletions R/Design.R
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Design = R6Class("Design",
xs = map(xs, function(x) Filter(Negate(is_scalar_na), x))
}
if (ps$has_trafo && trafo) {
xs = map(xs, function(x) ps$trafo(x, ps))
xs = map(xs, function(x) ps$trafo(x))
}
return(xs)
}
Expand All @@ -103,14 +103,14 @@ Design = R6Class("Design",
graph = graph[, list("parents" = list(unlist(get("parents")))), by = "id"]
topo = topo_sort(graph)
pids_sorted = topo$id
storage_types = ps$storage_type
for (param_id in pids_sorted) {
param = ps$params[[param_id]]
dd = ps$deps[get("id") == param_id, ]
for (j in seq_row(dd)) {
pcol = self$data[[dd$on[j]]]
# we are ok if parent was active and cond on parent is OK
not_ok = which(is.na(pcol) | !dd$cond[[j]]$test(pcol))
set(self$data, not_ok, j = param_id, value = as_type(NA, param$storage_type))
not_ok = which(is.na(pcol) | !condition_test(dd$cond[[j]], pcol))
set(self$data, not_ok, j = param_id, value = as_type(NA, storage_types[[param_id]]))
}
}
}
Expand Down
Loading

0 comments on commit 5a353d9

Please sign in to comment.