diff --git a/CHANGELOG.md b/CHANGELOG.md index b1fdc0def..67de90f28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ - Correct intensifier for Algorithm Configuration Facade (#1162, #1165) - Migrate sphinx docs to mkdocs (#1155) +## Bugfixes +- Fix kwargs for DifferentialEvolution (#1187) + # 2.2.1 ## Improvements diff --git a/setup.py b/setup.py index 02ce3c339..6ac234efe 100644 --- a/setup.py +++ b/setup.py @@ -74,7 +74,7 @@ def read_file(filepath: str) -> str: python_requires=">=3.8", install_requires=[ "numpy", - "scipy>=1.15.1", + "scipy>=1.9.2", "psutil", "pynisher>=1.0.0", "ConfigSpace>=1.0.0", diff --git a/smac/acquisition/maximizer/differential_evolution.py b/smac/acquisition/maximizer/differential_evolution.py index 56e4c9f67..b0e8f7da9 100644 --- a/smac/acquisition/maximizer/differential_evolution.py +++ b/smac/acquisition/maximizer/differential_evolution.py @@ -1,5 +1,7 @@ from __future__ import annotations +import inspect + import numpy as np from ConfigSpace import Configuration, ConfigurationSpace from scipy.optimize._differentialevolution import DifferentialEvolutionSolver @@ -14,6 +16,30 @@ __license__ = "3-clause BSD" +def check_kwarg(cls: type, kwarg_name: str) -> bool: + """ + Checks if a given class accepts a specific keyword argument in its __init__ method. + + Parameters + ---------- + cls (type): The class to inspect. + kwarg_name (str): The name of the keyword argument to check. + + Returns + ------- + bool: True if the class's __init__ method accepts the keyword argument, + otherwise False. + """ + # Get the signature of the class's __init__ method + init_signature = inspect.signature(cls.__init__) # type: ignore[misc] + + # Check if the kwarg_name is present in the signature as a parameter + for param in init_signature.parameters.values(): + if param.name == kwarg_name and param.default != inspect.Parameter.empty: + return True # It accepts the kwarg + return False # It does not accept the kwarg + + class DifferentialEvolution(AbstractAcquisitionMaximizer): """Get candidate solutions via `DifferentialEvolutionSolvers` from scipy. @@ -92,6 +118,11 @@ def func(x: np.ndarray) -> np.ndarray: transform_continuous_designs(design=x.T, origin="Diffrential Evolution", configspace=self._configspace) ) + accepts_seed = check_kwarg(DifferentialEvolutionSolver, "seed") + if accepts_seed: + kwargs = {"seed": self._rng.randint(1000)} + else: + kwargs = {"rng": self._rng.randint(1000)} ds = DifferentialEvolutionSolver( func, bounds=[[0, 1] for _ in range(len(self._configspace))], @@ -102,13 +133,13 @@ def func(x: np.ndarray) -> np.ndarray: tol=0.01, mutation=self.mutation, recombination=self.recombination, - rng=self._rng.randint(1000), polish=self.polish, callback=None, disp=False, init="latinhypercube", atol=0, vectorized=True, + **kwargs, ) _ = ds.solve()