Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0f0f0fb
feat: add OptimizerBatchSMAC
be-marc Feb 2, 2026
46ea8fe
...
be-marc Feb 3, 2026
92e0f28
...
be-marc Feb 3, 2026
cf4c33c
...
be-marc Feb 3, 2026
9a9c100
Merge branch 'main' into smac
be-marc Feb 28, 2026
3760093
...
be-marc Mar 4, 2026
93f4460
...
be-marc Mar 4, 2026
500aa4e
Merge remote-tracking branch 'origin/smac' into hebo
awinterstetter Mar 20, 2026
4a8fece
first implementation of optimize function
awinterstetter Apr 13, 2026
99a461e
hebo fixes and comments
awinterstetter Apr 14, 2026
75cc400
HEBO further draft
awinterstetter Apr 21, 2026
e31f542
moved HEBO to R-folder and added unit tests
awinterstetter Apr 26, 2026
54571d0
add assert to hebo helper
awinterstetter Apr 26, 2026
a3ab359
added new files to collate
awinterstetter Apr 26, 2026
9945572
updated documentation
awinterstetter Apr 27, 2026
02f2bb4
Merge remote-tracking branch 'origin/main' into hebo
awinterstetter Apr 30, 2026
9975531
fixed rush error
awinterstetter Apr 30, 2026
6d8d657
logger in line with smac branch
awinterstetter Apr 30, 2026
2fe7b44
fix for HEBO install fail in GitHub checks
awinterstetter May 1, 2026
72a3509
further teardown.R fix
awinterstetter May 3, 2026
0001ddf
made setup and teardown in line with smac branch
awinterstetter May 4, 2026
608a58f
align teardown with smac branch
awinterstetter May 4, 2026
1047b76
tests managed in separate environments
awinterstetter May 4, 2026
f37ab23
added py_require to zzz.R
awinterstetter May 4, 2026
59af8e7
reverted files to smac branch
awinterstetter May 5, 2026
481e1dc
adjustments to github workflow
awinterstetter May 14, 2026
98f2fe9
manage smac and hebo in separate environments
awinterstetter May 14, 2026
4aa083e
further fixes
awinterstetter May 14, 2026
6fda7a9
changed to Sys.setenv
awinterstetter May 17, 2026
38332fa
removed callr-wrapping
awinterstetter May 21, 2026
6e9ebaa
Revert "removed callr-wrapping"
awinterstetter May 21, 2026
48f9a02
added library("checkmate")
awinterstetter May 21, 2026
f3f192c
set environment to "managed"
awinterstetter May 21, 2026
61ebee3
remove paradox from remotes
awinterstetter May 21, 2026
de9ffff
introduce virtual environment
awinterstetter May 21, 2026
9ac8d54
added paradox to remote-packages
awinterstetter May 24, 2026
93af230
fix VE for hebo tests
awinterstetter May 24, 2026
51d5aaf
avoid NOTE regarding torchinductor_runner
awinterstetter May 24, 2026
38eeb6e
removed withr
awinterstetter May 24, 2026
9aeaf34
add withr to description
awinterstetter May 24, 2026
034eacb
added nolint
awinterstetter May 24, 2026
13cc189
update directory
awinterstetter May 24, 2026
25b4f0b
add withr
awinterstetter May 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/r-cmd-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,25 @@ jobs:
with:
r-version: ${{ matrix.config.r }}

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck
needs: check

- name: Create Python virtual environments
run: |
python3 -m venv ~/.virtualenvs/r-hebo
~/.virtualenvs/r-hebo/bin/pip install --upgrade pip --quiet
~/.virtualenvs/r-hebo/bin/pip install torch --index-url https://download.pytorch.org/whl/cpu --quiet
~/.virtualenvs/r-hebo/bin/pip install hebo --quiet
python3 -m venv ~/.virtualenvs/r-smac
~/.virtualenvs/r-smac/bin/pip install --upgrade pip --quiet
~/.virtualenvs/r-smac/bin/pip install smac ConfigSpace --quiet

