diff --git a/aiaccel/hpo/optuna/samplers/nelder_mead_sampler.py b/aiaccel/hpo/optuna/samplers/nelder_mead_sampler.py index 8e400c58..d349aa1b 100644 --- a/aiaccel/hpo/optuna/samplers/nelder_mead_sampler.py +++ b/aiaccel/hpo/optuna/samplers/nelder_mead_sampler.py @@ -1,7 +1,7 @@ from __future__ import annotations import numpy.typing as npt -from typing import Any, TypedDict +from typing import Any from collections.abc import Sequence import math @@ -19,23 +19,6 @@ __all__ = ["NelderMeadSampler", "NelderMeadEmptyError"] -class SearchSpaceRequired(TypedDict): - """ - Required keys - """ - - low: int | float - high: int | float - - -class SearchSpace(SearchSpaceRequired, total=False): - """ - Optional keys - """ - - log: bool - - class NelderMeadSampler(optuna.samplers.BaseSampler): """Sampler using the NelderMead algorithm @@ -103,24 +86,14 @@ class NelderMeadSampler(optuna.samplers.BaseSampler): def __init__( self, - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], seed: int | None = None, rng: np.random.RandomState | None = None, coeff: NelderMeadCoefficient | None = None, block: bool = False, sub_sampler: optuna.samplers.BaseSampler | None = None, ) -> None: - self._search_space = {} - for key, value in search_space.items(): - if "log" in value and value["log"]: - self._search_space[key] = { - "low": math.log(value["low"]), - "high": math.log(value["high"]), - "log": value["log"], - } - else: - self._search_space[key] = value | {"log": False} # type: ignore[assignment] - + self._search_space = search_space _rng = rng if rng is not None else np.random.RandomState(seed) if seed is not None else None self.nm = NelderMeadAlgorism( @@ -145,8 +118,7 @@ def sample_relative( def _get_params(self, study: Study, trial: FrozenTrial) -> npt.NDArray[np.float64] | None: try: - it = zip(self.nm.get_vertex(), self._search_space.values(), strict=False) - params = np.array([(space["high"] - space["low"]) * value + space["low"] for value, space in it]) + params = self.nm.get_vertex() except NelderMeadEmptyError as e: if self.sub_sampler is None: raise e @@ -158,11 +130,11 @@ def _get_params(self, study: Study, trial: FrozenTrial) -> npt.NDArray[np.float6 def _put_params(self, study: Study, trial: FrozenTrial, state: TrialState, values: Sequence[float] | None) -> None: if isinstance(values, list): system_attr = study._storage.get_trial_system_attrs(trial._trial_id) - raw_params = system_attr["params"] if "params" in system_attr else trial.params.values() - search_space = [(space["low"], space["high"]) for space in self._search_space.values()] - params = np.array( - [(value - low) / (high - low) for value, (low, high) in zip(raw_params, search_space, strict=False)] - ) + if "params" in system_attr and "fixed_params" not in system_attr: + params = np.array(system_attr["params"]) + else: # sub_sampler or enqueued + it = zip(trial.params.values(), self._search_space.values(), strict=False) + params = np.array([(value - low) / (high - low) for value, (low, high) in it]) self.nm.put_value( params, @@ -274,21 +246,10 @@ def sample_independent( A parameter value. """ - if ( - isinstance( - param_distribution, optuna.distributions.IntDistribution | optuna.distributions.FloatDistribution - ) - and param_distribution.log != self._search_space[param_name]["log"] - ): - raise ValueError( - f"Parameter {param_name} is set with log={self._search_space[param_name]['log']} " - f"but optuna.distributions.param_distribution.log={param_distribution.log}" - ) system_attr = study._storage.get_trial_system_attrs(trial._trial_id) if "sub_trial" in system_attr and self.sub_sampler is not None: param_value = self.sub_sampler.sample_independent(study, trial, param_name, param_distribution) - value = math.log(param_value) if self._search_space[param_name]["log"] else param_value - if self._search_space[param_name]["low"] <= value <= self._search_space[param_name]["high"]: + if self._search_space[param_name][0] <= param_value <= self._search_space[param_name][1]: return param_value else: raise ValueError( @@ -301,13 +262,20 @@ def sample_independent( param_index = list(self._search_space.keys()).index(param_name) param_value = system_attr["params"][param_index] - if self._search_space[param_name]["log"]: - param_value = math.exp(param_value) + # reverse normalization + assert hasattr(param_distribution, "high") + assert hasattr(param_distribution, "low") + assert hasattr(param_distribution, "log") + if param_distribution.log: # log scale + high = math.log(param_distribution.high) + low = math.log(param_distribution.low) + param_value = math.exp((high - low) * param_value + low) + else: + param_value = (param_distribution.high - param_distribution.low) * param_value + param_distribution.low if isinstance(param_distribution, optuna.distributions.IntDistribution): param_value = int(param_value) if hasattr(param_distribution, "step") and param_distribution.step is not None: - assert hasattr(param_distribution, "low") param_value -= (param_value - param_distribution.low) % param_distribution.step contains = param_distribution._contains(param_distribution.to_internal_repr(param_value)) diff --git a/examples/hpo/samplers/coco/experiment_coco.py b/examples/hpo/samplers/coco/experiment_coco.py index 5e594cca..323e276c 100644 --- a/examples/hpo/samplers/coco/experiment_coco.py +++ b/examples/hpo/samplers/coco/experiment_coco.py @@ -13,11 +13,11 @@ import cocoex import optuna -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler def _optimize_sequential( - study: optuna.Study, func: Callable[[list[float]], float], search_space: dict[str, SearchSpace] + study: optuna.Study, func: Callable[[list[float]], float], search_space: dict[str, tuple[int | float, int | float]] ) -> float | None: try: trial = study.ask() @@ -25,7 +25,7 @@ def _optimize_sequential( return None param = [] for name, distribution in search_space.items(): - param.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + param.append(trial.suggest_float(name, *distribution)) result = func(param) time.sleep(0.1) @@ -42,7 +42,7 @@ def _optimize_sequential_wrapper(args: list[Any]) -> float | None: def optimize( study: optuna.Study, func: Callable[[list[float]], float], - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], result_csv_name: str, num_trial: int = 1000, num_parallel: int = 10, @@ -105,9 +105,9 @@ def experiment_bbob() -> None: for problem in suite: # this loop will take several minutes or longer problem.observe_with(observer) # generates the data for cocopp post-processing - search_space: dict[str, SearchSpace] = {} + search_space: dict[str, tuple[int | float, int | float]] = {} for i in range(problem.dimension): - search_space[f"x{i}"] = {"low": -5.0, "high": 5.0} + search_space[f"x{i}"] = (-5.0, 5.0) print(search_space) if sampler_name == "nelder-mead": diff --git a/examples/hpo/samplers/example.py b/examples/hpo/samplers/example.py index 7ac7d0c6..cf039058 100644 --- a/examples/hpo/samplers/example.py +++ b/examples/hpo/samplers/example.py @@ -2,18 +2,18 @@ import optuna -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler -search_space: dict[str, SearchSpace] = { - "x": {"low": -10.0, "high": 10.0}, - "y": {"low": -10.0, "high": 10.0}, +search_space = { + "x": (-10.0, 10.0), + "y": (-10.0, 10.0), } def sphere(trial: optuna.trial.Trial) -> float: params = [] for name, distribution in search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + params.append(trial.suggest_float(name, *distribution)) return float(np.sum(np.asarray(params) ** 2)) diff --git a/examples/hpo/samplers/example_enqueue.py b/examples/hpo/samplers/example_enqueue.py index 913893aa..79086c7a 100644 --- a/examples/hpo/samplers/example_enqueue.py +++ b/examples/hpo/samplers/example_enqueue.py @@ -4,11 +4,11 @@ import optuna -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler -search_space: dict[str, SearchSpace] = { - "x": {"low": -10.0, "high": 10.0}, - "y": {"low": -10.0, "high": 10.0}, +search_space = { + "x": (-10.0, 10.0), + "y": (-10.0, 10.0), } @@ -31,14 +31,14 @@ def sphere(params: list[float]) -> float: except NelderMeadEmptyError: # random sampling study.enqueue_trial( { - "x": _rng.uniform(search_space["x"]["low"], search_space["x"]["high"]), - "y": _rng.uniform(search_space["y"]["low"], search_space["y"]["high"]), + "x": _rng.uniform(*search_space["x"]), + "y": _rng.uniform(*search_space["y"]), } ) trial = study.ask() - x = trial.suggest_float("x", search_space["x"]["low"], search_space["x"]["high"]) - y = trial.suggest_float("y", search_space["y"]["low"], search_space["y"]["high"]) + x = trial.suggest_float("x", *search_space["x"]) + y = trial.suggest_float("y", *search_space["y"]) trials.append(trial) params.append([x, y]) diff --git a/examples/hpo/samplers/example_parallel.py b/examples/hpo/samplers/example_parallel.py index 2213c4f9..6973016f 100644 --- a/examples/hpo/samplers/example_parallel.py +++ b/examples/hpo/samplers/example_parallel.py @@ -4,11 +4,11 @@ import optuna -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler -search_space: dict[str, SearchSpace] = { - "x": {"low": -10.0, "high": 10.0}, - "y": {"low": -10.0, "high": 10.0}, +search_space = { + "x": (-10.0, 10.0), + "y": (-10.0, 10.0), } @@ -17,7 +17,7 @@ def sphere(trial: optuna.trial.Trial) -> float: time.sleep(0.01) for name, distribution in search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + params.append(trial.suggest_float(name, *distribution)) return float(np.sum(np.asarray(params) ** 2)) diff --git a/examples/hpo/samplers/example_sub_sampler.py b/examples/hpo/samplers/example_sub_sampler.py index ebdd1202..a0e89b97 100644 --- a/examples/hpo/samplers/example_sub_sampler.py +++ b/examples/hpo/samplers/example_sub_sampler.py @@ -4,11 +4,11 @@ import optuna -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadSampler -search_space: dict[str, SearchSpace] = { - "x": {"low": -10.0, "high": 10.0}, - "y": {"low": -10.0, "high": 10.0}, +search_space = { + "x": (-10.0, 10.0), + "y": (-10.0, 10.0), } @@ -17,7 +17,7 @@ def sphere(trial: optuna.trial.Trial) -> float: time.sleep(0.01) for name, distribution in search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + params.append(trial.suggest_float(name, *distribution)) return float(np.sum(np.asarray(params) ** 2)) diff --git a/tests/hpo/optuna/samplers/test_nelder_mead_sampler.py b/tests/hpo/optuna/samplers/test_nelder_mead_sampler.py index df7f7e75..76e74795 100644 --- a/tests/hpo/optuna/samplers/test_nelder_mead_sampler.py +++ b/tests/hpo/optuna/samplers/test_nelder_mead_sampler.py @@ -15,12 +15,12 @@ import optuna import pytest -from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler, SearchSpace +from aiaccel.hpo.optuna.samplers.nelder_mead_sampler import NelderMeadEmptyError, NelderMeadSampler @pytest.fixture -def search_space() -> dict[str, SearchSpace]: - return {"x": {"low": -5.0, "high": 5.0}, "y": {"low": -5.0, "high": 5.0}} +def search_space() -> dict[str, tuple[int | float, int | float]]: + return {"x": (-5.0, 5.0), "y": (-5.0, 5.0)} @pytest.fixture @@ -34,7 +34,7 @@ def param_distribution() -> optuna.distributions.FloatDistribution: def create_sampler( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], sub_sampler: optuna.samplers.BaseSampler | None = None, ) -> NelderMeadSampler: return NelderMeadSampler(search_space=search_space, seed=42, sub_sampler=sub_sampler) @@ -66,7 +66,7 @@ def create_trial( def test_infer_relative_search_space( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -77,7 +77,7 @@ def test_infer_relative_search_space( def test_sample_relative( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -88,7 +88,7 @@ def test_sample_relative( def test_before_trial( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -103,11 +103,11 @@ def test_before_trial( sampler.before_trial(study, trial) system_attr = study._storage.get_trial_system_attrs(trial._trial_id) - assert np.array_equal(system_attr["params"], np.array([-1.0, 0.0])) + assert np.array_equal(system_attr["params"], np.array([0.4, 0.5])) def test_before_trial_enqueued( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -126,7 +126,7 @@ def test_before_trial_enqueued( def test_before_trial_sub_sampler( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -144,7 +144,7 @@ def test_before_trial_sub_sampler( def test_sample_independent( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -152,18 +152,19 @@ def test_sample_independent( study = create_study(sampler) trial = create_trial(state, param_distribution) study.add_trial(trial) - xs = np.array([-1.0, 0.0]) + xs = np.array([0.4, 0.5]) + expected_xs = np.array([-1.0, 0.0]) study._storage.set_trial_system_attr(trial._trial_id, "params", list(xs)) value = sampler.sample_independent(study, trial, "x", param_distribution) - assert value == xs[0] + assert value == expected_xs[0] value = sampler.sample_independent(study, trial, "y", param_distribution) - assert value == xs[1] + assert value == expected_xs[1] def test_after_trial( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -182,7 +183,7 @@ def test_after_trial( def test_after_trial_sub_sampler( - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], state: optuna.trial.TrialState, param_distribution: optuna.distributions.FloatDistribution, ) -> None: @@ -234,7 +235,7 @@ def sphere_sleep(x: list[float]) -> float: class BaseTestNelderMead: def common_setup( self, - search_space: dict[str, SearchSpace], + search_space: dict[str, tuple[int | float, int | float]], objective: Callable[[list[float]], float], result_file_name: str, study: optuna.Study, @@ -265,15 +266,15 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: def func(self, trial: optuna.trial.Trial) -> float: params = [] for name, distribution in self.search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + params.append(trial.suggest_float(name, *distribution)) return self.objective(params) class TestNelderMeadAckley(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": 0.0, "high": 10.0}, - "y": {"low": 0.0, "high": 10.0}, + search_space = { + "x": (0.0, 10.0), + "y": (0.0, 10.0), } sampler = NelderMeadSampler(search_space=search_space, seed=42) @@ -293,9 +294,9 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: class TestNelderMeadAckleyParallel(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": 0.0, "high": 10.0}, - "y": {"low": 0.0, "high": 10.0}, + search_space = { + "x": (0.0, 10.0), + "y": (0.0, 10.0), } sampler = NelderMeadSampler(search_space=search_space, seed=42, block=True) @@ -324,10 +325,10 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: class TestNelderMeadSphereParallel(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": -30.0, "high": 30.0}, - "y": {"low": -30.0, "high": 30.0}, - "z": {"low": -30.0, "high": 30.0}, + search_space = { + "x": (-30.0, 30.0), + "y": (-30.0, 30.0), + "z": (-30.0, 30.0), } sampler = NelderMeadSampler(search_space=search_space, seed=42, block=True) @@ -357,10 +358,10 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: class TestNelderMeadSphereEnqueue(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": -30.0, "high": 30.0}, - "y": {"low": -30.0, "high": 30.0}, - "z": {"low": -30.0, "high": 30.0}, + search_space = { + "x": (-30.0, 30.0), + "y": (-30.0, 30.0), + "z": (-30.0, 30.0), } self._rng = np.random.RandomState(seed=42) sampler = NelderMeadSampler(search_space=search_space, rng=self._rng) @@ -384,16 +385,16 @@ def optimize(self) -> None: except NelderMeadEmptyError: # random sampling self.study.enqueue_trial( { - "x": self._rng.uniform(self.search_space["x"]["low"], self.search_space["x"]["high"]), - "y": self._rng.uniform(self.search_space["y"]["low"], self.search_space["y"]["high"]), - "z": self._rng.uniform(self.search_space["z"]["low"], self.search_space["z"]["high"]), + "x": self._rng.uniform(*self.search_space["x"]), + "y": self._rng.uniform(*self.search_space["y"]), + "z": self._rng.uniform(*self.search_space["z"]), } ) trial = self.study.ask() - x = trial.suggest_float("x", self.search_space["x"]["low"], self.search_space["x"]["high"]) - y = trial.suggest_float("y", self.search_space["y"]["low"], self.search_space["y"]["high"]) - z = trial.suggest_float("z", self.search_space["z"]["low"], self.search_space["z"]["high"]) + x = trial.suggest_float("x", *self.search_space["x"]) + y = trial.suggest_float("y", *self.search_space["y"]) + z = trial.suggest_float("z", *self.search_space["z"]) trials.append(trial) params.append([x, y, z]) @@ -413,9 +414,9 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: class TestNelderMeadAckleySubSampler(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": 0.0, "high": 10.0}, - "y": {"low": 0.0, "high": 10.0}, + search_space = { + "x": (0.0, 10.0), + "y": (0.0, 10.0), } tpe_sampler = optuna.samplers.TPESampler(seed=43) sampler = NelderMeadSampler(search_space=search_space, seed=42, block=False, sub_sampler=tpe_sampler) @@ -436,8 +437,8 @@ def optimize(self) -> None: for _ in range(num_parallel): trial = self.study.ask() - x = trial.suggest_float("x", self.search_space["x"]["low"], self.search_space["x"]["high"]) - y = trial.suggest_float("y", self.search_space["y"]["low"], self.search_space["y"]["high"]) + x = trial.suggest_float("x", *self.search_space["x"]) + y = trial.suggest_float("y", *self.search_space["y"]) trials.append(trial) params.append([x, y]) @@ -456,9 +457,9 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: class TestNelderMeadAckleyInteger(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": -10, "high": 10}, - "y": {"low": -10.0, "high": 10.0}, + search_space = { + "x": (-10, 10), + "y": (-10.0, 10.0), } sampler = NelderMeadSampler(search_space=search_space, seed=42) @@ -477,17 +478,17 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: def func(self, trial: optuna.trial.Trial) -> float: params: list[int | float] = [] - params.append(trial.suggest_int("x", int(self.search_space["x"]["low"]), int(self.search_space["x"]["high"]))) - params.append(trial.suggest_float("y", self.search_space["y"]["low"], self.search_space["y"]["high"])) + params.append(trial.suggest_int("x", *[int(space) for space in self.search_space["x"]])) + params.append(trial.suggest_float("y", *self.search_space["y"])) return self.objective(params) class TestNelderMeadAckleyStep(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": -30, "high": 30}, - "y": {"low": -30.0, "high": 30.0}, + search_space = { + "x": (-30, 30), + "y": (-30.0, 30.0), } sampler = NelderMeadSampler(search_space=search_space, seed=42) @@ -506,19 +507,17 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: def func(self, trial: optuna.trial.Trial) -> float: params: list[int | float] = [] - params.append( - trial.suggest_int("x", int(self.search_space["x"]["low"]), int(self.search_space["x"]["high"]), step=2) - ) - params.append(trial.suggest_float("y", self.search_space["y"]["low"], self.search_space["y"]["high"], step=0.5)) + params.append(trial.suggest_int("x", *[int(space) for space in self.search_space["x"]], step=2)) + params.append(trial.suggest_float("y", *self.search_space["y"], step=0.5)) return self.objective(params) class TestNelderMeadAckleyLogScale(BaseTestNelderMead): def setup_method(self) -> None: - search_space: dict[str, SearchSpace] = { - "x": {"low": 1.0e-5, "high": 1.0e5, "log": True}, - "y": {"low": 1.0e-5, "high": 1.0e5, "log": True}, + search_space = { + "x": (1.0e-5, 1.0e5), + "y": (1.0e-5, 1.0e5), } sampler = NelderMeadSampler(search_space=search_space, seed=42) @@ -538,15 +537,15 @@ def validation(self, results: list[dict[str | Any, str | Any]]) -> None: def func(self, trial: optuna.trial.Trial) -> float: params = [] for name, distribution in self.search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"], log=distribution["log"])) + params.append(trial.suggest_float(name, *distribution, log=True)) return self.objective(params) class TestNelderMeadAckleyResumption(BaseTestNelderMead): def test_sampler(self) -> None: - self.search_space: dict[str, SearchSpace] = { - "x": {"low": -10, "high": 10}, - "y": {"low": 0.1, "high": 10.0}, + self.search_space = { + "x": (-10, 10), + "y": (-10, 10), } self.objective = ackley sampler = NelderMeadSampler(search_space=self.search_space, seed=42) @@ -587,5 +586,5 @@ def test_sampler(self) -> None: def func(self, trial: optuna.trial.Trial) -> float: params = [] for name, distribution in self.search_space.items(): - params.append(trial.suggest_float(name, distribution["low"], distribution["high"])) + params.append(trial.suggest_float(name, *distribution)) return self.objective(params)