From 3774d369ccf80845e90e292e350896b648e2992c Mon Sep 17 00:00:00 2001 From: gaurav Date: Wed, 23 Apr 2025 15:17:03 +0530 Subject: [PATCH 1/4] add nevregrd cma --- .tools/envs/testenv-linux.yml | 1 + .tools/envs/testenv-numpy.yml | 1 + .tools/envs/testenv-others.yml | 1 + .tools/envs/testenv-pandas.yml | 1 + environment.yml | 1 + pyproject.toml | 2 + src/optimagic/algorithms.py | 33 ++++ src/optimagic/config.py | 7 + .../optimizers/nevergrad_optimizers.py | 181 ++++++++++++++++++ 9 files changed, 228 insertions(+) create mode 100644 src/optimagic/optimizers/nevergrad_optimizers.py diff --git a/.tools/envs/testenv-linux.yml b/.tools/envs/testenv-linux.yml index 67fab9017..bfd69858d 100644 --- a/.tools/envs/testenv-linux.yml +++ b/.tools/envs/testenv-linux.yml @@ -22,6 +22,7 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests + - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests diff --git a/.tools/envs/testenv-numpy.yml b/.tools/envs/testenv-numpy.yml index 2cd35c4e0..90eb1ca18 100644 --- a/.tools/envs/testenv-numpy.yml +++ b/.tools/envs/testenv-numpy.yml @@ -20,6 +20,7 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests + - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests diff --git a/.tools/envs/testenv-others.yml b/.tools/envs/testenv-others.yml index 974cffec1..6a19fe3a7 100644 --- a/.tools/envs/testenv-others.yml +++ b/.tools/envs/testenv-others.yml @@ -20,6 +20,7 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests + - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests diff --git a/.tools/envs/testenv-pandas.yml b/.tools/envs/testenv-pandas.yml index 6d88f1016..7a3131471 100644 --- a/.tools/envs/testenv-pandas.yml +++ b/.tools/envs/testenv-pandas.yml @@ -20,6 +20,7 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests + - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests diff --git a/environment.yml b/environment.yml index 34ab4604b..6df094e32 100644 --- a/environment.yml +++ b/environment.yml @@ -25,6 +25,7 @@ dependencies: - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - myst-nb # docs + - nevergrad # run, tests - sphinx # docs - sphinx-copybutton # docs - sphinx-design # docs diff --git a/pyproject.toml b/pyproject.toml index 40b93ff8d..4c6f7bc95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "sqlalchemy>=1.3", "annotated-types", "typing-extensions", + "nevergrad", ] dynamic = ["version"] keywords = [ @@ -349,6 +350,7 @@ module = [ "cyipopt", "nlopt", "bokeh", + "nevergrad", "bokeh.layouts", "bokeh.models", "bokeh.plotting", diff --git a/src/optimagic/algorithms.py b/src/optimagic/algorithms.py index a892f5a51..1d3a7aa54 100644 --- a/src/optimagic/algorithms.py +++ b/src/optimagic/algorithms.py @@ -17,6 +17,7 @@ from optimagic.optimizers.ipopt import Ipopt from optimagic.optimizers.nag_optimizers import NagDFOLS, NagPyBOBYQA from optimagic.optimizers.neldermead import NelderMeadParallel +from optimagic.optimizers.nevergrad_optimizers import NevergradCMAES from optimagic.optimizers.nlopt_optimizers import ( NloptBOBYQA, NloptCCSAQ, @@ -170,6 +171,7 @@ def Scalar( @dataclass(frozen=True) class BoundedGlobalGradientFreeParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -362,6 +364,7 @@ def Scalar(self) -> BoundedGlobalGradientFreeNonlinearConstrainedScalarAlgorithm @dataclass(frozen=True) class BoundedGlobalGradientFreeScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -401,6 +404,7 @@ def Parallel(self) -> BoundedGlobalGradientFreeParallelScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalGradientFreeParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -456,6 +460,7 @@ def Scalar(self) -> GlobalGradientFreeNonlinearConstrainedParallelScalarAlgorith @dataclass(frozen=True) class GlobalGradientFreeParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -603,6 +608,7 @@ def Scalar(self) -> BoundedGradientFreeNonlinearConstrainedParallelScalarAlgorit @dataclass(frozen=True) class BoundedGradientFreeParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -697,6 +703,7 @@ def Scalar(self) -> BoundedGlobalNonlinearConstrainedParallelScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -1020,6 +1027,7 @@ def Local(self) -> GradientBasedLocalNonlinearConstrainedScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalGradientFreeAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -1083,6 +1091,7 @@ def Scalar(self) -> GlobalGradientFreeNonlinearConstrainedScalarAlgorithms: @dataclass(frozen=True) class GlobalGradientFreeScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -1126,6 +1135,7 @@ def Parallel(self) -> GlobalGradientFreeParallelScalarAlgorithms: @dataclass(frozen=True) class GlobalGradientFreeParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -1291,6 +1301,7 @@ def Scalar(self) -> BoundedGradientFreeNonlinearConstrainedScalarAlgorithms: @dataclass(frozen=True) class BoundedGradientFreeScalarAlgorithms(AlgoSelection): nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM @@ -1362,6 +1373,7 @@ def Parallel(self) -> BoundedGradientFreeLeastSquaresParallelAlgorithms: @dataclass(frozen=True) class BoundedGradientFreeParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pounders: Type[Pounders] = Pounders pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen @@ -1443,6 +1455,7 @@ def Scalar(self) -> GradientFreeNonlinearConstrainedParallelScalarAlgorithms: @dataclass(frozen=True) class GradientFreeParallelScalarAlgorithms(AlgoSelection): neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -1511,6 +1524,7 @@ def Scalar(self) -> BoundedGlobalNonlinearConstrainedScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -1559,6 +1573,7 @@ def Parallel(self) -> BoundedGlobalParallelScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -1627,6 +1642,7 @@ def Scalar(self) -> GlobalNonlinearConstrainedParallelScalarAlgorithms: @dataclass(frozen=True) class GlobalParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -1860,6 +1876,7 @@ def Scalar(self) -> BoundedNonlinearConstrainedParallelScalarAlgorithms: @dataclass(frozen=True) class BoundedParallelScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -2115,6 +2132,7 @@ def Local(self) -> GradientBasedLikelihoodLocalAlgorithms: @dataclass(frozen=True) class GlobalGradientFreeAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -2202,6 +2220,7 @@ def Scalar(self) -> GradientFreeLocalScalarAlgorithms: class BoundedGradientFreeAlgorithms(AlgoSelection): nag_dfols: Type[NagDFOLS] = NagDFOLS nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM @@ -2298,6 +2317,7 @@ def Scalar(self) -> GradientFreeNonlinearConstrainedScalarAlgorithms: class GradientFreeScalarAlgorithms(AlgoSelection): nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM @@ -2378,6 +2398,7 @@ def Parallel(self) -> GradientFreeLeastSquaresParallelAlgorithms: @dataclass(frozen=True) class GradientFreeParallelAlgorithms(AlgoSelection): neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pounders: Type[Pounders] = Pounders pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen @@ -2417,6 +2438,7 @@ def Scalar(self) -> GradientFreeParallelScalarAlgorithms: @dataclass(frozen=True) class BoundedGlobalAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -2498,6 +2520,7 @@ def Scalar(self) -> GlobalNonlinearConstrainedScalarAlgorithms: @dataclass(frozen=True) class GlobalScalarAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -2550,6 +2573,7 @@ def Parallel(self) -> GlobalParallelScalarAlgorithms: @dataclass(frozen=True) class GlobalParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -2811,6 +2835,7 @@ class BoundedScalarAlgorithms(AlgoSelection): fides: Type[Fides] = Fides ipopt: Type[Ipopt] = Ipopt nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_ccsaq: Type[NloptCCSAQ] = NloptCCSAQ nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA @@ -2911,6 +2936,7 @@ def Parallel(self) -> BoundedLeastSquaresParallelAlgorithms: @dataclass(frozen=True) class BoundedParallelAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pounders: Type[Pounders] = Pounders pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen @@ -3012,6 +3038,7 @@ def Scalar(self) -> NonlinearConstrainedParallelScalarAlgorithms: @dataclass(frozen=True) class ParallelScalarAlgorithms(AlgoSelection): neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen scipy_brute: Type[ScipyBrute] = ScipyBrute @@ -3118,6 +3145,7 @@ class GradientFreeAlgorithms(AlgoSelection): nag_dfols: Type[NagDFOLS] = NagDFOLS nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM @@ -3188,6 +3216,7 @@ def Scalar(self) -> GradientFreeScalarAlgorithms: @dataclass(frozen=True) class GlobalAlgorithms(AlgoSelection): + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_crs2_lm: Type[NloptCRS2LM] = NloptCRS2LM nlopt_direct: Type[NloptDirect] = NloptDirect nlopt_esch: Type[NloptESCH] = NloptESCH @@ -3319,6 +3348,7 @@ class BoundedAlgorithms(AlgoSelection): ipopt: Type[Ipopt] = Ipopt nag_dfols: Type[NagDFOLS] = NagDFOLS nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_ccsaq: Type[NloptCCSAQ] = NloptCCSAQ nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA @@ -3454,6 +3484,7 @@ class ScalarAlgorithms(AlgoSelection): ipopt: Type[Ipopt] = Ipopt nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_ccsaq: Type[NloptCCSAQ] = NloptCCSAQ nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA @@ -3582,6 +3613,7 @@ def Local(self) -> LikelihoodLocalAlgorithms: @dataclass(frozen=True) class ParallelAlgorithms(AlgoSelection): neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES pounders: Type[Pounders] = Pounders pygmo_gaco: Type[PygmoGaco] = PygmoGaco pygmo_pso_gen: Type[PygmoPsoGen] = PygmoPsoGen @@ -3629,6 +3661,7 @@ class Algorithms(AlgoSelection): nag_dfols: Type[NagDFOLS] = NagDFOLS nag_pybobyqa: Type[NagPyBOBYQA] = NagPyBOBYQA neldermead_parallel: Type[NelderMeadParallel] = NelderMeadParallel + nevergrad_cmaes: Type[NevergradCMAES] = NevergradCMAES nlopt_bobyqa: Type[NloptBOBYQA] = NloptBOBYQA nlopt_ccsaq: Type[NloptCCSAQ] = NloptCCSAQ nlopt_cobyla: Type[NloptCOBYLA] = NloptCOBYLA diff --git a/src/optimagic/config.py b/src/optimagic/config.py index d63ef54ac..023065eb4 100644 --- a/src/optimagic/config.py +++ b/src/optimagic/config.py @@ -54,6 +54,13 @@ else: IS_PYGMO_INSTALLED = True +try: + import nevergrad as ng # noqa: F401 +except ImportError: + IS_NEVERGRAD_INSTALLED = False +else: + IS_NEVERGRAD_INSTALLED = True + try: import cyipopt # noqa: F401 except ImportError: diff --git a/src/optimagic/optimizers/nevergrad_optimizers.py b/src/optimagic/optimizers/nevergrad_optimizers.py new file mode 100644 index 000000000..c653e38e4 --- /dev/null +++ b/src/optimagic/optimizers/nevergrad_optimizers.py @@ -0,0 +1,181 @@ +"""Implement nevergrad optimizers.""" + +from concurrent.futures import Future +from dataclasses import dataclass +from typing import Any, List + +import numpy as np +from numpy.typing import NDArray + +from optimagic import mark +from optimagic.config import IS_NEVERGRAD_INSTALLED +from optimagic.exceptions import NotInstalledError +from optimagic.optimization.algo_options import ( + STOPPING_MAXFUN_GLOBAL, +) +from optimagic.optimization.algorithm import Algorithm, InternalOptimizeResult +from optimagic.optimization.internal_optimization_problem import ( + InternalOptimizationProblem, +) +from optimagic.typing import ( + AggregationLevel, + Callable, + NonNegativeFloat, + PositiveInt, +) + +if IS_NEVERGRAD_INSTALLED: + import nevergrad as ng + + +@mark.minimizer( + name="nevergrad_cmaes", + solver_type=AggregationLevel.SCALAR, + is_available=IS_NEVERGRAD_INSTALLED, + is_global=True, + needs_jac=False, + needs_hess=False, + supports_parallelism=True, + supports_bounds=True, + supports_linear_constraints=False, + supports_nonlinear_constraints=False, + disable_history=False, +) +@dataclass(frozen=True) +class NevergradCMAES(Algorithm): + scale: NonNegativeFloat = 1.0 + population_size: int | None = None + elitist: bool = False + diagonal: bool = False + use_fast_implementation: bool = False + high_speed: bool = False + n_cores: PositiveInt = 1 + stopping_maxfun: PositiveInt = STOPPING_MAXFUN_GLOBAL + learning_rate_rank_one_update: NonNegativeFloat = 1.0 + learning_rate_rank_mu_update: NonNegativeFloat = 1.0 + ftol: NonNegativeFloat = 1e-11 + xtol: NonNegativeFloat = 1e-11 + random_init: bool = False + + def _solve_internal_problem( + self, problem: InternalOptimizationProblem, x0: NDArray[np.float64] + ) -> InternalOptimizeResult: + cma_options = { + "tolx": self.xtol, + "tolfun": self.ftol, + "CMA_rankmu": self.learning_rate_rank_mu_update, + "CMA_rankone": self.learning_rate_rank_one_update, + } + + optimizer = ng.optimizers.ParametrizedCMA( + scale=self.scale, + popsize=self.population_size, + elitist=self.elitist, + diagonal=self.diagonal, + high_speed=self.high_speed, + fcmaes=self.use_fast_implementation, + random_init=self.random_init, + inopts=cma_options, + ) + + res = nevergrad_internal( + problem=problem, + x0=x0, + optimizer=optimizer, + stopping_maxfun=self.stopping_maxfun, + n_cores=self.n_cores, + ) + + return res + + +""" helper function for nevergrad""" + + +def nevergrad_internal( + problem: InternalOptimizationProblem, + x0: NDArray[np.float64], + n_cores: int, + optimizer: Callable[..., Any], + stopping_maxfun: int, +) -> InternalOptimizeResult: + if not IS_NEVERGRAD_INSTALLED: + raise NotInstalledError("Nevergrad is not installed.") + + param = ng.p.Array( + init=np.clip(x0, problem.bounds.lower, problem.bounds.upper) + ).set_bounds(problem.bounds.lower, upper=problem.bounds.upper) + instrum = ng.p.Instrumentation(param) + + parametrized_optimizer = optimizer( + parametrization=instrum, budget=stopping_maxfun, num_workers=n_cores + ) + + executor = NevergradExecutor( + batch_fun=problem.batch_fun, n_cores=n_cores, budget=stopping_maxfun + ) + recommendation = parametrized_optimizer.minimize( + problem.fun, + executor=executor, + ) + best_x = recommendation.value[0][0] + + result = InternalOptimizeResult( + x=best_x, + fun=problem.fun(best_x), + success=True, + n_fun_evals=parametrized_optimizer.num_ask, + n_jac_evals=0, + ) + + return result + + +""" Custom Executor class that uses batch_fun inside """ + + +class NevergradExecutor: + def __init__( + self, + batch_fun: Callable[..., list[float | NDArray[np.float64]]], + n_cores: int, + budget: int, + ): + self._batch_fun: Callable[..., list[float | NDArray[np.float64]]] = batch_fun + self._n_cores: int = n_cores + self._budget: int = budget + self._batch_inputs: List[NDArray[np.float64]] = [] + self._futures: List[Future[Any]] = [] + self._submitted_count: int = 0 + + def submit( + self, func: Callable[..., Any], *args: Any, **kwargs: Any + ) -> Future[Any]: + future: Future[Any] = Future() + x = args[0] + self._batch_inputs.append(x) + self._futures.append(future) + self._submitted_count += 1 + + if len(self._batch_inputs) == self._n_cores: + self._run_batch() + + if self._submitted_count == self._budget: + self._flush() + + return future + + def _run_batch(self) -> None: + results = self._batch_fun( + x_list=self._batch_inputs, n_cores=len(self._batch_inputs) + ) + + for future, result in zip(self._futures, results, strict=False): + future.set_result(result) + + self._batch_inputs.clear() + self._futures.clear() + + def _flush(self) -> None: + if self._batch_inputs: + self._run_batch() From 9c0eafd67b161e5244feb006c834b85ac1f5d7b8 Mon Sep 17 00:00:00 2001 From: gauravmanmode Date: Wed, 30 Apr 2025 22:40:57 +0530 Subject: [PATCH 2/4] Update environment.yml --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index 9467842fb..83e340b3a 100644 --- a/environment.yml +++ b/environment.yml @@ -25,7 +25,6 @@ dependencies: - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - myst-nb # docs - - nevergrad # run, tests - sphinx # docs - sphinx-copybutton # docs - sphinx-design # docs @@ -43,6 +42,7 @@ dependencies: - DFO-LS>=1.5.3 # dev, tests - Py-BOBYQA # dev, tests - fides==0.7.4 # dev, tests + - nevergrad # dev, tests - kaleido # dev, tests - pre-commit>=4 # dev - -e . # dev From 4f76bf26d02fd22979fc5e3a0275598d477c9c43 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:11:31 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .tools/envs/testenv-linux.yml | 2 +- .tools/envs/testenv-numpy.yml | 2 +- .tools/envs/testenv-others.yml | 2 +- .tools/envs/testenv-pandas.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.tools/envs/testenv-linux.yml b/.tools/envs/testenv-linux.yml index 9a1947396..7ef601acd 100644 --- a/.tools/envs/testenv-linux.yml +++ b/.tools/envs/testenv-linux.yml @@ -22,7 +22,6 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests @@ -33,6 +32,7 @@ dependencies: - DFO-LS>=1.5.3 # dev, tests - Py-BOBYQA # dev, tests - fides==0.7.4 # dev, tests + - nevergrad # dev, tests - kaleido # dev, tests - pandas-stubs # dev, tests - types-cffi # dev, tests diff --git a/.tools/envs/testenv-numpy.yml b/.tools/envs/testenv-numpy.yml index 24d619375..9b2a0eb9e 100644 --- a/.tools/envs/testenv-numpy.yml +++ b/.tools/envs/testenv-numpy.yml @@ -20,7 +20,6 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests @@ -31,6 +30,7 @@ dependencies: - DFO-LS>=1.5.3 # dev, tests - Py-BOBYQA # dev, tests - fides==0.7.4 # dev, tests + - nevergrad # dev, tests - kaleido # dev, tests - types-cffi # dev, tests - types-openpyxl # dev, tests diff --git a/.tools/envs/testenv-others.yml b/.tools/envs/testenv-others.yml index 2592accd3..ee8a34b11 100644 --- a/.tools/envs/testenv-others.yml +++ b/.tools/envs/testenv-others.yml @@ -20,7 +20,6 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests @@ -31,6 +30,7 @@ dependencies: - DFO-LS>=1.5.3 # dev, tests - Py-BOBYQA # dev, tests - fides==0.7.4 # dev, tests + - nevergrad # dev, tests - kaleido # dev, tests - pandas-stubs # dev, tests - types-cffi # dev, tests diff --git a/.tools/envs/testenv-pandas.yml b/.tools/envs/testenv-pandas.yml index 87dc5f7cd..e69baf05f 100644 --- a/.tools/envs/testenv-pandas.yml +++ b/.tools/envs/testenv-pandas.yml @@ -20,7 +20,6 @@ dependencies: - pybaum>=0.1.2 # run, tests - scipy>=1.2.1 # run, tests - sqlalchemy # run, tests - - nevergrad # run, tests - seaborn # dev, tests - mypy=1.14.1 # dev, tests - pyyaml # dev, tests @@ -31,6 +30,7 @@ dependencies: - DFO-LS>=1.5.3 # dev, tests - Py-BOBYQA # dev, tests - fides==0.7.4 # dev, tests + - nevergrad # dev, tests - kaleido # dev, tests - types-cffi # dev, tests - types-openpyxl # dev, tests From c8114b27c7ed75296f57df5774d1396146bc800b Mon Sep 17 00:00:00 2001 From: gaurav Date: Thu, 1 May 2025 11:53:29 +0530 Subject: [PATCH 4/4] fixes --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 4849d5396..1f8329c2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ dependencies = [ "annotated-types", "typing-extensions", "iminuit", + "nevergrad", ] dynamic = ["version"] keywords = [