diff --git a/DESCRIPTION b/DESCRIPTION index 55d0869ea..16e8a09b6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -61,5 +61,5 @@ LazyData: yes Encoding: UTF-8 ByteCompile: yes Version: 1.1.3 -RoxygenNote: 6.0.1 +RoxygenNote: 6.1.1 VignetteBuilder: knitr diff --git a/R/evalTargetFun.R b/R/evalTargetFun.R index 125fe33ee..b41a7c0b6 100644 --- a/R/evalTargetFun.R +++ b/R/evalTargetFun.R @@ -25,60 +25,65 @@ evalTargetFun.OptState = function(opt.state, xs, extras) { # short names and so on nevals = length(xs) ny = control$n.objectives + imputeY = control$impute.y.fun # trafo X points xs.trafo = lapply(xs, trafoValue, par = par.set) - # handle noisy instances - if (isTRUE(control$noisy.instances > 1L)) { - nevals = nevals * control$noisy.instances - xs = rep(xs, each = control$noisy.instances) - extras = rep(extras, each = control$noisy.instances) - if (!control$noisy.self.replicating) { - xs.trafo = rep(xs.trafo, each = control$noisy.instances) - if (!is.na(control$noisy.instance.param)) { - inst.param = lapply(seq_len(control$noisy.instances), function(x) setNames(list(x), control$noisy.instance.param)) - xs.trafo = Map(c, xs.trafo, inst.param) - } - } - } - - - num.format = control$output.num.format - num.format.string = paste("%s = ", num.format, sep = "") - dobs = ensureVector(asInteger(getOptStateLoop(opt.state)), n = nevals, cl = "integer") - imputeY = control$impute.y.fun - - # function to measure of fun call - wrapFun = function(x) { - st = proc.time() - y = do.call(getOptProblemFun(opt.problem), insert(list(x = x), getOptProblemMoreArgs(opt.problem))) - user.extras = list() + wrapFun = function(x) { + st = proc.time() + y = do.call(getOptProblemFun(opt.problem), insert(list(x = x), getOptProblemMoreArgs(opt.problem))) + user.extras = list() # here we extract additional stuff which the user wants to log in the opt path - if (hasAttributes(y, "extras")) { - user.extras = attr(y, "extras") - y = setAttribute(y, "extras", NULL) - } - if (!is.null(control$noisy.instance.param) && !is.na(control$noisy.instance.param) && !control$noisy.self.replicating) { - user.extras = c(user.extras, x[control$noisy.instance.param]) - } - st = proc.time() - st - list(y = y, time = st[3], user.extras = user.extras) + if (hasAttributes(y, "extras")) { + user.extras = attr(y, "extras") + y = setAttribute(y, "extras", NULL) + } + if (!is.null(control$noisy.instance.param) && !is.na(control$noisy.instance.param) && !control$noisy.self.replicating) { + user.extras = c(user.extras, x[control$noisy.instance.param]) } + st = proc.time() - st + list(y = y, time = st[3], user.extras = user.extras) + } # do we have a valid y object? isYValid = function(y) { - !is.error(y) && testNumeric(y, len = ny, any.missing = FALSE, finite = TRUE) + if (!isTRUE(control$noisy.self.replicating)) { + len = NULL + } else { + len = ny + } + !is.error(y) && testNumeric(y, len = len, any.missing = FALSE, finite = TRUE) } # return error objects if we impute - res = parallelMap(wrapFun, xs.trafo, level = "mlrMBO.feval", - impute.error = if (is.null(imputeY)) NULL else identity) + res = parallelMap(wrapFun, xs.trafo, level = "mlrMBO.feval", impute.error = if (is.null(imputeY)) NULL else identity) + + # handle noisy instances + if (isTRUE(control$noisy.self.replicating)) { + nevals.each = lengths(extractSubList(res, "y", simplify = FALSE)) + nevals = sum(nevals.each) + + # replications for opt path stuff + repVec = function(x, fun = replicate) { + unlist(Map(fun, nevals.each, x, simplify = FALSE), recursive = FALSE) + } + xs = repVec(xs) + xs.trafo = repVec(xs.trafo) + + #set extras to NA that are only important for the first point + setNAfun = function(n, xs, ...) { + res = replicate(n = n, expr = xs, ...) + res[-1] = lapply(res[-1], function(x) { + x[c("train.time", "error.model", "propose.time")] = NA + x + }) + res + } + extras = repVec(extras, setNAfun) - # handle noisy instances of self.replicating functions - if (isTRUE(control$noisy.instances > 1L) && control$noisy.self.replicating) { - xs.trafo = rep(xs.trafo, each = control$noisy.instances) + # handle result list res = lapply(res, function(r) { if (is.error(r)) { rep(list(r), control$noisy.instances) @@ -91,6 +96,9 @@ evalTargetFun.OptState = function(opt.state, xs, extras) { res = unlist(res, recursive = FALSE) } + num.format.string = paste("%s = ", control$output.num.format, sep = "") + dobs = ensureVector(asInteger(getOptStateLoop(opt.state)), n = nevals, cl = "integer") + # loop evals and to some post-processing for (i in seq_len(nevals)) { r = res[[i]]; x = xs[[i]]; x.trafo = xs.trafo[[i]]; dob = dobs[i] diff --git a/R/setMBOControlNoisy.R b/R/setMBOControlNoisy.R index 7bd80cbc0..91383f81b 100644 --- a/R/setMBOControlNoisy.R +++ b/R/setMBOControlNoisy.R @@ -2,29 +2,17 @@ #' @description #' Extends an MBO control object with options for multipoint proposal. #' @template arg_control -#' @param instances [\code{integer(1)}]\cr -#' How many instances of one parameter will be calculated? -#' @param instance.param [\code{character(1)}]\cr -#' What is the name of the function param that defines the instance? #' @param self.replicating [\code{logical(1)}]\cr #' TRUE if the function returns a vector of noisy results for one input. Then \code{instances} specifies the length of the result we expect. #' @return [\code{\link{MBOControl}}]. #' @family MBOControl #' @export -setMBOControlNoisy = function(control, - instances = NULL, - instance.param = NULL, - self.replicating = NULL) { +setMBOControlNoisy = function(control, self.replicating) { assertClass(control, "MBOControl") - control$noisy.instances = assertInt(instances, lower = 1L, null.ok = TRUE, na.ok = FALSE) %??% control$noisy.instances - control$noisy.self.replicating = assertFlag(self.replicating, null.ok = TRUE, na.ok = FALSE) %??% control$noisy.self.replicating %??% FALSE - control$noisy.instance.param = assertString(instance.param, null.ok = TRUE, na.ok = TRUE) %??% control$noisy.instance.param %??% ifelse(control$noisy.self.replicating, "noisy.repl", NA_character_) - - if (control$noisy.self.replicating && control$noisy.instance.param != "noisy.repl") { - stop("You can not change the instance.param for self replicating functions.") - } + control$noisy.self.replicating = assertFlag(self.replicating %??% control$noisy.self.replicating %??% TRUE, na.ok = FALSE) + control$noisy.instance.param = "noisy.repl" return(control) }