- uses: mxschmitt/action-tmate@v3
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
with:
Expand Down
13 changes: 11 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ Authors@R: c(
person("Bernd", "Bischl", , "bernd_bischl@gmx.net", role = "aut",
comment = c(ORCID = "0000-0001-6002-6980")),
person("Martin", "Binder", , "martin.binder@mail.com", role = "aut"),
person("Olaf", "Mersmann", , "olafm@statistik.tu-dortmund.de", role = "ctb")
person("Olaf", "Mersmann", , "olafm@statistik.tu-dortmund.de", role = "ctb"),
person("Alexander", "Winterstetter", "alexanderwinterstetter@gmail.de", role = "ctb")
)
Description: Features highly configurable search spaces via the 'paradox'
package and optimizes every user-defined objective function. The
Expand All @@ -35,6 +36,7 @@ Imports:
R6
Suggests:
adagio,
callr,
emoa,
GenSA,
irace (>= 4.0.0),
Expand All @@ -44,9 +46,13 @@ Suggests:
processx,
progressr,
redux,
reticulate,
RhpcBLASctl,
rush (>= 1.0.0),
testthat (>= 3.0.0)
testthat (>= 3.0.0),
withr
Remotes:
mlr-org/paradox
Config/testthat/edition: 3
Config/testthat/parallel: false
Encoding: UTF-8
Expand Down Expand Up @@ -91,10 +97,12 @@ Collate:
'OptimizerBatchFocusSearch.R'
'OptimizerBatchGenSA.R'
'OptimizerBatchGridSearch.R'
'OptimizerBatchHEBO.R'
'OptimizerBatchIrace.R'
'OptimizerBatchLocalSearch.R'
'OptimizerBatchNLoptr.R'
'OptimizerBatchRandomSearch.R'
'OptimizerBatchSmac3.R'
'Progressor.R'
'mlr_terminators.R'
'Terminator.R'
Expand All @@ -114,6 +122,7 @@ Collate:
'bibentries.R'
'conditions.R'
'helper.R'
'helper_hebo.R'
'local_search.R'
'mlr_callbacks.R'
'mlr_test_functions.R'
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ export(OptimizerBatchDesignPoints)
export(OptimizerBatchFocusSearch)
export(OptimizerBatchGenSA)
export(OptimizerBatchGridSearch)
export(OptimizerBatchHEBO)
export(OptimizerBatchIrace)
export(OptimizerBatchLocalSearch)
export(OptimizerBatchNLoptr)
export(OptimizerBatchRandomSearch)
export(OptimizerBatchSmac3)
export(Terminator)
export(TerminatorClockTime)
export(TerminatorCombo)
Expand Down
6 changes: 3 additions & 3 deletions R/OptimizerAsync.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
#' There are three types of workers:
#'
#' - "mirai": Workers are started with \CRANpkg{mirai} on local or remote machines.
#' See `$start_workers()` in [Rush] for more details.
#' See `$start_workers()` in [rush::Rush] for more details.
#' [mirai::daemons()] must be created before starting the optimization.
#' - "processx": Workers are started as local processes with \CRANpkg{processx}.

#' See `$start_local_workers()` in [Rush] for more details.
#' See `$start_local_workers()` in [rush::Rush] for more details.
#' - "script": Workers are started by the user with a custom script.
#' See `$create_worker_script()` in [Rush] for more details.
#' See `$create_worker_script()` in [rush::Rush] for more details.
#'
#' The workers are started when the `$optimize()` method is called.
#' The main process waits until at least one worker is running.
Expand Down
156 changes: 156 additions & 0 deletions R/OptimizerBatchHEBO.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#' @title Heteroscedastic evolutionary bayesian optimization
#'
#' @export
#'

