import numpy as np
import pytest
import scipy.spatial.distance
import scirs2
class TestDistanceFunctions:
def test_euclidean_distance(self):
np.random.seed(42)
for dim in [2, 5, 10]:
u = np.ascontiguousarray(np.random.randn(dim))
v = np.ascontiguousarray(np.random.randn(dim))
scipy_dist = scipy.spatial.distance.euclidean(u, v)
scirs2_dist = scirs2.euclidean_py(u, v)
assert np.allclose(scipy_dist, scirs2_dist, rtol=1e-12)
def test_cosine_distance(self):
np.random.seed(42)
for dim in [2, 5, 10]:
u = np.ascontiguousarray(np.random.randn(dim))
v = np.ascontiguousarray(np.random.randn(dim))
scipy_dist = scipy.spatial.distance.cosine(u, v)
scirs2_dist = scirs2.cosine_py(u, v)
assert np.allclose(scipy_dist, scirs2_dist, rtol=1e-12)
@pytest.mark.skip(reason="hamming_py is a window function, not a distance function")
def test_hamming_distance(self):
np.random.seed(42)
u = np.ascontiguousarray(np.random.randint(0, 2, 20).astype(float))
v = np.ascontiguousarray(np.random.randint(0, 2, 20).astype(float))
scipy_dist = scipy.spatial.distance.hamming(u, v)
class TestPairwiseDistances:
def test_pdist_euclidean(self):
np.random.seed(42)
X = np.ascontiguousarray(np.random.randn(10, 3))
scipy_dists = scipy.spatial.distance.pdist(X, metric='euclidean')
scirs2_dists = scirs2.pdist_py(X, metric='euclidean')
assert np.allclose(scipy_dists, scirs2_dists, rtol=1e-10)
def test_cdist_euclidean(self):
np.random.seed(42)
X = np.ascontiguousarray(np.random.randn(10, 3))
Y = np.ascontiguousarray(np.random.randn(15, 3))
scipy_dists = scipy.spatial.distance.cdist(X, Y, metric='euclidean')
scirs2_dists = scirs2.cdist_py(X, Y, metric='euclidean')
assert scipy_dists.shape == scirs2_dists.shape
assert np.allclose(scipy_dists, scirs2_dists, rtol=1e-10)
class TestKDTree:
def test_kdtree_query(self):
np.random.seed(42)
data = np.ascontiguousarray(np.random.randn(100, 3))
tree = scirs2.KDTree(data)
query_point = np.ascontiguousarray(np.array([0.0, 0.0, 0.0]))
result = tree.query(query_point, k=1)
indices = result['indices']
distances = result['distances']
index = indices[0]
distance = distances[0]
assert 0 <= index < len(data)
assert distance >= 0
manual_distances = np.sqrt(np.sum((data - query_point)**2, axis=1))
min_dist = manual_distances.min()
assert np.allclose(distance, min_dist, rtol=1e-10)
def test_kdtree_query_multiple(self):
np.random.seed(42)
data = np.ascontiguousarray(np.random.randn(50, 2))
tree = scirs2.KDTree(data)
query_point = np.ascontiguousarray(np.array([0.0, 0.0]))
result = tree.query(query_point, k=5)
indices = result['indices']
distances = result['distances']
assert len(distances) == 5
assert len(indices) == 5
assert np.all(distances[:-1] <= distances[1:])
assert np.all(indices >= 0)
assert np.all(indices < len(data))
if __name__ == "__main__":
pytest.main([__file__, "-v"])