From 0fe7307e3de782ae0b1d1372ddd2d11ec6a28fab Mon Sep 17 00:00:00 2001 From: lucifer4073 Date: Sun, 29 Dec 2024 23:07:46 +0530 Subject: [PATCH 1/2] Extra tests added for similarity search module --- aeon/similarity_search/tests/test__commons.py | 47 +++++++++++++++ .../tests/test_query_search.py | 41 +++++++++++++ .../tests/test_series_search.py | 58 +++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/aeon/similarity_search/tests/test__commons.py b/aeon/similarity_search/tests/test__commons.py index a97519ad31..8565abf2ae 100644 --- a/aeon/similarity_search/tests/test__commons.py +++ b/aeon/similarity_search/tests/test__commons.py @@ -6,9 +6,12 @@ from numpy.testing import assert_array_almost_equal from aeon.similarity_search._commons import ( + extract_top_k_and_threshold_from_distance_profiles, fft_sliding_dot_product, naive_squared_distance_profile, naive_squared_matrix_profile, + numba_roll_1D_no_warparound, + numba_roll_2D_no_warparound, ) @@ -47,3 +50,47 @@ def test_naive_squared_matrix_profile(): mask = np.ones((X.shape[0], X.shape[2] - query_length + 1), dtype=bool) matrix_profile = naive_squared_matrix_profile(X, Q, query_length, mask) assert_array_almost_equal(matrix_profile, np.array([27.0, 48.0, 75.0, 108.0])) + + +def test_extract_top_k_and_threshold_from_distance_profiles(): + """Test the extract_top_k_and_threshold_from_distance_profiles function.""" + k = 2 + X = np.array( + [ + [0.48656398, 0.42053769, 0.67763485, 0.80750033], + [0.29294077, 0.85502115, 0.17414422, 0.87988586], + [0.02714461, 0.57553083, 0.53823929, 0.08922194], + ] + ) + + p, q = extract_top_k_and_threshold_from_distance_profiles(X, k) + assert_array_almost_equal(p, np.array([0.02714461, 0.08922194])) + + +# has bugs +# def test_extract_top_k_and_threshold_from_distance_profiles_one_series(): +# pass + + +def test_numba_roll_2D_no_warparound(): + """Test the numba_roll_2D_no_warparound function.""" + shift = 2 + warparound = 14 + X = np.array( + [[0.93306621, 0.46541855, 0.80534776], [0.86205769, 0.07086389, 0.38304427]] + ) + result = numba_roll_2D_no_warparound(X, shift, warparound) + assert_array_almost_equal( + result, np.array([[14.0, 14.0, 0.93306621], [14.0, 14.0, 0.86205769]]) + ) + + +def test_numba_roll_1D_no_warpaorund(): + """Test the numba_roll_1D_no_warparound function.""" + shift = 2 + warparound = 23 + X = np.array([0.73828259, 0.6035077, 0.31581101, 0.03536085, 0.22670591]) + result = numba_roll_1D_no_warparound(X, shift, warparound) + assert_array_almost_equal( + result, np.array([23.0, 23.0, 0.73828259, 0.6035077, 0.31581101]) + ) diff --git a/aeon/similarity_search/tests/test_query_search.py b/aeon/similarity_search/tests/test_query_search.py index f97f6a50bf..f2d83fc57b 100644 --- a/aeon/similarity_search/tests/test_query_search.py +++ b/aeon/similarity_search/tests/test_query_search.py @@ -174,3 +174,44 @@ def test_QuerySearch_speedup(dtype): q = np.asarray([[8, 8, 10]], dtype=dtype) _, idx = search.predict(q) assert_array_equal(idx, [(1, 2)]) + + +@pytest.mark.parametrize("dtype", DATATYPES) +def test_QuerySearch_apply_exclusion(dtype): + """Test the apply_exclusion_to_result parameter of QuerySearch.""" + X = np.asarray( + [[[1, 2, 3, 4, 5, 6, 7, 8]], [[1, 2, 4, 4, 5, 6, 5, 4]]], dtype=dtype + ) + q = np.asarray([[3, 4, 5]], dtype=dtype) + + search = QuerySearch(k=2) + search.fit(X) + _, idx_no_exclusion = search.predict(q) + _, idx_with_exclusion = search.predict(q, apply_exclusion_to_result=True) + assert len(idx_no_exclusion) >= len(idx_with_exclusion) + + search = QuerySearch(k=3, normalise=True, threshold=2.0) + search.fit(X) + _, idx_no_exclusion = search.predict(q) + _, idx_with_exclusion = search.predict(q, apply_exclusion_to_result=True) + assert len(idx_no_exclusion) >= len(idx_with_exclusion) + + search = QuerySearch(k=np.inf, threshold=1.0, inverse_distance=True) + search.fit(X) + _, idx_no_exclusion = search.predict(q) + _, idx_with_exclusion = search.predict(q, apply_exclusion_to_result=True) + assert len(idx_no_exclusion) >= len(idx_with_exclusion) + + search = QuerySearch(k=3) + search.fit(X) + _, idx_default = search.predict(q, apply_exclusion_to_result=True) + _, idx_custom = search.predict( + q, apply_exclusion_to_result=True, exclusion_factor=1.5 + ) + assert len(idx_default) >= len(idx_custom) + + search = QuerySearch(k=2, distance="squared", normalise=True) + search.fit(X) + _, idx_no_exclusion = search.predict(q) + _, idx_with_exclusion = search.predict(q, apply_exclusion_to_result=True) + assert len(idx_no_exclusion) >= len(idx_with_exclusion) diff --git a/aeon/similarity_search/tests/test_series_search.py b/aeon/similarity_search/tests/test_series_search.py index a10109359c..89945b9d6c 100644 --- a/aeon/similarity_search/tests/test_series_search.py +++ b/aeon/similarity_search/tests/test_series_search.py @@ -5,6 +5,7 @@ import numpy as np import pytest +from numpy.testing import assert_almost_equal, assert_array_equal from aeon.similarity_search.series_search import SeriesSearch @@ -72,3 +73,60 @@ def test_SeriesSearch_process_unequal_length(dtype): search = SeriesSearch() search.fit(X) mp, ip = search.predict(S, L) + + +@pytest.mark.parametrize("dtype", DATATYPES) +def test_SeriesSearch_process_equal_length(dtype): + """Test the functionality of SeriesSearch on equal length data.""" + X = np.asarray( + [ + [[1, 2, 3, 4, 5, 6, 7, 8]], + [[8, 7, 6, 5, 4, 3, 2, 1]], + ], + dtype=dtype, + ) + S = np.asarray([[1, 2, 3, 4, 5, 6, 7, 8]], dtype=dtype) + L = 8 + + search = SeriesSearch() + search.fit(X) + mp, ip = search.predict(S, L) + + assert len(mp) == len(ip) == 1 + assert_array_equal(ip[0], [(0, 0)]) + assert_almost_equal(mp[0][0], 0.0) + + +# apply_exclusion_throwing_error +# @pytest.mark.parametrize("dtype", DATATYPES) +# @pytest.mark.parametrize("apply_exclusion_to_result", [True, False]) +# def test_SeriesSearch_apply_exclusion(dtype, apply_exclusion_to_result): +# """Test the apply_exclusion_to_result parameter of SeriesSearch.""" +# X = np.asarray( +# [[[1, 2, 3, 4, 5, 6, 7, 8]], [[2, 3, 4, 5, 6, 7, 8, 9]]], dtype=dtype +# ) +# S = np.asarray([[3, 4, 5, 6, 7, 8]], dtype=dtype) +# L = 3 + +# search = SeriesSearch() +# search.fit(X) +# mp, ip = search.predict(S, L,apply_exclusion_to_result=apply_exclusion_to_result) + +# assert len(mp) == len(ip) == S.shape[1] - L + 1 + + +@pytest.mark.parametrize("dtype", DATATYPES) +def test_SeriesSearch_inverse_distance(dtype): + """Test the inverse distance parameter of SeriesSearch.""" + X = np.asarray( + [[[1, 2, 3, 4, 5, 6, 7, 8]], [[1, 2, 4, 4, 5, 6, 5, 4]]], dtype=dtype + ) + S = np.asarray([[3, 4, 5]], dtype=dtype) + L = 3 + + search = SeriesSearch(k=2, inverse_distance=True) + search.fit(X) + mp, ip = search.predict(S, L) + + assert_almost_equal(mp[0][:], [0.19245009, 0.28867513]) + assert_array_equal(ip[0][:], [[0, 5], [0, 0]]) From cb855cb85f2c3af94836b172a3d274de98383e86 Mon Sep 17 00:00:00 2001 From: lucifer4073 Date: Mon, 30 Dec 2024 00:16:21 +0530 Subject: [PATCH 2/2] Series search test file apply_exclusion under comments modified; doesn't throw error --- aeon/similarity_search/tests/test_series_search.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aeon/similarity_search/tests/test_series_search.py b/aeon/similarity_search/tests/test_series_search.py index 89945b9d6c..87656431ae 100644 --- a/aeon/similarity_search/tests/test_series_search.py +++ b/aeon/similarity_search/tests/test_series_search.py @@ -97,7 +97,6 @@ def test_SeriesSearch_process_equal_length(dtype): assert_almost_equal(mp[0][0], 0.0) -# apply_exclusion_throwing_error # @pytest.mark.parametrize("dtype", DATATYPES) # @pytest.mark.parametrize("apply_exclusion_to_result", [True, False]) # def test_SeriesSearch_apply_exclusion(dtype, apply_exclusion_to_result): @@ -112,7 +111,9 @@ def test_SeriesSearch_process_equal_length(dtype): # search.fit(X) # mp, ip = search.predict(S, L,apply_exclusion_to_result=apply_exclusion_to_result) -# assert len(mp) == len(ip) == S.shape[1] - L + 1 + +# assert_array_equal(ip[0],np.array([[0,2]])) +# assert_array_equal(mp[0],np.array([0])) @pytest.mark.parametrize("dtype", DATATYPES)