diff --git a/R/AcqFunctionMulti.R b/R/AcqFunctionMulti.R index 7bdb66ae..5b9543e3 100644 --- a/R/AcqFunctionMulti.R +++ b/R/AcqFunctionMulti.R @@ -10,6 +10,15 @@ #' Wrapping multiple [AcqFunction]s resulting in a multi-objective acquisition function composed of the individual ones. #' Note that the optimization direction of each wrapped acquisition function is corrected for maximization. #' +#' For each acquisition function, the same [Surrogate] must be used. +#' If acquisition functions passed during construction already have been initialized with a surrogate, it is checked whether +#' the surrogate is the same for all acquisition functions. +#' If acquisition functions have not been initialized with a surrogate, the surrogate passed during construction or lazy initialization +#' will be used for all acquisition functions. +#' +#' For optimization, [AcqOptimizer] can be used as for any other [AcqFunction], however, the [bbotk::Optimizer] wrapped within the [AcqOptimizer] +#' must support multi-objective optimization as indicated via the `multi-crit` property. +#' #' @family Acquisition Function #' @export #' @examples @@ -159,7 +168,7 @@ AcqFunctionMulti = R6Class("AcqFunctionMulti", }, #' @field acq_functions (list of [AcqFunction])\cr - #' Points to the list of the individual acqusition functions. + #' Points to the list of the individual acquisition functions. acq_functions = function(rhs) { if (!missing(rhs) && !identical(rhs, private$.acq_functions)) { stop("$acq_functions is read-only.") @@ -168,7 +177,7 @@ AcqFunctionMulti = R6Class("AcqFunctionMulti", }, #' @field acq_function_ids (character())\cr - #' Points to the ids of the individual acqusition functions. + #' Points to the ids of the individual acquisition functions. acq_function_ids = function(rhs) { if (!missing(rhs) && !identical(rhs, private$.acq_function_ids)) { stop("$acq_function_ids is read-only.") @@ -202,6 +211,13 @@ AcqFunctionMulti = R6Class("AcqFunctionMulti", set(values, j = j, value = - values[[j]]) } values + }, + + deep_clone = function(name, value) { + switch(name, + .acq_functions = value$clone(deep = TRUE), + value + ) } ) ) diff --git a/R/AcqOptimizer.R b/R/AcqOptimizer.R index 7c895940..3eec8339 100644 --- a/R/AcqOptimizer.R +++ b/R/AcqOptimizer.R @@ -9,10 +9,13 @@ #' \item{`n_candidates`}{`integer(1)`\cr #' Number of candidate points to propose. #' Note that this does not affect how the acquisition function itself is calculated (e.g., setting `n_candidates > 1` will not -#' result in computing the q- or multi-Expected Improvement) but rather the top `n-candidates` are selected from the +#' result in computing the q- or multi-Expected Improvement) but rather the top `n_candidates` are selected from the #' [bbotk::Archive] of the acquisition function [bbotk::OptimInstance]. #' Note that setting `n_candidates > 1` is usually not a sensible idea but it is still supported for experimental reasons. -#' Default is `1`.} +#' Note that in the case of the acquisition function [bbotk::OptimInstance] being multi-criteria, due to using an [AcqFunctionMulti], +#' selection of the best candidates is performed via non-dominated-sorting. +#' Default is `1`. +#' } #' \item{`logging_level`}{`character(1)`\cr #' Logging level during the acquisition function optimization. #' Can be `"fatal"`, `"error"`, `"warn"`, `"info"`, `"debug"` or `"trace"`. @@ -20,24 +23,26 @@ #' } #' \item{`warmstart`}{`logical(1)`\cr #' Should the acquisition function optimization be warm-started by evaluating the best point(s) present in the [bbotk::Archive] of -#' the actual [bbotk::OptimInstance]? +#' the actual [bbotk::OptimInstance] (which is contained in the archive of the [AcqFunction])? #' This is sensible when using a population based acquisition function optimizer, e.g., local search or mutation. #' Default is `FALSE`. +#' Note that in the case of the [bbotk::OptimInstance] being multi-criteria, selection of the best point(s) is performed via non-dominated-sorting. #' } #' \item{`warmstart_size`}{`integer(1) | "all"`\cr -#' Number of best points selected from the [bbotk::Archive] that are to be used for warm starting. -#' Can also be "all" to use all available points. +#' Number of best points selected from the [bbotk::Archive] of the actual [bbotk::OptimInstance] that are to be used for warm starting. +#' Can either be an integer or "all" to use all available points. #' Only relevant if `warmstart = TRUE`. #' Default is `1`. #' } #' \item{`skip_already_evaluated`}{`logical(1)`\cr -#' It can happen that the candidate resulting of the acquisition function optimization was already evaluated in a previous -#' iteration. Should this candidate proposal be ignored and the next best point be selected as a candidate? +#' It can happen that the candidate(s) resulting of the acquisition function optimization were already evaluated on the actual [bbotk::OptimInstance]. +#' Should such candidate proposals be ignored and only candidates that were yet not evaluated be considered? #' Default is `TRUE`. #' } #' \item{`catch_errors`}{`logical(1)`\cr #' Should errors during the acquisition function optimization be caught and propagated to the `loop_function` which can then handle #' the failed acquisition function optimization appropriately by, e.g., proposing a randomly sampled point for evaluation? +#' Setting this to `FALSE` can be helpful for debugging. #' Default is `TRUE`. #' } #' } @@ -123,6 +128,8 @@ AcqOptimizer = R6Class("AcqOptimizer", #' @description #' Helper for print outputs. + #' + #' @return (`character(1)`). format = function() { sprintf("<%s>", class(self)[1L]) }, @@ -139,7 +146,7 @@ AcqOptimizer = R6Class("AcqOptimizer", #' @description #' Optimize the acquisition function. #' - #' @return [data.table::data.table()] with 1 row per optimum and x as columns. + #' @return [data.table::data.table()] with 1 row per candidate. optimize = function() { is_multi_acq_function = self$acq_function$codomain$length > 1L diff --git a/R/ResultAssigner.R b/R/ResultAssigner.R index e558ac0d..e6f6997f 100644 --- a/R/ResultAssigner.R +++ b/R/ResultAssigner.R @@ -36,6 +36,8 @@ ResultAssigner = R6Class("ResultAssigner", #' @description #' Helper for print outputs. + #' + #' @return (`character(1)`). format = function() { sprintf("<%s>", class(self)[1L]) }, diff --git a/R/Surrogate.R b/R/Surrogate.R index b9e0dd17..a3c6e2c0 100644 --- a/R/Surrogate.R +++ b/R/Surrogate.R @@ -69,6 +69,8 @@ Surrogate = R6Class("Surrogate", #' @description #' Helper for print outputs. + #' + #' @return (`character(1)`). format = function() { sprintf("<%s>", class(self)[1L]) }, diff --git a/man/AcqOptimizer.Rd b/man/AcqOptimizer.Rd index b4c143b1..035c6d6e 100644 --- a/man/AcqOptimizer.Rd +++ b/man/AcqOptimizer.Rd @@ -13,10 +13,13 @@ Wraps an \link[bbotk:Optimizer]{bbotk::Optimizer} and \link[bbotk:Terminator]{bb \item{\code{n_candidates}}{\code{integer(1)}\cr Number of candidate points to propose. Note that this does not affect how the acquisition function itself is calculated (e.g., setting \code{n_candidates > 1} will not -result in computing the q- or multi-Expected Improvement) but rather the top \code{n-candidates} are selected from the +result in computing the q- or multi-Expected Improvement) but rather the top \code{n_candidates} are selected from the \link[bbotk:Archive]{bbotk::Archive} of the acquisition function \link[bbotk:OptimInstance]{bbotk::OptimInstance}. Note that setting \code{n_candidates > 1} is usually not a sensible idea but it is still supported for experimental reasons. -Default is \code{1}.} +Note that in the case of the acquisition function \link[bbotk:OptimInstance]{bbotk::OptimInstance} being multi-criteria, due to using an \link{AcqFunctionMulti}, +selection of the best candidates is performed via non-dominated-sorting. +Default is \code{1}. +} \item{\code{logging_level}}{\code{character(1)}\cr Logging level during the acquisition function optimization. Can be \code{"fatal"}, \code{"error"}, \code{"warn"}, \code{"info"}, \code{"debug"} or \code{"trace"}. @@ -24,24 +27,26 @@ Default is \code{"warn"}, i.e., only warnings are logged. } \item{\code{warmstart}}{\code{logical(1)}\cr Should the acquisition function optimization be warm-started by evaluating the best point(s) present in the \link[bbotk:Archive]{bbotk::Archive} of -the actual \link[bbotk:OptimInstance]{bbotk::OptimInstance}? +the actual \link[bbotk:OptimInstance]{bbotk::OptimInstance} (which is contained in the archive of the \link{AcqFunction})? This is sensible when using a population based acquisition function optimizer, e.g., local search or mutation. Default is \code{FALSE}. +Note that in the case of the \link[bbotk:OptimInstance]{bbotk::OptimInstance} being multi-criteria, selection of the best point(s) is performed via non-dominated-sorting. } \item{\code{warmstart_size}}{\code{integer(1) | "all"}\cr -Number of best points selected from the \link[bbotk:Archive]{bbotk::Archive} that are to be used for warm starting. -Can also be "all" to use all available points. +Number of best points selected from the \link[bbotk:Archive]{bbotk::Archive} of the actual \link[bbotk:OptimInstance]{bbotk::OptimInstance} that are to be used for warm starting. +Can either be an integer or "all" to use all available points. Only relevant if \code{warmstart = TRUE}. Default is \code{1}. } \item{\code{skip_already_evaluated}}{\code{logical(1)}\cr -It can happen that the candidate resulting of the acquisition function optimization was already evaluated in a previous -iteration. Should this candidate proposal be ignored and the next best point be selected as a candidate? +It can happen that the candidate(s) resulting of the acquisition function optimization were already evaluated on the actual \link[bbotk:OptimInstance]{bbotk::OptimInstance}. +Should such candidate proposals be ignored and only candidates that were yet not evaluated be considered? Default is \code{TRUE}. } \item{\code{catch_errors}}{\code{logical(1)}\cr Should errors during the acquisition function optimization be caught and propagated to the \code{loop_function} which can then handle the failed acquisition function optimization appropriately by, e.g., proposing a randomly sampled point for evaluation? +Setting this to \code{FALSE} can be helpful for debugging. Default is \code{TRUE}. } } @@ -152,6 +157,9 @@ Helper for print outputs. \if{html}{\out{
}}\preformatted{AcqOptimizer$format()}\if{html}{\out{
}} } +\subsection{Returns}{ +(\code{character(1)}). +} } \if{html}{\out{
}} \if{html}{\out{}} @@ -176,7 +184,7 @@ Optimize the acquisition function. } \subsection{Returns}{ -\code{\link[data.table:data.table]{data.table::data.table()}} with 1 row per optimum and x as columns. +\code{\link[data.table:data.table]{data.table::data.table()}} with 1 row per candidate. } } \if{html}{\out{
}} diff --git a/man/ResultAssigner.Rd b/man/ResultAssigner.Rd index a6f5485e..01e0211a 100644 --- a/man/ResultAssigner.Rd +++ b/man/ResultAssigner.Rd @@ -89,6 +89,9 @@ Helper for print outputs. \if{html}{\out{
}}\preformatted{ResultAssigner$format()}\if{html}{\out{
}} } +\subsection{Returns}{ +(\code{character(1)}). +} } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/Surrogate.Rd b/man/Surrogate.Rd index 73ed916a..db339406 100644 --- a/man/Surrogate.Rd +++ b/man/Surrogate.Rd @@ -150,6 +150,9 @@ Helper for print outputs. \if{html}{\out{
}}\preformatted{Surrogate$format()}\if{html}{\out{
}} } +\subsection{Returns}{ +(\code{character(1)}). +} } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/mlr_acqfunctions_multi.Rd b/man/mlr_acqfunctions_multi.Rd index 27c99a3e..344632ff 100644 --- a/man/mlr_acqfunctions_multi.Rd +++ b/man/mlr_acqfunctions_multi.Rd @@ -7,6 +7,15 @@ \description{ Wrapping multiple \link{AcqFunction}s resulting in a multi-objective acquisition function composed of the individual ones. Note that the optimization direction of each wrapped acquisition function is corrected for maximization. + +For each acquisition function, the same \link{Surrogate} must be used. +If acquisition functions passed during construction already have been initialized with a surrogate, it is checked whether +the surrogate is the same for all acquisition functions. +If acquisition functions have not been initialized with a surrogate, the surrogate passed during construction or lazy initialization +will be used for all acquisition functions. + +For optimization, \link{AcqOptimizer} can be used as for any other \link{AcqFunction}, however, the \link[bbotk:Optimizer]{bbotk::Optimizer} wrapped within the \link{AcqOptimizer} +must support multi-objective optimization as indicated via the \code{multi-crit} property. } \section{Dictionary}{ @@ -80,10 +89,10 @@ Other Acquisition Function: Surrogate.} \item{\code{acq_functions}}{(list of \link{AcqFunction})\cr -Points to the list of the individual acqusition functions.} +Points to the list of the individual acquisition functions.} \item{\code{acq_function_ids}}{(character())\cr -Points to the ids of the individual acqusition functions.} +Points to the ids of the individual acquisition functions.} } \if{html}{\out{}} }