From d23869e01a119d8de6fa83c4c70676e2c5c3c1b0 Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Thu, 4 May 2023 15:18:49 -0700 Subject: [PATCH] add scipy shgo optimizers (with cobyla and slsqp) --- notwacube.py | 9 +++++++++ scipycube2.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/notwacube.py b/notwacube.py index 696757e..355b14b 100644 --- a/notwacube.py +++ b/notwacube.py @@ -2,6 +2,7 @@ from dlibcube2 import dlib_cube from nloptcube2 import nlopt_neldermead_cube from randomcube2 import another_random_cube, quasirandom_cube from scipycube2 import ( + make_shgo, scipy_basinhopping_cube, scipy_bfgs_2j_cube, scipy_bfgs_3j_cube, @@ -34,6 +35,13 @@ BASELINE_OPTIMIZERS = [ quasirandom_cube, ] +SHGO_OPTIMIZERS = [ + make_shgo(method="cobyla"), + make_shgo(method="slsqp"), + make_shgo(method="cobyla", mei=True), + make_shgo(method="slsqp", mei=True), +] + def collect_everything(): G = globals().values() @@ -109,6 +117,7 @@ else: book_of_optimizers = dict( baseline=BASELINE_OPTIMIZERS, everything=FUCKING_EVERYTHING, + shgo=SHGO_OPTIMIZERS, negative=PREVIOUSLY_NEGATIVE, positive=PREVIOUSLY_POSITIVE, whitelisted=WHITELISTED_OPTIMIZERS, diff --git a/scipycube2.py b/scipycube2.py index 23e2fd7..25e8bfd 100644 --- a/scipycube2.py +++ b/scipycube2.py @@ -186,6 +186,58 @@ def scipy_direct_l_cube(objective, n_trials, n_dim, with_count): return (fopt, xopt, feval_count) if with_count else (fopt, xopt) +def make_shgo(method="cobyla", init="large", it=1, mei=False, li=False, ftol=12): + from scipy.optimize import shgo, Bounds + + if method == "cobyqa": + from cobyqa import minimize as cobyqa + from cobyqa.optimize import EXIT_RHOEND_SUCCESS, EXIT_MAXFEV_WARNING + + raise NotImplementedError("TODO") + else: + # from scipy.optimize import minimize + # https://docs.scipy.org/doc/scipy/reference/optimize.minimize-cobyla.html + pass + + def f(objective, n_trials, n_dim, with_count): + _objective = wrap_untrustworthy( + objective, n_trials, bounding="clip", raising=True + ) + bounds = Bounds([0.0] * n_dim, [1.0] * n_dim) + npt = dict( + large=(n_dim + 1) * (n_dim + 2) // 2, medium=2 * n_dim + 1, small=n_dim + 1 + )[init] + _method = method if method != "cobyqa" else method # TODO: handle cobyqa case. + try: + shgo( + _objective, + bounds=bounds, + n=npt, + iters=it, + minimizer_kwargs=dict(method=_method, ftol=10**-ftol), + options=dict(maxfev=n_trials, minimize_every_iter=mei, local_iters=li), + sampling_method="simplicial", + ) + except ExhaustedTrialsError: + pass + fopt, xopt, feval_count = _objective(final) + return (fopt, xopt, feval_count) if with_count else (fopt, xopt) + + name = f"shgo_{method}" + if it != 1: + name += f"_it{it}" + if li: + name += f"_li{li}" + if mei: + name += "_mei" + if init != "large": + name += f"_{init}" + if ftol != 12: + name += f"_ft{ftol:02}" + f.__name__ = name + "_cube" + return f + + scipy_bfgs_2j_cube = make_scipy("BFGS", jacobian="2-point") scipy_bfgs_3j_cube = make_scipy("BFGS", jacobian="3-point") scipy_cg_2j_cube = make_scipy("CG", jacobian="2-point")