|
| 1 | +"""IOH-based problem suite, replacing cocoex. |
| 2 | +
|
| 3 | +Drop-in replacement for ``cocoex.Suite("bbob", "", "")``: |
| 4 | +
|
| 5 | + suite = IOHSuite() |
| 6 | + problem = suite.get_problem("bbob_f001_i01_d05") |
| 7 | + y = problem(x) |
| 8 | + dim = problem.dimension |
| 9 | + lb = problem.lower_bounds # np.ndarray |
| 10 | + ub = problem.upper_bounds # np.ndarray |
| 11 | +
|
| 12 | +Problem IDs follow the format ``bbob_f{fid:03d}_i{iid:02d}_d{dim:02d}``. |
| 13 | +""" |
| 14 | + |
| 15 | +from __future__ import annotations |
| 16 | + |
| 17 | +import re |
| 18 | + |
| 19 | +import numpy as np |
| 20 | + |
| 21 | +_ID_PATTERN = re.compile(r"^bbob_f(\d+)_i(\d+)_d(\d+)$") |
| 22 | + |
| 23 | + |
| 24 | +class IOHProblemWrapper: |
| 25 | + """Wraps an IOH BBOB problem with the interface expected by DASEnv.""" |
| 26 | + |
| 27 | + __slots__ = ("_p",) |
| 28 | + |
| 29 | + def __init__(self, p) -> None: |
| 30 | + self._p = p |
| 31 | + |
| 32 | + @property |
| 33 | + def dimension(self) -> int: |
| 34 | + return int(self._p.meta_data.n_variables) |
| 35 | + |
| 36 | + @property |
| 37 | + def lower_bounds(self) -> np.ndarray: |
| 38 | + return np.asarray(self._p.bounds.lb, dtype=np.float64) |
| 39 | + |
| 40 | + @property |
| 41 | + def upper_bounds(self) -> np.ndarray: |
| 42 | + return np.asarray(self._p.bounds.ub, dtype=np.float64) |
| 43 | + |
| 44 | + def __call__(self, x) -> float: |
| 45 | + return float(self._p(x)) |
| 46 | + |
| 47 | + |
| 48 | +class IOHSuite: |
| 49 | + """Drop-in replacement for ``cocoex.Suite("bbob", "", "")``. |
| 50 | +
|
| 51 | + Stateless — a new IOH problem object is created for every ``get_problem`` |
| 52 | + call, so the suite is safely shareable across threads and picklable. |
| 53 | + """ |
| 54 | + |
| 55 | + def get_problem(self, problem_id: str) -> IOHProblemWrapper: |
| 56 | + """Return a wrapped BBOB problem for the given *problem_id*. |
| 57 | +
|
| 58 | + Parameters |
| 59 | + ---------- |
| 60 | + problem_id: |
| 61 | + String of the form ``bbob_f{fid:03d}_i{iid:02d}_d{dim:02d}``. |
| 62 | + """ |
| 63 | + m = _ID_PATTERN.match(problem_id) |
| 64 | + if m is None: |
| 65 | + raise ValueError( |
| 66 | + f"Cannot parse problem_id {problem_id!r}. " |
| 67 | + "Expected format: bbob_f<fid>_i<iid>_d<dim>" |
| 68 | + ) |
| 69 | + fid, iid, dim = int(m.group(1)), int(m.group(2)), int(m.group(3)) |
| 70 | + |
| 71 | + import ioh |
| 72 | + |
| 73 | + p = ioh.get_problem(fid, iid, dim, problem_class=ioh.ProblemClass.BBOB) |
| 74 | + return IOHProblemWrapper(p) |
0 commit comments