OptimizerBatchHEBO = R6Class(
"OptimizerBatchHEBO",
inherit = OptimizerBatch,
public = list(
initialize = function() {
param_set = ps(
# optimizer interface
n_suggestions = p_int(lower = 1L, init = 1L), # remove as HEBO only handles single crit
n_init = p_int(lower = 1L),
seed = p_int(lower = 0L),

# surrogate model
surrogate = p_fct(levels = c("gp", "rf"), init = "gp"),
rf_n_estimators = p_int(lower = 1L, depends = quote(surrogate == "rf")),
gp_lr = p_dbl(lower = 0, depends = quote(surrogate == "gp")),
gp_num_epochs = p_int(lower = 1L, depends = quote(surrogate == "gp")),
gp_noise_free = p_lgl(depends = quote(surrogate == "gp")),
gp_noise_lb = p_dbl(lower = 0, depends = quote(surrogate == "gp")),
gp_pred_likeli = p_lgl(depends = quote(surrogate == "gp")),

# acquisition function
acq_function = p_fct(levels = c("mace", "lcb"), init = "mace"),

# evolutionary search for acquisition optimization
es = p_fct(
levels = c(
"ga",
"brkga",
"de",
"nelder-mead",
"pattern-search",
"cmaes",
"pso",
"nsga2",
"rnsga2",
"nsga3",
"unsga3",
"rnsga3",
"moead",
"ctaea"
),
init = "nsga2"
)
)

super$initialize(
id = "hebo",
param_set = param_set,
param_classes = c("ParamDbl", "ParamInt", "ParamFct", "ParamLgl"),
properties = c("single-crit"),
packages = "reticulate",
label = "Heteroscedastic Evolutionary Bayesian Optimization",
man = "bbotk::mlr_optimizers_hebo"
)
}
),

private = list(
.optimize = function(inst) {
assert_python_packages(c("hebo"))
hebo = reticulate::import("hebo")

pv = self$param_set$values

search_space = inst$search_space
space = paramset_to_hebo_space(search_space)
optimizer_args = list(
space = space,
rand_sample = as.integer(pv$n_init %??% (1L + search_space$length)),
es = pv$es %??% "nsga2"
)

# add nn; evtl boosting
# add unit tests see SMAC3
if (!is.null(pv$surrogate)) {
if (pv$surrogate == "rf") {
optimizer_args$model_name = "rf"
optimizer_args$model_config = list(
n_estimators = as.integer(pv$rf_n_estimators %??% 20L)
)
} else if (pv$surrogate == "gp") {
optimizer_args$model_name = "gp"
optimizer_args$model_config = list(
lr = pv$gp_lr %??% 0.01,
num_epochs = as.integer(pv$gp_num_epochs %??% 100L),
verbose = pv$gp_verbose %??% FALSE,
print_every = as.integer(pv$gp_print_every %??% 10L),
noise_free = pv$gp_noise_free %??% FALSE,
noise_lb = pv$gp_noise_lb %??% 8e-4,
pred_likeli = pv$gp_pred_likeli %??% FALSE
)
}
}

if (!is.null(pv$acq_function)) {
acq_mod = hebo$acquisitions$acq
optimizer_args$acq_cls = switch(
pv$acq_function,
"lcb" = acq_mod$LCB,
"mace" = acq_mod$MACE,
stopf(
"Unsupported HEBO acquisition function '%s'. Supported values are 'mace' and 'lcb'.",
pv$acq_function
)
)
}

if (!is.null(pv$seed)) {
optimizer_args$scramble_seed = as.integer(pv$seed)
}

hebo_optimizer = invoke(hebo$optimizers$hebo$HEBO, .args = optimizer_args)

repeat {
if (inst$is_terminated) {
break
}

# tryCatch muss noch etwas ausgestaltet werden, siehe folgender Kommentar
# hebo$optimizers$hebo$HEBO()$quasi_sample --- default HEBO sampler evtl notwendig, wenn suggest fehlschlägt; useful wenn SM zusammenbricht; wrappen in Trycatch von suggest funktion falls das passiert
# ISSUE 1 - HEBO suggest doesnt expose metadata as SMAC3
# trial_info exposes paraeters as a pandas DataFrame
trial_info = tryCatch(
hebo_optimizer$suggest(n_suggestions = as.integer(pv$n_suggestions %??% 1L)),
# rausfinden wie HEBO suggest verwendet um mehrere configs oder einzelne configs zu kriegen; gibt mehrere Möglichkeiten das zu machen bei MBO interessant wie HEBO das macht
error = function(e) NULL
)
if (is.null(trial_info)) {
break
}

# convert pandas DataFrame to R data.frame-like object
trial_info_dt = setDT(reticulate::py_to_r(trial_info))

# evaluation of that config
res = inst$eval_batch(trial_info_dt)

# evaluated target columns are turned into a numeric matrix
y = as.matrix(res[, inst$archive$cols_y, with = FALSE])

# signs are flipped
# ist es möglich bei HEBO auch multi-objective zu machen, also dass da mehrere y zurückkomen; das auch wichtig für denOptimizer ob er nicht nur SingleCrit oder auch MultiCrit kann
y = y * matrix(inst$objective_multiplicator, nrow = nrow(y), ncol = ncol(y), byrow = TRUE)

hebo_optimizer$observe(trial_info, y)
}
}
)
)

mlr_optimizers$add("hebo", OptimizerBatchHEBO)
Loading
Loading