Skip to content

Commit

Permalink
Add tests for scipy.sparse.csgraph and scipy.sparse.linalg (#683)
Browse files Browse the repository at this point in the history
* Add tests for scipy.sparse.csgraph and linalg

* Separate tests

* Add parameters
  • Loading branch information
mtsokol committed May 21, 2024
1 parent 554cc7b commit b0f1a81
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 11 deletions.
1 change: 1 addition & 0 deletions ci/array-api-skips.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
array_api_tests/test_searching_functions.py::test_nonzero_zerodim_error
array_api_tests/test_special_cases.py::test_unary[sign((x_i is -0 or x_i == +0)) -> 0]
1 change: 0 additions & 1 deletion ci/array-api-xfails.txt
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i
array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i < 0) -> True]
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is NaN) -> False]
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is NaN) -> True]
array_api_tests/test_special_cases.py::test_unary[sign((x_i is -0 or x_i == +0)) -> 0]
array_api_tests/test_special_cases.py::test_unary[sin((x_i is +infinity or x_i == -infinity)) -> NaN]
array_api_tests/test_special_cases.py::test_unary[sqrt(x_i < 0) -> NaN]
array_api_tests/test_special_cases.py::test_unary[tan((x_i is +infinity or x_i == -infinity)) -> NaN]
Expand Down
15 changes: 15 additions & 0 deletions sparse/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,23 @@

import pytest

import numpy as np


@pytest.fixture(scope="session", params=[sparse.BackendType.Numba, sparse.BackendType.Finch])
def backend(request):
with sparse.Backend(backend=request.param):
yield request.param


