dfbench 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dfbench/__init__.py +48 -0
- dfbench/algorithms/__init__.py +219 -0
- dfbench/algorithms/derivative_free/__init__.py +23 -0
- dfbench/algorithms/derivative_free/_dfo_common.py +150 -0
- dfbench/algorithms/derivative_free/_scipy_common.py +124 -0
- dfbench/algorithms/derivative_free/nelder_mead.py +97 -0
- dfbench/algorithms/derivative_free/omads_mads.py +385 -0
- dfbench/algorithms/derivative_free/pdfo/__init__.py +11 -0
- dfbench/algorithms/derivative_free/pdfo/lincoa.py +139 -0
- dfbench/algorithms/derivative_free/pdfo/newuoa.py +127 -0
- dfbench/algorithms/derivative_free/pdfo/uobyqa.py +122 -0
- dfbench/algorithms/derivative_free/powell.py +94 -0
- dfbench/algorithms/derivative_free/pybobyqa.py +170 -0
- dfbench/algorithms/evolutionary/__init__.py +35 -0
- dfbench/algorithms/evolutionary/cmaes_sep_cma.py +192 -0
- dfbench/algorithms/evolutionary/evosax_es.py +336 -0
- dfbench/algorithms/evolutionary/evox_es.py +307 -0
- dfbench/algorithms/evolutionary/evox_pso.py +198 -0
- dfbench/algorithms/evolutionary/jax_es.py +361 -0
- dfbench/algorithms/evolutionary/nevergrad/__init__.py +11 -0
- dfbench/algorithms/evolutionary/nevergrad/_common.py +66 -0
- dfbench/algorithms/evolutionary/nevergrad/ngopt.py +126 -0
- dfbench/algorithms/evolutionary/nevergrad/oneplusone.py +130 -0
- dfbench/algorithms/evolutionary/nevergrad/tbpsa.py +143 -0
- dfbench/algorithms/evolutionary/pycma_cmaes.py +599 -0
- dfbench/algorithms/evolutionary/random_search.py +92 -0
- dfbench/algorithms/generative/vae_sampling.py +488 -0
- dfbench/algorithms/global_search/__init__.py +12 -0
- dfbench/algorithms/global_search/basin_hopping.py +142 -0
- dfbench/algorithms/global_search/dual_annealing.py +133 -0
- dfbench/algorithms/gradient_based/__init__.py +151 -0
- dfbench/algorithms/gradient_based/adam_gd.py +87 -0
- dfbench/algorithms/gradient_based/custom_jax.py +867 -0
- dfbench/algorithms/gradient_based/lbfgs_gd.py +157 -0
- dfbench/algorithms/gradient_based/na_adam_gd.py +266 -0
- dfbench/algorithms/gradient_based/optax/__init__.py +68 -0
- dfbench/algorithms/gradient_based/optax/_common.py +198 -0
- dfbench/algorithms/gradient_based/optax/adabelief.py +32 -0
- dfbench/algorithms/gradient_based/optax/adadelta.py +31 -0
- dfbench/algorithms/gradient_based/optax/adafactor.py +31 -0
- dfbench/algorithms/gradient_based/optax/adagrad.py +30 -0
- dfbench/algorithms/gradient_based/optax/adam.py +28 -0
- dfbench/algorithms/gradient_based/optax/adamax.py +32 -0
- dfbench/algorithms/gradient_based/optax/adamaxw.py +33 -0
- dfbench/algorithms/gradient_based/optax/adamw.py +33 -0
- dfbench/algorithms/gradient_based/optax/adan.py +35 -0
- dfbench/algorithms/gradient_based/optax/amsgrad.py +32 -0
- dfbench/algorithms/gradient_based/optax/lamb.py +33 -0
- dfbench/algorithms/gradient_based/optax/lion.py +33 -0
- dfbench/algorithms/gradient_based/optax/lookahead.py +129 -0
- dfbench/algorithms/gradient_based/optax/nadam.py +32 -0
- dfbench/algorithms/gradient_based/optax/nadamw.py +33 -0
- dfbench/algorithms/gradient_based/optax/noisy_sgd.py +33 -0
- dfbench/algorithms/gradient_based/optax/novograd.py +35 -0
- dfbench/algorithms/gradient_based/optax/oadam.py +33 -0
- dfbench/algorithms/gradient_based/optax/ogd.py +28 -0
- dfbench/algorithms/gradient_based/optax/polyak_sgd.py +111 -0
- dfbench/algorithms/gradient_based/optax/radam.py +33 -0
- dfbench/algorithms/gradient_based/optax/rmsprop.py +33 -0
- dfbench/algorithms/gradient_based/optax/rprop.py +35 -0
- dfbench/algorithms/gradient_based/optax/sam.py +147 -0
- dfbench/algorithms/gradient_based/optax/schedule_free_adam.py +45 -0
- dfbench/algorithms/gradient_based/optax/sgd.py +73 -0
- dfbench/algorithms/gradient_based/optax/sign.py +56 -0
- dfbench/algorithms/gradient_based/optax/sm3.py +28 -0
- dfbench/algorithms/gradient_based/optax/sophia.py +140 -0
- dfbench/algorithms/gradient_based/optax/yogi.py +34 -0
- dfbench/algorithms/gradient_based/optax_lbfgs.py +121 -0
- dfbench/algorithms/gradient_based/sa_gd.py +241 -0
- dfbench/algorithms/gradient_based/scipy/__init__.py +31 -0
- dfbench/algorithms/gradient_based/scipy/_common.py +398 -0
- dfbench/algorithms/gradient_based/scipy/bfgs.py +54 -0
- dfbench/algorithms/gradient_based/scipy/cobyla.py +65 -0
- dfbench/algorithms/gradient_based/scipy/cobyqa.py +65 -0
- dfbench/algorithms/gradient_based/scipy/dogleg.py +70 -0
- dfbench/algorithms/gradient_based/scipy/lbfgsb.py +62 -0
- dfbench/algorithms/gradient_based/scipy/newton_cg.py +58 -0
- dfbench/algorithms/gradient_based/scipy/nonlinear_cg.py +52 -0
- dfbench/algorithms/gradient_based/scipy/slsqp.py +52 -0
- dfbench/algorithms/gradient_based/scipy/sr1.py +82 -0
- dfbench/algorithms/gradient_based/scipy/tnc.py +62 -0
- dfbench/algorithms/gradient_based/scipy/trust_constr.py +75 -0
- dfbench/algorithms/gradient_based/scipy/trust_krylov.py +68 -0
- dfbench/algorithms/gradient_based/scipy/trust_ncg.py +71 -0
- dfbench/algorithms/surrogate_based/__init__.py +46 -0
- dfbench/algorithms/surrogate_based/ax_baxus.py +237 -0
- dfbench/algorithms/surrogate_based/ax_saasbo.py +162 -0
- dfbench/algorithms/surrogate_based/botorch/__init__.py +24 -0
- dfbench/algorithms/surrogate_based/botorch/_botorch_common.py +179 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_bo.py +295 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_gebo.py +225 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_linebo.py +217 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_qkg.py +160 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_qnei.py +167 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_rembo.py +181 -0
- dfbench/algorithms/surrogate_based/botorch/botorch_turbo.py +489 -0
- dfbench/algorithms/surrogate_based/hebo_bo.py +118 -0
- dfbench/algorithms/surrogate_based/restir.py +371 -0
- dfbench/algorithms/surrogate_based/smac_bo.py +131 -0
- dfbench/algorithms/surrogate_based/turbo_lbfgs.py +276 -0
- dfbench/benchmark/__init__.py +8 -0
- dfbench/benchmark/benchmark.py +923 -0
- dfbench/benchmark/metrics.py +369 -0
- dfbench/core/_init_env.py +16 -0
- dfbench/core/algorithm.py +205 -0
- dfbench/core/config.py +51 -0
- dfbench/core/display.py +526 -0
- dfbench/core/objective.py +2110 -0
- dfbench/core/problem.py +66 -0
- dfbench/core/utils.py +44 -0
- dfbench/problems/__init__.py +34 -0
- dfbench/problems/base_problem.py +334 -0
- dfbench/problems/uifo/__init__.py +15 -0
- dfbench/problems/uifo/uifo_problem.py +589 -0
- dfbench/problems/voyager/__init__.py +13 -0
- dfbench/problems/voyager/constrained_voyager_problem.py +258 -0
- dfbench/problems/voyager/voyager_problem.py +197 -0
- dfbench/problems/voyager/voyager_tuning_problem.py +183 -0
- dfbench-0.1.0.dist-info/METADATA +554 -0
- dfbench-0.1.0.dist-info/RECORD +122 -0
- dfbench-0.1.0.dist-info/WHEEL +4 -0
- dfbench-0.1.0.dist-info/licenses/LICENSE +21 -0
dfbench/__init__.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Differometor Benchmark package.
|
|
2
|
+
|
|
3
|
+
Provides optimization algorithms, problem definitions, and benchmarking tools.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
### Core classes
|
|
7
|
+
`from dfbench import Objective`
|
|
8
|
+
|
|
9
|
+
### Protocols
|
|
10
|
+
`from dfbench import ContinuousProblem, OptimizationAlgorithm, AlgorithmType`
|
|
11
|
+
|
|
12
|
+
### Algorithms (hierarchical)
|
|
13
|
+
`from dfbench.algorithms import AdamGD, EvoxES, BotorchBO`
|
|
14
|
+
|
|
15
|
+
### Problems (hierarchical)
|
|
16
|
+
`from dfbench.problems import VoyagerProblem, UIFOProblem`
|
|
17
|
+
|
|
18
|
+
### Benchmarking (hierarchical)
|
|
19
|
+
`from dfbench.benchmark import Benchmark, AlgorithmConfig`
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
# Initialize environment variables first
|
|
23
|
+
import dfbench.core._init_env # noqa: F401
|
|
24
|
+
|
|
25
|
+
# Import protocols
|
|
26
|
+
from dfbench.core.problem import ContinuousProblem
|
|
27
|
+
from dfbench.core.algorithm import OptimizationAlgorithm, AlgorithmType
|
|
28
|
+
|
|
29
|
+
# Import core utilities
|
|
30
|
+
from dfbench.core.config import create_parser
|
|
31
|
+
from dfbench.core.utils import t2j, j2t
|
|
32
|
+
|
|
33
|
+
# Import Objective for external use
|
|
34
|
+
from dfbench.core.objective import Objective
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
# Core
|
|
39
|
+
"Objective",
|
|
40
|
+
# Protocols
|
|
41
|
+
"ContinuousProblem",
|
|
42
|
+
"OptimizationAlgorithm",
|
|
43
|
+
"AlgorithmType",
|
|
44
|
+
# Utilities
|
|
45
|
+
"create_parser",
|
|
46
|
+
"t2j",
|
|
47
|
+
"j2t",
|
|
48
|
+
]
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""Optimization algorithms."""
|
|
2
|
+
|
|
3
|
+
from dfbench.algorithms.derivative_free.nelder_mead import NelderMead
|
|
4
|
+
from dfbench.algorithms.derivative_free.omads_mads import OmadsMADS, OmadsOrthoMADS
|
|
5
|
+
from dfbench.algorithms.derivative_free.powell import Powell
|
|
6
|
+
from dfbench.algorithms.global_search.basin_hopping import BasinHopping
|
|
7
|
+
from dfbench.algorithms.global_search.dual_annealing import DualAnnealing
|
|
8
|
+
from dfbench.algorithms.evolutionary.evox_es import EvoxES
|
|
9
|
+
from dfbench.algorithms.evolutionary.evox_pso import EvoxPSO
|
|
10
|
+
from dfbench.algorithms.evolutionary.nevergrad.ngopt import NevergradNGOpt
|
|
11
|
+
from dfbench.algorithms.evolutionary.nevergrad.oneplusone import NevergradOnePlusOne
|
|
12
|
+
from dfbench.algorithms.evolutionary.nevergrad.tbpsa import NevergradTBPSA
|
|
13
|
+
from dfbench.algorithms.evolutionary.random_search import RandomSearch
|
|
14
|
+
from dfbench.algorithms.evolutionary.pycma_cmaes import (
|
|
15
|
+
PyCMACMAES,
|
|
16
|
+
PyCMAActiveCMAES,
|
|
17
|
+
PyCMAIPOP,
|
|
18
|
+
PyCMABIPOP,
|
|
19
|
+
)
|
|
20
|
+
from dfbench.algorithms.evolutionary.cmaes_sep_cma import CMAESSepCMA
|
|
21
|
+
from dfbench.algorithms.evolutionary.evosax_es import EvosaxMAES, EvosaxLMMAES
|
|
22
|
+
from dfbench.algorithms.evolutionary.jax_es import JAXOnePlusOneES, JAXMuLambdaES
|
|
23
|
+
from dfbench.algorithms.gradient_based.adam_gd import AdamGD
|
|
24
|
+
from dfbench.algorithms.gradient_based.custom_jax import (
|
|
25
|
+
ARCJAX,
|
|
26
|
+
ASAMJAX,
|
|
27
|
+
AdamToLBFGSJAX,
|
|
28
|
+
EntropySGDJAX,
|
|
29
|
+
GDRestartsJAX,
|
|
30
|
+
GaussianSmoothingGDJAX,
|
|
31
|
+
NoisyAdamJAX,
|
|
32
|
+
OAdamJAX,
|
|
33
|
+
OGDJAX,
|
|
34
|
+
PerturbedGDJAX,
|
|
35
|
+
SGHMCJAX,
|
|
36
|
+
SGLDJAX,
|
|
37
|
+
)
|
|
38
|
+
from dfbench.algorithms.gradient_based.scipy.bfgs import BFGS
|
|
39
|
+
from dfbench.algorithms.gradient_based.scipy.cobyla import COBYLA
|
|
40
|
+
from dfbench.algorithms.gradient_based.scipy.cobyqa import COBYQA
|
|
41
|
+
from dfbench.algorithms.gradient_based.scipy.dogleg import Dogleg
|
|
42
|
+
from dfbench.algorithms.gradient_based.lbfgs_gd import LBFGSGD
|
|
43
|
+
from dfbench.algorithms.gradient_based.scipy.lbfgsb import LBFGSB
|
|
44
|
+
from dfbench.algorithms.gradient_based.na_adam_gd import NAAdamGD
|
|
45
|
+
from dfbench.algorithms.gradient_based.scipy.newton_cg import NewtonCG
|
|
46
|
+
from dfbench.algorithms.gradient_based.scipy.nonlinear_cg import NonlinearCG
|
|
47
|
+
from dfbench.algorithms.gradient_based.sa_gd import SAGD
|
|
48
|
+
from dfbench.algorithms.gradient_based.scipy.slsqp import SLSQP
|
|
49
|
+
from dfbench.algorithms.gradient_based.scipy.sr1 import SR1
|
|
50
|
+
from dfbench.algorithms.gradient_based.scipy.tnc import TNC
|
|
51
|
+
from dfbench.algorithms.gradient_based.scipy.trust_constr import TrustConstr
|
|
52
|
+
from dfbench.algorithms.gradient_based.scipy.trust_krylov import TrustKrylov
|
|
53
|
+
from dfbench.algorithms.gradient_based.scipy.trust_ncg import TrustNCG
|
|
54
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_bo import BotorchBO
|
|
55
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_turbo import BotorchTuRBO
|
|
56
|
+
from dfbench.algorithms.surrogate_based.restir import ReSTIR
|
|
57
|
+
from dfbench.algorithms.surrogate_based.ax_baxus import BAxUS
|
|
58
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_qnei import BotorchqNEI
|
|
59
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_qkg import BotorchqKG
|
|
60
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_rembo import REMBO
|
|
61
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_gebo import GEBO
|
|
62
|
+
from dfbench.algorithms.surrogate_based.botorch.botorch_linebo import LineBO
|
|
63
|
+
from dfbench.algorithms.surrogate_based.hebo_bo import HEBO
|
|
64
|
+
from dfbench.algorithms.surrogate_based.turbo_lbfgs import TuRBOLBFGS
|
|
65
|
+
from dfbench.algorithms.generative.vae_sampling import VAESampling
|
|
66
|
+
from dfbench.algorithms.derivative_free.pdfo.uobyqa import PDFOUOBYQA
|
|
67
|
+
from dfbench.algorithms.derivative_free.pdfo.newuoa import PDFONEWUOA
|
|
68
|
+
from dfbench.algorithms.derivative_free.pdfo.lincoa import PDFOLINCOA
|
|
69
|
+
from dfbench.algorithms.derivative_free.pybobyqa import PyBOBYQA
|
|
70
|
+
|
|
71
|
+
# Optax
|
|
72
|
+
from dfbench.algorithms.gradient_based.optax.adam import OptaxAdam
|
|
73
|
+
from dfbench.algorithms.gradient_based.optax.adamw import OptaxAdamW
|
|
74
|
+
from dfbench.algorithms.gradient_based.optax.adabelief import OptaxAdaBelief
|
|
75
|
+
from dfbench.algorithms.gradient_based.optax.adafactor import OptaxAdafactor
|
|
76
|
+
from dfbench.algorithms.gradient_based.optax.amsgrad import OptaxAMSGrad
|
|
77
|
+
from dfbench.algorithms.gradient_based.optax.adagrad import OptaxAdaGrad
|
|
78
|
+
from dfbench.algorithms.gradient_based.optax.adadelta import OptaxAdaDelta
|
|
79
|
+
from dfbench.algorithms.gradient_based.optax.adamax import OptaxAdaMax
|
|
80
|
+
from dfbench.algorithms.gradient_based.optax.adamaxw import OptaxAdaMaxW
|
|
81
|
+
from dfbench.algorithms.gradient_based.optax.adan import OptaxAdan
|
|
82
|
+
from dfbench.algorithms.gradient_based.optax.lion import OptaxLion
|
|
83
|
+
from dfbench.algorithms.gradient_based.optax.lamb import OptaxLAMB
|
|
84
|
+
from dfbench.algorithms.gradient_based.optax.nadam import OptaxNadam
|
|
85
|
+
from dfbench.algorithms.gradient_based.optax.nadamw import OptaxNadamW
|
|
86
|
+
from dfbench.algorithms.gradient_based.optax.rmsprop import OptaxRMSProp
|
|
87
|
+
from dfbench.algorithms.gradient_based.optax.rprop import OptaxRProp
|
|
88
|
+
from dfbench.algorithms.gradient_based.optax.radam import OptaxRAdam
|
|
89
|
+
from dfbench.algorithms.gradient_based.optax.sgd import OptaxSGD, OptaxSGDM, OptaxNAG
|
|
90
|
+
from dfbench.algorithms.gradient_based.optax.noisy_sgd import OptaxNoisySGD
|
|
91
|
+
from dfbench.algorithms.gradient_based.optax.polyak_sgd import OptaxPolyakSGD
|
|
92
|
+
from dfbench.algorithms.gradient_based.optax.sam import OptaxSAM
|
|
93
|
+
from dfbench.algorithms.gradient_based.optax.sophia import OptaxSophia
|
|
94
|
+
from dfbench.algorithms.gradient_based.optax.lookahead import OptaxLookahead
|
|
95
|
+
from dfbench.algorithms.gradient_based.optax.schedule_free_adam import OptaxScheduleFreeAdam
|
|
96
|
+
from dfbench.algorithms.gradient_based.optax.yogi import OptaxYogi
|
|
97
|
+
from dfbench.algorithms.gradient_based.optax.novograd import OptaxNovoGrad
|
|
98
|
+
from dfbench.algorithms.gradient_based.optax.ogd import OptaxOGD
|
|
99
|
+
from dfbench.algorithms.gradient_based.optax.oadam import OptaxOAdam
|
|
100
|
+
from dfbench.algorithms.gradient_based.optax.sign import OptaxSignSGD, OptaxSignum
|
|
101
|
+
from dfbench.algorithms.gradient_based.optax.sm3 import OptaxSM3
|
|
102
|
+
from dfbench.algorithms.gradient_based.optax_lbfgs import OptaxLBFGS
|
|
103
|
+
|
|
104
|
+
# External-package algorithms: imported only when their dependencies exist.
|
|
105
|
+
try:
|
|
106
|
+
from dfbench.algorithms.surrogate_based.ax_saasbo import AxSAASBO
|
|
107
|
+
except ImportError:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
from dfbench.algorithms.surrogate_based.smac_bo import SMAC
|
|
112
|
+
except ImportError:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
__all__ = [
|
|
116
|
+
"BasinHopping",
|
|
117
|
+
"DualAnnealing",
|
|
118
|
+
"NelderMead",
|
|
119
|
+
"OmadsMADS",
|
|
120
|
+
"OmadsOrthoMADS",
|
|
121
|
+
"Powell",
|
|
122
|
+
"EvoxES",
|
|
123
|
+
"EvoxPSO",
|
|
124
|
+
"NevergradNGOpt",
|
|
125
|
+
"NevergradOnePlusOne",
|
|
126
|
+
"NevergradTBPSA",
|
|
127
|
+
"RandomSearch",
|
|
128
|
+
"PyCMACMAES",
|
|
129
|
+
"PyCMAActiveCMAES",
|
|
130
|
+
"PyCMAIPOP",
|
|
131
|
+
"PyCMABIPOP",
|
|
132
|
+
"CMAESSepCMA",
|
|
133
|
+
"EvosaxMAES",
|
|
134
|
+
"EvosaxLMMAES",
|
|
135
|
+
"JAXOnePlusOneES",
|
|
136
|
+
"JAXMuLambdaES",
|
|
137
|
+
"AdamGD",
|
|
138
|
+
"SGLDJAX",
|
|
139
|
+
"ASAMJAX",
|
|
140
|
+
"AdamToLBFGSJAX",
|
|
141
|
+
"EntropySGDJAX",
|
|
142
|
+
"SGHMCJAX",
|
|
143
|
+
"ARCJAX",
|
|
144
|
+
"OGDJAX",
|
|
145
|
+
"OAdamJAX",
|
|
146
|
+
"PerturbedGDJAX",
|
|
147
|
+
"NoisyAdamJAX",
|
|
148
|
+
"GDRestartsJAX",
|
|
149
|
+
"GaussianSmoothingGDJAX",
|
|
150
|
+
"BFGS",
|
|
151
|
+
"COBYLA",
|
|
152
|
+
"COBYQA",
|
|
153
|
+
"Dogleg",
|
|
154
|
+
"LBFGSGD",
|
|
155
|
+
"LBFGSB",
|
|
156
|
+
"NAAdamGD",
|
|
157
|
+
"NewtonCG",
|
|
158
|
+
"NonlinearCG",
|
|
159
|
+
"SAGD",
|
|
160
|
+
"SLSQP",
|
|
161
|
+
"SR1",
|
|
162
|
+
"TNC",
|
|
163
|
+
"TrustConstr",
|
|
164
|
+
"TrustKrylov",
|
|
165
|
+
"TrustNCG",
|
|
166
|
+
"BotorchBO",
|
|
167
|
+
"BotorchTuRBO",
|
|
168
|
+
"ReSTIR",
|
|
169
|
+
"AxSAASBO",
|
|
170
|
+
"BAxUS",
|
|
171
|
+
"BotorchqNEI",
|
|
172
|
+
"BotorchqKG",
|
|
173
|
+
"REMBO",
|
|
174
|
+
"GEBO",
|
|
175
|
+
"LineBO",
|
|
176
|
+
"HEBO",
|
|
177
|
+
"SMAC",
|
|
178
|
+
"TuRBOLBFGS",
|
|
179
|
+
"VAESampling",
|
|
180
|
+
"PDFOUOBYQA",
|
|
181
|
+
"PDFONEWUOA",
|
|
182
|
+
"PDFOLINCOA",
|
|
183
|
+
"PyBOBYQA",
|
|
184
|
+
# Optax batch
|
|
185
|
+
"OptaxAdam",
|
|
186
|
+
"OptaxAdamW",
|
|
187
|
+
"OptaxAdaBelief",
|
|
188
|
+
"OptaxAdafactor",
|
|
189
|
+
"OptaxAMSGrad",
|
|
190
|
+
"OptaxAdaGrad",
|
|
191
|
+
"OptaxAdaDelta",
|
|
192
|
+
"OptaxAdaMax",
|
|
193
|
+
"OptaxAdaMaxW",
|
|
194
|
+
"OptaxAdan",
|
|
195
|
+
"OptaxLion",
|
|
196
|
+
"OptaxLAMB",
|
|
197
|
+
"OptaxNadam",
|
|
198
|
+
"OptaxNadamW",
|
|
199
|
+
"OptaxRMSProp",
|
|
200
|
+
"OptaxRProp",
|
|
201
|
+
"OptaxRAdam",
|
|
202
|
+
"OptaxSGD",
|
|
203
|
+
"OptaxSGDM",
|
|
204
|
+
"OptaxNAG",
|
|
205
|
+
"OptaxNoisySGD",
|
|
206
|
+
"OptaxPolyakSGD",
|
|
207
|
+
"OptaxSAM",
|
|
208
|
+
"OptaxSophia",
|
|
209
|
+
"OptaxLookahead",
|
|
210
|
+
"OptaxScheduleFreeAdam",
|
|
211
|
+
"OptaxYogi",
|
|
212
|
+
"OptaxNovoGrad",
|
|
213
|
+
"OptaxOGD",
|
|
214
|
+
"OptaxOAdam",
|
|
215
|
+
"OptaxSignSGD",
|
|
216
|
+
"OptaxSignum",
|
|
217
|
+
"OptaxSM3",
|
|
218
|
+
"OptaxLBFGS",
|
|
219
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Derivative-free optimization algorithms.
|
|
2
|
+
|
|
3
|
+
Includes mesh-based direct search (OMADS), Powell-style trust-region methods
|
|
4
|
+
(PDFO: UOBYQA, NEWUOA, LINCOA; plus Py-BOBYQA), and SciPy classics
|
|
5
|
+
(Nelder-Mead, Powell).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dfbench.algorithms.derivative_free.nelder_mead import NelderMead
|
|
9
|
+
from dfbench.algorithms.derivative_free.omads_mads import OmadsMADS, OmadsOrthoMADS
|
|
10
|
+
from dfbench.algorithms.derivative_free.pdfo import PDFOLINCOA, PDFONEWUOA, PDFOUOBYQA
|
|
11
|
+
from dfbench.algorithms.derivative_free.powell import Powell
|
|
12
|
+
from dfbench.algorithms.derivative_free.pybobyqa import PyBOBYQA
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"NelderMead",
|
|
16
|
+
"OmadsMADS",
|
|
17
|
+
"OmadsOrthoMADS",
|
|
18
|
+
"PDFOLINCOA",
|
|
19
|
+
"PDFONEWUOA",
|
|
20
|
+
"PDFOUOBYQA",
|
|
21
|
+
"Powell",
|
|
22
|
+
"PyBOBYQA",
|
|
23
|
+
]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Common derivative-free optimization wrapper utilities.
|
|
2
|
+
|
|
3
|
+
Provides shared infrastructure for wrapping DFO solvers (PDFO, Py-BOBYQA, etc.)
|
|
4
|
+
so they integrate cleanly with the Objective / OptimizationAlgorithm interface.
|
|
5
|
+
|
|
6
|
+
Key responsibilities:
|
|
7
|
+
- Convert between JAX arrays and NumPy arrays expected by solvers.
|
|
8
|
+
- Evaluate ``obj.value(...)`` in bounded space and log results.
|
|
9
|
+
- Enforce Objective budgets via a callback / early-termination mechanism.
|
|
10
|
+
- Support multistart restarts with fresh random starting points.
|
|
11
|
+
- Handle NaN / Inf returns and solver failure codes gracefully.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import jax.numpy as jnp
|
|
18
|
+
from jax import random
|
|
19
|
+
from jaxtyping import Array, Float
|
|
20
|
+
|
|
21
|
+
from dfbench.core.objective import Objective
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Large but finite penalty returned when the solver evaluates an infeasible
|
|
25
|
+
# or NaN-producing point. Using ``np.inf`` would crash most DFO solvers.
|
|
26
|
+
_NAN_PENALTY = 1e30
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class _BudgetExhausted(Exception):
|
|
30
|
+
"""Raised inside a DFO callback when the Objective budget is exhausted.
|
|
31
|
+
|
|
32
|
+
For pure-Python solvers (e.g. Py-BOBYQA) this propagates immediately and
|
|
33
|
+
terminates the optimisation loop. For Fortran-backed solvers (PDFO/prima)
|
|
34
|
+
f2py stores the exception and re-raises it after the current Fortran call
|
|
35
|
+
returns, which also causes prima to abort early.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def dfo_objective_wrapper(
|
|
40
|
+
obj: Objective,
|
|
41
|
+
) -> callable:
|
|
42
|
+
"""Return a NumPy-compatible scalar function that evaluates ``obj.value``.
|
|
43
|
+
|
|
44
|
+
The returned callable accepts a 1-D ``np.ndarray``, converts it to a JAX
|
|
45
|
+
array, evaluates through ``obj.value`` (which logs the evaluation), and
|
|
46
|
+
returns a Python float.
|
|
47
|
+
|
|
48
|
+
NaN / Inf losses are replaced with ``_NAN_PENALTY`` so that DFO solvers
|
|
49
|
+
do not crash. When the Objective budget is exceeded the wrapper raises
|
|
50
|
+
``_BudgetExhausted`` instead of calling the (expensive) physics evaluation.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
``fun(x: np.ndarray) -> float``
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def _fun(x: np.ndarray) -> float:
|
|
57
|
+
if obj.budget_exceeded:
|
|
58
|
+
raise _BudgetExhausted
|
|
59
|
+
params = jnp.asarray(x)
|
|
60
|
+
loss = obj.value(params)
|
|
61
|
+
loss_f = float(loss)
|
|
62
|
+
if not np.isfinite(loss_f):
|
|
63
|
+
return _NAN_PENALTY
|
|
64
|
+
return loss_f
|
|
65
|
+
|
|
66
|
+
return _fun
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def random_bounded_start(
|
|
70
|
+
obj: Objective,
|
|
71
|
+
key,
|
|
72
|
+
) -> tuple[np.ndarray, "jax.Array"]:
|
|
73
|
+
"""Sample a uniformly random starting point within problem bounds.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
obj: Objective (must be in bounded mode).
|
|
77
|
+
key: JAX PRNG key; a new sub-key is split off and the updated key
|
|
78
|
+
is returned alongside the sample.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
(x0, new_key) – x0 is a 1-D ``np.ndarray`` of shape ``(n_params,)``.
|
|
82
|
+
"""
|
|
83
|
+
key, subkey = random.split(key)
|
|
84
|
+
lower, upper = obj.problem.bounds
|
|
85
|
+
x0_jax = random.uniform(subkey, shape=(obj.n_params,), minval=lower, maxval=upper)
|
|
86
|
+
return np.asarray(x0_jax, dtype=np.float64), key
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def clip_to_bounds(x: np.ndarray, obj: Objective) -> np.ndarray:
|
|
90
|
+
"""Clip a parameter vector to the problem bounds (in-place safe).
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Clipped copy of *x*.
|
|
94
|
+
"""
|
|
95
|
+
lower = np.asarray(obj.problem.bounds[0], dtype=np.float64)
|
|
96
|
+
upper = np.asarray(obj.problem.bounds[1], dtype=np.float64)
|
|
97
|
+
return np.clip(x, lower, upper)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def solver_bounds_np(obj: Objective) -> tuple[np.ndarray, np.ndarray]:
|
|
101
|
+
"""Return ``(lower, upper)`` as plain NumPy float64 arrays."""
|
|
102
|
+
lower = np.asarray(obj.problem.bounds[0], dtype=np.float64)
|
|
103
|
+
upper = np.asarray(obj.problem.bounds[1], dtype=np.float64)
|
|
104
|
+
return lower, upper
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def multistart_loop(
|
|
108
|
+
obj: Objective,
|
|
109
|
+
key,
|
|
110
|
+
solve_fn: callable,
|
|
111
|
+
n_restarts: int = 1,
|
|
112
|
+
init_params: Float[Array, "..."] | None = None,
|
|
113
|
+
) -> None:
|
|
114
|
+
"""Run *solve_fn* up to *n_restarts* times with fresh random starts.
|
|
115
|
+
|
|
116
|
+
``solve_fn(x0: np.ndarray)`` should call the DFO solver once from
|
|
117
|
+
starting point *x0*. It may raise or return; either way the best
|
|
118
|
+
result is tracked by the Objective automatically.
|
|
119
|
+
|
|
120
|
+
The first restart uses *init_params* (if provided); subsequent restarts
|
|
121
|
+
sample uniformly within bounds.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
obj: The Objective instance (already logging).
|
|
125
|
+
key: JAX PRNG key for sampling restarts.
|
|
126
|
+
solve_fn: ``(x0: np.ndarray) -> None`` – runs one solver call.
|
|
127
|
+
n_restarts: Total number of solver invocations.
|
|
128
|
+
init_params: Optional starting point for the first restart.
|
|
129
|
+
"""
|
|
130
|
+
for i in range(n_restarts):
|
|
131
|
+
if obj.budget_exceeded:
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
if i == 0 and init_params is not None:
|
|
135
|
+
x0 = np.asarray(init_params, dtype=np.float64)
|
|
136
|
+
else:
|
|
137
|
+
x0, key = random_bounded_start(obj, key)
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
solve_fn(x0)
|
|
141
|
+
except _BudgetExhausted:
|
|
142
|
+
break
|
|
143
|
+
except Exception as exc: # noqa: BLE001
|
|
144
|
+
if obj.budget_exceeded:
|
|
145
|
+
# Exception was likely triggered (directly or indirectly) by
|
|
146
|
+
# _BudgetExhausted propagating through the solver; stop quietly.
|
|
147
|
+
break
|
|
148
|
+
# DFO solvers may raise on degenerate geometry, singular models,
|
|
149
|
+
# etc. Log and continue with next restart.
|
|
150
|
+
print(f"[DFO restart {i+1}/{n_restarts}] solver raised {type(exc).__name__}: {exc}")
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Shared utilities for SciPy-based derivative-free optimizers.
|
|
2
|
+
|
|
3
|
+
Provides numpy↔JAX wrappers, bounds conversion, and budget-aware
|
|
4
|
+
callbacks so individual algorithm modules stay DRY.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
import jax.numpy as jnp
|
|
11
|
+
from scipy.optimize import Bounds
|
|
12
|
+
|
|
13
|
+
from dfbench.core.objective import Objective
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SciPyBudgetExceeded(RuntimeError):
|
|
17
|
+
"""Raised inside a SciPy objective/callback when the Objective budget is spent."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Large but finite penalty returned when the objective produces NaN/Inf.
|
|
21
|
+
# Using ``np.inf`` causes SciPy's derivative-free solvers (Nelder-Mead,
|
|
22
|
+
# Powell, basin-hopping, dual-annealing) to terminate prematurely or crash.
|
|
23
|
+
_NAN_PENALTY = 1e30
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Bounds helpers
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def scipy_bounds(obj: Objective) -> Bounds:
|
|
32
|
+
"""Convert problem bounds to :class:`scipy.optimize.Bounds`."""
|
|
33
|
+
lb = np.asarray(obj.problem.bounds[0], dtype=np.float64)
|
|
34
|
+
ub = np.asarray(obj.problem.bounds[1], dtype=np.float64)
|
|
35
|
+
return Bounds(lb, ub)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def scipy_bounds_list(obj: Objective) -> list[tuple[float, float]]:
|
|
39
|
+
"""Return bounds as ``[(lb0, ub0), …]`` (format used by *dual_annealing*)."""
|
|
40
|
+
lb = np.asarray(obj.problem.bounds[0], dtype=np.float64)
|
|
41
|
+
ub = np.asarray(obj.problem.bounds[1], dtype=np.float64)
|
|
42
|
+
return list(zip(lb.tolist(), ub.tolist()))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
# Objective wrappers
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def make_scipy_fun(obj: Objective):
|
|
51
|
+
"""Return a numpy-in / float-out wrapper around ``obj.value()``.
|
|
52
|
+
|
|
53
|
+
Raises :class:`SciPyBudgetExceeded` when the evaluation budget is spent so
|
|
54
|
+
the calling SciPy routine can be interrupted cleanly.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def fun(x_np: np.ndarray) -> float:
|
|
58
|
+
if obj.budget_exceeded:
|
|
59
|
+
raise SciPyBudgetExceeded
|
|
60
|
+
loss = float(obj.value(jnp.asarray(x_np)))
|
|
61
|
+
if not np.isfinite(loss):
|
|
62
|
+
return _NAN_PENALTY
|
|
63
|
+
return loss
|
|
64
|
+
|
|
65
|
+
return fun
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def make_scipy_fun_and_grad(obj: Objective):
|
|
69
|
+
"""Return a wrapper calling ``obj.value_and_grad()`` → ``(float, ndarray)``.
|
|
70
|
+
|
|
71
|
+
Intended for use with ``jac=True`` in :func:`scipy.optimize.minimize` so
|
|
72
|
+
that value and gradient are obtained in a single Objective call, avoiding
|
|
73
|
+
double-counted evaluations.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def fun(x_np: np.ndarray) -> tuple[float, np.ndarray]:
|
|
77
|
+
if obj.budget_exceeded:
|
|
78
|
+
raise SciPyBudgetExceeded
|
|
79
|
+
loss, grad = obj.value_and_grad(jnp.asarray(x_np))
|
|
80
|
+
loss_f = float(loss)
|
|
81
|
+
grad_np = np.asarray(grad, dtype=np.float64)
|
|
82
|
+
if not np.isfinite(loss_f) or not np.all(np.isfinite(grad_np)):
|
|
83
|
+
return _NAN_PENALTY, np.zeros_like(x_np, dtype=np.float64)
|
|
84
|
+
return loss_f, grad_np
|
|
85
|
+
|
|
86
|
+
return fun
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------------------------
|
|
90
|
+
# Callbacks
|
|
91
|
+
# ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def make_budget_callback(obj: Objective):
|
|
95
|
+
"""Return a ``callback(xk)`` that raises :class:`SciPyBudgetExceeded`."""
|
|
96
|
+
|
|
97
|
+
def callback(xk, *_args, **_kwargs):
|
|
98
|
+
if obj.budget_exceeded:
|
|
99
|
+
raise SciPyBudgetExceeded
|
|
100
|
+
|
|
101
|
+
return callback
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# ---------------------------------------------------------------------------
|
|
105
|
+
# Bounded step-taker for basin-hopping
|
|
106
|
+
# ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class BoundedStep:
|
|
110
|
+
"""Random displacement clipped to problem bounds.
|
|
111
|
+
|
|
112
|
+
Drop-in replacement for SciPy's default ``RandomDisplacement`` that
|
|
113
|
+
guarantees the perturbed point remains feasible.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self, stepsize: float, lb: np.ndarray, ub: np.ndarray) -> None:
|
|
117
|
+
self.stepsize = stepsize
|
|
118
|
+
self.lb = lb
|
|
119
|
+
self.ub = ub
|
|
120
|
+
|
|
121
|
+
def __call__(self, x: np.ndarray) -> np.ndarray:
|
|
122
|
+
scale = self.stepsize * (self.ub - self.lb)
|
|
123
|
+
x_new = x + np.random.uniform(-scale, scale, size=x.shape)
|
|
124
|
+
return np.clip(x_new, self.lb, self.ub)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Nelder-Mead simplex algorithm via :func:`scipy.optimize.minimize`."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import jax.numpy as jnp
|
|
7
|
+
from jaxtyping import Array, Float
|
|
8
|
+
from scipy.optimize import minimize
|
|
9
|
+
|
|
10
|
+
from dfbench.core.algorithm import AlgorithmType, OptimizationAlgorithm
|
|
11
|
+
from dfbench.core.objective import Objective
|
|
12
|
+
from dfbench.algorithms.derivative_free._scipy_common import (
|
|
13
|
+
SciPyBudgetExceeded,
|
|
14
|
+
make_scipy_fun,
|
|
15
|
+
scipy_bounds,
|
|
16
|
+
make_budget_callback,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NelderMead(OptimizationAlgorithm):
|
|
21
|
+
"""Nelder-Mead simplex derivative-free local optimizer.
|
|
22
|
+
|
|
23
|
+
Uses ``scipy.optimize.minimize(method='Nelder-Mead')`` in **bounded**
|
|
24
|
+
parameter space (requires SciPy >= 1.7).
|
|
25
|
+
|
|
26
|
+
Suitable as a local refinement method or for low-dimensional problems
|
|
27
|
+
where gradient information is unavailable or unreliable.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
algorithm_str: ``"nelder_mead"``
|
|
31
|
+
algorithm_type: :attr:`AlgorithmType.EVOLUTIONARY`
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
algorithm_str: str = "nelder_mead"
|
|
35
|
+
algorithm_type: AlgorithmType = AlgorithmType.EVOLUTIONARY
|
|
36
|
+
|
|
37
|
+
def __init__(self) -> None:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
def optimize(
|
|
41
|
+
self,
|
|
42
|
+
problem_objective: Objective,
|
|
43
|
+
init_params: Float[Array, "..."] | None = None,
|
|
44
|
+
random_seed: int | None = None,
|
|
45
|
+
xatol: float = 1e-8,
|
|
46
|
+
fatol: float = 1e-8,
|
|
47
|
+
adaptive: bool = True,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Run Nelder-Mead simplex optimization.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
problem_objective: Pre-configured Objective instance.
|
|
53
|
+
init_params: Starting point. If *None*, sampled uniformly in bounds.
|
|
54
|
+
random_seed: Seed for reproducibility (controls initial point).
|
|
55
|
+
xatol: Absolute parameter tolerance for convergence.
|
|
56
|
+
fatol: Absolute function-value tolerance for convergence.
|
|
57
|
+
adaptive: Adapt simplex parameters to dimensionality (recommended
|
|
58
|
+
for n > 1).
|
|
59
|
+
"""
|
|
60
|
+
obj = problem_objective
|
|
61
|
+
|
|
62
|
+
random_seed, _key = self.prepare(
|
|
63
|
+
obj, unbounded=False, random_seed=random_seed
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if init_params is None:
|
|
67
|
+
params = obj.random_params_bounded()
|
|
68
|
+
else:
|
|
69
|
+
params = init_params
|
|
70
|
+
|
|
71
|
+
# JIT warmup
|
|
72
|
+
_ = obj.value(params)
|
|
73
|
+
|
|
74
|
+
obj.start_logging()
|
|
75
|
+
|
|
76
|
+
fun = make_scipy_fun(obj)
|
|
77
|
+
x0 = np.asarray(params, dtype=np.float64)
|
|
78
|
+
bounds = scipy_bounds(obj)
|
|
79
|
+
callback = make_budget_callback(obj)
|
|
80
|
+
maxfev = obj.evals_left if obj.evals_left is not None else 10_000
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
minimize(
|
|
84
|
+
fun,
|
|
85
|
+
x0,
|
|
86
|
+
method="Nelder-Mead",
|
|
87
|
+
bounds=bounds,
|
|
88
|
+
callback=callback,
|
|
89
|
+
options={
|
|
90
|
+
"maxfev": maxfev,
|
|
91
|
+
"xatol": xatol,
|
|
92
|
+
"fatol": fatol,
|
|
93
|
+
"adaptive": adaptive,
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
except SciPyBudgetExceeded:
|
|
97
|
+
pass
|