diff --git a/smac/acquisition/maximizer/differential_evolution.py b/smac/acquisition/maximizer/differential_evolution.py index 855842783..4751ea427 100644 --- a/smac/acquisition/maximizer/differential_evolution.py +++ b/smac/acquisition/maximizer/differential_evolution.py @@ -1,9 +1,10 @@ from __future__ import annotations import numpy as np -from ConfigSpace import Configuration +from ConfigSpace import Configuration, ConfigurationSpace from scipy.optimize._differentialevolution import DifferentialEvolutionSolver +from smac.acquisition.function.abstract_acquisition_function import AbstractAcquisitionFunction from smac.acquisition.maximizer import AbstractAcquisitionMaximizer from smac.utils.configspace import transform_continuous_designs @@ -24,7 +25,42 @@ class DifferentialEvolution(AbstractAcquisitionMaximizer): [1] Storn, R and Price, K, Differential Evolution - a Simple and Efficient Heuristic for Global Optimization over Continuous Spaces, Journal of Global Optimization, 1997, 11, 341 - 359. + + Parameters + ---------- + configspace : ConfigurationSpace + acquisition_function : AbstractAcquisitionFunction + challengers : int, defaults to 50000 + Number of challengers. + max_iter: int | None, defaults to None + Maximum number of iterations that the DE will perform. + strategy: str, defaults to "best1bin" + The strategy to use for the DE. + polish: bool, defaults to True + Whether to polish the final solution using L-BFGS-B. + mutation: tuple[float, float], defaults to (0.5, 1.0) + The mutation constant. + recombination: float, defaults to 0.7 + The recombination constant. + seed : int, defaults to 0 """ + def __init__(self, + configspace: ConfigurationSpace, + acquisition_function: AbstractAcquisitionFunction | None = None, + max_iter: int = 1000, + challengers: int = 50000, + strategy: str = "best1bin", + polish: bool = True, + mutation: tuple[float, float] = (0.5, 1.0), + recombination: float =0.7, + seed: int = 0): + super().__init__(configspace, acquisition_function, challengers, seed) + # raise NotImplementedError("DifferentialEvolution is not yet implemented.") + self.max_iter = max_iter + self.strategy = strategy + self.polish = polish + self.mutation = mutation + self.recombination = recombination def _maximize( self, @@ -37,26 +73,31 @@ def _maximize( def func(x: np.ndarray) -> np.ndarray: assert self._acquisition_function is not None - return -self._acquisition_function([transform_continuous_designs( - design=np.expand_dims(x, axis=0), origin="Diffrential Evolution", configspace=self._configspace - )[0]]) + if len(x.shape) == 1: + return -self._acquisition_function([transform_continuous_designs( + design=np.expand_dims(x, axis=0), origin="Diffrential Evolution", configspace=self._configspace + )[0]]) + return -self._acquisition_function(transform_continuous_designs( + design=x.T, origin="Diffrential Evolution", configspace=self._configspace + )) ds = DifferentialEvolutionSolver( func, bounds=[[0, 1] for _ in range(len(self._configspace))], args=(), - strategy="best1bin", - maxiter=1000, - popsize=50, + strategy=self.strategy, + maxiter=self.max_iter, + popsize=self._challengers // self.max_iter, tol=0.01, - mutation=(0.5, 1), - recombination=0.7, + mutation=self.mutation, + recombination=self.recombination, seed=self._rng.randint(1000), - polish=True, + polish=self.polish, callback=None, disp=False, init="latinhypercube", atol=0, + vectorized=True ) _ = ds.solve()