Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4572eb0
First dacboenv compatibility
thibautklenke Dec 31, 2025
02ce9e6
Handle BO runs as episodes
thibautklenke Jan 1, 2026
be7d8ea
Refine benchmark info
thibautklenke Jan 1, 2026
d6b3925
Refine config defaults
thibautklenke Jan 1, 2026
a24da3c
DACBO example notebook
thibautklenke Jan 1, 2026
aea7c46
Update dacbo defaults and instance format
thibautklenke Jan 2, 2026
b618fce
DACBO: Update defaults
thibautklenke Jan 4, 2026
050759a
DACBO: Requirements
thibautklenke Jan 4, 2026
0177ca4
DACBO: Update example notebook
thibautklenke Jan 4, 2026
2ef2ccb
DACBO: Set default reward to symlogregret
thibautklenke Jan 5, 2026
6ad67f4
DACBO: Update benchmark info
thibautklenke Jan 5, 2026
404a63d
DACBO: Update example notebook
thibautklenke Jan 5, 2026
d4c8cd9
DACBO: Update instance set, include task ids into config
thibautklenke Jan 5, 2026
f3ceb8e
DACBO: Update example notebook
thibautklenke Jan 5, 2026
0ad7483
DACBO: Use all BBOB 2D as default
thibautklenke Jan 6, 2026
8907937
DACBO: Update example notebook
thibautklenke Jan 6, 2026
a1e5b49
Merge remote-tracking branch 'origin/development' into dacboenv
jmtoepperwien Feb 23, 2026
5e6f903
feat(DACBO): possible to input instance sets relative to hydra's search
jmtoepperwien Mar 6, 2026
36a3526
feat: better dacboenv integration into dacbench
jmtoepperwien Mar 23, 2026
998182e
feat: tests for dacbo
jmtoepperwien Mar 23, 2026
62c217e
feat(DACBO): use instance selector of DACBench
jmtoepperwien Mar 23, 2026
f51270d
test(DACBO): expand env test coverage to match dacboenv-integrated br…
jmtoepperwien Mar 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
12 changes: 12 additions & 0 deletions dacbench/benchmarks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,15 @@
"Theory Benchmark not installed. If you want to use this benchmark, "
"please follow the installation guide."
)

dacbo_spec = importlib.util.find_spec("dacboenv")
found = dacbo_spec is not None
if found:
from dacbench.benchmarks.dacbo_benchmark import DACBOBenchmark

__all__.append("DACBOBenchmark")
else:
warnings.warn( # noqa: B028
"DACBOEnv not installed. If you want to use this benchmark, "
"please follow the installation guide."
)
111 changes: 111 additions & 0 deletions dacbench/benchmarks/dacbo_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""DACBOEnv Benchmark."""

from __future__ import annotations

from importlib.resources import files
from pathlib import Path

import dacboenv
import numpy as np
import yaml
from dacboenv.env.action import AcqParameterActionSpace
from omegaconf import OmegaConf

from dacbench.abstract_benchmark import AbstractBenchmark, objdict
from dacbench.envs.dacbo import DACBOEnv


def load_default_optimizer():
"""Handles dacboenv configs to configure WEI as default."""
dacboenv_path = files("dacboenv")
base = OmegaConf.load(dacboenv_path / "configs/env/opt/base.yaml")
base.dacboenv.optimizer_cfg.smac_cfg.smac_kwargs = None
override = OmegaConf.load(
dacboenv_path / "configs/env/action/wei_alpha_continuous.yaml"
)
cfg = OmegaConf.merge(base, override)
cfg = OmegaConf.create({"optimizer": cfg.dacboenv.optimizer_cfg})

def replace_refs(node):
if isinstance(node, str):
return node.replace("dacboenv.optimizer_cfg", "optimizer")
if isinstance(node, dict):
return {k: replace_refs(v) for k, v in node.items()}
if isinstance(node, list):
return [replace_refs(v) for v in node]
return node

cfg = OmegaConf.create(replace_refs(OmegaConf.to_container(cfg, resolve=False)))
cfg.outdir = "runs/SMAC-DACBO/${benchmark_id}/${task_id}/${seed}"

return cfg


INFO = {
"identifier": "DACBO",
"name": "DACBO",
"reward": "Incumbent cost",
Comment thread
benjamc marked this conversation as resolved.
Outdated
"state_description": [
obs.name for obs in dacboenv.env.observation.ALL_OBSERVATIONS
],
}

DACBO_DEFAULTS = objdict(
{
"reward_range": [-np.inf, np.inf],
"seed": 0,
"instance_set_path": "bbob_2_default.yaml",
"optimizer_cfg": load_default_optimizer(),
"observation_keys": [
"ubr_difference",
"acq_value_EI",
"acq_value_PI",
"previous_param",
],
"action_space_class": AcqParameterActionSpace,
"action_space_kwargs": {"bounds": [0, 1], "adjustment_type": "continuous"},
"reward_keys": None,
Comment thread
benjamc marked this conversation as resolved.
Outdated
"benchmark_info": INFO,
}
)


class DACBOBenchmark(AbstractBenchmark):
"""DACBOEnv benchmark."""

def __init__(self, config_path=None, config=None):
"""Init DACBOEnv benchmark."""
super().__init__(config_path, config)

if not self.config:
self.config = objdict(DACBO_DEFAULTS.copy())

for key in DACBO_DEFAULTS:
if key not in self.config:
self.config[key] = DACBO_DEFAULTS[key]

def get_environment(self):
"""Returns the internal env."""
return DACBOEnv(self.config)

def read_instance_set(self):
"""Reads the instance set."""
assert self.config.instance_set_path
if Path(self.config.instance_set_path).is_file():
path = self.config.instance_set_path
else:
path = (
Path(__file__).resolve().parent
/ "../instance_sets/dacbo/"
/ self.config.instance_set_path
)

with open(path) as f:
instance_data = yaml.safe_load(f)
print(instance_data)
self.config["instance_set"] = {
0: instance_data["task_ids"]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it a dict?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required by the abstract env:

self.instance_id_list = sorted(self.instance_set.keys())

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then the instance set should be the product of task ids and seeds.
internally we don't use it anyway, but that would be the correct setting, can you please change that?
might be relevant for stuff like curriculum learning

} # Instance selection is handled by the internal env
self.config["inner_seeds"] = instance_data.get("inner_seeds", None)

assert len(self.config["instance_set"][0]) > 0, "ERROR: empty instance set"
34 changes: 34 additions & 0 deletions dacbench/envs/dacbo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""DACBO Env."""

from __future__ import annotations

import numpy as np
from dacboenv.dacboenv import DACBOEnv as DEnv

from dacbench.abstract_env import AbstractEnv


class DACBOEnv(AbstractEnv):
"""DACBO env."""

def __init__(self, config):
"""Init DACBO env."""
self._env = DEnv(task_ids=config["instance_set"][0], **config)
self.reset()
config[
"cutoff"
] = np.inf # Not used. DACBO handles BO runs (i.e. episodes) internally
config["observation_space"] = self._env.observation_space
config["action_space"] = self._env.action_space
super().__init__(config)

def step(self, action):
"""Takes one env step."""
state, reward, terminated, truncated, info = self._env.step(action)
if truncated: # Reset BO loop, select new instance
self._env.reset()
return state, reward, terminated, truncated, info

def reset(self, seed=None):
"""Resets the internal env."""
return self._env.reset()
2 changes: 2 additions & 0 deletions dacbench/instance_sets/dacbo/bbob_2_default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
task_ids: ["bbob/2/1/0", "bbob/2/20/0"]
inner_seeds: [1, 2, 3]
Loading