Done !
| Server IP : 194.181.228.65 / Your IP : 216.73.217.86 Web Server : LiteSpeed System : Linux wn13.webd.pl 5.14.0-687.46.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Sep 11 09:03:19 EDT 2026 x86_64 User : prusit ( 133039) PHP Version : 5.6.40 Disable Function : exec, system, shell_exec, passthru, proc_open, proc_close, popen MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /lib64/python3.9/site-packages/scipy/optimize/tests/ |
Upload File : |
"""
Unit test for DIRECT optimization algorithm.
"""
from numpy.testing import (assert_allclose,
assert_array_less)
import pytest
import numpy as np
from scipy.optimize import direct, Bounds
class TestDIRECT:
def setup_method(self):
self.fun_calls = 0
self.bounds_sphere = 4*[(-2, 3)]
self.optimum_sphere_pos = np.zeros((4, ))
self.optimum_sphere = 0.0
self.bounds_stylinski_tang = Bounds([-4., -4.], [4., 4.])
self.maxiter = 1000
# test functions
def sphere(self, x):
self.fun_calls += 1
return np.square(x).sum()
def inv(self, x):
if np.sum(x) == 0:
raise ZeroDivisionError()
return 1/np.sum(x)
def nan_fun(self, x):
return np.nan
def inf_fun(self, x):
return np.inf
def styblinski_tang(self, pos):
x, y = pos
return 0.5 * (x**4 - 16 * x**2 + 5 * x + y**4 - 16 * y**2 + 5 * y)
@pytest.mark.parametrize("locally_biased", [True, False])
def test_direct(self, locally_biased):
res = direct(self.sphere, self.bounds_sphere,
locally_biased=locally_biased)
# test accuracy
assert_allclose(res.x, self.optimum_sphere_pos,
rtol=1e-3, atol=1e-3)
assert_allclose(res.fun, self.optimum_sphere, atol=1e-5, rtol=1e-5)
# test that result lies within bounds
_bounds = np.asarray(self.bounds_sphere)
assert_array_less(_bounds[:, 0], res.x)
assert_array_less(res.x, _bounds[:, 1])
# test number of function evaluations. Original DIRECT overshoots by
# up to 500 evaluations in last iteration
assert res.nfev <= 1000 * (len(self.bounds_sphere) + 1)
# test that number of function evaluations is correct
assert res.nfev == self.fun_calls
# test that number of iterations is below supplied maximum
assert res.nit <= self.maxiter
@pytest.mark.parametrize("locally_biased", [True, False])
def test_direct_callback(self, locally_biased):
# test that callback does not change the result
res = direct(self.sphere, self.bounds_sphere,
locally_biased=locally_biased)
def callback(x):
x = 2*x
dummy = np.square(x)
print("DIRECT minimization algorithm callback test")
return dummy
res_callback = direct(self.sphere, self.bounds_sphere,
locally_biased=locally_biased,
callback=callback)
assert_allclose(res.x, res_callback.x)
assert res.nit == res_callback.nit
assert res.nfev == res_callback.nfev
assert res.status == res_callback.status
assert res.success == res_callback.success
assert res.fun == res_callback.fun
assert_allclose(res.x, res_callback.x)
assert res.message == res_callback.message
# test accuracy
assert_allclose(res_callback.x, self.optimum_sphere_pos,
rtol=1e-3, atol=1e-3)
assert_allclose(res_callback.fun, self.optimum_sphere,
atol=1e-5, rtol=1e-5)
@pytest.mark.parametrize("locally_biased", [True, False])
def test_exception(self, locally_biased):
bounds = 4*[(-10, 10)]
with pytest.raises(ZeroDivisionError):
direct(self.inv, bounds=bounds,
locally_biased=locally_biased)
@pytest.mark.parametrize("locally_biased", [True, False])
def test_nan(self, locally_biased):
bounds = 4*[(-10, 10)]
direct(self.nan_fun, bounds=bounds,
locally_biased=locally_biased)
@pytest.mark.parametrize("len_tol", [1e-3, 1e-4])
@pytest.mark.parametrize("locally_biased", [True, False])
def test_len_tol(self, len_tol, locally_biased):
bounds = 4*[(-10., 10.)]
res = direct(self.sphere, bounds=bounds, len_tol=len_tol,
vol_tol=1e-30, locally_biased=locally_biased)
assert res.status == 5
assert res.success
assert_allclose(res.x, np.zeros((4, )))
@pytest.mark.parametrize("f_min_rtol", [1e-3, 1e-5, 1e-7])
@pytest.mark.parametrize("locally_biased", [True, False])
def test_f_min(self, f_min_rtol, locally_biased):
# test that desired function value is reached within
# relative tolerance of f_min_rtol
f_min = 1.
bounds = 4*[(-2., 10.)]
res = direct(self.sphere, bounds=bounds, f_min=f_min,
f_min_rtol=f_min_rtol,
locally_biased=locally_biased)
assert res.status == 3
assert res.success
assert res.fun < f_min * (1. + f_min_rtol)
def circle_with_args(self, x, a, b):
return np.square(x[0] - a) + np.square(x[1] - b).sum()
@pytest.mark.parametrize("locally_biased", [True, False])
def test_f_circle_with_args(self, locally_biased):
bounds = 2*[(-2.0, 2.0)]
res = direct(self.circle_with_args, bounds, args=(1, 1), maxfun=1250,
locally_biased=locally_biased)
assert_allclose(res.x, np.array([1., 1.]), rtol=1e-5)
@pytest.mark.parametrize("locally_biased", [True, False])
def test_failure_maxfun(self, locally_biased):
# test that if optimization runs for the maximal number of
# evaluations, success = False is returned
maxfun = 100
result = direct(self.styblinski_tang, self.bounds_stylinski_tang,
maxfun=maxfun, locally_biased=locally_biased)
assert result.success is False
assert result.status == 1
assert result.nfev >= maxfun
@pytest.mark.parametrize("locally_biased", [True, False])
def test_failure_maxiter(self, locally_biased):
# test that if optimization runs for the maximal number of
# iterations, success = False is returned
maxiter = 10
result = direct(self.styblinski_tang, self.bounds_stylinski_tang,
maxiter=maxiter, locally_biased=locally_biased)
assert result.success is False
assert result.status == 2
assert result.nit >= maxiter
@pytest.mark.parametrize("locally_biased", [True, False])
def test_bounds_variants(self, locally_biased):
# test that new and old bounds yield same result
lb = [-6., 1., -5.]
ub = [-1., 3., 5.]
x_opt = np.array([-1., 1., 0.])
bounds_old = list(zip(lb, ub))
bounds_new = Bounds(lb, ub)
res_old_bounds = direct(self.sphere, bounds_old,
locally_biased=locally_biased)
res_new_bounds = direct(self.sphere, bounds_new,
locally_biased=locally_biased)
assert res_new_bounds.nfev == res_old_bounds.nfev
assert res_new_bounds.message == res_old_bounds.message
assert res_new_bounds.success == res_old_bounds.success
assert res_new_bounds.nit == res_old_bounds.nit
assert_allclose(res_new_bounds.x, res_old_bounds.x)
assert_allclose(res_new_bounds.x, x_opt, rtol=1e-2)
@pytest.mark.parametrize("locally_biased", [True, False])
@pytest.mark.parametrize("eps", [1e-5, 1e-4, 1e-3])
def test_epsilon(self, eps, locally_biased):
result = direct(self.styblinski_tang, self.bounds_stylinski_tang,
eps=eps, vol_tol=1e-6,
locally_biased=locally_biased)
assert result.status == 4
assert result.success
@pytest.mark.parametrize("locally_biased", [True, False])
def test_segmentation_fault(self, locally_biased):
# test that an excessive number of function evaluations
# does not result in segmentation fault
bounds = [(-5., 20.)] * 100
result = direct(self.sphere, bounds, maxfun=10000000,
maxiter=1000000, locally_biased=locally_biased)
assert result is not None
@pytest.mark.parametrize("locally_biased", [True, False])
def test_inf_fun(self, locally_biased):
# test that an objective value of infinity does not crash DIRECT
bounds = [(-5., 5.)] * 2
result = direct(self.inf_fun, bounds,
locally_biased=locally_biased)
assert result is not None