@pytest.fixture(scope="module")
def graph():
return np.array(
[
[0, 1, 1, 0, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
]
)
155 changes: 145 additions & 10 deletions sparse/tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import pytest

import numpy as np
import scipy.sparse as sp
import scipy as sp
import scipy.sparse as sps
import scipy.sparse.csgraph as spgraph
import scipy.sparse.linalg as splin
from numpy.testing import assert_almost_equal, assert_equal

Expand Down Expand Up @@ -32,7 +34,7 @@ def storage():

def test_finch_backend():
np_eye = np.eye(5)
sp_arr = sp.csr_matrix(np_eye)
sp_arr = sps.csr_matrix(np_eye)

with sparse.Backend(backend=sparse.BackendType.Finch):
import finch
Expand Down Expand Up @@ -69,19 +71,152 @@ def test_asarray(backend, format, order):


@pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")])
def test_scipy_sparse_dispatch(backend, format, order):
def test_scipy_spsolve(backend, format, order):
x = np.eye(10, order=order) * 2
y = np.ones((10, 1), order=order)
x_pydata = sparse.asarray(x, format=format)
y_pydata = sparse.asarray(y, format="coo")

x_sp = sparse.asarray(x, format=format)
y_sp = sparse.asarray(y, format="coo")

actual = splin.spsolve(x_sp, y_sp)
actual = splin.spsolve(x_pydata, y_pydata)
expected = np.linalg.solve(x, y.ravel())

assert_almost_equal(actual, expected)

actual = splin.inv(x_sp)
expected = np.linalg.inv(x)

@pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")])
def test_scipy_inv(backend, format, order):
x = np.eye(10, order=order) * 2
x_pydata = sparse.asarray(x, format=format)

actual = splin.inv(x_pydata)
expected = np.linalg.inv(x)
assert_almost_equal(actual.todense(), expected)


@pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759")
@pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")])
def test_scipy_norm(backend, format, order):
x = np.eye(10, order=order) * 2
x_pydata = sparse.asarray(x, format=format)

actual = splin.norm(x_pydata)
expected = sp.linalg.norm(x)
assert_almost_equal(actual, expected)


@pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759")
@pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")])
def test_scipy_lsqr(backend, format, order):
x = np.eye(10, order=order) * 2
y = np.ones((10, 1), order=order)
x_pydata = sparse.asarray(x, format=format)

actual_x, _ = splin.lsqr(x_pydata, y)[:2]
expected_x, _ = sp.linalg.lstsq(x, y)[:2]
assert_almost_equal(actual_x, expected_x.ravel())


@pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759")
@pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")])
def test_scipy_eigs(backend, format, order):
x = np.eye(10, order=order) * 2
x_pydata = sparse.asarray(x, format=format)
x_sp = sps.coo_matrix(x)

actual_vals, _ = splin.eigs(x_pydata, k=3)
expected_vals, _ = splin.eigs(x_sp, k=3)
assert_almost_equal(actual_vals, expected_vals)


@pytest.mark.parametrize(
"matrix_fn, format, order",
[(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C"), (sps.coo_matrix, "coo", "F")],
)
def test_scipy_connected_components(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_n_components, actual_labels = spgraph.connected_components(sp_graph)
expected_n_components, expected_labels = spgraph.connected_components(graph)
assert actual_n_components == expected_n_components
assert_equal(actual_labels, expected_labels)


@pytest.mark.parametrize(
"matrix_fn, format, order",
[(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C"), (sps.coo_matrix, "coo", "F")],
)
def test_scipy_laplacian(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_lap = spgraph.laplacian(sp_graph)
expected_lap = spgraph.laplacian(graph)
assert_equal(actual_lap.todense(), expected_lap.toarray())


@pytest.mark.parametrize("matrix_fn, format, order", [(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C")])
def test_scipy_shortest_path(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_dist_matrix, actual_predecessors = spgraph.shortest_path(sp_graph, return_predecessors=True)
expected_dist_matrix, expected_predecessors = spgraph.shortest_path(graph, return_predecessors=True)
assert_equal(actual_dist_matrix, expected_dist_matrix)
assert_equal(actual_predecessors, expected_predecessors)


@pytest.mark.parametrize(
"matrix_fn, format, order",
[(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C"), (sps.coo_matrix, "coo", "F")],
)
def test_scipy_breadth_first_tree(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_bft = spgraph.breadth_first_tree(sp_graph, 0, directed=False)
expected_bft = spgraph.breadth_first_tree(graph, 0, directed=False)
assert_equal(actual_bft.todense(), expected_bft.toarray())


@pytest.mark.parametrize(
"matrix_fn, format, order",
[(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C"), (sps.coo_matrix, "coo", "F")],
)
def test_scipy_dijkstra(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_dist_matrix = spgraph.dijkstra(sp_graph, directed=False)
expected_dist_matrix = spgraph.dijkstra(graph, directed=False)
assert_equal(actual_dist_matrix, expected_dist_matrix)


@pytest.mark.parametrize(
"matrix_fn, format, order",
[(sps.csc_matrix, "csc", "F"), (sps.csr_matrix, "csr", "C"), (sps.coo_matrix, "coo", "F")],
)
def test_scipy_minimum_spanning_tree(backend, graph, matrix_fn, format, order):
graph = matrix_fn(np.array(graph, order=order))
sp_graph = sparse.asarray(graph, format=format)

actual_span_tree = spgraph.minimum_spanning_tree(sp_graph)
expected_span_tree = spgraph.minimum_spanning_tree(graph)
assert_equal(actual_span_tree.todense(), expected_span_tree.toarray())


@pytest.mark.skip(reason="https://github.com/scikit-learn/scikit-learn/pull/29031")
@pytest.mark.parametrize("matrix_fn, format, order", [(sps.csc_matrix, "csc", "F")])
def test_scikit_learn_dispatch(backend, graph, matrix_fn, format, order):
from sklearn.cluster import KMeans

graph = matrix_fn(np.array(graph, order=order))

sp_graph = sparse.asarray(graph, format=format)

neigh = KMeans(n_clusters=2)
actual_labels = neigh.fit_predict(sp_graph)

neigh = KMeans(n_clusters=2)
expected_labels = neigh.fit_predict(graph)

assert_equal(actual_labels, expected_labels)

0 comments on commit b0f1a81

Please sign in to comment.