Skip to content

Commit c825853

Browse files
authored
Merge pull request #288 from mlr-org/start_values
feat: allow custom start values for cmaes and nloptr
2 parents ae6cac6 + 748e49c commit c825853

File tree

7 files changed

+86
-20
lines changed

7 files changed

+86
-20
lines changed

R/OptimizerBatchCmaes.R

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
#' \describe{
1717
#' \item{`sigma`}{`numeric(1)`}
1818
#' \item{`start_values`}{`character(1)`\cr
19-
#' Create `random` start values or based on `center` of search space? In the
20-
#' latter case, it is the center of the parameters before a trafo is applied.}
19+
#' Create `"random"` start values or based on `"center"` of search space?
20+
#' In the latter case, it is the center of the parameters before a trafo is applied.
21+
#' If set to `"custom"`, the start values can be passed via the `start` parameter.}
22+
#' \item{`start`}{`numeric()`\cr
23+
#' Custom start values. Only applicable if `start_values` parameter is set to `"custom"`.}
2124
#' }
2225
#'
2326
#' For the meaning of the control parameters, see [adagio::pureCMAES()]. Note
@@ -70,10 +73,11 @@ OptimizerBatchCmaes = R6Class("OptimizerBatchCmaes",
7073
initialize = function() {
7174
param_set = ps(
7275
sigma = p_dbl(default = 0.5),
73-
start_values = p_fct(levels = c("random", "center"), tags = "required")
76+
start_values = p_fct(default = "random", levels = c("random", "center", "custom")),
77+
start = p_uty(default = NULL, depends = start_values == "custom")
7478
)
75-
# old paradox; new paradox can use 'init = "random"'
7679
param_set$values$start_values = "random"
80+
param_set$values$start = NULL
7781

7882
super$initialize(
7983
id = "cmaes",
@@ -90,15 +94,29 @@ OptimizerBatchCmaes = R6Class("OptimizerBatchCmaes",
9094
private = list(
9195
.optimize = function(inst) {
9296
pv = self$param_set$values
93-
pv$par = search_start(inst$search_space, type = pv$start_values)
94-
pv$start_values = NULL
97+
98+
if (pv$start_values == "custom") {
99+
pv$par = pv$start
100+
pv$start_values = NULL
101+
pv$start = NULL
102+
} else {
103+
pv$par = search_start(inst$search_space, type = pv$start_values)
104+
pv$start_values = NULL
105+
pv$start = NULL
106+
}
107+
95108
pv$stopeval = .Machine$integer.max # make sure pureCMAES does not stop
96109
pv$stopfitness = -Inf
97110

98-
if (length(pv$par) < 2) warning("CMA-ES is typically applied to search space dimensions between three and fifty. A lower search space dimension might crash.")
111+
if (length(pv$par) < 2L) {
112+
warning("CMA-ES is typically applied to search space dimensions between three and fifty. A lower search space dimension might crash.")
113+
}
99114

100-
invoke(adagio::pureCMAES, fun = inst$objective_function, lower = inst$search_space$lower,
101-
upper = inst$search_space$upper, .args = pv)
115+
invoke(adagio::pureCMAES,
116+
fun = inst$objective_function,
117+
lower = inst$search_space$lower,
118+
upper = inst$search_space$upper,
119+
.args = pv)
102120
}
103121
)
104122
)

R/OptimizerBatchNLoptr.R

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
#' \item{`ftol_rel`}{`numeric(1)`}
1717
#' \item{`ftol_abs`}{`numeric(1)`}
1818
#' \item{`start_values`}{`character(1)`\cr
19-
#' Create `random` start values or based on `center` of search space?
20-
#' In the latter case, it is the center of the parameters before a trafo is applied.}
19+
#' Create `"random"` start values or based on `"center"` of search space?
20+
#' In the latter case, it is the center of the parameters before a trafo is applied.
21+
#' If set to `"custom"`, the start values can be passed via the `start` parameter.}
22+
#' \item{`start`}{`numeric()`\cr
23+
#' Custom start values. Only applicable if `start_values` parameter is set to `"custom"`.}
2124
#' \item{`approximate_eval_grad_f`}{`logical(1)`\cr
2225
#' Should gradients be numerically approximated via finite differences ([nloptr::nl.grad]).
2326
#' Only required for certain algorithms.
@@ -103,10 +106,12 @@ OptimizerBatchNLoptr = R6Class("OptimizerBatchNLoptr", inherit = OptimizerBatch,
103106
xtol_abs = p_dbl(default = 0, lower = 0, upper = Inf, special_vals = list(-1)),
104107
ftol_rel = p_dbl(default = 0, lower = 0, upper = Inf, special_vals = list(-1)),
105108
ftol_abs = p_dbl(default = 0, lower = 0, upper = Inf, special_vals = list(-1)),
106-
start_values = p_fct(default = "random", levels = c("random", "center")),
109+
start_values = p_fct(default = "random", levels = c("random", "center", "custom")),
110+
start = p_uty(default = NULL, depends = start_values == "custom"),
107111
approximate_eval_grad_f = p_lgl(default = FALSE)
108112
)
109113
param_set$values$start_values = "random"
114+
param_set$values$start = NULL
110115
param_set$values$approximate_eval_grad_f = FALSE
111116

112117
super$initialize(
@@ -125,8 +130,15 @@ OptimizerBatchNLoptr = R6Class("OptimizerBatchNLoptr", inherit = OptimizerBatch,
125130
.optimize = function(inst) {
126131
pv = self$param_set$values
127132

128-
pv$x0 = search_start(inst$search_space, type = pv$start_values)
129-
pv$start_values = NULL
133+
if (pv$start_values == "custom") {
134+
pv$x0 = pv$start
135+
pv$start_values = NULL
136+
pv$start = NULL
137+
} else {
138+
pv$x0 = search_start(inst$search_space, type = pv$start_values)
139+
pv$start_values = NULL
140+
pv$start = NULL
141+
}
130142

131143
if (pv$approximate_eval_grad_f) {
132144
eval_grad_f = function(x) {

R/zzz.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@
3030
}
3131
} # nocov end
3232

33-
utils::globalVariables("batch_nr")
33+
utils::globalVariables(c("batch_nr", "start_values"))
3434

3535
leanify_package()

man/mlr_optimizers_cmaes.Rd

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/mlr_optimizers_nloptr.Rd

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_OptimizerCmaes.R

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@ test_that("OptimizerBatchCmaes", {
2020
instance = OptimInstanceBatchSingleCrit$new(
2121
objective = objective,
2222
search_space = search_space,
23-
terminator = trm("evals", n_evals = 10))
23+
terminator = trm("evals", n_evals = 10L))
2424

2525
z = test_optimizer(instance, "cmaes", real_evals = 10L)
2626

2727
expect_class(z$optimizer, "OptimizerBatchCmaes")
2828
expect_snapshot(z$optimizer)
2929

3030
expect_error(test_optimizer_2d("cmaes", term_evals = 10L), "multi-crit objectives")
31+
32+
instance$archive$clear()
33+
optimizer = opt("cmaes", start_values = "custom", start = c(-9.1, 1.3))
34+
optimizer$optimize(instance)
35+
# start values are used for the initial mean vector so a deterministic test is not applicable
3136
})

tests/testthat/test_OptimizerNLoptr.R

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,29 @@ test_that("OptimizerBatchNLoptr", {
1212
xtol_rel = -1, xtol_abs = -1, ftol_rel = -1, ftol_abs = -1, term_evals = 5L)
1313
expect_class(z$optimizer, "OptimizerBatchNLoptr")
1414
expect_snapshot(z$optimizer)
15+
16+
search_space = domain = ps(
17+
x1 = p_dbl(-10, 10),
18+
x2 = p_dbl(-5, 5)
19+
)
20+
21+
codomain = ps(y = p_dbl(tags = "maximize"))
22+
23+
objective_function = function(xs) {
24+
c(y = -(xs[[1]] - 2)^2 - (xs[[2]] + 3)^2 + 10)
25+
}
26+
27+
objective = ObjectiveRFun$new(
28+
fun = objective_function,
29+
domain = domain,
30+
codomain = codomain)
31+
32+
instance = OptimInstanceBatchSingleCrit$new(
33+
objective = objective,
34+
search_space = search_space,
35+
terminator = trm("evals", n_evals = 10L))
36+
37+
optimizer = opt("nloptr", algorithm = "NLOPT_LN_BOBYQA", start_values = "custom", start = c(-9.1, 1.3))
38+
optimizer$optimize(instance)
39+
expect_equal(unlist(instance$archive$data[1L, c("x1", "x2")]), c(x1 = -9.1, x2 = 1.3))
1540
})

0 commit comments

Comments
 (0)