from __future__ import annotations
import math
import os
import random
from concurrent.futures import ThreadPoolExecutor
from typing import Iterable, Sequence
import numpy as np
from scipy.optimize import shgo
os.environ.setdefault("OMP_NUM_THREADS", "1")
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
os.environ.setdefault("MKL_NUM_THREADS", "1")
os.environ.setdefault("NUMEXPR_NUM_THREADS", "1")
def rosen(x: Sequence[float] | np.ndarray) -> float:
x = np.asarray(x, dtype=float)
xi = x[:-1]
xi1 = x[1:]
return float(np.sum(100.0 * (xi1 - xi * xi) ** 2 + (1.0 - xi) ** 2))
def rastrigin(x: Sequence[float] | np.ndarray, a: float) -> float:
x = np.asarray(x, dtype=float)
n = x.size
return float(a * n + np.sum(x * x - a * np.cos(2.0 * math.pi * x)))
def rastrigin_fake_long(x: Sequence[float] | np.ndarray, a: float) -> float:
x = np.asarray(x, dtype=float)
scale = float(os.getenv("FAKE_LONG_SCALE", "0.0001"))
base = random.random() * 19_000_000.0 + 11_000_000.0
iters = max(1, int(base * scale))
per_iter = float(np.sum(np.sin(x * x) + np.cos(x)))
dummy = 0.0
for _ in range(iters):
dummy += math.sin(per_iter) + per_iter
return rastrigin(x, a) + dummy * 1e-20
def assert_allclose(vec: Iterable[float], target: float, tol: float, name: str) -> None:
for i, v in enumerate(vec):
if abs(v - target) >= tol:
raise AssertionError(f"{name}: result at index {i} is not close to {target}: {v}")
def test_basic_rosen() -> None:
bounds = [(0.0, 2.0)] * 10
res = shgo(rosen, bounds=bounds)
print("SHGO result for rosen:", res)
assert_allclose(res.x, 1.0, 1e-5, "basic_rosen")
print("Basic rosen test passed")
def test_rastrigin_partial() -> None:
f = lambda x: rastrigin(x, 10.0)
bounds = [(-5.0, 5.0)] * 3
res = shgo(f, bounds=bounds)
print("SHGO result for rastrigin:", res)
assert_allclose(res.x, 0.0, 1e-5, "rastrigin_partial")
print("Rastrigin with closure test passed")
def test_rastrigin_extra_parameters() -> None:
f = lambda x: rastrigin(x, 10.0)
options = {
'f_tol': 1e-6,
'minimize_every_iter': False,
}
minimizer_kwargs = {
'method': 'COBYQA', 'options': {
'tol': 1e-6,
'maxiter': 200,
},
}
def cb(xk: np.ndarray) -> None:
print("Callback at x =", xk)
d = 3
bounds = [(-5.0, 5.0)] * d
n = 150
iters = 10
res = shgo(
f,
bounds=bounds,
n=n,
iters=iters,
callback=cb,
minimizer_kwargs=minimizer_kwargs,
options=options,
sampling_method='sobol',
)
print("SHGO result for rastrigin with non-standard params:", res)
assert_allclose(res.x, 0.0, 1e-5, "rastrigin_extra_parameters")
print("Rastrigin with non-standard params test passed")
def test_rastrigin_fake_long_partial() -> None:
f = lambda x: rastrigin_fake_long(x, 10.0)
bounds = [(-5.0, 5.0)] * 3
try:
import multiprocessing as mp
mp.set_start_method('spawn', force=True)
except Exception:
pass
with ThreadPoolExecutor(max_workers=15) as ex:
res = shgo(f, bounds=bounds, workers=ex.map)
print("SHGO result for fake long rastrigin:", res)
assert_allclose(res.x, 0.0, 1e-5, "rastrigin_fake_long_partial")
print("Long-running Rastrigin test passed")
def main() -> None:
test_basic_rosen()
test_rastrigin_partial()
test_rastrigin_extra_parameters()
test_rastrigin_fake_long_partial()
if __name__ == "__main__":
main()