File pytest-run-parallel-compat.patch of Package python-scipy
From cde31bc9630313bacf98f6b2ea7234bbb24ea5e4 Mon Sep 17 00:00:00 2001
From: crusaderky <crusaderky@gmail.com>
Date: Wed, 9 Jul 2025 15:44:35 +0100
Subject: [PATCH] TST: linalg: make `test_expm_multiply` frendierly to
pytest-run-parallel
---
.../sparse/linalg/tests/test_expm_multiply.py | 90 +++++++++----------
1 file changed, 40 insertions(+), 50 deletions(-)
Index: scipy-1.16.2/scipy/sparse/linalg/tests/test_expm_multiply.py
===================================================================
--- scipy-1.16.2.orig/scipy/sparse/linalg/tests/test_expm_multiply.py
+++ scipy-1.16.2/scipy/sparse/linalg/tests/test_expm_multiply.py
@@ -24,18 +24,13 @@ COMPLEX_DTYPES = (np.complex64, np.compl
DTYPES = REAL_DTYPES + COMPLEX_DTYPES
-def estimated(func):
+def estimated_warns():
"""If trace is estimated, it should warn.
We warn that estimation of trace might impact performance.
All result have to be correct nevertheless!
-
"""
- def wrapped(*args, **kwds):
- with pytest.warns(UserWarning,
- match="Trace of LinearOperator not available"):
- return func(*args, **kwds)
- return wrapped
+ return pytest.warns(UserWarning, match="Trace of LinearOperator not available")
def less_than_or_close(a, b):
@@ -81,73 +76,68 @@ class TestExpmActionSimple:
assert_(less_than_or_close(estimated, exact))
assert_(less_than_or_close(exact, 3*estimated))
- @pytest.mark.thread_unsafe
def test_expm_multiply(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
n = 40
k = 3
nsamples = 10
for i in range(nsamples):
- A = scipy.linalg.inv(np.random.randn(n, n))
- B = np.random.randn(n, k)
+ A = scipy.linalg.inv(rng.standard_normal((n, n)))
+ B = rng.standard_normal((n, k))
observed = expm_multiply(A, B)
expected = np.dot(sp_expm(A), B)
assert_allclose(observed, expected)
- observed = estimated(expm_multiply)(aslinearoperator(A), B)
+ with estimated_warns():
+ observed = expm_multiply(aslinearoperator(A), B)
assert_allclose(observed, expected)
traceA = np.trace(A)
observed = expm_multiply(aslinearoperator(A), B, traceA=traceA)
assert_allclose(observed, expected)
- @pytest.mark.thread_unsafe
def test_matrix_vector_multiply(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
n = 40
nsamples = 10
for i in range(nsamples):
- A = scipy.linalg.inv(np.random.randn(n, n))
- v = np.random.randn(n)
+ A = scipy.linalg.inv(rng.standard_normal((n, n)))
+ v = rng.standard_normal(n)
observed = expm_multiply(A, v)
expected = np.dot(sp_expm(A), v)
assert_allclose(observed, expected)
- observed = estimated(expm_multiply)(aslinearoperator(A), v)
+ with estimated_warns():
+ observed = expm_multiply(aslinearoperator(A), v)
assert_allclose(observed, expected)
- @pytest.mark.thread_unsafe
def test_scaled_expm_multiply(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
n = 40
k = 3
nsamples = 10
for i, t in product(range(nsamples), [0.2, 1.0, 1.5]):
with np.errstate(invalid='ignore'):
- A = scipy.linalg.inv(np.random.randn(n, n))
- B = np.random.randn(n, k)
+ A = scipy.linalg.inv(rng.standard_normal((n, n)))
+ B = rng.standard_normal((n, k))
observed = _expm_multiply_simple(A, B, t=t)
expected = np.dot(sp_expm(t*A), B)
assert_allclose(observed, expected)
- observed = estimated(_expm_multiply_simple)(
- aslinearoperator(A), B, t=t
- )
+ with estimated_warns():
+ observed = _expm_multiply_simple(aslinearoperator(A), B, t=t)
assert_allclose(observed, expected)
- @pytest.mark.thread_unsafe
def test_scaled_expm_multiply_single_timepoint(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
t = 0.1
n = 5
k = 2
- A = np.random.randn(n, n)
- B = np.random.randn(n, k)
+ A = rng.standard_normal((n, n))
+ B = rng.standard_normal((n, k))
observed = _expm_multiply_simple(A, B, t=t)
expected = sp_expm(t*A).dot(B)
assert_allclose(observed, expected)
- observed = estimated(_expm_multiply_simple)(
- aslinearoperator(A), B, t=t
- )
+ with estimated_warns():
+ observed = _expm_multiply_simple(aslinearoperator(A), B, t=t)
assert_allclose(observed, expected)
- @pytest.mark.thread_unsafe
def test_sparse_expm_multiply(self):
rng = np.random.default_rng(1234)
n = 40
@@ -165,10 +155,10 @@ class TestExpmActionSimple:
" CSC matrix format")
expected = sp_expm(A).dot(B)
assert_allclose(observed, expected)
- observed = estimated(expm_multiply)(aslinearoperator(A), B)
+ with estimated_warns():
+ observed = expm_multiply(aslinearoperator(A), B)
assert_allclose(observed, expected)
- @pytest.mark.thread_unsafe
def test_complex(self):
A = np.array([
[1j, 1j],
@@ -179,7 +169,8 @@ class TestExpmActionSimple:
1j * np.exp(1j) + 1j * (1j*np.cos(1) - np.sin(1)),
1j * np.exp(1j)], dtype=complex)
assert_allclose(observed, expected)
- observed = estimated(expm_multiply)(aslinearoperator(A), B)
+ with estimated_warns():
+ observed = expm_multiply(aslinearoperator(A), B)
assert_allclose(observed, expected)
@@ -211,21 +202,20 @@ class TestExpmActionInterval:
for solution, t in zip(X, samples):
assert_allclose(solution, sp_expm(t*A).dot(target))
- @pytest.mark.thread_unsafe
@pytest.mark.fail_slow(20)
def test_expm_multiply_interval_vector(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
interval = {'start': 0.1, 'stop': 3.2, 'endpoint': True}
for num, n in product([14, 13, 2], [1, 2, 5, 20, 40]):
- A = scipy.linalg.inv(np.random.randn(n, n))
- v = np.random.randn(n)
+ A = scipy.linalg.inv(rng.standard_normal((n, n)))
+ v = rng.standard_normal(n)
samples = np.linspace(num=num, **interval)
X = expm_multiply(A, v, num=num, **interval)
for solution, t in zip(X, samples):
assert_allclose(solution, sp_expm(t*A).dot(v))
# test for linear operator with unknown trace -> estimate trace
- Xguess = estimated(expm_multiply)(aslinearoperator(A), v,
- num=num, **interval)
+ with estimated_warns():
+ Xguess = expm_multiply(aslinearoperator(A), v, num=num, **interval)
# test for linear operator with given trace
Xgiven = expm_multiply(aslinearoperator(A), v, num=num, **interval,
traceA=np.trace(A))
@@ -239,20 +229,19 @@ class TestExpmActionInterval:
assert_allclose(sol_given, correct)
assert_allclose(sol_wrong, correct)
- @pytest.mark.thread_unsafe
@pytest.mark.fail_slow(20)
def test_expm_multiply_interval_matrix(self):
- np.random.seed(1234)
+ rng = np.random.default_rng(1234)
interval = {'start': 0.1, 'stop': 3.2, 'endpoint': True}
for num, n, k in product([14, 13, 2], [1, 2, 5, 20, 40], [1, 2]):
- A = scipy.linalg.inv(np.random.randn(n, n))
- B = np.random.randn(n, k)
+ A = scipy.linalg.inv(rng.standard_normal((n, n)))
+ B = rng.standard_normal((n, k))
samples = np.linspace(num=num, **interval)
X = expm_multiply(A, B, num=num, **interval)
for solution, t in zip(X, samples):
assert_allclose(solution, sp_expm(t*A).dot(B))
- X = estimated(expm_multiply)(aslinearoperator(A), B, num=num,
- **interval)
+ with estimated_warns():
+ X = expm_multiply(aslinearoperator(A), B, num=num, **interval)
for solution, t in zip(X, samples):
assert_allclose(solution, sp_expm(t*A).dot(B))
@@ -324,7 +313,6 @@ class TestExpmActionInterval:
raise Exception(msg)
-@pytest.mark.thread_unsafe
@pytest.mark.parametrize("dtype_a", DTYPES)
@pytest.mark.parametrize("dtype_b", DTYPES)
@pytest.mark.parametrize("b_is_matrix", [False, True])
@@ -349,7 +337,8 @@ def test_expm_multiply_dtype(dtype_a, dt
# single application
sol_mat = expm_multiply(A, B)
- sol_op = estimated(expm_multiply)(aslinearoperator(A), B)
+ with estimated_warns():
+ sol_op = expm_multiply(aslinearoperator(A), B)
direct_sol = np.dot(sp_expm(A), B)
assert_allclose_(sol_mat, direct_sol)
assert_allclose_(sol_op, direct_sol)
@@ -360,7 +349,8 @@ def test_expm_multiply_dtype(dtype_a, dt
interval = {'start': 0.1, 'stop': 3.2, 'num': 13, 'endpoint': True}
samples = np.linspace(**interval)
X_mat = expm_multiply(A, B, **interval)
- X_op = estimated(expm_multiply)(aslinearoperator(A), B, **interval)
+ with estimated_warns():
+ X_op = expm_multiply(aslinearoperator(A), B, **interval)
for sol_mat, sol_op, t in zip(X_mat, X_op, samples):
direct_sol = sp_expm(t*A).dot(B)
assert_allclose_(sol_mat, direct_sol)