forked from giotto-ai/giotto-tda
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Place hypothesis tests in test_ripser and remove superseded tests the…
…re. Add regression test for giotto-ai#465
- Loading branch information
Showing
2 changed files
with
85 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,97 @@ | ||
import numpy as np | ||
import scipy as sp | ||
from .. import ripser | ||
import pytest | ||
from hypothesis import given | ||
from hypothesis.extra.numpy import arrays | ||
from hypothesis.strategies import floats, integers, composite | ||
from numpy.testing import assert_almost_equal | ||
from scipy.sparse import coo_matrix | ||
|
||
X = np.random.random((50, 50)) | ||
# Without this line, there might be different results because GUDHI | ||
# assumes zeros in the diagonal | ||
np.fill_diagonal(X, 0) | ||
maxdim = 2 | ||
from gtda.externals import ripser | ||
|
||
|
||
def test_with_collapser(): | ||
diags_collapsed = ripser( | ||
X, | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
collapse_edges=True)['dgms'] | ||
diags_not_collapsed = ripser( | ||
X, | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
collapse_edges=False)['dgms'] | ||
@composite | ||
def get_dense_distance_matrices(draw): | ||
"""Generate 2d dense square arrays of floats, with zero along the | ||
diagonal.""" | ||
shapes = draw(integers(min_value=2, max_value=30)) | ||
distance_matrix = draw(arrays(dtype=np.float, | ||
elements=floats(allow_nan=False, | ||
allow_infinity=True, | ||
min_value=0), | ||
shape=(shapes, shapes), unique=False)) | ||
np.fill_diagonal(distance_matrix, 0) | ||
return distance_matrix | ||
|
||
for i in range(maxdim): | ||
assert np.array_equal(diags_collapsed[i], diags_not_collapsed[i]) | ||
|
||
@composite | ||
def get_sparse_distance_matrices(draw): | ||
"""Generate 2d sparse matrices of floats, with zero along the diagonal.""" | ||
shapes = draw(integers(min_value=2, max_value=40)) | ||
distance_matrix = draw(arrays(dtype=np.float, | ||
elements=floats(allow_nan=False, | ||
allow_infinity=True, | ||
min_value=0), | ||
shape=(shapes, shapes), unique=False)) | ||
distance_matrix = np.triu(distance_matrix, k=1) | ||
distance_matrix = coo_matrix(distance_matrix) | ||
row, col, data = \ | ||
distance_matrix.row, distance_matrix.col, distance_matrix.data | ||
not_inf_idx = data != np.inf | ||
row = row[not_inf_idx] | ||
col = col[not_inf_idx] | ||
data = data[not_inf_idx] | ||
shape = (np.max(row) + 1, np.max(col) + 1) if not_inf_idx.any() else (0, 0) | ||
distance_matrix = coo_matrix((data, (row, col)), shape=shape) | ||
return distance_matrix | ||
|
||
def test_with_collapser_with_tresh(): | ||
thresh = 0.1 | ||
diags_collapsed_thresh = ripser( | ||
X, | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
thresh=thresh, | ||
collapse_edges=True)['dgms'] | ||
diags_not_collapsed_thresh = ripser( | ||
X, metric='precomputed', maxdim=maxdim, thresh=thresh, | ||
collapse_edges=False)['dgms'] | ||
|
||
for i in range(maxdim): | ||
assert np.array_equal(diags_collapsed_thresh[i], | ||
diags_not_collapsed_thresh[i]) | ||
@pytest.mark.parametrize('thresh', [False, True]) | ||
@given(distance_matrix=get_dense_distance_matrices()) | ||
def test_collapse_consistent_with_no_collapse_dense(thresh, distance_matrix): | ||
thresh = np.max(distance_matrix) / 2 if thresh else np.inf | ||
maxdim = 3 | ||
pd_collapse = ripser(distance_matrix, thresh=thresh, maxdim=maxdim, | ||
metric='precomputed', collapse_edges=True)['dgms'] | ||
pd_no_collapse = ripser(distance_matrix, thresh=thresh, maxdim=maxdim, | ||
metric='precomputed', collapse_edges=False)['dgms'] | ||
for i in range(maxdim + 1): | ||
pd_collapse[i] = np.sort(pd_collapse[i], axis=0) | ||
pd_no_collapse[i] = np.sort(pd_no_collapse[i], axis=0) | ||
assert_almost_equal(pd_collapse[i], pd_no_collapse[i]) | ||
|
||
|
||
def test_with_collapser_coo(): | ||
X_tri = np.triu(X, 1) | ||
diags_collapsed = ripser( | ||
sp.sparse.coo_matrix(X_tri), | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
collapse_edges=True)['dgms'] | ||
diags_not_collapsed = ripser( | ||
sp.sparse.coo_matrix(X_tri), | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
collapse_edges=False)['dgms'] | ||
@pytest.mark.parametrize('thresh', [False, True]) | ||
@given(distance_matrix=get_sparse_distance_matrices()) | ||
def test_collapse_consistent_with_no_collapse_coo(thresh, distance_matrix): | ||
if thresh and distance_matrix.nnz: | ||
thresh = np.max(distance_matrix) / 2 | ||
else: | ||
thresh = np.inf | ||
maxdim = 3 | ||
pd_collapse = ripser(distance_matrix, thresh=thresh, maxdim=maxdim, | ||
metric='precomputed', collapse_edges=True)['dgms'] | ||
pd_no_collapse = ripser(distance_matrix, thresh=thresh, maxdim=maxdim, | ||
metric='precomputed', collapse_edges=False)['dgms'] | ||
for i in range(maxdim + 1): | ||
pd_collapse[i] = np.sort(pd_collapse[i], axis=0) | ||
pd_no_collapse[i] = np.sort(pd_no_collapse[i], axis=0) | ||
assert_almost_equal(pd_collapse[i], pd_no_collapse[i]) | ||
|
||
for i in range(maxdim): | ||
assert np.array_equal(diags_collapsed[i], diags_not_collapsed[i]) | ||
|
||
|
||
def test_with_collapser_coo_thresh(): | ||
thresh = 0.1 | ||
X_tri = np.triu(X, 1) | ||
diags_collapsed = ripser( | ||
sp.sparse.coo_matrix(X_tri), | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
thresh=thresh, | ||
collapse_edges=True)['dgms'] | ||
diags_not_collapsed = ripser( | ||
sp.sparse.coo_matrix(X_tri), | ||
metric='precomputed', | ||
maxdim=maxdim, | ||
thresh=thresh, | ||
collapse_edges=False)['dgms'] | ||
|
||
for i in range(maxdim): | ||
assert np.array_equal(diags_collapsed[i], diags_not_collapsed[i]) | ||
def test_coo_results_independent_of_order(): | ||
"""Regression test for PR #465""" | ||
data = np.array([6., 8., 2., 4., 5., 9., 10., 3., 1., 1.]) | ||
row = np.array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]) | ||
col = np.array([4, 1, 3, 2, 4, 3, 2, 3, 4, 4]) | ||
dm = coo_matrix((data, (row, col))) | ||
diagrams = ripser(dm, metric="precomputed")['dgms'] | ||
diagrams_csr = ripser(dm.tocsr(), metric="precomputed")['dgms'] | ||
expected = [np.array([[0., 1.], | ||
[0., 1.], | ||
[0., 2.], | ||
[0., 5.], | ||
[0., np.inf]]), | ||
np.array([], shape=(0, 2), dtype=np.float64)] | ||
for i in range(2): | ||
assert np.array_equal(diagrams[i], expected[i]) | ||
assert np.array_equal(diagrams_csr[i], expected[i]) |