From 10deabed4d3e213a3e4e5c0b52db9f85a68d998b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lennart=20Sch=C3=A4permeier?= Date: Sat, 29 Jan 2022 11:59:18 +0100 Subject: [PATCH] checkmate for run_mole --- R/mole.R | 62 +++++++++++++++++++++++++++++++++++++++++++++---- man/run_mole.Rd | 23 ++++++++++++++---- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/R/mole.R b/R/mole.R index f7906bf..af75fdf 100644 --- a/R/mole.R +++ b/R/mole.R @@ -1,4 +1,18 @@ #' Execute MOLE algorithm +#' +#' Calling \code{run_mole} executes a run of the MOLE algorithm with the given parameter setting. +#' +#' The most important parameters to consider are: +#' +#' \itemize{ +#' \item \code{fn}: The function to optimize +#' \item \code{starting_points}: Pre-defined starting points for MOLE +#' \item \code{descent_step_max}, \code{explore_step_max}: Here it may be beneficial to deviate from the +#' default setting of \code{1e-1}. A reasonable choice in many situations is 1/100 of the diagonal +#' of the search space. +#' \item \code{refine_hv_target}: If post-processing for HV optimization should be used, +#' set this to the target value for the normalized hypervolume. +#' } #' #' @param fn Bi-objective \code{smoof} function to optimize #' @param starting_points Matrix of starting points to pass to MOLE @@ -16,7 +30,7 @@ #' @param explore_angle_max Maximal admissible angle between consecutive steps for exploration along locally efficient set #' @param explore_scale_factor Multiplicative factor by which to scale consecutive descent steps #' @param refine_after_nstarts Number of starting points to fully evaluate before starting refinement -#' @param refine_hv_target Target normalized Hypervolume gap +#' @param refine_hv_target Normalized Hypervolume gap target #' @param custom_descent_fn Custom descent function implemented in R (optional) #' @param lower Lower box constraints, if different than specified in \code{fn} (optional) #' @param upper Lower box constraints, if different than specified in \code{fn} (optional) @@ -44,19 +58,22 @@ run_mole <- function(fn, descent_step_max = 1e-1, descent_scale_factor = 2, descent_armijo_factor = 1e-4, - descent_history_size = 100, - descent_max_iter = 1000, + descent_history_size = 100L, + descent_max_iter = 1000L, explore_step_min = 1e-4, explore_step_max = 1e-1, explore_angle_max = 45, explore_scale_factor = 2, - refine_after_nstarts = 10, + refine_after_nstarts = 10L, refine_hv_target = 2e-5, custom_descent_fn = NULL, lower = NULL, upper = NULL, max_budget = Inf, logging = "info") { + + # ==== Configure defaults if values are missing ==== + if (is.null(lower)) { lower <- smoof::getLowerBoxConstraints(fn) } @@ -64,7 +81,44 @@ run_mole <- function(fn, if (is.null(upper)) { upper <- smoof::getUpperBoxConstraints(fn) } + + # ==== Checkmate ==== + + checkmate::assert_class(fn, "smoof_function") + n_dimensions <- smoof::getNumberOfParameters(fn) + checkmate::assert_true(smoof::getNumberOfObjectives(fn) == 2L) + + checkmate::assert_matrix(starting_points, any.missing = FALSE, ncols = n_dimensions) + + checkmate::assert_numeric(epsilon_gradient, lower = .Machine$double.eps, finite = TRUE) + + checkmate::assert_numeric(descent_direction_min, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_numeric(descent_step_min, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_numeric(descent_step_max, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_true(descent_step_min <= descent_step_max) + checkmate::assert_numeric(descent_scale_factor, lower = 1 + .Machine$double.eps, finite = TRUE) + checkmate::assert_numeric(descent_armijo_factor, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_integerish(descent_history_size, lower = 0) + checkmate::assert_integerish(descent_max_iter, lower = 0) + + checkmate::assert_numeric(explore_step_min, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_numeric(explore_step_max, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_true(explore_step_min <= explore_step_max) + checkmate::assert_numeric(explore_angle_max, lower = .Machine$double.eps, finite = TRUE) + checkmate::assert_numeric(explore_scale_factor, lower = 1 + .Machine$double.eps, finite = TRUE) + checkmate::assert_integerish(refine_after_nstarts, lower = 1) + checkmate::assert_numeric(refine_hv_target, upper = 1) + checkmate::assert_function(custom_descent_fn, null.ok = TRUE) + checkmate::assert_vector(lower, len = n_dimensions, any.missing = FALSE) + checkmate::assert_vector(upper, len = n_dimensions, any.missing = FALSE) + checkmate::assert_true(all(lower <= upper)) + + checkmate::assert_numeric(max_budget, lower = 1) + checkmate::assert_choice(logging, c("none", "info", "debug")) + + # ==== Call MOLE implementation ==== + run_mole_cpp(fn = fn, starting_points = starting_points, lower = lower, diff --git a/man/run_mole.Rd b/man/run_mole.Rd index 277add8..ef2d2c7 100644 --- a/man/run_mole.Rd +++ b/man/run_mole.Rd @@ -14,13 +14,13 @@ run_mole( descent_step_max = 0.1, descent_scale_factor = 2, descent_armijo_factor = 1e-04, - descent_history_size = 100, - descent_max_iter = 1000, + descent_history_size = 100L, + descent_max_iter = 1000L, explore_step_min = 1e-04, explore_step_max = 0.1, explore_angle_max = 45, explore_scale_factor = 2, - refine_after_nstarts = 10, + refine_after_nstarts = 10L, refine_hv_target = 2e-05, custom_descent_fn = NULL, lower = NULL, @@ -62,7 +62,7 @@ run_mole( \item{refine_after_nstarts}{Number of starting points to fully evaluate before starting refinement} -\item{refine_hv_target}{Target normalized Hypervolume gap} +\item{refine_hv_target}{Normalized Hypervolume gap target} \item{custom_descent_fn}{Custom descent function implemented in R (optional)} @@ -82,7 +82,20 @@ List containing: } } \description{ -Execute MOLE algorithm +Calling \code{run_mole} executes a run of the MOLE algorithm with the given parameter setting. +} +\details{ +The most important parameters to consider are: + +\itemize{ + \item \code{fn}: The function to optimize + \item \code{starting_points}: Pre-defined starting points for MOLE + \item \code{descent_step_max}, \code{explore_step_max}: Here it may be beneficial to deviate from the + default setting of \code{1e-1}. A reasonable choice in many situations is 1/100 of the diagonal + of the search space. + \item \code{refine_hv_target}: If post-processing for HV optimization should be used, + set this to the target value for the normalized hypervolume. +} } \examples{ fn <- makeAsparFunction()