diff --git a/scipy/_lib/tests/test_import_cycles.py b/scipy/_lib/tests/test_import_cycles.py index e61c57093f62..feaf2ff4cf64 100644 --- a/scipy/_lib/tests/test_import_cycles.py +++ b/scipy/_lib/tests/test_import_cycles.py @@ -1,3 +1,4 @@ +import pytest import sys import subprocess @@ -7,6 +8,7 @@ # Check that all modules are importable in a new Python process. # This is not necessarily true if there are import cycles present. +@pytest.mark.slow def test_public_modules_importable(): pids = [subprocess.Popen([sys.executable, '-c', f'import {module}']) for module in PUBLIC_MODULES] diff --git a/scipy/integrate/tests/test_quadpack.py b/scipy/integrate/tests/test_quadpack.py index 90bf6006cf1f..a7f6c7d195b0 100644 --- a/scipy/integrate/tests/test_quadpack.py +++ b/scipy/integrate/tests/test_quadpack.py @@ -342,6 +342,7 @@ def simpfunc(z, y, x, t): # Note order of arguments. (2.,)), 2*8/3.0 * (b**4.0 - a**4.0)) + @pytest.mark.xslow @pytest.mark.parametrize( "x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, expected", [ diff --git a/scipy/interpolate/tests/test_gil.py b/scipy/interpolate/tests/test_gil.py index 0902308fb6af..818cd7275bf3 100644 --- a/scipy/interpolate/tests/test_gil.py +++ b/scipy/interpolate/tests/test_gil.py @@ -28,7 +28,7 @@ def run(self): return WorkerThread() - @pytest.mark.slow + @pytest.mark.xslow @pytest.mark.xfail(reason='race conditions, may depend on system load') def test_rectbivariatespline(self): def generate_params(n_points): diff --git a/scipy/interpolate/tests/test_rgi.py b/scipy/interpolate/tests/test_rgi.py index 5503b39dc67e..5dd7b0a418b7 100644 --- a/scipy/interpolate/tests/test_rgi.py +++ b/scipy/interpolate/tests/test_rgi.py @@ -476,7 +476,7 @@ def f(x, y): ]) def test_descending_points_nd(self, method, ndims, func): - if ndims == 5 and method in {"cubic", "quintic"}: + if ndims >= 4 and method in {"cubic", "quintic"}: pytest.skip("too slow; OOM (quintic); or nearly so (cubic)") rng = np.random.default_rng(42) diff --git a/scipy/optimize/tests/test__differential_evolution.py b/scipy/optimize/tests/test__differential_evolution.py index d5638a120aaa..8f83c1601648 100644 --- a/scipy/optimize/tests/test__differential_evolution.py +++ b/scipy/optimize/tests/test__differential_evolution.py @@ -1339,7 +1339,7 @@ def c1(x): assert_(np.all(res.x >= np.array(bounds)[:, 0])) assert_(np.all(res.x <= np.array(bounds)[:, 1])) - @pytest.mark.slow + @pytest.mark.xslow @pytest.mark.xfail(platform.machine() == 'ppc64le', reason="fails on ppc64le") def test_L8(self): diff --git a/scipy/optimize/tests/test_minimize_constrained.py b/scipy/optimize/tests/test_minimize_constrained.py index 6dad4bad5a39..1f68bfafae66 100644 --- a/scipy/optimize/tests/test_minimize_constrained.py +++ b/scipy/optimize/tests/test_minimize_constrained.py @@ -2,7 +2,7 @@ import pytest from scipy.linalg import block_diag from scipy.sparse import csc_matrix -from numpy.testing import (TestCase, assert_array_almost_equal, +from numpy.testing import (assert_array_almost_equal, assert_array_less, assert_, assert_allclose, suppress_warnings) from scipy.optimize import (NonlinearConstraint, @@ -443,67 +443,70 @@ def hess(x, v): return NonlinearConstraint(fun, -np.inf, 0, jac, hess) -class TestTrustRegionConstr(TestCase): - - @pytest.mark.slow - def test_list_of_problems(self): - list_of_problems = [Maratos(), - Maratos(constr_hess='2-point'), - Maratos(constr_hess=SR1()), - Maratos(constr_jac='2-point', constr_hess=SR1()), - MaratosGradInFunc(), - HyperbolicIneq(), - HyperbolicIneq(constr_hess='3-point'), - HyperbolicIneq(constr_hess=BFGS()), - HyperbolicIneq(constr_jac='3-point', - constr_hess=BFGS()), - Rosenbrock(), - IneqRosenbrock(), - EqIneqRosenbrock(), - BoundedRosenbrock(), - Elec(n_electrons=2), - Elec(n_electrons=2, constr_hess='2-point'), - Elec(n_electrons=2, constr_hess=SR1()), - Elec(n_electrons=2, constr_jac='3-point', - constr_hess=SR1())] - - for prob in list_of_problems: - for grad in (prob.grad, '3-point', False): - for hess in (prob.hess, - '3-point', - SR1(), - BFGS(exception_strategy='damp_update'), - BFGS(exception_strategy='skip_update')): - - # Remove exceptions - if grad in ('2-point', '3-point', 'cs', False) and \ - hess in ('2-point', '3-point', 'cs'): - continue - if prob.grad is True and grad in ('3-point', False): - continue - with suppress_warnings() as sup: - sup.filter(UserWarning, "delta_grad == 0.0") - result = minimize(prob.fun, prob.x0, - method='trust-constr', - jac=grad, hess=hess, - bounds=prob.bounds, - constraints=prob.constr) - - if prob.x_opt is not None: - assert_array_almost_equal(result.x, prob.x_opt, - decimal=5) - # gtol - if result.status == 1: - assert_array_less(result.optimality, 1e-8) - # xtol - if result.status == 2: - assert_array_less(result.tr_radius, 1e-8) - - if result.method == "tr_interior_point": - assert_array_less(result.barrier_parameter, 1e-8) - # max iter - if result.status in (0, 3): - raise RuntimeError("Invalid termination condition.") +class TestTrustRegionConstr: + list_of_problems = [Maratos(), + Maratos(constr_hess='2-point'), + Maratos(constr_hess=SR1()), + Maratos(constr_jac='2-point', constr_hess=SR1()), + MaratosGradInFunc(), + HyperbolicIneq(), + HyperbolicIneq(constr_hess='3-point'), + HyperbolicIneq(constr_hess=BFGS()), + HyperbolicIneq(constr_jac='3-point', + constr_hess=BFGS()), + Rosenbrock(), + IneqRosenbrock(), + EqIneqRosenbrock(), + BoundedRosenbrock(), + Elec(n_electrons=2), + Elec(n_electrons=2, constr_hess='2-point'), + Elec(n_electrons=2, constr_hess=SR1()), + Elec(n_electrons=2, constr_jac='3-point', + constr_hess=SR1())] + + @pytest.mark.parametrize('prob', list_of_problems) + @pytest.mark.parametrize('grad', ('prob.grad', '3-point', False)) + @pytest.mark.parametrize('hess', ("prob.hess", '3-point', SR1(), + BFGS(exception_strategy='damp_update'), + BFGS(exception_strategy='skip_update'))) + def test_list_of_problems(self, prob, grad, hess): + grad = prob.grad if grad == "prob.grad" else grad + hess = prob.hess if hess == "prob.hess" else hess + # Remove exceptions + if (grad in {'2-point', '3-point', 'cs', False} and + hess in {'2-point', '3-point', 'cs'}): + pytest.skip("Numerical Hessian needs analytical gradient") + if prob.grad is True and grad in {'3-point', False}: + pytest.skip("prob.grad incompatible with grad in {'3-point', False}") + sensitive = (isinstance(prob, BoundedRosenbrock) and grad == '3-point' + and isinstance(hess, BFGS)) + if sensitive: + pytest.xfail("Seems sensitive to initial conditions w/ Accelerate") + with suppress_warnings() as sup: + sup.filter(UserWarning, "delta_grad == 0.0") + result = minimize(prob.fun, prob.x0, + method='trust-constr', + jac=grad, hess=hess, + bounds=prob.bounds, + constraints=prob.constr) + + if prob.x_opt is not None: + assert_array_almost_equal(result.x, prob.x_opt, + decimal=5) + # gtol + if result.status == 1: + assert_array_less(result.optimality, 1e-8) + # xtol + if result.status == 2: + assert_array_less(result.tr_radius, 1e-8) + + if result.method == "tr_interior_point": + assert_array_less(result.barrier_parameter, 1e-8) + + # check for max iter + message = f"Invalid termination condition: {result.status}." + assert result.status not in {0, 3}, message + def test_default_jac_and_hess(self): def fun(x): @@ -641,7 +644,7 @@ def obj(x): assert result['success'] -class TestEmptyConstraint(TestCase): +class TestEmptyConstraint: """ Here we minimize x^2+y^2 subject to x^2-y^2>1. The actual minimum is at (0, 0) which fails the constraint. diff --git a/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py b/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py index 4b060d77d1f7..3fe07ba31296 100644 --- a/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py +++ b/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py @@ -548,9 +548,7 @@ def test_diagonal_data_types(n, m): # and where we choose A and B to be diagonal. vals = np.arange(1, n + 1) - # list_sparse_format = ['bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil'] - list_sparse_format = ['coo'] - sparse_formats = len(list_sparse_format) + list_sparse_format = ['bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil'] for s_f_i, s_f in enumerate(list_sparse_format): As64 = diags([vals * vals], [0], (n, n), format=s_f) @@ -629,15 +627,13 @@ def Mf32precond(x): listY = [Yf64, Yf32] tests = list(itertools.product(listA, listB, listM, listX, listY)) - # This is one of the slower tests because there are >1,000 configs - # to test here, instead of checking product of all input, output types - # test each configuration for the first sparse format, and then - # for one additional sparse format. this takes 2/7=30% as long as - # testing all configurations for all sparse formats. - if s_f_i > 0: - tests = tests[s_f_i - 1::sparse_formats-1] for A, B, M, X, Y in tests: + # This is one of the slower tests because there are >1,000 configs + # to test here. Flip a biased coin to decide whether to run each + # test to get decent coverage in less time. + if rnd.random() < 0.95: + continue # too many tests eigvals, _ = lobpcg(A, X, B=B, M=M, Y=Y, tol=1e-4, maxiter=100, largest=False) assert_allclose(eigvals, diff --git a/scipy/sparse/linalg/tests/test_propack.py b/scipy/sparse/linalg/tests/test_propack.py index 64eb888fd994..2dac7133997a 100644 --- a/scipy/sparse/linalg/tests/test_propack.py +++ b/scipy/sparse/linalg/tests/test_propack.py @@ -89,6 +89,7 @@ def test_svdp(ctor, dtype, irl, which): check_svdp(n, m, ctor, dtype, k, irl, which) +@pytest.mark.xslow @pytest.mark.parametrize('dtype', _dtypes) @pytest.mark.parametrize('irl', (False, True)) @pytest.mark.timeout(120) # True, complex64 > 60 s: prerel deps cov 64bit blas