diff --git a/README.rst b/README.rst index a8b8892fb..8d0cf995c 100644 --- a/README.rst +++ b/README.rst @@ -82,7 +82,7 @@ Typical usage (1-dimensional time series data) with `STUMP `_. +We tested the performance of computing the exact matrix profile using the Numba JIT compiled version of the code on randomly generated time series data with various lengths (i.e., ``np.random.default_rng().random(n)``) along with different `CPU and GPU hardware resources `_. .. image:: https://raw.githubusercontent.com/stumpy-dev/stumpy/main/docs/images/performance.png :alt: STUMPY Performance Plot diff --git a/conftest.py b/conftest.py index fe4951163..fddda4f62 100644 --- a/conftest.py +++ b/conftest.py @@ -4,3 +4,15 @@ # to fix eventual module import errors that can arise, for example when # running tests from inside VS code. # See https://stackoverflow.com/a/34520971 +import json + +from stumpy import rng + + +def pytest_configure(config): + """ + Called after command line options have been parsed + and all plugins and initial conftest files been loaded. + """ + state = json.dumps(rng.RNG.bit_generator.state, indent=4) + print(f"stumpy/rng.py: RNG.bit_generator.state = {state}") diff --git a/docs/Tutorial_Fast_Approximate_Matrix_Profiles.ipynb b/docs/Tutorial_Fast_Approximate_Matrix_Profiles.ipynb index ebe788fb6..98ecab402 100644 --- a/docs/Tutorial_Fast_Approximate_Matrix_Profiles.ipynb +++ b/docs/Tutorial_Fast_Approximate_Matrix_Profiles.ipynb @@ -334,11 +334,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Please keep in mind that the approximate matrix profile is computed by randomly computing distances along a subset of diagonals. So, each time you initialize a new `scrump` object by calling `stumpy.scrump`, this will randomly shuffle the order that the distances are computed, which inevitably results in different approximate matrix profiles (except when `percentage=1.0`). Depending on your use case, to ensure reproducible results, you may consider setting random seed prior to calling `stumpy.scrump`:\n", + "Please keep in mind that the approximate matrix profile is computed by randomly computing distances along a subset of diagonals. So, each time you initialize a new `scrump` object by calling `stumpy.scrump`, this will randomly shuffle the order that the distances are computed, which inevitably results in different approximate matrix profiles (except when `percentage=1.0`). Depending on your use case, to ensure reproducible results, you may consider fixing the random state prior to calling `stumpy.scrump`:\n", "\n", "```\n", - "seed = np.random.randint(100000)\n", - "np.random.seed(seed)\n", + "# Get and set random state\n", + "from stumpy import rng\n", + "state = rng.get_state()\n", + "rng.set_state(state)\n", + "\n", "approx = stumpy.scrump(steam_df['steam flow'], m, percentage=0.01, pre_scrump=False)\n", "```\n", "\n", @@ -503,7 +506,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.14.6" } }, "nbformat": 4, diff --git a/docs/Tutorial_Matrix_Profiles_For_Streaming_Data.ipynb b/docs/Tutorial_Matrix_Profiles_For_Streaming_Data.ipynb index 4a29b3d9e..986423479 100644 --- a/docs/Tutorial_Matrix_Profiles_For_Streaming_Data.ipynb +++ b/docs/Tutorial_Matrix_Profiles_For_Streaming_Data.ipynb @@ -47,7 +47,8 @@ "metadata": {}, "outputs": [], "source": [ - "T = np.random.rand(336)" + "rng = np.random.default_rng()\n", + "T = rng.random(336)" ] }, { @@ -122,7 +123,7 @@ "metadata": {}, "outputs": [], "source": [ - "t = np.random.rand()" + "t = rng.random()" ] }, { @@ -155,7 +156,7 @@ "outputs": [], "source": [ "for i in range(1000):\n", - " t = np.random.rand()\n", + " t = rng.random()\n", " stream.update(t)" ] }, @@ -183,7 +184,7 @@ "metadata": {}, "outputs": [], "source": [ - "T_full = np.random.rand(64)\n", + "T_full = rng.random(64)\n", "m = 8\n", "\n", "mp = stumpy.stump(T_full, m)\n", @@ -280,7 +281,7 @@ } ], "source": [ - "T_full = np.random.rand(1_000)\n", + "T_full = rng.random(1_000)\n", "T_stream = T_full[:20].copy()\n", "m = 10\n", "\n", @@ -266241,7 +266242,7 @@ } ], "source": [ - "T_full = np.random.rand(64)\n", + "T_full = rng.random(64)\n", "m = 8\n", "\n", "T_stream = T_full[:10].copy()\n", @@ -266302,7 +266303,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.4" + "version": "3.14.6" } }, "nbformat": 4, diff --git a/docs/Tutorial_Multidimensional_Motif_Discovery.ipynb b/docs/Tutorial_Multidimensional_Motif_Discovery.ipynb index 839c23b7f..111cc4fc5 100644 --- a/docs/Tutorial_Multidimensional_Motif_Discovery.ipynb +++ b/docs/Tutorial_Multidimensional_Motif_Discovery.ipynb @@ -571,7 +571,7 @@ ], "source": [ "for i in range(4, 11):\n", - " df[f'T{i}'] = np.random.uniform(0.1, -0.1, size=df.shape[0]).cumsum()\n", + " df[f'T{i}'] = np.random.default_rng().uniform(0.1, -0.1, size=df.shape[0]).cumsum()\n", " \n", "df = df.sample(frac=1, axis=\"columns\") # Randomly shuffle the columns\n", "\n", @@ -804,7 +804,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.4" + "version": "3.14.6" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/docs/Tutorial_Pattern_Matching.ipynb b/docs/Tutorial_Pattern_Matching.ipynb index 9985f14f9..504f6e243 100644 --- a/docs/Tutorial_Pattern_Matching.ipynb +++ b/docs/Tutorial_Pattern_Matching.ipynb @@ -645,8 +645,9 @@ } ], "source": [ - "Q_random = np.random.rand(100)\n", - "T_random = np.random.rand(1_000_000)\n", + "rng = np.random.default_rng()\n", + "Q_random = rng.random(100)\n", + "T_random = rng.random(1_000_000)\n", "\n", "naive_distance_profile = compute_naive_distance_profile(Q_random, T_random)" ] @@ -736,7 +737,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.14.6" } }, "nbformat": 4, diff --git a/docs/Tutorial_Time_Series_Chains.ipynb b/docs/Tutorial_Time_Series_Chains.ipynb index 143e2a6f0..1876c7efd 100644 --- a/docs/Tutorial_Time_Series_Chains.ipynb +++ b/docs/Tutorial_Time_Series_Chains.ipynb @@ -70,11 +70,12 @@ } ], "source": [ - "x = np.random.rand(20)\n", - "y = np.random.rand(20)\n", + "rng = np.random.default_rng()\n", + "x = rng.random(20)\n", + "y = rng.random(20)\n", "n = 10\n", - "motifs_x = 0.5 * np.ones(n) + np.random.uniform(-0.05, 0.05, n)\n", - "motifs_y = 0.5 * np.ones(n) + np.random.uniform(-0.05, 0.05, n)\n", + "motifs_x = 0.5 * np.ones(n) + rng.uniform(-0.05, 0.05, n)\n", + "motifs_y = 0.5 * np.ones(n) + rng.uniform(-0.05, 0.05, n)\n", "sin_x = np.linspace(0, np.pi/2, n+1)\n", "sin_y = np.sin(sin_x)/4\n", "chains_x = 0.5 * np.ones(n+1) + 0.02 * np.arange(n+1)\n", @@ -605,7 +606,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.4" + "version": "3.14.6" } }, "nbformat": 4, diff --git a/stumpy/core.py b/stumpy/core.py index f5d6ebcf3..65744eea0 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -3717,7 +3717,8 @@ def check_ignore_trivial(T_A, T_B, ignore_trivial): import numpy as np import warnings - T = np.random.rand(10_000) + rng = np.random.default_rng() + T = rng.random(10_000) m = 50 with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="Arrays T_A, T_B are equal") @@ -4493,7 +4494,8 @@ def check_self_join(ignore_trivial): import numpy as np import warnings - T = np.random.rand(10_000) + rng = np.random.default_rng() + T = rng.random(10_000) m = 50 with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="`ignore_trivial` cannot be `False`") diff --git a/stumpy/floss.py b/stumpy/floss.py index d73912154..5c78101cc 100644 --- a/stumpy/floss.py +++ b/stumpy/floss.py @@ -84,13 +84,13 @@ def _iac( IAC : numpy.ndarray Idealized arc curve (IAC) """ - np.random.seed(seed) + local_rng = np.random.default_rng(seed) - I = np.random.randint(0, width, size=width, dtype=np.int64) + I = local_rng.integers(0, width, size=width, dtype=np.int64) if bidirectional is False: # Idealized 1-dimensional matrix profile index I[:-1] = width for i in range(width - 1): - I[i] = np.random.randint(i + 1, width, dtype=np.int64) + I[i] = local_rng.integers(i + 1, width, dtype=np.int64) target_AC = _nnmark(I) @@ -99,7 +99,7 @@ def _iac( hist_dist = scipy.stats.rv_histogram( (target_AC, np.append(np.arange(width), width)) ) - data = hist_dist.rvs(size=n_samples) + data = hist_dist.rvs(size=n_samples, random_state=local_rng) a, b, c, d = scipy.stats.beta.fit(data, floc=0, fscale=width) params[i, 0] = a diff --git a/stumpy/rng.py b/stumpy/rng.py new file mode 100644 index 000000000..1d48d6f5d --- /dev/null +++ b/stumpy/rng.py @@ -0,0 +1,114 @@ +from contextlib import contextmanager + +import numpy as np + +bit_gen = np.random.PCG64() +RNG = np.random.Generator(bit_gen) +# RNG.bit_generator.state = { +# Set/paste RNG state here +# } + +PREV_STATE = None +FIXED_STATE = { + # DO NOT CHANGE/ALTER!! + "bit_generator": "PCG64", + "state": { + "state": 195349167630453735115769518810051464980, + "inc": 247589055400886363559049235690497450585, + }, + "has_uint32": 0, + "uinteger": 0, +} + + +def _get_state(): + """ + Get a copy of the current RNG state + + Parameters + ---------- + None + + Returns + ------- + state : dict + A copy of the current RNG state + """ + return RNG.bit_generator.state.copy() + + +def _set_state(state): + """ + Store existing RNG state and set RNG state + + Parameters + ---------- + state : dict + The RNG state to set + + Returns + ------- + None + """ + global PREV_STATE + PREV_STATE = _get_state() + RNG.bit_generator.state = state + + +def _reset_state(): + """ + Restore the RNG state to the last recorded RNG state + + Parameters + ---------- + None + + Returns + ------- + None + """ + global PREV_STATE + RNG.bit_generator.state = PREV_STATE.copy() + PREV_STATE = None + + +def _fix_state(): + """ + Set the RNG state to a fixed, hardcoded, safe state + + Parameters + ---------- + None + + Returns + ------- + None + """ + _set_state(FIXED_STATE) + + +@contextmanager +def fix_state(*args): + """ + A context manager for setting the RNG state to a fixed, hardcoded, safe state + + This is exceptionally rare and you probably want to use `state = get_state()` + and `set_state(state)` instead. + + Parameters + ---------- + None + + Returns + ------- + None + """ + _fix_state() + try: + yield + finally: + _reset_state() + + +get_state = _get_state +set_state = _set_state diff --git a/stumpy/scraamp.py b/stumpy/scraamp.py index dc17726cc..f9c932d95 100644 --- a/stumpy/scraamp.py +++ b/stumpy/scraamp.py @@ -6,7 +6,7 @@ import numpy as np from numba import njit, prange -from . import config, core +from . import config, core, rng from .aamp import _aamp @@ -78,7 +78,7 @@ def _preprocess_prescraamp(T_A, m, T_B=None, s=None): else: # AB-join s = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) - indices = np.random.permutation(range(0, l, s)).astype(np.int64) + indices = rng.RNG.permutation(range(0, l, s)).astype(np.int64) return (T_A, T_B, T_A_subseq_isfinite, T_B_subseq_isfinite, indices, s, excl_zone) @@ -718,7 +718,7 @@ def __init__( core._merge_topk_PI(self._P, P, self._I, I) if self._ignore_trivial: - self._diags = np.random.permutation( + self._diags = rng.RNG.permutation( range(self._excl_zone + 1, self._n_A - self._m + 1) ).astype(np.int64) if self._diags.shape[0] == 0: # pragma: no cover @@ -728,7 +728,7 @@ def __init__( f"Please try a value of `m <= {max_m}`" ) else: - self._diags = np.random.permutation( + self._diags = rng.RNG.permutation( range(-(self._n_A - self._m + 1) + 1, self._n_B - self._m + 1) ).astype(np.int64) diff --git a/stumpy/scrump.py b/stumpy/scrump.py index 03739cdd6..2e4810f80 100644 --- a/stumpy/scrump.py +++ b/stumpy/scrump.py @@ -6,7 +6,7 @@ import numpy as np from numba import njit, prange -from . import config, core, sdp +from . import config, core, rng, sdp from .scraamp import prescraamp, scraamp from .stump import _stump @@ -116,7 +116,7 @@ def _preprocess_prescrump( else: # AB-join s = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) - indices = np.random.permutation(range(0, l, s)).astype(np.int64) + indices = rng.RNG.permutation(range(0, l, s)).astype(np.int64) return ( T_A, @@ -378,6 +378,7 @@ def _compute_PI( P_squared[thread_idx, j], idx, squared_distance_profile[j] ) core._shift_insert_at_index(I[thread_idx, j], idx, i) + # core._shift_insert_at_index(I[thread_idx, j, :idx], idx, i) @njit( @@ -997,7 +998,7 @@ def __init__( core._merge_topk_PI(self._P, P, self._I, I) if self._ignore_trivial: - self._diags = np.random.permutation( + self._diags = rng.RNG.permutation( range(self._excl_zone + 1, self._n_A - self._m + 1) ).astype(np.int64) if self._diags.shape[0] == 0: # pragma: no cover @@ -1007,7 +1008,7 @@ def __init__( f"Please try a value of `m <= {max_m}`" ) else: - self._diags = np.random.permutation( + self._diags = rng.RNG.permutation( range(-(self._n_A - self._m + 1) + 1, self._n_B - self._m + 1) ).astype(np.int64) diff --git a/test.sh b/test.sh index 194288574..8eaf7ff9f 100755 --- a/test.sh +++ b/test.sh @@ -175,7 +175,7 @@ set_ray_coveragerc() show_coverage_report() { set_ray_coveragerc - coverage report --show-missing --fail-under=100 --skip-covered --omit=fastmath.py,docstring.py,versions.py $fcoveragerc + coverage report --show-missing --fail-under=100 --skip-covered --omit=fastmath.py,docstring.py,versions.py,conftest.py $fcoveragerc check_errs $? } diff --git a/tests/naive.py b/tests/naive.py index c316a87e8..26667aa32 100644 --- a/tests/naive.py +++ b/tests/naive.py @@ -4,7 +4,7 @@ from scipy.spatial.distance import cdist from scipy.stats import norm -from stumpy import config, core +from stumpy import config, core, rng def is_ptp_zero_1d(a, w): # `a` is 1-D @@ -1818,7 +1818,7 @@ def prescrump( P = np.full((l, k), np.inf, dtype=np.float64) I = np.full((l, k), -1, dtype=np.int64) - for i in np.random.permutation(range(0, l, s)): + for i in rng.RNG.permutation(range(0, l, s)): distance_profile = dist_matrix[i] if exclusion_zone is not None: apply_exclusion_zone(distance_profile, i, exclusion_zone, np.inf) @@ -1914,11 +1914,11 @@ def scrump( pass if exclusion_zone is not None: - diags = np.random.permutation(range(exclusion_zone + 1, n_A - m + 1)).astype( + diags = rng.RNG.permutation(range(exclusion_zone + 1, n_A - m + 1)).astype( np.int64 ) else: - diags = np.random.permutation(range(-(n_A - m + 1) + 1, n_B - m + 1)).astype( + diags = rng.RNG.permutation(range(-(n_A - m + 1) + 1, n_B - m + 1)).astype( np.int64 ) @@ -1981,7 +1981,7 @@ def prescraamp(T_A, m, T_B, s, exclusion_zone=None, p=2.0, k=1): P = np.full((l, k), np.inf, dtype=np.float64) I = np.full((l, k), -1, dtype=np.int64) - for i in np.random.permutation(range(0, l, s)): + for i in rng.RNG.permutation(range(0, l, s)): distance_profile = distance_matrix[i] if exclusion_zone is not None: apply_exclusion_zone(distance_profile, i, exclusion_zone, np.inf) @@ -2054,11 +2054,11 @@ def scraamp(T_A, m, T_B, percentage, exclusion_zone, pre_scraamp, s, p=2.0, k=1) l = n_A - m + 1 if exclusion_zone is not None: - diags = np.random.permutation(range(exclusion_zone + 1, n_A - m + 1)).astype( + diags = rng.RNG.permutation(range(exclusion_zone + 1, n_A - m + 1)).astype( np.int64 ) else: - diags = np.random.permutation(range(-(n_A - m + 1) + 1, n_B - m + 1)).astype( + diags = rng.RNG.permutation(range(-(n_A - m + 1) + 1, n_B - m + 1)).astype( np.int64 ) diff --git a/tests/test_aamp.py b/tests/test_aamp.py index ab5dfc64a..ac83786a9 100644 --- a/tests/test_aamp.py +++ b/tests/test_aamp.py @@ -4,7 +4,7 @@ import pandas as pd import pytest -from stumpy import config +from stumpy import config, rng from stumpy.aamp import aamp test_data = [ @@ -13,8 +13,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -72,7 +72,7 @@ def test_aamp_constant_subsequence_self_join(): def test_aamp_one_constant_subsequence_A_B_join(): - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) m = 3 ref_mp = naive.aamp(T_A, m, T_B=T_B) @@ -122,8 +122,8 @@ def test_aamp_two_constant_subsequences_A_B_join(): def test_aamp_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -143,9 +143,9 @@ def test_aamp_identical_subsequence_self_join(): def test_aamp_identical_subsequence_A_B_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_aamp_mmotifs.py b/tests/test_aamp_mmotifs.py index b205fa2a5..da433e29a 100755 --- a/tests/test_aamp_mmotifs.py +++ b/tests/test_aamp_mmotifs.py @@ -3,7 +3,7 @@ import numpy.testing as npt import pytest -from stumpy import config +from stumpy import config, rng from stumpy.aamp_mmotifs import aamp_mmotifs test_data = [ @@ -51,32 +51,30 @@ def test_aamp_mmotifs_default_parameters(): - motif_distances_ref = np.array( - [[0.0, 0.06315749, 0.25275899, 0.34087884, 0.3452315]] - ) - motif_indices_ref = np.array([[19, 77, 63, 52, 71]]) - motif_subspaces_ref = [np.array([2])] + motif_distances_ref = np.array([[0.0, 0.10660435, 0.27927693]]) + motif_indices_ref = np.array([[19, 41, 34]]) + motif_subspaces_ref = [np.array([1])] motif_mdls_ref = [ - np.array([411.60964047, 423.69925001, 449.11032383, 476.95855027, 506.62406252]) + np.array([411.60964047, 433.21928095, 429.77443751, 457.74925683, 477.80793557]) ] - np.random.seed(0) - T = np.random.rand(500).reshape(5, 100) - - m = 5 - excl_zone = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) - P, I = naive.maamp(T, m, excl_zone) - ( - motif_distances_cmp, - motif_indices_cmp, - motif_subspaces_cmp, - motif_mdls_cmp, - ) = aamp_mmotifs(T, P, I) - - npt.assert_array_almost_equal(motif_distances_ref, motif_distances_cmp) - npt.assert_array_almost_equal(motif_indices_ref, motif_indices_cmp) - npt.assert_array_almost_equal(motif_subspaces_ref, motif_subspaces_cmp) - npt.assert_array_almost_equal(motif_mdls_ref, motif_mdls_cmp) + with rng.fix_state(): + T = rng.RNG.random(size=(5, 100)) + + m = 5 + excl_zone = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) + P, I = naive.maamp(T, m, excl_zone) + ( + motif_distances_cmp, + motif_indices_cmp, + motif_subspaces_cmp, + motif_mdls_cmp, + ) = aamp_mmotifs(T, P, I) + + npt.assert_array_almost_equal(motif_distances_ref, motif_distances_cmp) + npt.assert_array_almost_equal(motif_indices_ref, motif_indices_cmp) + npt.assert_array_almost_equal(motif_subspaces_ref, motif_subspaces_cmp) + npt.assert_array_almost_equal(motif_mdls_ref, motif_mdls_cmp) @pytest.mark.parametrize("T", test_data) diff --git a/tests/test_aamp_motifs.py b/tests/test_aamp_motifs.py index 17e2488f0..5708d8163 100644 --- a/tests/test_aamp_motifs.py +++ b/tests/test_aamp_motifs.py @@ -3,7 +3,7 @@ import numpy.testing as npt import pytest -from stumpy import core +from stumpy import core, rng from stumpy.aamp_motifs import aamp_match, aamp_motifs test_data = [ @@ -15,7 +15,7 @@ np.array([0.0, 1.0, 2.0]), np.array([0.1, 1.0, 2.0, 3.0, -1.0, 0.1, 1.0, 2.0, -0.5]), ), - (np.random.uniform(-1000, 1000, [8]), np.random.uniform(-1000, 1000, [64])), + (rng.RNG.uniform(-1000, 1000, [8]), rng.RNG.uniform(-1000, 1000, [64])), ] @@ -71,61 +71,57 @@ def test_aamp_motifs_one_motif(): def test_aamp_motifs_two_motifs(): # Fix seed, because in some case motifs can be off by an index resulting in test # fails, which is caused since one of the motifs is not repeated perfectly in T. - np.random.seed(1234) - - # The time series is random noise with two motifs for m=10: - # * (almost) identical step functions at indices 10, 110 and 210 - # * identical linear slopes at indices 70 and 170 - T = np.random.normal(size=300) - m = 20 - - T[10:30] = 1 - T[12:28] = 2 - - # This is not part of the motif in the aamp case - T[110:130] = 3 - T[112:128] = 6 - T[120] = 6.6 - - T[210:230] = 1 - T[212:228] = 2 - T[220] = 1.9 - # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[110:130])) = 0.47 - # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[210:230])) = 0.24 - # naive.distance(naive.z_norm(T[110:130]), naive.z_norm(T[210:230])) = 0.72 - # Hence T[10:30] is the motif representative for this motif - - T[70:90] = np.arange(m) * 0.1 - T[170:190] = np.arange(m) * 0.1 - # naive.distance(naive.z_norm(T[70:90]), naive.z_norm(T[170:190])) = 0.0 - - max_motifs = 2 - - mp = naive.aamp(T, m) - - # left_indices = [[70, 170], [10, 210]] - left_profile_values = [ - [0.0, 0.0], - [ - 0.0, - naive.distance(T[10:30], T[210:230]), - ], - ] - - right_distance_values, right_indices = aamp_motifs( - T, - mp[:, 0], - max_motifs=max_motifs, - max_distance=0.5, - cutoff=np.inf, - ) + with rng.fix_state(): + # The time series is random noise with two motifs for m=20: + # * (almost) identical step functions at indices 10, 110 and 210 + # * identical linear slopes at indices 70 and 170 + T = rng.RNG.random(size=300) + m = 20 + + T[10:30] = 1 + T[12:28] = 2 + + # This is not part of the motif in the aamp case + T[110:130] = 3 + T[112:128] = 6 + T[120] = 6.6 + + T[210:230] = 1 + T[212:228] = 2 + T[220] = 1.9 + # naive.distance(T[10:30], T[110:130]) == 16.65 + # naive.distance(T[10:30], T[210:230]) == 0.1 + # naive.distance(T[110:130], T[210:230]) == 16.68 + # Hence T[10:30] is the motif representative for this motif + + T[70:90] = np.arange(m) * 0.1 + T[170:190] = np.arange(m) * 0.1 + # naive.distance(T[70:90], T[170:190]) = 0.0 + + max_motifs = 2 + + mp = naive.aamp(T, m) + + # left_indices = [[70, 170], [10, 210]] + left_profile_values = [ + [0.0, 0.0], + [ + 0.0, + naive.distance(T[10:30], T[210:230]), + ], + ] - # We ignore indices because of sorting ambiguities for equal distances. - # As long as the distances are correct, the indices will be too. - npt.assert_almost_equal(left_profile_values, right_distance_values, decimal=6) + right_distance_values, right_indices = aamp_motifs( + T, + mp[:, 0], + max_motifs=max_motifs, + max_distance=0.5, + cutoff=np.inf, + ) - # Reset seed - np.random.seed(None) + # We ignore indices because of sorting ambiguities for equal distances. + # As long as the distances are correct, the indices will be too. + npt.assert_almost_equal(left_profile_values, right_distance_values, decimal=6) def test_aamp_naive_match_exact(): diff --git a/tests/test_aamp_ostinato.py b/tests/test_aamp_ostinato.py index e74b58c86..09d9fae17 100644 --- a/tests/test_aamp_ostinato.py +++ b/tests/test_aamp_ostinato.py @@ -5,7 +5,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import core +from stumpy import core, rng from stumpy.aamp_ostinato import aamp_ostinato, aamp_ostinatoed @@ -24,27 +24,34 @@ def dask_cluster(): pass -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) -def test_random_ostinato(seed): - m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] +def test_random_ostinato(): + for _ in range(25): + m = 50 + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m) - comp_radius, comp_Ts_idx, comp_subseq_idx = aamp_ostinato(Ts, m) + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m) + comp_radius, comp_Ts_idx, comp_subseq_idx = aamp_ostinato(Ts, m) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) -@pytest.mark.parametrize("seed", [41, 88, 290, 292, 310, 328, 538, 556, 563, 570]) -def test_deterministic_ostinato(seed): +def test_deterministic_ostinato(): + state = rng.get_state() + rng.set_state( + { + "bit_generator": "PCG64", + "state": { + "state": 136943825700000385711366942645458644078, + "inc": 332366955175428936936330404254354698391, + }, + "has_uint32": 0, + "uinteger": 0, + } + ) m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for p in [1.0, 2.0, 3.0]: ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m, p=p) @@ -54,35 +61,18 @@ def test_deterministic_ostinato(seed): npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + rng.set_state(state) # Reset the RNG state to what it was before this test -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) -def test_random_ostinatoed(seed, dask_cluster): - with Client(dask_cluster) as dask_client: - m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] - - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m) - comp_radius, comp_Ts_idx, comp_subseq_idx = aamp_ostinatoed(dask_client, Ts, m) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) - - -@pytest.mark.parametrize("seed", [41, 88, 290, 292, 310, 328, 538, 556, 563, 570]) -def test_deterministic_ostinatoed(seed, dask_cluster): +def test_random_ostinatoed(dask_cluster): with Client(dask_cluster) as dask_client: - m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + for _ in range(25): + m = 50 + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - for p in [1.0, 2.0, 3.0]: - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m, p=p) + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = aamp_ostinatoed( - dask_client, Ts, m, p=p + dask_client, Ts, m ) npt.assert_almost_equal(ref_radius, comp_radius) @@ -90,12 +80,32 @@ def test_deterministic_ostinatoed(seed, dask_cluster): npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) +def test_deterministic_ostinatoed(dask_cluster): + with rng.fix_state(): + with Client(dask_cluster) as dask_client: + for _ in range(10): + m = 50 + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] + + for p in [1.0, 2.0, 3.0]: + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato( + Ts, m, p=p + ) + comp_radius, comp_Ts_idx, comp_subseq_idx = aamp_ostinatoed( + dask_client, Ts, m, p=p + ) + + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + + def test_input_not_overwritten_ostinato(): # aamp_ostinato preprocesses its input, a list of time series, # by replacing nan value with 0 in each time series. # This test ensures that the original input is not overwritten m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -111,7 +121,7 @@ def test_input_not_overwritten_ostinato(): def test_extract_several_consensus_ostinato(): # This test is to further ensure that the function `aamp_ostinato` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [256, 512, 1024]] + Ts = [rng.RNG.random(n) for n in [256, 512, 1024]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] @@ -149,7 +159,7 @@ def test_input_not_overwritten_ostinatoed(dask_cluster): # This test ensures that the original input is not overwritten with Client(dask_cluster) as dask_client: m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -167,7 +177,7 @@ def test_input_not_overwritten_ostinatoed(dask_cluster): def test_extract_several_consensus_ostinatoed(dask_cluster): # This test is to further ensure that the function `ostinatoed` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [256, 512, 1024]] + Ts = [rng.RNG.random(n) for n in [256, 512, 1024]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] diff --git a/tests/test_aamp_stimp.py b/tests/test_aamp_stimp.py index 7f5faa202..72e289e65 100644 --- a/tests/test_aamp_stimp.py +++ b/tests/test_aamp_stimp.py @@ -5,11 +5,12 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster +from stumpy import rng from stumpy.aamp_stimp import aamp_stimp, aamp_stimped T = [ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, [64]).astype(np.float64), ] n = [9, 10, 16] @@ -37,9 +38,7 @@ def test_aamp_stimp_1_percent(T): min_m = 3 n = T.shape[0] - min_m + 1 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() pan = aamp_stimp( T, min_m=min_m, @@ -54,7 +53,7 @@ def test_aamp_stimp_1_percent(T): ref_PAN = np.full((pan.M_.shape[0], T.shape[0]), fill_value=np.inf) - np.random.seed(seed) + rng.set_state(state) for idx, m in enumerate(pan.M_[:n]): zone = int(np.ceil(m / 4)) s = zone @@ -97,9 +96,7 @@ def test_aamp_stimp_max_m(T): max_m = 5 n = T.shape[0] - min_m + 1 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() pan = aamp_stimp( T, min_m=min_m, @@ -114,7 +111,7 @@ def test_aamp_stimp_max_m(T): ref_PAN = np.full((pan.M_.shape[0], T.shape[0]), fill_value=np.inf) - np.random.seed(seed) + rng.set_state(state) for idx, m in enumerate(pan.M_[:n]): zone = int(np.ceil(m / 4)) s = zone diff --git a/tests/test_aampdist.py b/tests/test_aampdist.py index f1c915d62..ed361a09d 100644 --- a/tests/test_aampdist.py +++ b/tests/test_aampdist.py @@ -5,6 +5,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster +from stumpy import rng from stumpy.aampdist import _aampdist_vect, aampdist, aampdisted @@ -29,8 +30,8 @@ def dask_cluster(): np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] diff --git a/tests/test_aampdist_snippets.py b/tests/test_aampdist_snippets.py index 7356f3101..c5ed74183 100644 --- a/tests/test_aampdist_snippets.py +++ b/tests/test_aampdist_snippets.py @@ -3,10 +3,10 @@ import numpy.testing as npt import pytest -from stumpy import config +from stumpy import config, rng from stumpy.aampdist_snippets import aampdist_snippets -test_data = [np.random.uniform(-1000, 1000, [64]).astype(np.float64)] +test_data = [rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64)] s = [6, 7, 8] percentage = [0.7, 0.8, 0.9] m = [8, 9, 10] diff --git a/tests/test_aamped.py b/tests/test_aamped.py index df35ff318..1986d3bf8 100644 --- a/tests/test_aamped.py +++ b/tests/test_aamped.py @@ -6,7 +6,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import config +from stumpy import config, rng from stumpy.aamped import aamped @@ -31,8 +31,8 @@ def dask_cluster(): np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -191,7 +191,7 @@ def test_aamped_one_constant_subsequence_self_join_df(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_one_constant_subsequence_A_B_join(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -211,7 +211,7 @@ def test_aamped_one_constant_subsequence_A_B_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_one_constant_subsequence_A_B_join_df(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -233,7 +233,7 @@ def test_aamped_one_constant_subsequence_A_B_join_df(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_one_constant_subsequence_A_B_join_swap(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -253,7 +253,7 @@ def test_aamped_one_constant_subsequence_A_B_join_swap(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_one_constant_subsequence_A_B_join_df_swap(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -275,8 +275,8 @@ def test_aamped_one_constant_subsequence_A_B_join_df_swap(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_identical_subsequence_self_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -297,9 +297,9 @@ def test_aamped_identical_subsequence_self_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_aamped_identical_subsequence_A_B_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_aampi.py b/tests/test_aampi.py index 03c6d6914..c1ca2d24a 100644 --- a/tests/test_aampi.py +++ b/tests/test_aampi.py @@ -4,7 +4,7 @@ import pandas as pd import pytest -from stumpy import config, core +from stumpy import config, core, rng from stumpy.aampi import aampi substitution_locations = [(slice(0, 0), 0, -1, slice(1, 3), [0, 3])] @@ -20,14 +20,13 @@ def test_aampi_self_join(): m = 3 for p in [1.0, 2.0, 3.0]: - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) stream = aampi(T, m, egress=False, p=p) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -56,13 +55,13 @@ def test_aampi_self_join(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) + rng.set_state(state) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) T = pd.Series(T) stream = aampi(T, m, egress=False, p=p) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -83,11 +82,10 @@ def test_aampi_self_join_egress(): m = 3 for p in [1.0, 2.0, 3.0]: - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) ref_mp = naive.aampi_egress(T, m, p=p) ref_P = ref_mp.P_.copy() @@ -113,7 +111,7 @@ def test_aampi_self_join_egress(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -138,8 +136,8 @@ def test_aampi_self_join_egress(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(n) + rng.set_state(state) + T = rng.RNG.random(n) T = pd.Series(T) ref_mp = naive.aampi_egress(T, m, p=p) @@ -158,7 +156,7 @@ def test_aampi_self_join_egress(): npt.assert_almost_equal(ref_I, comp_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -189,20 +187,17 @@ def test_aampi_self_join_egress(): def test_aampi_init_nan_inf_self_join(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) - # seed = 58638 - for substitution_location in substitution_locations: - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) if substitution_location == -1: substitution_location = T.shape[0] - 1 T[substitution_location] = substitute stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -218,9 +213,9 @@ def test_aampi_init_nan_inf_self_join(substitute, substitution_locations): npt.assert_almost_equal(ref_P, comp_P) npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) + rng.set_state(state) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) if substitution_location == -1: # pragma: no cover substitution_location = T.shape[0] - 1 @@ -228,7 +223,7 @@ def test_aampi_init_nan_inf_self_join(substitute, substitution_locations): T = pd.Series(T) stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -245,13 +240,10 @@ def test_aampi_init_nan_inf_self_join(substitute, substitution_locations): def test_aampi_init_nan_inf_self_join_egress(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) - # seed = 58638 - for substitution_location in substitution_locations: - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) if substitution_location == -1: substitution_location = T.shape[0] - 1 @@ -281,7 +273,7 @@ def test_aampi_init_nan_inf_self_join_egress(substitute, substitution_locations) npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -306,9 +298,9 @@ def test_aampi_init_nan_inf_self_join_egress(substitute, substitution_locations) npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) + rng.set_state(state) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) T = pd.Series(T) ref_mp = naive.aampi_egress(T, m) @@ -330,7 +322,7 @@ def test_aampi_init_nan_inf_self_join_egress(substitute, substitution_locations) naive.replace_inf(comp_left_P) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -361,12 +353,10 @@ def test_aampi_init_nan_inf_self_join_egress(substitute, substitution_locations) def test_aampi_stream_nan_inf_self_join(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) - for substitution_location in substitution_locations: - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(64) + T = rng.RNG.random(64) stream = aampi(T[:n], m, egress=False) if substitution_location == -1: @@ -389,8 +379,8 @@ def test_aampi_stream_nan_inf_self_join(substitute, substitution_locations): npt.assert_almost_equal(ref_P, comp_P) npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) stream = aampi(pd.Series(T[:n]), m, egress=False) if substitution_location == -1: # pragma: no cover @@ -413,12 +403,10 @@ def test_aampi_stream_nan_inf_self_join(substitute, substitution_locations): def test_aampi_stream_nan_inf_self_join_egress(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) - for substitution_location in substitution_locations: - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(64) + T = rng.RNG.random(64) ref_mp = naive.aampi_egress(T[:n], m) ref_P = ref_mp.P_.copy() @@ -470,8 +458,8 @@ def test_aampi_stream_nan_inf_self_join_egress(substitute, substitution_location npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) ref_mp = naive.aampi_egress(T[:n], m) ref_P = ref_mp.P_.copy() @@ -526,13 +514,12 @@ def test_aampi_stream_nan_inf_self_join_egress(substitute, substitution_location def test_aampi_constant_subsequence_self_join(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -548,12 +535,12 @@ def test_aampi_constant_subsequence_self_join(): npt.assert_almost_equal(ref_P, comp_P) # npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) + rng.set_state(state) T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) T = pd.Series(T) stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -568,8 +555,7 @@ def test_aampi_constant_subsequence_self_join(): def test_aampi_constant_subsequence_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) @@ -597,7 +583,7 @@ def test_aampi_constant_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -621,7 +607,7 @@ def test_aampi_constant_subsequence_self_join_egress(): npt.assert_almost_equal(ref_left_P, comp_left_P) # npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) + rng.set_state(state) T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) T = pd.Series(T) @@ -649,7 +635,7 @@ def test_aampi_constant_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -677,9 +663,7 @@ def test_aampi_constant_subsequence_self_join_egress(): def test_aampi_update_constant_subsequence_self_join(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) - T_full = np.random.rand(64) # generate random data + T_full = rng.RNG.random(64) # generate random data T_full[40:55] = 3 # add constant level interval T_stream = T_full[:10].copy() @@ -715,10 +699,7 @@ def test_aampi_update_constant_subsequence_self_join(): def test_aampi_update_constant_subsequence_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) - - T_full = np.random.rand(64) # generate random data + T_full = rng.RNG.random(64) # generate random data T_full[40:55] = 3 # add constant level interval T_stream = T_full[:10].copy() @@ -778,16 +759,15 @@ def test_aampi_update_constant_subsequence_self_join_egress(): def test_aampi_identical_subsequence_self_join(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -803,15 +783,15 @@ def test_aampi_identical_subsequence_self_join(): npt.assert_almost_equal(ref_P, comp_P, decimal=config.STUMPY_TEST_PRECISION) # npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) - identical = np.random.rand(8) - T = np.random.rand(20) + rng.set_state(state) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical T = pd.Series(T) stream = aampi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -826,11 +806,10 @@ def test_aampi_identical_subsequence_self_join(): def test_aampi_identical_subsequence_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical @@ -860,7 +839,7 @@ def test_aampi_identical_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -886,9 +865,9 @@ def test_aampi_identical_subsequence_self_join_egress(): ) # npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - identical = np.random.rand(8) - T = np.random.rand(20) + rng.set_state(state) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical T = pd.Series(T) @@ -919,7 +898,7 @@ def test_aampi_identical_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -947,7 +926,7 @@ def test_aampi_identical_subsequence_self_join_egress(): def test_aampi_profile_index_match(): - T_full = np.random.rand(64) + T_full = rng.RNG.random(64) m = 3 T_full_subseq = core.rolling_window(T_full, m) warm_start = 8 @@ -984,14 +963,13 @@ def test_aampi_self_join_KNN(): m = 3 for k in range(2, 4): for p in [1.0, 2.0, 3.0]: - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) stream = aampi(T, m, egress=False, p=p, k=k) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -1021,13 +999,13 @@ def test_aampi_self_join_KNN(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) + rng.set_state(state) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) T = pd.Series(T) stream = aampi(T, m, egress=False, p=p, k=k) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -1048,11 +1026,10 @@ def test_aampi_self_join_egress_KNN(): m = 3 for k in range(2, 4): for p in [1.0, 2.0, 3.0]: - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) ref_mp = naive.aampi_egress(T, m, p=p, k=k) ref_P = ref_mp.P_.copy() @@ -1078,7 +1055,7 @@ def test_aampi_self_join_egress_KNN(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -1103,8 +1080,8 @@ def test_aampi_self_join_egress_KNN(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(n) + rng.set_state(state) + T = rng.RNG.random(n) T = pd.Series(T) ref_mp = naive.aampi_egress(T, m, p=p, k=k) @@ -1123,7 +1100,7 @@ def test_aampi_self_join_egress_KNN(): npt.assert_almost_equal(ref_I, comp_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -1153,11 +1130,8 @@ def test_aampi_self_join_egress_passing_mp(): m = 3 for p in [1.0, 2.0, 3.0]: - seed = np.random.randint(100000) - np.random.seed(seed) - n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) mp = naive.aamp(T, m, p=p) ref_mp = naive.aampi_egress(T, m, p=p, mp=mp) @@ -1184,7 +1158,7 @@ def test_aampi_self_join_egress_passing_mp(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) diff --git a/tests/test_cache.py b/tests/test_cache.py index 4b70b48ae..970070efb 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -1,7 +1,6 @@ import numba -import numpy as np -from stumpy import cache +from stumpy import cache, rng from stumpy.stump import stump @@ -11,7 +10,7 @@ def test_cache_get_njit_funcs(): def test_cache_save_after_clear(): - T = np.random.rand(10) + T = rng.RNG.random(10) m = 3 cache_dir = "stumpy/__pycache__" diff --git a/tests/test_core.py b/tests/test_core.py index 5be54321e..b1f1e0cef 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -11,7 +11,7 @@ from numba import cuda from scipy.spatial.distance import cdist -from stumpy import config, core +from stumpy import config, core, rng from stumpy.stump import stump if cuda.is_available(): @@ -141,7 +141,7 @@ def naive_bfs_indices(n, fill_value=None): np.array([9, 8100, -60], dtype=np.float64), np.array([584, -11, 23, 79, 1001], dtype=np.float64), ), - (np.random.uniform(-1000, 1000, [8]), np.random.uniform(-1000, 1000, [64])), + (rng.RNG.uniform(-1000, 1000, size=8), rng.RNG.uniform(-1000, 1000, size=64)), ] n = list(range(1, 50)) @@ -150,11 +150,11 @@ def naive_bfs_indices(n, fill_value=None): def test_check_bad_dtype(): for dtype in [np.int32, np.int64, np.float32]: with pytest.raises(TypeError): - core.check_dtype(np.random.rand(10).astype(dtype)) + core.check_dtype(rng.RNG.random(10).astype(dtype)) def test_check_dtype_float64(): - assert core.check_dtype(np.random.rand(10)) + assert core.check_dtype(rng.RNG.random(10)) def test_get_max_window_size(): @@ -188,7 +188,7 @@ def test_check_max_window_size(): def test_check_window_size_excl_zone(): # To ensure warning is raised if there is at least one subsequence # that has no non-trivial neighbor - T = np.random.rand(10) + T = rng.RNG.random(10) m = 7 # For `len(T) == 10` and `m == 7`, the `excl_zone` is ceil(m / 4) = 2. @@ -208,7 +208,7 @@ def test_sliding_dot_product(Q, T): def test_welford_nanvar(): - T = np.random.rand(64) + T = rng.RNG.random(64) m = 10 ref_var = np.nanvar(T) @@ -230,7 +230,7 @@ def test_welford_nanvar_catastrophic_cancellation(): def test_welford_nanvar_nan(): - T = np.random.rand(64) + T = rng.RNG.random(64) m = 10 T[1] = np.nan @@ -247,7 +247,7 @@ def test_welford_nanvar_nan(): def test_welford_nanstd(): - T = np.random.rand(64) + T = rng.RNG.random(64) m = 10 ref_var = np.nanstd(T) @@ -260,7 +260,7 @@ def test_welford_nanstd(): def test_rolling_std_1d(): - a = np.random.rand(64) + a = rng.RNG.random(64) for w in range(3, 6): ref_std = naive.rolling_nanstd(a, w) @@ -276,7 +276,7 @@ def test_rolling_std_1d(): def test_rolling_std_2d(): w = 5 for n_rows in range(1, 4): - a = np.random.rand(n_rows * 64).reshape(n_rows, 64) + a = rng.RNG.random(size=(n_rows, 64)) ref_std = naive.rolling_nanstd(a, w) # welford = False (default) @@ -289,7 +289,7 @@ def test_rolling_std_2d(): def test_rolling_nanmin_1d(): - T = np.random.rand(64) + T = rng.RNG.random(64) for m in range(1, 12): ref_min = np.nanmin(T) comp_min = core._rolling_nanmin_1d(T) @@ -301,7 +301,7 @@ def test_rolling_nanmin_1d(): def test_rolling_nanmin(): - T = np.random.rand(64) + T = rng.RNG.random(64) for m in range(1, 12): ref_min = np.nanmin(core.rolling_window(T, m), axis=1) comp_min = core.rolling_nanmin(T, m) @@ -313,7 +313,7 @@ def test_rolling_nanmin(): def test_rolling_nanmax_1d(): - T = np.random.rand(64) + T = rng.RNG.random(64) for m in range(1, 12): ref_max = np.nanmax(T) comp_max = core._rolling_nanmax_1d(T) @@ -325,7 +325,7 @@ def test_rolling_nanmax_1d(): def test_rolling_nanmax(): - T = np.random.rand(64) + T = rng.RNG.random(64) for m in range(1, 12): ref_max = np.nanmax(core.rolling_window(T, m), axis=1) comp_max = core.rolling_nanmax(T, m) @@ -387,8 +387,8 @@ def test_compute_mean_std_chunked_many(Q, T): def test_compute_mean_std_multidimensional(Q, T): m = Q.shape[0] - Q = np.array([Q, np.random.uniform(-1000, 1000, [Q.shape[0]])]) - T = np.array([T, T, np.random.uniform(-1000, 1000, [T.shape[0]])]) + Q = np.array([Q, rng.RNG.uniform(-1000, 1000, size=Q.shape[0])]) + T = np.array([T, T, rng.RNG.uniform(-1000, 1000, size=T.shape[0])]) ref_μ_Q, ref_σ_Q = naive_compute_mean_std_multidimensional(Q, m) ref_M_T, ref_Σ_T = naive_compute_mean_std_multidimensional(T, m) @@ -405,8 +405,8 @@ def test_compute_mean_std_multidimensional(Q, T): def test_compute_mean_std_multidimensional_chunked(Q, T): m = Q.shape[0] - Q = np.array([Q, np.random.uniform(-1000, 1000, [Q.shape[0]])]) - T = np.array([T, T, np.random.uniform(-1000, 1000, [T.shape[0]])]) + Q = np.array([Q, rng.RNG.uniform(-1000, 1000, size=Q.shape[0])]) + T = np.array([T, T, rng.RNG.uniform(-1000, 1000, size=T.shape[0])]) with patch("stumpy.config.STUMPY_MEAN_STD_NUM_CHUNKS", 2): ref_μ_Q, ref_σ_Q = naive_compute_mean_std_multidimensional(Q, m) @@ -424,8 +424,8 @@ def test_compute_mean_std_multidimensional_chunked(Q, T): def test_compute_mean_std_multidimensional_chunked_many(Q, T): m = Q.shape[0] - Q = np.array([Q, np.random.uniform(-1000, 1000, [Q.shape[0]])]) - T = np.array([T, T, np.random.uniform(-1000, 1000, [T.shape[0]])]) + Q = np.array([Q, rng.RNG.uniform(-1000, 1000, size=Q.shape[0])]) + T = np.array([T, T, rng.RNG.uniform(-1000, 1000, size=T.shape[0])]) with patch("stumpy.config.STUMPY_MEAN_STD_NUM_CHUNKS", 128): ref_μ_Q, ref_σ_Q = naive_compute_mean_std_multidimensional(Q, m) @@ -918,7 +918,7 @@ def test_preprocess_diagonal(): def test_replace_distance(): - right = np.random.rand(30).reshape(5, 6) + right = rng.RNG.random(size=(5, 6)) left = right.copy() np.fill_diagonal(right, config.STUMPY_MAX_DISTANCE - 1e-9) np.fill_diagonal(left, np.inf) @@ -926,7 +926,7 @@ def test_replace_distance(): def test_array_to_temp_file(): - left = np.random.rand() + left = rng.RNG.random() fname = core.array_to_temp_file(left) right = np.load(fname, allow_pickle=False) os.remove(fname) @@ -938,7 +938,7 @@ def test_count_diagonal_ndist(): for n_A in range(10, 15): for n_B in range(10, 15): for m in range(3, 6): - diags = np.random.permutation( + diags = rng.RNG.permutation( range(-(n_A - m + 1) + 1, n_B - m + 1) ).astype(np.int64) ones_matrix = np.ones((n_A - m + 1, n_B - m + 1), dtype=np.int64) @@ -1107,12 +1107,12 @@ def test_get_mask_slices(): def test_idx_to_mp(): n = 64 m = 5 - T = np.random.rand(n) + T = rng.RNG.random(n) # T[1] = np.nan # T[8] = np.inf # T[:] = 1.0 l = n - m + 1 - I = np.random.randint(0, l, l) + I = rng.RNG.integers(0, l, l) # `normalize == True` and `T_subseq_isconstant` is None (default) ref_mp = naive_idx_to_mp(I, T, m) @@ -1120,7 +1120,7 @@ def test_idx_to_mp(): npt.assert_almost_equal(ref_mp, cmp_mp) # `normalize == True` and `T_subseq_isconstant` is provided - T_subseq_isconstant = np.random.choice([True, False], l, replace=True) + T_subseq_isconstant = rng.RNG.choice([True, False], l, replace=True) ref_mp = naive_idx_to_mp(I, T, m, T_subseq_isconstant=T_subseq_isconstant) cmp_mp = core._idx_to_mp(I, T, m, T_subseq_isconstant=T_subseq_isconstant) npt.assert_almost_equal(ref_mp, cmp_mp) @@ -1171,7 +1171,7 @@ def test_bfs_indices_fill_value(n): def test_select_P_ABBA_val_inf(): - P_ABBA = np.random.rand(10) + P_ABBA = rng.RNG.random(10) k = 2 P_ABBA[k:] = np.inf p_abba = P_ABBA.copy() @@ -1187,13 +1187,13 @@ def test_merge_topk_PI_without_overlap(): # is no overlap between row IA[i] and row IB[i]. n = 50 for k in range(1, 6): - PA = np.random.rand(n * k).reshape(n, k) + PA = rng.RNG.random(size=(n, k)) PA[:, :] = np.sort(PA, axis=1) # sorting each row separately - PB = np.random.rand(n * k).reshape(n, k) - col_idx = np.random.randint(0, k, size=n) + PB = rng.RNG.random(size=(n, k)) + col_idx = rng.RNG.integers(0, k, size=n) for i in range(n): # creating ties between values of PA and PB - val = np.random.choice(PA[i], size=1, replace=False) + val = rng.RNG.choice(PA[i], size=1, replace=False) PB[i, col_idx[i]] = val.item() PB[:, :] = np.sort(PB, axis=1) # sorting each row separately @@ -1220,17 +1220,17 @@ def test_merge_topk_PI_with_overlap(): for k in range(1, 6): # note: we do not have overlap issue when k is 1. The `k=1` is considered # for the sake of consistency with the `without-overlap` test function. - PA = np.random.rand(n * k).reshape(n, k) - PB = np.random.rand(n * k).reshape(n, k) + PA = rng.RNG.random(size=(n, k)) + PB = rng.RNG.random(size=(n, k)) IA = np.arange(n * k).reshape(n, k) IB = IA + n * k - num_overlaps = np.random.randint(1, k + 1, size=n) + num_overlaps = rng.RNG.integers(1, k + 1, size=n) for i in range(n): # create overlaps - col_IDX = np.random.choice(np.arange(k), num_overlaps[i], replace=False) - imprecision = np.random.uniform(low=-1e-06, high=1e-06, size=len(col_IDX)) + col_IDX = rng.RNG.choice(np.arange(k), num_overlaps[i], replace=False) + imprecision = rng.RNG.uniform(low=-1e-06, high=1e-06, size=len(col_IDX)) PB[i, col_IDX] = PA[i, col_IDX] + imprecision IB[i, col_IDX] = IA[i, col_IDX] @@ -1259,15 +1259,15 @@ def test_merge_topk_PI_with_overlap(): def test_merge_topk_PI_with_1D_input(): # including some overlaps randomly n = 50 - PA = np.random.rand(n) - PB = np.random.rand(n) + PA = rng.RNG.random(n) + PB = rng.RNG.random(n) IA = np.arange(n) IB = IA + n - n_overlaps = np.random.randint(1, n + 1) - IDX_rows_with_overlaps = np.random.choice(np.arange(n), n_overlaps, replace=False) - imprecision = np.random.uniform(low=-1e-06, high=1e-06, size=n_overlaps) + n_overlaps = rng.RNG.integers(1, n + 1) + IDX_rows_with_overlaps = rng.RNG.choice(np.arange(n), n_overlaps, replace=False) + imprecision = rng.RNG.uniform(low=-1e-06, high=1e-06, size=n_overlaps) PB[IDX_rows_with_overlaps] = PA[IDX_rows_with_overlaps] + imprecision IB[IDX_rows_with_overlaps] = IA[IDX_rows_with_overlaps] @@ -1312,13 +1312,13 @@ def test_merge_topk_ρI_without_overlap(): # is no overlap between row IA[i] and row IB[i]. n = 50 for k in range(1, 6): - ρA = np.random.rand(n * k).reshape(n, k) + ρA = rng.RNG.random(size=(n, k)) ρA[:, :] = np.sort(ρA, axis=1) # sorting each row separately - ρB = np.random.rand(n * k).reshape(n, k) - col_idx = np.random.randint(0, k, size=n) + ρB = rng.RNG.random(size=(n, k)) + col_idx = rng.RNG.integers(0, k, size=n) for i in range(n): # creating ties between values of PA and PB - val = np.random.choice(ρA[i], size=1, replace=False) + val = rng.RNG.choice(ρA[i], size=1, replace=False) ρB[i, col_idx[i]] = val.item() ρB[:, :] = np.sort(ρB, axis=1) # sorting each row separately @@ -1345,17 +1345,17 @@ def test_merge_topk_ρI_with_overlap(): for k in range(1, 6): # note: we do not have overlap issue when k is 1. The `k=1` is considered # for the sake of consistency with the `without-overlap` test function. - ρA = np.random.rand(n * k).reshape(n, k) - ρB = np.random.rand(n * k).reshape(n, k) + ρA = rng.RNG.random(size=(n, k)) + ρB = rng.RNG.random(size=(n, k)) IA = np.arange(n * k).reshape(n, k) IB = IA + n * k - num_overlaps = np.random.randint(1, k + 1, size=n) + num_overlaps = rng.RNG.integers(1, k + 1, size=n) for i in range(n): # create overlaps - col_IDX = np.random.choice(np.arange(k), num_overlaps[i], replace=False) - imprecision = np.random.uniform(low=-1e-06, high=1e-06, size=len(col_IDX)) + col_IDX = rng.RNG.choice(np.arange(k), num_overlaps[i], replace=False) + imprecision = rng.RNG.uniform(low=-1e-06, high=1e-06, size=len(col_IDX)) ρB[i, col_IDX] = ρA[i, col_IDX] + imprecision IB[i, col_IDX] = IA[i, col_IDX] @@ -1384,15 +1384,15 @@ def test_merge_topk_ρI_with_overlap(): def test_merge_topk_ρI_with_1D_input(): # including some overlaps randomly n = 50 - ρA = np.random.rand(n) - ρB = np.random.rand(n) + ρA = rng.RNG.random(n) + ρB = rng.RNG.random(n) IA = np.arange(n) IB = IA + n - n_overlaps = np.random.randint(1, n + 1) - IDX_rows_with_overlaps = np.random.choice(np.arange(n), n_overlaps, replace=False) - imprecision = np.random.uniform(low=-1e-06, high=1e-06, size=n_overlaps) + n_overlaps = rng.RNG.integers(1, n + 1) + IDX_rows_with_overlaps = rng.RNG.choice(np.arange(n), n_overlaps, replace=False) + imprecision = rng.RNG.uniform(low=-1e-06, high=1e-06, size=n_overlaps) ρB[IDX_rows_with_overlaps] = ρA[IDX_rows_with_overlaps] + imprecision IB[IDX_rows_with_overlaps] = IA[IDX_rows_with_overlaps] @@ -1434,12 +1434,12 @@ def test_merge_topk_ρI_with_1D_input_hardcoded(): def test_shift_insert_at_index(): for k in range(1, 6): - a = np.random.rand(k) + a = rng.RNG.random(k) ref = np.empty(k, dtype=np.float64) comp = np.empty(k, dtype=np.float64) indices = np.arange(k + 1) - values = np.random.rand(k + 1) + values = rng.RNG.random(k + 1) # test shift = "right" for idx, v in zip(indices, values): @@ -1468,13 +1468,13 @@ def test_shift_insert_at_index(): def test_check_P(): with pytest.raises(ValueError): - core._check_P(np.random.rand(10).reshape(2, 5)) + core._check_P(rng.RNG.random(size=(2, 5))) def test_find_matches_all(): # max_matches: None, i.e. find all matches max_distance = np.inf - D = np.random.rand(64) + D = rng.RNG.random(64) for excl_zone in range(3): ref = naive.find_matches(D, excl_zone, max_distance, max_matches=None) comp = core._find_matches(D, excl_zone, max_distance, max_matches=None) @@ -1484,9 +1484,9 @@ def test_find_matches_all(): def test_find_matches_maxmatch(): max_distance = np.inf - D = np.random.rand(64) + D = rng.RNG.random(64) for excl_zone in range(3): - max_matches = np.random.randint(0, 100) + max_matches = rng.RNG.integers(0, 100) ref = naive.find_matches(D, excl_zone, max_distance, max_matches) comp = core._find_matches(D, excl_zone, max_distance, max_matches) @@ -1509,11 +1509,11 @@ def test_gpu_searchsorted(): device_bfs = cuda.to_device(core._bfs_indices(k, fill_value=-1)) nlevel = np.floor(np.log2(k) + 1).astype(np.int64) - A = np.sort(np.random.rand(n, k), axis=1) + A = np.sort(rng.RNG.random(size=(n, k)), axis=1) device_A = cuda.to_device(A) - V[:] = np.random.rand(n) - for i, idx in enumerate(np.random.choice(np.arange(n), size=k, replace=False)): + V[:] = rng.RNG.random(n) + for i, idx in enumerate(rng.RNG.choice(np.arange(n), size=k, replace=False)): V[idx] = A[idx, i] # create ties device_V = cuda.to_device(V) @@ -1548,7 +1548,7 @@ def test_client_to_func(): def test_apply_include(): - D = np.random.uniform(-1000, 1000, [10, 20]).astype(np.float64) + D = rng.RNG.uniform(-1000, 1000, [10, 20]).astype(np.float64) ref_D = np.empty(D.shape) comp_D = np.empty(D.shape) for width in range(D.shape[0]): @@ -1683,7 +1683,7 @@ def test_process_isconstant_1d(): m = 8 # case 1: without nan - T = np.random.rand(n) + T = rng.RNG.random(n) T_subseq_isconstant_ref = naive.rolling_isconstant(T, m, isconstant_custom_func) T_subseq_isconstant_comp = core.process_isconstant(T, m, isconstant_custom_func) @@ -1691,10 +1691,10 @@ def test_process_isconstant_1d(): npt.assert_array_equal(T_subseq_isconstant_ref, T_subseq_isconstant_comp) # case 2: with nan - T = np.random.rand(n) - idx = np.random.randint(n) + T = rng.RNG.random(n) + idx = rng.RNG.integers(n) T[idx] = np.nan - T_subseq_isconstant = np.random.choice([True, False], n - m + 1, replace=True) + T_subseq_isconstant = rng.RNG.choice([True, False], n - m + 1, replace=True) T_subseq_isfinite = core.rolling_isfinite(T, m) @@ -1714,11 +1714,11 @@ def test_process_isconstant_2d(): d = 3 # case 1: without nan - T = np.random.rand(d, n) + T = rng.RNG.random(size=(d, n)) T_subseq_isconstant = [ None, isconstant_custom_func, - np.random.choice([True, False], n - m + 1, replace=True), + rng.RNG.choice([True, False], n - m + 1, replace=True), ] T_subseq_isconstant_ref = np.array( @@ -1730,8 +1730,8 @@ def test_process_isconstant_2d(): npt.assert_array_equal(T_subseq_isconstant_ref, T_subseq_isconstant_comp) # case 2: with nan - T = np.random.rand(d, n) - i, j = np.random.choice(np.arange(n - m + 1), size=2, replace=False) + T = rng.RNG.random(size=(d, n)) + i, j = rng.RNG.choice(np.arange(n - m + 1), size=2, replace=False) T[-1, i : i + m] = 0.0 T[-1, j : j + m] = 0.0 T[-1, j] = np.nan @@ -1764,7 +1764,7 @@ def test_process_isconstant_1d_default(): m = 8 # case 1: without nan - T = np.random.rand(n) + T = rng.RNG.random(n) T[:m] = 0.5 # constant subsequence T_subseq_isconstant_ref = naive.rolling_isconstant(T, m, a_subseq_isconstant=None) @@ -1773,7 +1773,7 @@ def test_process_isconstant_1d_default(): npt.assert_array_equal(T_subseq_isconstant_ref, T_subseq_isconstant_comp) # case 2: with nan - T = np.random.rand(n) + T = rng.RNG.random(n) T[:m] = 0.5 # constant subsequence T[-m:] = np.nan # non-finite subsequence @@ -1787,8 +1787,8 @@ def test_update_incremental_PI_egressFalse(): # This tests the function `core._update_incremental_PI` # when `egress` is False, meaning new data point is being # appended to the historical data. - T = np.random.rand(64) - t = np.random.rand() # new datapoint + T = rng.RNG.random(64) + t = rng.RNG.random() # new datapoint T_new = np.append(T, t) m = 3 @@ -1829,8 +1829,8 @@ def test_update_incremental_PI_egressFalse(): def test_update_incremental_PI_egressTrue(): - T = np.random.rand(64) - t = np.random.rand() # new data point + T = rng.RNG.random(64) + t = rng.RNG.random() # new data point m = 3 excl_zone = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) @@ -1891,66 +1891,66 @@ def test_update_incremental_PI_egressTrue_MemoryCheck(): # a new data point is appended. However, the updated matrix profile index for the # middle subsequence `s` should still refer to the first subsequence in # the historical data. - seed = 0 - np.random.seed(seed) + with rng.fix_state(): + T = rng.RNG.random(64) + m = 3 + excl_zone = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) - T = np.random.rand(64) - m = 3 - excl_zone = int(np.ceil(m / config.STUMPY_EXCL_ZONE_DENOM)) - - s = np.random.rand(m) - T[:m] = s - T[30 : 30 + m] = s - T[-m:] = s - - t = np.random.rand() # new data point - T_with_t = np.append(T, t) - - # In egress=True mode, a new data point, t, is being appended - # to the historical data, T, while the oldest data point is - # being removed. Therefore, the first subsequence in T - # and the last subsequence does not get a chance to meet each - # other. Therefore, their pairwise distances should be excluded - # from the distance matrix. - D = naive.distance_matrix(T_with_t, T_with_t, m) - D[-1, 0] = np.inf - D[0, -1] = np.inf + s = rng.RNG.random(m) + T[:m] = s + T[30 : 30 + m] = s + T[-m:] = s - l = len(T_with_t) - m + 1 - for i in range(l): - core.apply_exclusion_zone(D[i], i, excl_zone, np.inf) + t = rng.RNG.random() # new data point + T_with_t = np.append(T, t) - T_new = np.append(T[1:], t) - dist_profile = naive.distance_profile(T_new[-m:], T_new, m) - core.apply_exclusion_zone(dist_profile, len(dist_profile) - 1, excl_zone, np.inf) + # In egress=True mode, a new data point, t, is being appended + # to the historical data, T, while the oldest data point is + # being removed. Therefore, the first subsequence in T + # and the last subsequence does not get a chance to meet each + # other. Therefore, their pairwise distances should be excluded + # from the distance matrix. + D = naive.distance_matrix(T_with_t, T_with_t, m) + D[-1, 0] = np.inf + D[0, -1] = np.inf - for k in range(1, 4): - # ref - P = np.empty((l, k), dtype=np.float64) - I = np.empty((l, k), dtype=np.int64) + l = len(T_with_t) - m + 1 for i in range(l): - IDX = np.argsort(D[i], kind="mergesort")[:k] - I[i] = IDX - P[i] = D[i, IDX] - - P_ref = P[1:].copy() - I_ref = I[1:].copy() - - # comp - mp = naive.stump(T, m, row_wise=True, k=k) - P_comp = mp[:, :k].astype(np.float64) - I_comp = mp[:, k : 2 * k].astype(np.int64) + core.apply_exclusion_zone(D[i], i, excl_zone, np.inf) - P_comp[:-1] = P_comp[1:] - P_comp[-1] = np.inf - I_comp[:-1] = I_comp[1:] - I_comp[-1] = -1 - core._update_incremental_PI( - dist_profile, P_comp, I_comp, excl_zone, n_appended=1 + T_new = np.append(T[1:], t) + dist_profile = naive.distance_profile(T_new[-m:], T_new, m) + core.apply_exclusion_zone( + dist_profile, len(dist_profile) - 1, excl_zone, np.inf ) - npt.assert_almost_equal(P_ref, P_comp) - npt.assert_almost_equal(I_ref, I_comp) + for k in range(1, 4): + # ref + P = np.empty((l, k), dtype=np.float64) + I = np.empty((l, k), dtype=np.int64) + for i in range(l): + IDX = np.argsort(D[i], kind="mergesort")[:k] + I[i] = IDX + P[i] = D[i, IDX] + + P_ref = P[1:].copy() + I_ref = I[1:].copy() + + # comp + mp = naive.stump(T, m, row_wise=True, k=k) + P_comp = mp[:, :k].astype(np.float64) + I_comp = mp[:, k : 2 * k].astype(np.int64) + + P_comp[:-1] = P_comp[1:] + P_comp[-1] = np.inf + I_comp[:-1] = I_comp[1:] + I_comp[-1] = -1 + core._update_incremental_PI( + dist_profile, P_comp, I_comp, excl_zone, n_appended=1 + ) + + npt.assert_almost_equal(P_ref, P_comp) + npt.assert_almost_equal(I_ref, I_comp) def test_check_self_join(): diff --git a/tests/test_floss.py b/tests/test_floss.py index af06c71e5..f873a243d 100644 --- a/tests/test_floss.py +++ b/tests/test_floss.py @@ -5,7 +5,7 @@ import numpy.testing as npt import pytest -from stumpy import core +from stumpy import core, rng from stumpy.aamp import aamp from stumpy.floss import _cac, _iac, _nnmark, _rea, floss, fluss from stumpy.stump import stump @@ -94,7 +94,7 @@ def naive_rea(cac, n_regimes, L, excl_factor): return np.array(loc_regimes, dtype=np.int64) -test_data = [np.random.randint(0, 50, size=50, dtype=np.int64)] +test_data = [rng.RNG.integers(0, 50, size=50, dtype=np.int64)] substitution_locations = [(slice(0, 0), 0, -1, slice(1, 3), [0, 3])] substitution_values = [np.nan, np.inf] @@ -154,7 +154,7 @@ def test_fluss(I): def test_floss(): - data = np.random.uniform(-1000, 1000, [64]) + data = rng.RNG.uniform(-1000, 1000, size=64) m = 5 n = 30 old_data = data[:n] @@ -215,7 +215,7 @@ def test_floss(): def test_aamp_floss(): - data = np.random.uniform(-1000, 1000, [64]) + data = rng.RNG.uniform(-1000, 1000, size=64) m = 5 n = 30 old_data = data[:n] @@ -287,7 +287,7 @@ def test_aamp_floss(): @pytest.mark.parametrize("substitute", substitution_values) @pytest.mark.parametrize("substitution_locations", substitution_locations) def test_floss_inf_nan(substitute, substitution_locations): - T = np.random.uniform(-1000, 1000, [64]) + T = rng.RNG.uniform(-1000, 1000, size=64) m = 5 n = 30 data = T.copy() @@ -359,7 +359,7 @@ def test_floss_inf_nan(substitute, substitution_locations): @pytest.mark.parametrize("substitute", substitution_values) @pytest.mark.parametrize("substitution_locations", substitution_locations) def test_aamp_floss_inf_nan(substitute, substitution_locations): - T = np.random.uniform(-1000, 1000, [64]) + T = rng.RNG.uniform(-1000, 1000, size=64) m = 5 n = 30 data = T.copy() @@ -431,7 +431,7 @@ def test_aamp_floss_inf_nan(substitute, substitution_locations): def test_floss_with_isconstant(): - data = np.random.uniform(-1, 1, [64]) + data = rng.RNG.uniform(-1, 1, size=64) m = 5 n = 30 old_data = data[:n] diff --git a/tests/test_gpu_aamp.py b/tests/test_gpu_aamp.py index 7b180bc24..dc6e12fa5 100644 --- a/tests/test_gpu_aamp.py +++ b/tests/test_gpu_aamp.py @@ -5,7 +5,7 @@ import pandas as pd from numba import cuda -from stumpy import config +from stumpy import config, rng if cuda.is_available(): from stumpy.gpu_aamp import gpu_aamp @@ -33,8 +33,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -188,7 +188,7 @@ def test_gpu_aamp_constant_subsequence_self_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_aamp_one_constant_subsequence_A_B_join(): - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) m = 3 ref_mp = naive.aamp(T_B, m, T_B=T_A) @@ -244,8 +244,8 @@ def test_gpu_aamp_two_constant_subsequences_A_B_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_aamp_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -268,9 +268,9 @@ def test_gpu_aamp_identical_subsequence_self_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_aamp_identical_subsequence_A_B_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_gpu_aamp_ostinato.py b/tests/test_gpu_aamp_ostinato.py index 39069a49a..74f7c79a2 100644 --- a/tests/test_gpu_aamp_ostinato.py +++ b/tests/test_gpu_aamp_ostinato.py @@ -4,6 +4,8 @@ import numpy.testing as npt from numba import cuda +from stumpy import rng + try: from numba.errors import NumbaPerformanceWarning except ModuleNotFoundError: @@ -28,14 +30,10 @@ @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=2, replace=False) -) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_random_gpu_aamp_ostinato(seed): +def test_random_gpu_aamp_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_aamp_ostinato(Ts, m) @@ -46,20 +44,19 @@ def test_random_gpu_aamp_ostinato(seed): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize("seed", [41, 88]) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_deterministic_gpu_aamp_ostinato(seed): +def test_deterministic_gpu_aamp_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + with rng.fix_state(): + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - for p in [1.0, 2.0, 3.0]: - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m, p=p) - comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_aamp_ostinato(Ts, m, p=p) + for p in [1.0, 2.0, 3.0]: + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.aamp_ostinato(Ts, m, p=p) + comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_aamp_ostinato(Ts, m, p=p) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @@ -69,7 +66,7 @@ def test_input_not_overwritten(): # by replacing nan value with 0 in each time series. # This test ensures that the original input is not overwritten m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -87,7 +84,7 @@ def test_input_not_overwritten(): def test_extract_several_consensus(): # This test is to further ensure that the function `gpu_aamp_ostinato` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [64, 128]] + Ts = [rng.RNG.random(n) for n in [64, 128]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] diff --git a/tests/test_gpu_aamp_stimp.py b/tests/test_gpu_aamp_stimp.py index e1226b457..390583c5b 100644 --- a/tests/test_gpu_aamp_stimp.py +++ b/tests/test_gpu_aamp_stimp.py @@ -4,6 +4,8 @@ import numpy.testing as npt from numba import cuda +from stumpy import rng + if cuda.is_available(): from stumpy.gpu_aamp_stimp import gpu_aamp_stimp else: # pragma: no cover @@ -27,7 +29,7 @@ T = [ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ] diff --git a/tests/test_gpu_aampdist.py b/tests/test_gpu_aampdist.py index c53b1bd88..08ca149f5 100644 --- a/tests/test_gpu_aampdist.py +++ b/tests/test_gpu_aampdist.py @@ -4,6 +4,8 @@ import numpy.testing as npt from numba import cuda +from stumpy import rng + if cuda.is_available(): from stumpy.gpu_aampdist import gpu_aampdist else: # pragma: no cover @@ -29,8 +31,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] diff --git a/tests/test_gpu_mpdist.py b/tests/test_gpu_mpdist.py index 49850d3d9..733312f8a 100644 --- a/tests/test_gpu_mpdist.py +++ b/tests/test_gpu_mpdist.py @@ -5,6 +5,8 @@ import numpy.testing as npt from numba import cuda +from stumpy import rng + if cuda.is_available(): from stumpy.gpu_mpdist import gpu_mpdist else: # pragma: no cover @@ -30,8 +32,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] diff --git a/tests/test_gpu_ostinato.py b/tests/test_gpu_ostinato.py index 081de959d..70d327b89 100644 --- a/tests/test_gpu_ostinato.py +++ b/tests/test_gpu_ostinato.py @@ -4,6 +4,8 @@ import numpy.testing as npt from numba import cuda +from stumpy import rng + try: from numba.errors import NumbaPerformanceWarning except ModuleNotFoundError: @@ -29,14 +31,10 @@ @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=2, replace=False) -) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_random_gpu_ostinato(seed): +def test_random_gpu_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato(Ts, m) @@ -47,34 +45,29 @@ def test_random_gpu_ostinato(seed): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize("seed", [79, 109]) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_deterministic_gpu_ostinato(seed): +def test_deterministic_gpu_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + with rng.fix_state(): + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) - comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato(Ts, m) + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) + comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato(Ts, m) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_random_gpu_ostinato_with_isconstant(seed): +def test_random_gpu_ostinato_with_isconstant(): isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] Ts_subseq_isconstant = [isconstant_custom_func for _ in range(len(Ts))] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( @@ -90,36 +83,35 @@ def test_random_gpu_ostinato_with_isconstant(seed): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) -@pytest.mark.parametrize("seed", [79, 109, 112, 133, 151, 161, 251, 275, 309, 355]) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_deterministic_gpu_ostinato_with_isconstant(seed): +def test_deterministic_gpu_ostinato_with_isconstant(): isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) - m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] - - l = 64 - m + 1 - subseq_isconsant = np.full(l, 0, dtype=bool) - subseq_isconsant[np.random.randint(0, l)] = True - Ts_subseq_isconstant = [ - subseq_isconsant, - None, - isconstant_custom_func, - ] + with rng.fix_state(): + m = 50 + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( - Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant - ) - comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato( - Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant - ) + l = 64 - m + 1 + subseq_isconsant = np.full(l, 0, dtype=bool) + subseq_isconsant[rng.RNG.integers(0, l)] = True + Ts_subseq_isconstant = [ + subseq_isconsant, + None, + isconstant_custom_func, + ] - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( + Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant + ) + comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato( + Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant + ) + + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @@ -129,7 +121,7 @@ def test_input_not_overwritten(): # by replacing nan value with 0 in each time series. # This test ensures that the original input is not overwritten m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -147,7 +139,7 @@ def test_input_not_overwritten(): def test_extract_several_consensus(): # This test is to further ensure that the function `gpu_ostinato` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [64, 128]] + Ts = [rng.RNG.random(n) for n in [64, 128]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] diff --git a/tests/test_gpu_stimp.py b/tests/test_gpu_stimp.py index 0507adf9a..1b509f042 100644 --- a/tests/test_gpu_stimp.py +++ b/tests/test_gpu_stimp.py @@ -18,6 +18,8 @@ import naive import pytest +from stumpy import rng + TEST_THREADS_PER_BLOCK = 10 if not cuda.is_available(): # pragma: no cover @@ -26,7 +28,7 @@ T = [ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ] @@ -80,7 +82,7 @@ def test_gpu_stimp(T): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_stimp_with_isconstant(): - T = np.random.uniform(-1, 1, [64]) + T = rng.RNG.uniform(-1, 1, size=64) isconstant_func = functools.partial( naive.isconstant_func_stddev_threshold, stddev_threshold=0.5 ) diff --git a/tests/test_gpu_stump.py b/tests/test_gpu_stump.py index 78913bd24..15d368db4 100644 --- a/tests/test_gpu_stump.py +++ b/tests/test_gpu_stump.py @@ -6,7 +6,7 @@ import pandas as pd from numba import cuda -from stumpy import config +from stumpy import config, rng if cuda.is_available(): from stumpy.gpu_stump import gpu_stump @@ -34,8 +34,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -185,7 +185,7 @@ def test_gpu_stump_constant_subsequence_self_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_stump_one_constant_subsequence_A_B_join(): - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) m = 3 ref_mp = naive.stump(T_B, m, T_B=T_A, row_wise=True) @@ -241,8 +241,8 @@ def test_gpu_stump_two_constant_subsequences_A_B_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_stump_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -265,9 +265,9 @@ def test_gpu_stump_identical_subsequence_self_join(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) def test_gpu_stump_identical_subsequence_A_B_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_maamp.py b/tests/test_maamp.py index 6ee8d4731..7a24d6a26 100644 --- a/tests/test_maamp.py +++ b/tests/test_maamp.py @@ -4,7 +4,7 @@ import pandas as pd import pytest -from stumpy import config, core +from stumpy import config, core, rng from stumpy.maamp import ( _get_first_maamp_profile, _multi_mass_absolute, @@ -16,7 +16,7 @@ test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] substitution_locations = [(slice(0, 0), 0, -1, slice(1, 3), [0, 3])] @@ -24,22 +24,22 @@ def test_multi_mass_absolute_seeded(): - np.random.seed(5) - T = np.random.uniform(-1000, 1000, [3, 10]).astype(np.float64) - m = 5 + with rng.fix_state(): + T = rng.RNG.uniform(-1000, 1000, size=(3, 10)).astype(np.float64) + m = 5 - trivial_idx = 2 + trivial_idx = 2 - Q = T[:, trivial_idx : trivial_idx + m] + Q = T[:, trivial_idx : trivial_idx + m] - ref = naive.multi_mass_absolute(Q, T, m) + ref = naive.multi_mass_absolute(Q, T, m) - T, T_subseq_isfinite = core.preprocess_non_normalized(T, m) - comp = _multi_mass_absolute( - Q, T, m, T_subseq_isfinite[:, trivial_idx], T_subseq_isfinite - ) + T, T_subseq_isfinite = core.preprocess_non_normalized(T, m) + comp = _multi_mass_absolute( + Q, T, m, T_subseq_isfinite[:, trivial_idx], T_subseq_isfinite + ) - npt.assert_almost_equal(ref, comp, decimal=config.STUMPY_TEST_PRECISION) + npt.assert_almost_equal(ref, comp, decimal=config.STUMPY_TEST_PRECISION) @pytest.mark.parametrize("T, m", test_data) @@ -160,7 +160,7 @@ def test_maamp_mdl(T, m): def test_naive_maamp(): - T = np.random.uniform(-1000, 1000, [1, 1000]).astype(np.float64) + T = rng.RNG.uniform(-1000, 1000, size=(1, 1000)).astype(np.float64) m = 20 zone = int(np.ceil(m / 4)) @@ -272,7 +272,7 @@ def test_maamp_wrapper_include(T, m): def test_constant_subsequence_self_join(): T_A = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -284,11 +284,11 @@ def test_constant_subsequence_self_join(): def test_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) diff --git a/tests/test_maamped.py b/tests/test_maamped.py index 81afc7227..6ed6fe68b 100644 --- a/tests/test_maamped.py +++ b/tests/test_maamped.py @@ -6,7 +6,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import config +from stumpy import config, rng from stumpy.maamped import maamped @@ -27,7 +27,7 @@ def dask_cluster(): test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] substitution_locations = [slice(0, 0), 0, -1, slice(1, 3), [0, 3]] @@ -119,7 +119,7 @@ def test_maamped_constant_subsequence_self_join(dask_cluster): T_A = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -133,11 +133,11 @@ def test_maamped_constant_subsequence_self_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_maamped_identical_subsequence_self_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) diff --git a/tests/test_mmparray.py b/tests/test_mmparray.py index b5803b94d..76277ed80 100644 --- a/tests/test_mmparray.py +++ b/tests/test_mmparray.py @@ -3,12 +3,13 @@ import numpy.testing as npt import pytest +from stumpy import rng from stumpy.maamp import maamp from stumpy.mstump import mstump test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] diff --git a/tests/test_motifs.py b/tests/test_motifs.py index cfe56c170..45386a487 100644 --- a/tests/test_motifs.py +++ b/tests/test_motifs.py @@ -5,7 +5,7 @@ import numpy.testing as npt import pytest -from stumpy import core +from stumpy import core, rng from stumpy.motifs import match, motifs @@ -155,7 +155,7 @@ def naive_match( np.array([0.0, 1.0, 2.0]), np.array([0.1, 1.0, 2.0, 3.0, -1.0, 0.1, 1.0, 2.0, -0.5]), ), - (np.random.uniform(-1000, 1000, [8]), np.random.uniform(-1000, 1000, [64])), + (rng.RNG.uniform(-1000, 1000, size=8), rng.RNG.uniform(-1000, 1000, size=64)), ] @@ -184,61 +184,58 @@ def test_motifs_one_motif(): def test_motifs_two_motifs(): # Fix seed, because in some case motifs can be off by an index resulting in test # fails, which is caused since one of the motifs is not repeated perfectly in T. - np.random.seed(1234) - - # The time series is random noise with two motifs for m=10: - # * (almost) identical step functions at indices 10, 110 and 210 - # * identical linear slopes at indices 70 and 170 - T = np.random.normal(size=300) - m = 20 - - T[10:30] = 1 - T[12:28] = 2 - - T[110:130] = 3 - T[112:128] = 6 - T[120] = 6.6 - - T[210:230] = 1 - T[212:228] = 2 - T[220] = 1.9 - # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[110:130])) = 0.47 - # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[210:230])) = 0.24 - # naive.distance(naive.z_norm(T[110:130]), naive.z_norm(T[210:230])) = 0.72 - # Hence T[10:30] is the motif representative for this motif - - T[70:90] = np.arange(m) * 0.1 - T[170:190] = np.arange(m) * 0.1 - # naive.distance(naive.z_norm(T[70:90]), naive.z_norm(T[170:190])) = 0.0 - - max_motifs = 2 - - mp = naive.stump(T, m) - - # left_indices = [[70, 170, -1], [10, 210, 110]] - left_profile_values = [ - [0.0, 0.0, np.nan], - [ - 0.0, - naive.distance(core.z_norm(T[10:30]), core.z_norm(T[210:230])), - naive.distance(core.z_norm(T[10:30]), core.z_norm(T[110:130])), - ], - ] - - right_distance_values, right_indices = motifs( - T, - mp[:, 0], - max_motifs=max_motifs, - max_distance=0.5, - cutoff=np.inf, - ) + with rng.fix_state(): + + # The time series is random noise with two motifs for m=10: + # * (almost) identical step functions at indices 10, 110 and 210 + # * identical linear slopes at indices 70 and 170 + T = rng.RNG.normal(size=300) + m = 20 + + T[10:30] = 1 + T[12:28] = 2 + + T[110:130] = 3 + T[112:128] = 6 + T[120] = 6.6 + + T[210:230] = 1 + T[212:228] = 2 + T[220] = 1.9 + # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[110:130])) = 0.47 + # naive.distance(naive.z_norm(T[10:30]), naive.z_norm(T[210:230])) = 0.24 + # naive.distance(naive.z_norm(T[110:130]), naive.z_norm(T[210:230])) = 0.72 + # Hence T[10:30] is the motif representative for this motif + + T[70:90] = np.arange(m) * 0.1 + T[170:190] = np.arange(m) * 0.1 + # naive.distance(naive.z_norm(T[70:90]), naive.z_norm(T[170:190])) = 0.0 + + max_motifs = 2 + + mp = naive.stump(T, m) + + # left_indices = [[70, 170, -1], [10, 210, 110]] + left_profile_values = [ + [0.0, 0.0, np.nan], + [ + 0.0, + naive.distance(core.z_norm(T[10:30]), core.z_norm(T[210:230])), + naive.distance(core.z_norm(T[10:30]), core.z_norm(T[110:130])), + ], + ] - # We ignore indices because of sorting ambiguities for equal distances. - # As long as the distances are correct, the indices will be too. - npt.assert_almost_equal(left_profile_values, right_distance_values) + right_distance_values, right_indices = motifs( + T, + mp[:, 0], + max_motifs=max_motifs, + max_distance=0.5, + cutoff=np.inf, + ) - # Reset seed - np.random.seed(None) + # We ignore indices because of sorting ambiguities for equal distances. + # As long as the distances are correct, the indices will be too. + npt.assert_almost_equal(left_profile_values, right_distance_values) def test_motifs_max_matches(): @@ -530,8 +527,8 @@ def test_match_mean_stddev_isconstant(Q, T): def test_multi_match(): - T = np.random.uniform(-1000, 1000, size=(2, 64)) - Q = np.random.uniform(-1000, 1000, size=(2, 64)) + T = rng.RNG.uniform(-1000, 1000, size=(2, 64)) + Q = rng.RNG.uniform(-1000, 1000, size=(2, 64)) m = Q.shape[-1] excl_zone = int(np.ceil(m / 4)) @@ -555,8 +552,8 @@ def test_multi_match(): def test_multi_match_isconstant(): - T = np.random.rand(2, 64) - Q = np.random.rand(2, 8) + T = rng.RNG.random(size=(2, 64)) + Q = rng.RNG.random(size=(2, 8)) m = Q.shape[-1] excl_zone = int(np.ceil(m / 4)) @@ -595,7 +592,7 @@ def test_multi_match_isconstant(): def test_motifs(): - T = np.random.rand(64) + T = rng.RNG.random(64) m = 3 max_motifs = 3 @@ -628,7 +625,7 @@ def test_motifs_with_isconstant(): naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) - T = np.random.rand(64) + T = rng.RNG.random(64) m = 3 max_motifs = 3 @@ -660,7 +657,7 @@ def test_motifs_with_isconstant(): def test_motifs_with_max_matches_none(): - T = np.random.rand(16) + T = rng.RNG.random(16) m = 3 max_motifs = 1 diff --git a/tests/test_mparray.py b/tests/test_mparray.py index 1ac0cf34a..97e157980 100644 --- a/tests/test_mparray.py +++ b/tests/test_mparray.py @@ -4,7 +4,7 @@ import pandas as pd import pytest -from stumpy import config +from stumpy import config, rng from stumpy.aamp import aamp from stumpy.mparray import mparray from stumpy.stump import stump @@ -15,8 +15,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, [8]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, [64]).astype(np.float64), ), ] diff --git a/tests/test_mpdist.py b/tests/test_mpdist.py index 7e0984f10..99300c29e 100644 --- a/tests/test_mpdist.py +++ b/tests/test_mpdist.py @@ -7,6 +7,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster +from stumpy import rng from stumpy.mpdist import _mpdist_vect, mpdist, mpdisted @@ -31,8 +32,8 @@ def dask_cluster(): np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -111,10 +112,10 @@ def test_mpdist(T_A, T_B): @pytest.mark.parametrize("T_A, T_B", test_data) def test_mpdist_with_isconstant(T_A, T_B): m = 3 - T_A_subseq_isconstant = np.random.choice( + T_A_subseq_isconstant = rng.RNG.choice( [True, False], size=len(T_A) - m + 1, replace=True ) - T_B_subseq_isconstant = np.random.choice( + T_B_subseq_isconstant = rng.RNG.choice( [True, False], size=len(T_B) - m + 1, replace=True ) ref_mpdist = naive.mpdist( @@ -177,10 +178,10 @@ def test_mpdisted(T_A, T_B, dask_cluster): def test_mpdisted_with_isconstant(T_A, T_B, dask_cluster): with Client(dask_cluster) as dask_client: m = 3 - T_A_subseq_isconstant = np.random.choice( + T_A_subseq_isconstant = rng.RNG.choice( [True, False], size=len(T_A) - m + 1, replace=True ) - T_B_subseq_isconstant = np.random.choice( + T_B_subseq_isconstant = rng.RNG.choice( [True, False], size=len(T_B) - m + 1, replace=True ) ref_mpdist = naive.mpdist( diff --git a/tests/test_mstump.py b/tests/test_mstump.py index 3e97cf58a..01ebf747b 100644 --- a/tests/test_mstump.py +++ b/tests/test_mstump.py @@ -7,7 +7,7 @@ import polars as pl import pytest -from stumpy import config, core +from stumpy import config, core, rng from stumpy.mstump import ( _get_first_mstump_profile, _get_multi_QT, @@ -29,7 +29,7 @@ def naive_rolling_window_dot_product(Q, T): test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), ] substitution_locations = [(slice(0, 0), 0, -1, slice(1, 3), [0, 3])] @@ -37,35 +37,35 @@ def naive_rolling_window_dot_product(Q, T): def test_multi_mass_seeded(): - np.random.seed(5) - T = np.random.uniform(-1000, 1000, [3, 10]).astype(np.float64) - m = 5 + with rng.fix_state(): + T = rng.RNG.uniform(-1000, 1000, size=(3, 10)).astype(np.float64) + m = 5 - trivial_idx = 2 - - Q = T[:, trivial_idx : trivial_idx + m] + trivial_idx = 2 - ref = naive.multi_mass(Q, T, m) + Q = T[:, trivial_idx : trivial_idx + m] - T_subseq_isconstant = core.rolling_isconstant(T, m) - M_T, Σ_T = core.compute_mean_std(T, m) + ref = naive.multi_mass(Q, T, m) - Q_subseq_isconstant = np.expand_dims(T_subseq_isconstant[:, trivial_idx], 1) + T_subseq_isconstant = core.rolling_isconstant(T, m) + M_T, Σ_T = core.compute_mean_std(T, m) - comp = _multi_mass( - Q, - T, - m, - M_T, - Σ_T, - M_T[:, trivial_idx], - Σ_T[:, trivial_idx], - T_subseq_isconstant=T_subseq_isconstant, - Q_subseq_isconstant=Q_subseq_isconstant, - query_idx=trivial_idx, - ) + Q_subseq_isconstant = np.expand_dims(T_subseq_isconstant[:, trivial_idx], 1) + + comp = _multi_mass( + Q, + T, + m, + M_T, + Σ_T, + M_T[:, trivial_idx], + Σ_T[:, trivial_idx], + T_subseq_isconstant=T_subseq_isconstant, + Q_subseq_isconstant=Q_subseq_isconstant, + query_idx=trivial_idx, + ) - npt.assert_almost_equal(ref, comp, decimal=config.STUMPY_TEST_PRECISION) + npt.assert_almost_equal(ref, comp, decimal=config.STUMPY_TEST_PRECISION) @pytest.mark.parametrize("T, m", test_data) @@ -222,7 +222,7 @@ def test_mdl(T, m): def test_naive_mstump(): - T = np.random.uniform(-1000, 1000, [1, 1000]).astype(np.float64) + T = rng.RNG.uniform(-1000, 1000, size=(1, 1000)).astype(np.float64) m = 20 zone = int(np.ceil(m / 4)) @@ -339,7 +339,7 @@ def test_mstump_wrapper_include(T, m): def test_constant_subsequence_self_join(): T_A = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -351,11 +351,11 @@ def test_constant_subsequence_self_join(): def test_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -414,13 +414,13 @@ def test_multi_mass_with_isconstant(): m = 8 # case 1: Q is not multi-subseq of T - T = np.random.uniform(-1000, 1000, size=[d, n]) - T_subseq_isconstant = np.random.choice( + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) + T_subseq_isconstant = rng.RNG.choice( [True, False], size=(d, n - m + 1), replace=True ) - Q = np.random.uniform(-1000, 1000, size=[d, m]) - Q_subseq_isconstant = np.random.choice([True, False], size=(d, 1), replace=True) + Q = rng.RNG.uniform(-1000, 1000, size=(d, m)) + Q_subseq_isconstant = rng.RNG.choice([True, False], size=(d, 1), replace=True) ref = naive.multi_mass( Q, @@ -451,12 +451,12 @@ def test_multi_mass_with_isconstant(): npt.assert_almost_equal(ref, comp, decimal=config.STUMPY_TEST_PRECISION) # case 2: Q is a multi-subseq of T - T = np.random.uniform(-1000, 1000, size=[d, n]) - T_subseq_isconstant = np.random.choice( + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) + T_subseq_isconstant = rng.RNG.choice( [True, False], size=(d, n - m + 1), replace=True ) - query_idx = np.random.randint(0, n - m + 1) + query_idx = rng.RNG.integers(0, n - m + 1) Q = T[:, query_idx : query_idx + m] Q_subseq_isconstant = np.expand_dims(T_subseq_isconstant[:, query_idx], 1) @@ -496,8 +496,8 @@ def test_multi_distance_profile_with_isconstant_case1(): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) - T_subseq_isconstant = np.random.choice( + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) + T_subseq_isconstant = rng.RNG.choice( [True, False], size=(d, n - m + 1), replace=True ) @@ -519,12 +519,12 @@ def test_multi_distance_profile_with_isconstant_case2(): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) T_subseq_isconstant = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) - query_idx = np.random.randint(0, n - m + 1) + query_idx = rng.RNG.integers(0, n - m + 1) ref_D = naive.multi_distance_profile( query_idx, T, m, T_subseq_isconstant=T_subseq_isconstant @@ -543,16 +543,16 @@ def test_multi_distance_profile_with_isconstant_case3(): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) T_subseq_isconstant = [ None, - np.random.choice([True, False], n - m + 1, replace=True), + rng.RNG.choice([True, False], n - m + 1, replace=True), functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ), ] - query_idx = np.random.randint(0, n - m + 1) + query_idx = rng.RNG.integers(0, n - m + 1) ref_D = naive.multi_distance_profile( query_idx, T, m, T_subseq_isconstant=T_subseq_isconstant @@ -570,7 +570,7 @@ def test_mstump_with_isconstant_case1(): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) T_subseq_isconstant = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) @@ -592,10 +592,10 @@ def test_mstump_with_isconstant_case2(): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) T_subseq_isconstant = [ None, - np.random.choice([True, False], n - m + 1, replace=True), + rng.RNG.choice([True, False], n - m + 1, replace=True), functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ), diff --git a/tests/test_mstumped.py b/tests/test_mstumped.py index aaa669921..ba68b440a 100644 --- a/tests/test_mstumped.py +++ b/tests/test_mstumped.py @@ -8,7 +8,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import config +from stumpy import config, rng from stumpy.mstumped import mstumped @@ -29,7 +29,7 @@ def dask_cluster(): test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] substitution_locations = [slice(0, 0), 0, -1, slice(1, 3), [0, 3]] @@ -121,7 +121,7 @@ def test_mstumped_constant_subsequence_self_join(dask_cluster): T_A = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -135,11 +135,11 @@ def test_mstumped_constant_subsequence_self_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_mstumped_identical_subsequence_self_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical - T = np.array([T_A, T_A, np.random.rand(T_A.shape[0])]) + T = np.array([T_A, T_A, rng.RNG.random(T_A.shape[0])]) m = 3 excl_zone = int(np.ceil(m / 4)) @@ -234,10 +234,10 @@ def test_mstumped_with_isconstant(dask_cluster): n = 64 m = 8 - T = np.random.uniform(-1000, 1000, size=[d, n]) + T = rng.RNG.uniform(-1000, 1000, size=(d, n)) T_subseq_isconstant = [ None, - np.random.choice([True, False], n - m + 1, replace=True), + rng.RNG.choice([True, False], n - m + 1, replace=True), functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ), diff --git a/tests/test_non_normalized_decorator.py b/tests/test_non_normalized_decorator.py index fb8038ec1..80767fb89 100644 --- a/tests/test_non_normalized_decorator.py +++ b/tests/test_non_normalized_decorator.py @@ -5,7 +5,7 @@ from dask.distributed import Client, LocalCluster from numba import cuda -from stumpy import core +from stumpy import core, rng from stumpy.aamp import aamp from stumpy.aamp_mmotifs import aamp_mmotifs from stumpy.aamp_motifs import aamp_match, aamp_motifs @@ -80,19 +80,19 @@ def dask_cluster(): test_data = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] def test_mass(): - Q = np.random.rand(10) - T = np.random.rand(20) + Q = rng.RNG.random(10) + T = rng.RNG.random(20) ref = core.mass_absolute(Q, T) comp = core.mass(Q, T, normalize=False) npt.assert_almost_equal(ref, comp) - Q = np.random.rand(10) - T = np.random.rand(20) + Q = rng.RNG.random(10) + T = rng.RNG.random(20) T, T_subseq_isfinite = core.preprocess_non_normalized(T, 10) T_squared = np.sum(core.rolling_window(T * T, Q.shape[0]), axis=-1) ref = core.mass_absolute(Q, T) @@ -132,11 +132,9 @@ def test_scrump(T, m): T = T.copy() T = T[0] - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref = scraamp(T, m) - np.random.seed(seed) + rng.set_state(state) comp = scrump(T, m, normalize=False) npt.assert_almost_equal(ref.P_, comp.P_) @@ -151,11 +149,9 @@ def test_scrump_plus_plus(T, m): if T.ndim > 1: T = T.copy() T = T[0] - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref = scraamp(T, m, pre_scraamp=True) - np.random.seed(seed) + rng.set_state(state) comp = scrump(T, m, pre_scrump=True, normalize=False) npt.assert_almost_equal(ref.P_, comp.P_) @@ -171,11 +167,9 @@ def test_scrump_plus_plus_full(T, m): T = T.copy() T = T[0] - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref = scraamp(T, m, percentage=0.1, pre_scraamp=True) - np.random.seed(seed) + rng.set_state(state) comp = scrump(T, m, percentage=0.1, pre_scrump=True, normalize=False) npt.assert_almost_equal(ref.P_, comp.P_) @@ -222,7 +216,7 @@ def test_stumpi(T, m): ref_stream = aampi(T, m) comp_stream = stumpi(T, m, normalize=False) for i in range(10): - t = np.random.rand() + t = rng.RNG.random() ref_stream.update(t) comp_stream.update(t) npt.assert_almost_equal(ref_stream.P_, comp_stream.P_) @@ -230,7 +224,7 @@ def test_stumpi(T, m): def test_ostinato(): m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = aamp_ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = ostinato(Ts, m, normalize=False) @@ -243,7 +237,7 @@ def test_ostinato(): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_ostinatoed(dask_cluster): m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] with Client(dask_cluster) as dask_client: ref_radius, ref_Ts_idx, ref_subseq_idx = aamp_ostinatoed(dask_client, Ts, m) @@ -262,7 +256,7 @@ def test_gpu_ostinato(): pytest.skip("Skipping Tests No GPUs Available") m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = gpu_aamp_ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = gpu_ostinato(Ts, m, normalize=False) @@ -273,8 +267,8 @@ def test_gpu_ostinato(): def test_mpdist(): - T_A = np.random.uniform(-1000, 1000, [8]).astype(np.float64) - T_B = np.random.uniform(-1000, 1000, [64]).astype(np.float64) + T_A = rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64) + T_B = rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64) m = 5 ref = aampdist(T_A, T_B, m) @@ -284,8 +278,8 @@ def test_mpdist(): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_mpdisted(dask_cluster): - T_A = np.random.uniform(-1000, 1000, [8]).astype(np.float64) - T_B = np.random.uniform(-1000, 1000, [64]).astype(np.float64) + T_A = rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64) + T_B = rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64) m = 5 with Client(dask_cluster) as dask_client: @@ -299,8 +293,8 @@ def test_gpu_mpdist(): if not cuda.is_available(): # pragma: no cover pytest.skip("Skipping Tests No GPUs Available") - T_A = np.random.uniform(-1000, 1000, [8]).astype(np.float64) - T_B = np.random.uniform(-1000, 1000, [64]).astype(np.float64) + T_A = rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64) + T_B = rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64) m = 5 ref = gpu_aampdist(T_A, T_B, m) @@ -392,7 +386,7 @@ def test_mmotifs(T, m): @pytest.mark.filterwarnings("ignore:All-NaN slice encountered") def test_snippets(): - T = np.random.rand(64) + T = rng.RNG.random(64) m = 10 k = 2 @@ -421,14 +415,13 @@ def test_stimp(T, m): T = T.copy() T = T[0] n = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() ref = aamp_stimp(T, m) for i in range(n): ref.update() - np.random.seed(seed) + rng.set_state(state) cmp = stimp(T, m, normalize=False) for i in range(n): cmp.update() @@ -453,14 +446,13 @@ def test_stimped(T, m, dask_cluster): T = T.copy() T = T[0] n = 3 - seed = np.random.randint(100000) with Client(dask_cluster) as dask_client: - np.random.seed(seed) + state = rng.get_state() ref = aamp_stimped(dask_client, T, m) for i in range(n): ref.update() - np.random.seed(seed) + rng.set_state(state) cmp = stimped(dask_client, T, m, normalize=False) for i in range(n): cmp.update() @@ -488,14 +480,12 @@ def test_gpu_stimp(T, m): T = T.copy() T = T[0] n = 3 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref = gpu_aamp_stimp(T, m) for i in range(n): ref.update() - np.random.seed(seed) + rng.set_state(state) cmp = gpu_stimp(T, m, normalize=False) for i in range(n): cmp.update() diff --git a/tests/test_ostinato.py b/tests/test_ostinato.py index 75189dfdf..d4b719061 100644 --- a/tests/test_ostinato.py +++ b/tests/test_ostinato.py @@ -7,7 +7,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import core +from stumpy import core, rng from stumpy.ostinato import ostinato, ostinatoed @@ -26,13 +26,9 @@ def dask_cluster(): pass -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) -def test_random_ostinato(seed): +def test_random_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = ostinato(Ts, m) @@ -42,11 +38,22 @@ def test_random_ostinato(seed): npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) -@pytest.mark.parametrize("seed", [79, 109, 112, 133, 151, 161, 251, 275, 309, 355]) -def test_deterministic_ostinato(seed): +def test_deterministic_ostinato(): m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + state = rng.get_state() + + rng.set_state( + { + "bit_generator": "PCG64", + "state": { + "state": 50020120384657517908110798649414789211, + "inc": 1260484487869375200479822856118111137, + }, + "has_uint32": 0, + "uinteger": 0, + } + ) + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = ostinato(Ts, m) @@ -55,15 +62,13 @@ def test_deterministic_ostinato(seed): npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + rng.set_state(state) # Reset the RNG state to what it was before this test + -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) -def test_random_ostinatoed(seed, dask_cluster): +def test_random_ostinatoed(dask_cluster): with Client(dask_cluster) as dask_client: m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) comp_radius, comp_Ts_idx, comp_subseq_idx = ostinatoed(dask_client, Ts, m) @@ -73,32 +78,27 @@ def test_random_ostinatoed(seed, dask_cluster): npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) -@pytest.mark.parametrize("seed", [79, 109, 112, 133, 151, 161, 251, 275, 309, 355]) -def test_deterministic_ostinatoed(seed, dask_cluster): +def test_deterministic_ostinatoed(dask_cluster): with Client(dask_cluster) as dask_client: m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + with rng.fix_state(): + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) - comp_radius, comp_Ts_idx, comp_subseq_idx = ostinatoed(dask_client, Ts, m) + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato(Ts, m) + comp_radius, comp_Ts_idx, comp_subseq_idx = ostinatoed(dask_client, Ts, m) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) -@pytest.mark.parametrize( - "seed", np.random.choice(np.arange(10000), size=25, replace=False) -) -def test_random_ostinato_with_isconstant(seed): +def test_random_ostinato_with_isconstant(): isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] Ts_subseq_isconstant = [isconstant_custom_func for _ in range(len(Ts))] ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( @@ -113,36 +113,35 @@ def test_random_ostinato_with_isconstant(seed): npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) -@pytest.mark.parametrize("seed", [79, 109, 112, 133, 151, 161, 251, 275, 309, 355]) -def test_deterministic_ostinatoed_with_isconstant(seed, dask_cluster): +def test_deterministic_ostinatoed_with_isconstant(dask_cluster): isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 ) with Client(dask_cluster) as dask_client: m = 50 - np.random.seed(seed) - Ts = [np.random.rand(n) for n in [64, 128, 256]] - - l = 64 - m + 1 - subseq_isconsant = np.full(l, 0, dtype=bool) - subseq_isconsant[np.random.randint(0, l)] = True - Ts_subseq_isconstant = [ - subseq_isconsant, - None, - isconstant_custom_func, - ] - - ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( - Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant - ) - comp_radius, comp_Ts_idx, comp_subseq_idx = ostinatoed( - dask_client, Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant - ) + with rng.fix_state(): + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] + + l = 64 - m + 1 + subseq_isconsant = np.full(l, 0, dtype=bool) + subseq_isconsant[rng.RNG.integers(0, l)] = True + Ts_subseq_isconstant = [ + subseq_isconsant, + None, + isconstant_custom_func, + ] + + ref_radius, ref_Ts_idx, ref_subseq_idx = naive.ostinato( + Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant + ) + comp_radius, comp_Ts_idx, comp_subseq_idx = ostinatoed( + dask_client, Ts, m, Ts_subseq_isconstant=Ts_subseq_isconstant + ) - npt.assert_almost_equal(ref_radius, comp_radius) - npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) - npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) + npt.assert_almost_equal(ref_radius, comp_radius) + npt.assert_almost_equal(ref_Ts_idx, comp_Ts_idx) + npt.assert_almost_equal(ref_subseq_idx, comp_subseq_idx) def test_input_not_overwritten_ostinato(): @@ -150,7 +149,7 @@ def test_input_not_overwritten_ostinato(): # by replacing nan value with 0 in each time series. # This test ensures that the original input is not overwritten m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -166,7 +165,7 @@ def test_input_not_overwritten_ostinato(): def test_extract_several_consensus_ostinato(): # This test is to further ensure that the function `ostinato` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [256, 512, 1024]] + Ts = [rng.RNG.random(n) for n in [256, 512, 1024]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] @@ -200,7 +199,7 @@ def test_input_not_overwritten_ostinatoed(dask_cluster): # This test ensures that the original input is not overwritten with Client(dask_cluster) as dask_client: m = 50 - Ts = [np.random.rand(n) for n in [64, 128, 256]] + Ts = [rng.RNG.random(n) for n in [64, 128, 256]] for T in Ts: T[0] = np.nan @@ -218,7 +217,7 @@ def test_input_not_overwritten_ostinatoed(dask_cluster): def test_extract_several_consensus_ostinatoed(dask_cluster): # This test is to further ensure that the function `ostinatoed` # does not tamper with the original data. - Ts = [np.random.rand(n) for n in [256, 512, 1024]] + Ts = [rng.RNG.random(n) for n in [256, 512, 1024]] Ts_ref = [T.copy() for T in Ts] Ts_comp = [T.copy() for T in Ts] diff --git a/tests/test_precision.py b/tests/test_precision.py index 12654bd7c..708465605 100644 --- a/tests/test_precision.py +++ b/tests/test_precision.py @@ -8,7 +8,7 @@ import pytest from numba import cuda -from stumpy import cache, config, core, fastmath, sdp +from stumpy import cache, config, core, fastmath, rng, sdp if cuda.is_available(): from stumpy.gpu_stump import gpu_stump @@ -21,6 +21,81 @@ except ModuleNotFoundError: from numba.core.errors import NumbaPerformanceWarning + +test_data = [ + # seed = 332 + # np.random.seed(seed) + # T = np.random.uniform(-1000.0, 1000.0, [64]) + np.array( + [ + 836.349989350273290256, + 526.800862055943639461, + -429.339375142462358781, + 860.078846179842571473, + -596.812914971213785975, + 593.127160844603395162, + 633.075798396083314401, + -750.776773161861342487, + -665.810204117144508018, + -174.607860313390034435, + -710.208321817786327301, + 753.532886560284850930, + -838.186757410647146571, + 173.299013001693140268, + 703.222990535601979900, + -807.064168431504754153, + 962.883899197580944929, + 38.810424278810096155, + -83.862617990669846790, + 18.550959664470177302, + -662.512127934688805908, + -747.060775456810347350, + 760.462217296095332131, + -130.112948062053078502, + 683.272031839069086345, + -908.349670788853018166, + 557.546937977237575979, + 640.792333789786312082, + 391.562294309980586604, + -911.469920938469613247, + 743.180478392348163652, + -887.714941208484106028, + -286.934569476950514400, + -562.818879750450264510, + 306.910774071569505850, + -830.856058225298170328, + 208.087981330164382143, + -651.135621003526352979, + 235.249465940220005677, + 600.462506051327750356, + -843.324044229922378690, + -722.536288038352608964, + 876.710973289016123999, + -336.923085822701693814, + 521.587179728839601012, + 872.169364663994997500, + -56.626714461904150255, + 719.145878188693018274, + -851.663239330660871929, + 680.558711336155511162, + 61.668445663497273301, + 600.716760574291583907, + 93.433236590898076201, + 380.439820449711930905, + -341.580795812605344963, + 455.065177017377891389, + -92.403701334716984661, + -321.681699561015022937, + 731.415976214936563338, + -694.499688446164896050, + 21.217923163572738332, + 243.395272972420485758, + 889.609495142733749162, + -743.441543901967293095, + ] + ) +] + TEST_THREADS_PER_BLOCK = 10 @@ -29,9 +104,77 @@ def test_mpdist_snippets_s(): # a subsequence (of length `s`) and itelf becomes non-zero # in the performant version. Fixing this loss-of-precision can # result in this test being passed. - seed = 0 - np.random.seed(seed) - T = np.random.uniform(-1000, 1000, [64]).astype(np.float64) + # seed = 0 + # np.random.seed(seed) + # T = np.random.uniform(-1000, 1000, [64]).astype(np.float64) + T = np.array( + [ + 97.627007854649505703, + 430.378732744838941926, + 205.526752143287751551, + 89.766365993793726830, + -152.690401322190581368, + 291.788226133312207367, + -124.825577474614973994, + 783.546001564159496411, + 927.325521002058508202, + -233.116962348444587860, + 583.450076165329164724, + 57.789839505808956233, + 136.089122187864631996, + 851.193276585322109895, + -857.927883604226167336, + -825.741400596918538213, + -959.563205119348594963, + 665.239691095875969040, + 556.313501899701009279, + 740.024296493638303218, + 957.236684465528014698, + 598.317128433447237512, + -77.041275494136300495, + 561.058352572910962408, + -763.451148262133528988, + 279.842042655047634980, + -713.293425181907196020, + 889.337834099167821478, + 43.696643500143352412, + -170.676120018952815371, + -470.888775790746080929, + 548.467378868433343087, + -87.699335566902902883, + 136.867897737297028016, + -962.420399127289670105, + 235.270994151754109680, + 224.191445444842827328, + 233.867993749513829016, + 887.496157029248365689, + 363.640598206966842554, + -280.984198852427994098, + -125.936092401317097256, + 395.262391854529710145, + -879.549056741460390185, + 333.533430891335342494, + 341.275739236318827352, + -579.234877852318163605, + -742.147404690293342355, + -369.143298151632279769, + -272.578458114754766939, + 140.393540835759267793, + -122.796973075359304062, + 976.747676118452318406, + -795.910378503943888973, + -582.246487810330563661, + -677.380964230007521110, + 306.216650930796845387, + -493.416794920435791028, + -67.378454287387427257, + -511.148815996794496641, + -682.060832708960560922, + -779.249717671389703355, + 312.659178930546829633, + -723.634097302772374860, + ] + ) m = 10 k = 3 s = 3 @@ -61,7 +204,7 @@ def test_mpdist_snippets_s(): def test_distace_profile(): # This test function raises an error when the distance profile between # the query `Q = T[i: i+m]` and `T` becomes non-zero at index `i`. - T = np.random.rand(64) + T = rng.RNG.random(64) m = 3 T, M_T, Σ_T, T_subseq_isconstant = core.preprocess(T, m) @@ -75,12 +218,10 @@ def test_distace_profile(): npt.assert_almost_equal(D_ref, D_comp) -def test_calculate_squared_distance(): +@pytest.mark.parametrize("T", test_data) +def test_calculate_squared_distance(T): # This test function raises an error if the distance between a subsequence # and another does not satisfy the symmetry property. - seed = 332 - np.random.seed(seed) - T = np.random.uniform(-1000.0, 1000.0, [64]) m = 3 T_subseq_isconstant = core.rolling_isconstant(T, m) @@ -120,15 +261,13 @@ def test_calculate_squared_distance(): npt.assert_almost_equal(ref, comp, decimal=14) -def test_snippets(): +@pytest.mark.parametrize("T", test_data) +def test_snippets(T): # This test function raises an error if there is a considerable loss of precision # that violates the symmetry property of a distance measure. m = 10 k = 3 s = 3 - seed = 332 - np.random.seed(seed) - T = np.random.uniform(-1000.0, 1000.0, [64]) isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, quantile_threshold=0.05 @@ -195,15 +334,13 @@ def test_snippets(): @pytest.mark.filterwarnings("ignore", category=NumbaPerformanceWarning) @patch("stumpy.config.STUMPY_THREADS_PER_BLOCK", TEST_THREADS_PER_BLOCK) -def test_distance_symmetry_property_in_gpu(): +@pytest.mark.parametrize("T", test_data) +def test_distance_symmetry_property_in_gpu(T): if not cuda.is_available(): # pragma: no cover pytest.skip("Skipping Tests No GPUs Available") # This test function raises an error if the distance between a subsequence # and another one does not satisfy the symmetry property. - seed = 332 - np.random.seed(seed) - T = np.random.uniform(-1000.0, 1000.0, [64]) m = 3 i, j = 2, 10 diff --git a/tests/test_ray.py b/tests/test_ray.py index 58e752bea..836e1a479 100644 --- a/tests/test_ray.py +++ b/tests/test_ray.py @@ -9,6 +9,7 @@ RAY_IMPORTED = True except ImportError: # pragma: no cover RAY_IMPORTED = False +from stumpy import rng from stumpy.aamp_stimp import aamp_stimped from stumpy.aamped import aamped from stumpy.maamped import maamped @@ -36,19 +37,19 @@ def ray_cluster(): np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] test_mdata = [ (np.array([[584, -11, 23, 79, 1001, 0, -19]], dtype=np.float64), 3), - (np.random.uniform(-1000, 1000, [5, 20]).astype(np.float64), 5), + (rng.RNG.uniform(-1000, 1000, size=(5, 20)).astype(np.float64), 5), ] T = [ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ] diff --git a/tests/test_rng.py b/tests/test_rng.py new file mode 100644 index 000000000..c0bd44d1e --- /dev/null +++ b/tests/test_rng.py @@ -0,0 +1,29 @@ +import numpy.testing as npt + +from stumpy import rng + + +def test_fix_state(): + init_state = rng.get_state() + + with rng.fix_state(): + state = rng.get_state() + assert state == rng.FIXED_STATE + + state = rng.get_state() + assert state == init_state + + +def test_random(): + with rng.fix_state(): + assert rng.RNG.random() == 0.1442355276650238 + assert rng.RNG.integers(1_000_000) == 616778 + assert rng.RNG.uniform(0, 1_000_000) == 945097.9509917531 + npt.assert_almost_equal( + rng.RNG.permutation([10, 20, 30, 40, 50]), [20, 40, 10, 50, 30] + ) + npt.assert_almost_equal( + rng.RNG.choice([10, 20, 30, 40, 50], 10, replace=True), + [40, 10, 50, 20, 50, 10, 20, 10, 20, 50], + ) + assert rng.RNG.normal() == -0.1655864933503086 diff --git a/tests/test_scraamp.py b/tests/test_scraamp.py index faccf0fa6..c8b60797d 100644 --- a/tests/test_scraamp.py +++ b/tests/test_scraamp.py @@ -3,7 +3,7 @@ import numpy.testing as npt import pytest -from stumpy import config +from stumpy import config, rng from stumpy.aamp import aamp from stumpy.scraamp import prescraamp, scraamp @@ -13,8 +13,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -31,12 +31,10 @@ def test_prescraamp_self_join(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_B, m, T_B, s=s, exclusion_zone=zone, p=p) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_B, m, s=s, p=p) npt.assert_almost_equal(ref_P, comp_P) @@ -49,12 +47,10 @@ def test_prescraamp_A_B_join(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_A, m, T_B, s=s, p=p) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_A, m, T_B=T_B, s=s, p=p) npt.assert_almost_equal(ref_P, comp_P) @@ -66,12 +62,10 @@ def test_prescraamp_A_B_join_swap(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_B, m, T_A, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_B, m, T_B=T_A, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -84,12 +78,10 @@ def test_prescraamp_self_join_larger_window(T_A, T_B, m): if len(T_B) > m: zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_B, m, T_B, s=s, exclusion_zone=zone) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_B, m, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -111,14 +103,12 @@ def test_scraamp_self_join(T_A, T_B, percentages): for p in [1.0, 2.0, 3.0]: for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_B, m, T_B, percentage, zone, False, None, p=p ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, @@ -148,14 +138,12 @@ def test_scraamp_A_B_join(T_A, T_B, percentages): for p in [1.0, 2.0, 3.0]: for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_A, m, T_B, percentage, None, False, None, p=p ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_A, m, @@ -186,14 +174,12 @@ def test_scraamp_A_B_join_swap(T_A, T_B, percentages): m = 3 for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, _, ref_left_I, ref_right_I = naive.scraamp( T_B, m, T_A, percentage, None, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, T_A, ignore_trivial=False, percentage=percentage, pre_scraamp=False ) @@ -220,14 +206,12 @@ def test_scraamp_self_join_larger_window(T_A, T_B, m, percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_B, m, T_B, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, ignore_trivial=True, percentage=percentage, pre_scraamp=False ) @@ -388,9 +372,7 @@ def test_scraamp_plus_plus_self_join(T_A, T_B, percentages): for p in [1.0, 2.0, 3.0]: for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp( T_B, m, T_B, s=s, exclusion_zone=zone, p=p ) @@ -400,7 +382,7 @@ def test_scraamp_plus_plus_self_join(T_A, T_B, percentages): naive.merge_topk_PI(ref_P, ref_P_aux, ref_I, ref_I_aux) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, @@ -434,9 +416,7 @@ def test_scraamp_plus_plus_A_B_join(T_A, T_B, percentages): for p in [1.0, 2.0, 3.0]: for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_A, m, T_B, s=s, p=p) ref_P_aux, ref_I_aux, ref_left_I_aux, ref_right_I_aux = naive.scraamp( T_A, m, T_B, percentage, None, False, None, p=p, k=1 @@ -446,6 +426,7 @@ def test_scraamp_plus_plus_A_B_join(T_A, T_B, percentages): ref_left_I = ref_left_I_aux ref_right_I = ref_right_I_aux + rng.set_state(state) approx = scraamp( T_A, m, @@ -566,12 +547,10 @@ def test_scraamp_constant_subsequence_self_join(percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, _, _, _ = naive.scraamp(T, m, T, percentage, zone, False, None) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T, m, ignore_trivial=True, percentage=percentage, pre_scraamp=False ) @@ -592,20 +571,18 @@ def test_scraamp_constant_subsequence_self_join(percentages): @pytest.mark.parametrize("percentages", percentages) def test_scraamp_identical_subsequence_self_join(percentages): - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical m = 3 zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, _, _, _ = naive.scraamp(T, m, T, percentage, zone, False, None) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T, m, ignore_trivial=True, percentage=percentage, pre_scraamp=False ) @@ -642,14 +619,12 @@ def test_scraamp_nan_inf_self_join( zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_B_sub, m, T_B_sub, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp(T_B_sub, m, percentage=percentage, pre_scraamp=False) approx.update() comp_P = approx.P_ @@ -674,14 +649,12 @@ def test_scraamp_nan_zero_mean_self_join(percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T, m, T, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp(T, m, percentage=percentage, pre_scraamp=False) approx.update() comp_P = approx.P_ @@ -704,12 +677,10 @@ def test_prescraamp_A_B_join_larger_window(T_A, T_B): zone = int(np.ceil(m / 4)) if len(T_A) > m and len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_A, m, T_B, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_A, m, T_B, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -723,14 +694,12 @@ def test_prescraamp_self_join_KNN(T_A, T_B): for k in range(2, 4): for p in [1.0, 2.0, 3.0]: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp( T_B, m, T_B, s=s, exclusion_zone=zone, p=p, k=k ) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_B, m, s=s, p=p, k=k) npt.assert_almost_equal(ref_P, comp_P) @@ -744,12 +713,10 @@ def test_prescraamp_A_B_join_KNN(T_A, T_B): for k in range(2, 4): for p in [1.0, 2.0, 3.0]: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_A, m, T_B, s=s, p=p, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_A, m, T_B=T_B, s=s, p=p, k=k) npt.assert_almost_equal(ref_P, comp_P) @@ -765,14 +732,12 @@ def test_scraamp_self_join_KNN(T_A, T_B, percentages): for k in range(2, 4): for p in [1.0, 2.0, 3.0]: for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_B, m, T_B, percentage, zone, False, None, p=p, k=k ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, @@ -803,14 +768,12 @@ def test_scraamp_A_B_join_KNN(T_A, T_B, percentages): for k in range(2, 4): for p in [1.0, 2.0, 3.0]: for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scraamp( T_A, m, T_B, percentage, None, False, None, p=p, k=k ) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_A, m, @@ -845,9 +808,7 @@ def test_scraamp_plus_plus_self_join_KNN(T_A, T_B, percentages): for p in [1.0, 2.0, 3.0]: for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp( T_B, m, T_B, s=s, exclusion_zone=zone, p=p, k=k ) @@ -857,7 +818,7 @@ def test_scraamp_plus_plus_self_join_KNN(T_A, T_B, percentages): naive.merge_topk_PI(ref_P, ref_P_aux, ref_I, ref_I_aux) - np.random.seed(seed) + rng.set_state(state) approx = scraamp( T_B, m, @@ -892,12 +853,10 @@ def test_prescraamp_self_join_larger_window_m_5_k_5(T_A, T_B, m): if len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_B, m, T_B, s=s, exclusion_zone=zone, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_B, m, s=s, k=k) npt.assert_almost_equal(ref_P, comp_P) @@ -912,12 +871,10 @@ def test_prescraamp_A_B_join_larger_window_m_5_k_5(T_A, T_B): if len(T_A) > m and len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescraamp(T_A, m, T_B, s=s, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescraamp(T_A, m, T_B, s=s, k=k) npt.assert_almost_equal(ref_P, comp_P) diff --git a/tests/test_scrump.py b/tests/test_scrump.py index 7c1ea76a6..e072960fd 100644 --- a/tests/test_scrump.py +++ b/tests/test_scrump.py @@ -5,7 +5,7 @@ import numpy.testing as npt import pytest -from stumpy import config +from stumpy import config, rng from stumpy.scrump import prescrump, scrump from stumpy.stump import stump @@ -15,8 +15,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -31,12 +31,8 @@ def test_prescrump_self_join(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) ref_P, ref_I = naive.prescrump(T_B, m, T_B, s=s, exclusion_zone=zone) - np.random.seed(seed) comp_P, comp_I = prescrump(T_B, m, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -48,12 +44,10 @@ def test_prescrump_A_B_join(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_A, m, T_B, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_A, m, T_B=T_B, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -65,12 +59,10 @@ def test_prescrump_A_B_join_swap(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_B, m, T_A, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_B, m, T_B=T_A, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -83,12 +75,10 @@ def test_prescrump_self_join_larger_window(T_A, T_B, m): if len(T_B) > m: zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_B, m, T_B, s=s, exclusion_zone=zone) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_B, m, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -104,9 +94,7 @@ def test_prescrump_self_join_with_isconstant(T_A, T_B): m = 3 zone = int(np.ceil(m / 4)) for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump( T_B, m, @@ -117,7 +105,7 @@ def test_prescrump_self_join_with_isconstant(T_A, T_B): T_B_subseq_isconstant=isconstant_custom_func, ) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump( T_B, m, s=s, T_A_subseq_isconstant=isconstant_custom_func ) @@ -138,14 +126,12 @@ def test_scrump_self_join(T_A, T_B, percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_B, m, T_B, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, ignore_trivial=True, percentage=percentage, pre_scrump=False ) @@ -169,14 +155,12 @@ def test_scrump_A_B_join(T_A, T_B, percentages): m = 3 for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_A, m, T_B, percentage, None, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_A, m, T_B, ignore_trivial=False, percentage=percentage, pre_scrump=False ) @@ -201,14 +185,12 @@ def test_scrump_A_B_join_swap(T_A, T_B, percentages): m = 3 for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, _, ref_left_I, ref_right_I = naive.scrump( T_B, m, T_A, percentage, None, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, T_A, ignore_trivial=False, percentage=percentage, pre_scrump=False ) @@ -235,14 +217,12 @@ def test_scrump_self_join_larger_window(T_A, T_B, m, percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_B, m, T_B, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, ignore_trivial=True, percentage=percentage, pre_scrump=False ) @@ -272,9 +252,7 @@ def test_scrump_self_join_with_isconstant(T_A, T_B, percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_B, m, @@ -287,7 +265,7 @@ def test_scrump_self_join_with_isconstant(T_A, T_B, percentages): T_B_subseq_isconstant=isconstant_custom_func, ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, @@ -447,9 +425,7 @@ def test_scrump_plus_plus_self_join(T_A, T_B, percentages): for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_B, m, T_B, s=s, exclusion_zone=zone, k=1) ref_P_aux, ref_I_aux, _, _ = naive.scrump( T_B, m, T_B, percentage, zone, True, s, k=1 @@ -457,7 +433,7 @@ def test_scrump_plus_plus_self_join(T_A, T_B, percentages): naive.merge_topk_PI(ref_P, ref_P_aux, ref_I, ref_I_aux) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, ignore_trivial=True, percentage=percentage, pre_scrump=True, s=s ) @@ -482,9 +458,6 @@ def test_scrump_plus_plus_A_B_join(T_A, T_B, percentages): for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) ref_P, ref_I = naive.prescrump(T_A, m, T_B, s=s, k=1) ref_P_aux, ref_I_aux, ref_left_I_aux, ref_right_I_aux = naive.scrump( @@ -616,14 +589,12 @@ def test_scrump_constant_subsequence_self_join(percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T, m, T, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T, m, ignore_trivial=True, percentage=percentage, pre_scrump=False ) @@ -644,20 +615,18 @@ def test_scrump_constant_subsequence_self_join(percentages): @pytest.mark.parametrize("percentages", percentages) def test_scrump_identical_subsequence_self_join(percentages): - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical m = 3 zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, _, _, _ = naive.scrump(T, m, T, percentage, zone, False, None) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T, m, ignore_trivial=True, percentage=percentage, pre_scrump=False ) @@ -694,14 +663,12 @@ def test_scrump_nan_inf_self_join( zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_B_sub, m, T_B_sub, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump(T_B_sub, m, percentage=percentage, pre_scrump=False) approx.update() comp_P = approx.P_ @@ -726,14 +693,12 @@ def test_scrump_nan_zero_mean_self_join(percentages): zone = int(np.ceil(m / 4)) for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T, m, T, percentage, zone, False, None ) - np.random.seed(seed) + rng.set_state(state) approx = scrump(T, m, percentage=percentage, pre_scrump=False) approx.update() comp_P = approx.P_ @@ -756,12 +721,10 @@ def test_prescrump_A_B_join_larger_window(T_A, T_B): zone = int(np.ceil(m / 4)) if len(T_A) > m and len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_A, m, T_B, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_A, m, T_B, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -774,12 +737,10 @@ def test_prescrump_self_join_KNN(T_A, T_B): zone = int(np.ceil(m / 4)) for k in range(2, 4): for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_B, m, T_B, s=s, exclusion_zone=zone, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_B, m, s=s, k=k) npt.assert_almost_equal(ref_I, comp_I) @@ -792,12 +753,10 @@ def test_prescrump_A_B_join_KNN(T_A, T_B): zone = int(np.ceil(m / 4)) for k in range(2, 4): for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_A, m, T_B, s=s) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_A, m, T_B=T_B, s=s) npt.assert_almost_equal(ref_P, comp_P) @@ -812,14 +771,12 @@ def test_scrump_self_join_KNN(T_A, T_B, percentages): for k in range(2, 4): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_B, m, T_B, percentage, zone, False, None, k=k ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, @@ -848,14 +805,12 @@ def test_scrump_A_B_join_KNN(T_A, T_B, percentages): m = 3 for k in range(2, 4): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I, ref_left_I, ref_right_I = naive.scrump( T_A, m, T_B, percentage, None, False, None, k=k ) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_A, m, @@ -889,9 +844,7 @@ def test_scrump_plus_plus_self_join_KNN(T_A, T_B, percentages): for k in range(2, 4): for s in range(1, zone + 1): for percentage in percentages: - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump( T_B, m, T_B, s=s, exclusion_zone=zone, k=k ) @@ -900,7 +853,7 @@ def test_scrump_plus_plus_self_join_KNN(T_A, T_B, percentages): ) naive.merge_topk_PI(ref_P, ref_P_aux, ref_I, ref_I_aux) - np.random.seed(seed) + rng.set_state(state) approx = scrump( T_B, m, @@ -929,12 +882,10 @@ def test_prescrump_self_join_larger_window_m_5_k_5(T_A, T_B): if len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_B, m, T_B, s=s, exclusion_zone=zone, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_B, m, s=s, k=k) npt.assert_almost_equal(ref_P, comp_P) @@ -948,123 +899,16 @@ def test_prescrump_A_B_join_larger_window_m_5_k_5(T_A, T_B): zone = int(np.ceil(m / 4)) if len(T_A) > m and len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump(T_A, m, T_B, s=s, k=k) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump(T_A, m, T_B, s=s, k=k) npt.assert_almost_equal(ref_P, comp_P) npt.assert_almost_equal(ref_I, comp_I) -def test_prescrump_self_join_KNN_no_overlap(): - # This test is particularly designed to raise error in a rare case described - # as follows: Let's denote `I[i]` as the array with length `k` that contains - # the start indices of the best-so-far top-k nearest neighbors of `subseq i`, - # (`S_i`). Also, we denote `P[i]` as their corresponding distances sorted in - # ascending order. Let's denote `d` as the distance between `S_i` and `S_j`. P[i] - # and I[i] must be updated if (1) `j` is not in I[i] and (2) `d` < P[i,-1]. - # Regarding the former condition, one needs to check the whole array I[i]. Checking - # the array I[i, :idx], where `idx = np.searchsorted(P[i], 'd', side='right')` is - # not completely correct and that is due to imprecision in numerical calculation. - # It may happen that `j` is not in `I[i, :idx]`, but it is in fact at `I[i, idx]` - # (or any other position in array I[i]). And, its corresponding distance, i.e - # P[i, idx], is d + 1e-5, for instance. In theory, this should be exactly `d`. - # However, due to imprecision, we may calculated a slightly different value - # for such distance in one of previous iterations in function prescrump. This - # test results in error if someone tries to change the performant code of prescrump - # function and check `I[i, :idx]` rather than the full array `I[i]`. - T = np.array( - [ - -916.64703784, - -327.42056679, - 379.19386284, - -281.80427628, - -189.85401773, - -38.69610569, - 187.89889345, - 578.65862523, - 528.09687811, - -667.42973795, - -285.27749324, - -211.28930925, - -703.93802657, - -820.53780562, - -955.91174663, - 383.65471851, - 932.08809422, - -563.57569746, - 784.0546579, - -343.14886064, - -612.72329848, - -270.09273091, - -448.39346549, - 578.03202014, - 867.15436674, - -783.55167049, - -494.78062922, - -311.18567747, - 522.70052256, - 933.45474094, - 192.34822368, - -162.11374908, - -612.95359279, - -449.62297051, - -351.79138459, - -77.70189101, - -439.46519487, - -660.48431174, - 548.69362177, - 485.36004744, - -535.3566627, - -568.0955257, - 755.26647273, - 736.1079588, - -597.65672557, - 379.3299783, - 731.38211912, - 247.34827447, - 545.41888454, - 644.94300763, - 20.99042666, - 788.19859515, - -898.24325898, - -929.47841134, - -738.45875181, - 66.01030291, - 512.945841, - -44.07720164, - 302.97141464, - -696.95271302, - 662.98385163, - -712.3807531, - -43.62688539, - 74.16927482, - ] - ) - - # test_cases: dict() with `key: value` pair, where key is `(m, k)`, and value - # is a list of random `seeds` - test_cases = { - (3, 2): [4279, 9133, 8190], - (3, 5): [1267, 4016, 4046], - (5, 2): [6327, 4926, 3712], - (5, 5): [3032, 3032, 8117], - } - for (m, k), specified_seeds in test_cases.items(): - zone = int(np.ceil(m / 4)) - for seed in specified_seeds: - np.random.seed(seed) - ref_P, ref_I = naive.prescrump(T, m, T, s=1, exclusion_zone=zone, k=k) - comp_P, comp_I = prescrump(T, m, s=1, k=k) - - npt.assert_almost_equal(ref_P, comp_P) - npt.assert_almost_equal(ref_I, comp_I) - - @pytest.mark.parametrize("T_A, T_B", test_data) def test_prescrump_self_join_larger_window_m_5_k_5_with_isconstant(T_A, T_B): isconstant_custom_func = functools.partial( @@ -1077,9 +921,7 @@ def test_prescrump_self_join_larger_window_m_5_k_5_with_isconstant(T_A, T_B): if len(T_B) > m: for s in range(1, zone + 1): - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() ref_P, ref_I = naive.prescrump( T_B, m, @@ -1091,7 +933,7 @@ def test_prescrump_self_join_larger_window_m_5_k_5_with_isconstant(T_A, T_B): T_B_subseq_isconstant=isconstant_custom_func, ) - np.random.seed(seed) + rng.set_state(state) comp_P, comp_I = prescrump( T_B, m, s=s, k=k, T_A_subseq_isconstant=isconstant_custom_func ) diff --git a/tests/test_sdp.py b/tests/test_sdp.py index b8d98eeb9..5be393747 100644 --- a/tests/test_sdp.py +++ b/tests/test_sdp.py @@ -3,11 +3,10 @@ from operator import eq, lt import naive -import numpy as np import pytest from numpy import testing as npt -from stumpy import sdp +from stumpy import rng, sdp # README # Real FFT algorithm performs more efficiently when the length @@ -113,8 +112,8 @@ def test_sdp(n_T, remainder, comparator): n_Q_values = sorted(n_Q for n_Q in set(n_Q_values) if n_Q <= n_T) for n_Q in n_Q_values: - Q = np.random.rand(n_Q) - T = np.random.rand(n_T) + Q = rng.RNG.random(n_Q) + T = rng.RNG.random(n_T) ref = naive.rolling_window_dot_product(Q, T) for func_name in get_sdp_function_names(): func = getattr(sdp, func_name) @@ -139,8 +138,8 @@ def test_sdp_power2(): n_Q = 2**q for p in range(q, pmax + 1): n_T = 2**p - Q = np.random.rand(n_Q) - T = np.random.rand(n_T) + Q = rng.RNG.random(n_Q) + T = rng.RNG.random(n_T) ref = naive.rolling_window_dot_product(Q, T) comp = func(Q, T) diff --git a/tests/test_snippets.py b/tests/test_snippets.py index 1aa893885..68999bf65 100644 --- a/tests/test_snippets.py +++ b/tests/test_snippets.py @@ -5,10 +5,10 @@ import numpy.testing as npt import pytest -from stumpy import config +from stumpy import config, rng from stumpy.snippets import _get_all_profiles, snippets -test_data = [np.random.uniform(-1000, 1000, [64]).astype(np.float64)] +test_data = [rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64)] s = [3, 6, 7, 8] percentage = [0.4, 0.7, 0.8, 0.9] m = [8, 9, 10] diff --git a/tests/test_stamp.py b/tests/test_stamp.py index 3ec3e9b47..230eb4614 100644 --- a/tests/test_stamp.py +++ b/tests/test_stamp.py @@ -5,7 +5,7 @@ import numpy.testing as npt import pytest -from stumpy import core +from stumpy import core, rng from stumpy.stamp import _mass_PI, stamp test_data = [ @@ -14,8 +14,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -151,7 +151,7 @@ def test_stamp_nan_zero_mean_self_join(): def test_stamp_mass_PI_with_isconstant_case1(): # case1: The query `Q` is not constant - T_B = np.random.uniform(-1, 1, [64]) + T_B = rng.RNG.uniform(-1, 1, size=64) isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, stddev_threshold=0.5 ) @@ -162,7 +162,7 @@ def test_stamp_mass_PI_with_isconstant_case1(): T_B_subseq_isconstant = naive.rolling_isconstant(T_B, m, isconstant_custom_func) M_T, Σ_T = core.compute_mean_std(T_B, m) - trivial_idx = np.random.choice(np.flatnonzero(~T_B_subseq_isconstant)) + trivial_idx = rng.RNG.choice(np.flatnonzero(~T_B_subseq_isconstant)) Q = T_B[trivial_idx : trivial_idx + m] ref_P, ref_I, ref_left_I, ref_right_I = naive.mass_PI( @@ -220,7 +220,7 @@ def test_stamp_mass_PI_with_isconstant_case1(): def test_stamp_mass_PI_with_isconstant_case2(): # case2: The query `Q` is constant - T_B = np.random.uniform(-1, 1, [64]) + T_B = rng.RNG.uniform(-1, 1, size=64) isconstant_custom_func = functools.partial( naive.isconstant_func_stddev_threshold, stddev_threshold=0.5 ) @@ -231,7 +231,7 @@ def test_stamp_mass_PI_with_isconstant_case2(): T_B_subseq_isconstant = naive.rolling_isconstant(T_B, m, isconstant_custom_func) M_T, Σ_T = core.compute_mean_std(T_B, m) - trivial_idx = np.random.choice(np.flatnonzero(T_B_subseq_isconstant)) + trivial_idx = rng.RNG.choice(np.flatnonzero(T_B_subseq_isconstant)) Q = T_B[trivial_idx : trivial_idx + m] ref_P, ref_I, ref_left_I, ref_right_I = naive.mass_PI( diff --git a/tests/test_stimp.py b/tests/test_stimp.py index e160fb40b..2e329c97d 100644 --- a/tests/test_stimp.py +++ b/tests/test_stimp.py @@ -7,11 +7,12 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster +from stumpy import rng from stumpy.stimp import stimp, stimped T = [ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ] @@ -37,9 +38,7 @@ def test_stimp_1_percent(T): min_m = 3 n = T.shape[0] - min_m + 1 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() pan = stimp( T, min_m=min_m, @@ -55,7 +54,7 @@ def test_stimp_1_percent(T): ref_PAN = np.full((pan.M_.shape[0], T.shape[0]), fill_value=np.inf) - np.random.seed(seed) + rng.set_state(state) for idx, m in enumerate(pan.M_[:n]): zone = int(np.ceil(m / 4)) s = zone @@ -92,9 +91,7 @@ def test_stimp_max_m(T): max_m = 5 n = T.shape[0] - min_m + 1 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() pan = stimp( T, min_m=min_m, @@ -110,7 +107,7 @@ def test_stimp_max_m(T): ref_PAN = np.full((pan.M_.shape[0], T.shape[0]), fill_value=np.inf) - np.random.seed(seed) + rng.set_state(state) for idx, m in enumerate(pan.M_[:n]): zone = int(np.ceil(m / 4)) s = zone @@ -269,7 +266,7 @@ def test_stimped(T, dask_cluster): def test_stimp_1_percent_with_isconstant(): - T = np.random.uniform(-1, 1, [64]) + T = rng.RNG.uniform(-1, 1, size=64) isconstant_func = functools.partial( naive.isconstant_func_stddev_threshold, stddev_threshold=0.5 ) @@ -279,9 +276,7 @@ def test_stimp_1_percent_with_isconstant(): min_m = 3 n = T.shape[0] - min_m + 1 - seed = np.random.randint(100000) - - np.random.seed(seed) + state = rng.get_state() pan = stimp( T, min_m=min_m, @@ -298,7 +293,7 @@ def test_stimp_1_percent_with_isconstant(): ref_PAN = np.full((pan.M_.shape[0], T.shape[0]), fill_value=np.inf) - np.random.seed(seed) + rng.set_state(state) for idx, m in enumerate(pan.M_[:n]): zone = int(np.ceil(m / 4)) s = zone @@ -347,7 +342,7 @@ def test_stimp_1_percent_with_isconstant(): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stimped_with_isconstant(dask_cluster): - T = np.random.uniform(-1, 1, [64]) + T = rng.RNG.uniform(-1, 1, size=64) isconstant_func = functools.partial( naive.isconstant_func_stddev_threshold, stddev_threshold=0.5 ) diff --git a/tests/test_stomp.py b/tests/test_stomp.py index 3ae67ce46..2afbe860f 100644 --- a/tests/test_stomp.py +++ b/tests/test_stomp.py @@ -3,6 +3,7 @@ import numpy.testing as npt import pytest +from stumpy import rng from stumpy.stomp import _stomp test_data = [ @@ -11,8 +12,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] diff --git a/tests/test_stump.py b/tests/test_stump.py index e26f5def8..bc3c17e2e 100644 --- a/tests/test_stump.py +++ b/tests/test_stump.py @@ -7,7 +7,7 @@ import polars as pl import pytest -from stumpy import config +from stumpy import config, rng from stumpy.stump import stump test_data = [ @@ -16,8 +16,8 @@ np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -83,7 +83,7 @@ def test_stump_constant_subsequence_self_join(): def test_stump_one_constant_subsequence_A_B_join(): - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64))) m = 3 ref_mp = naive.stump(T_A, m, T_B=T_B, row_wise=True) @@ -133,8 +133,8 @@ def test_stump_two_constant_subsequences_A_B_join(): def test_stump_identical_subsequence_self_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -155,9 +155,9 @@ def test_stump_identical_subsequence_self_join(): def test_stump_identical_subsequence_A_B_join(): - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_stumped.py b/tests/test_stumped.py index 86e17f812..22d4fce1a 100644 --- a/tests/test_stumped.py +++ b/tests/test_stumped.py @@ -9,7 +9,7 @@ import tornado.ioloop from dask.distributed import Client, LocalCluster -from stumpy import config +from stumpy import config, rng from stumpy.stumped import stumped @@ -34,8 +34,8 @@ def dask_cluster(): np.array([584, -11, 23, 79, 1001, 0, -19], dtype=np.float64), ), ( - np.random.uniform(-1000, 1000, [8]).astype(np.float64), - np.random.uniform(-1000, 1000, [64]).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=8).astype(np.float64), + rng.RNG.uniform(-1000, 1000, size=64).astype(np.float64), ), ] @@ -202,7 +202,7 @@ def test_stumped_one_constant_subsequence_self_join_df(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_one_constant_subsequence_A_B_join(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -222,7 +222,7 @@ def test_stumped_one_constant_subsequence_A_B_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_one_constant_subsequence_A_B_join_df(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -244,7 +244,7 @@ def test_stumped_one_constant_subsequence_A_B_join_df(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_one_constant_subsequence_A_B_join_swap(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -264,7 +264,7 @@ def test_stumped_one_constant_subsequence_A_B_join_swap(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_one_constant_subsequence_A_B_join_df_swap(dask_cluster): with Client(dask_cluster) as dask_client: - T_A = np.random.rand(20) + T_A = rng.RNG.random(20) T_B = np.concatenate( (np.zeros(20, dtype=np.float64), np.ones(5, dtype=np.float64)) ) @@ -286,8 +286,8 @@ def test_stumped_one_constant_subsequence_A_B_join_df_swap(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_identical_subsequence_self_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_A[11 : 11 + identical.shape[0]] = identical m = 3 @@ -309,9 +309,9 @@ def test_stumped_identical_subsequence_self_join(dask_cluster): @pytest.mark.filterwarnings("ignore:\\s+Port 8787 is already in use:UserWarning") def test_stumped_identical_subsequence_A_B_join(dask_cluster): with Client(dask_cluster) as dask_client: - identical = np.random.rand(8) - T_A = np.random.rand(20) - T_B = np.random.rand(20) + identical = rng.RNG.random(8) + T_A = rng.RNG.random(20) + T_B = rng.RNG.random(20) T_A[1 : 1 + identical.shape[0]] = identical T_B[11 : 11 + identical.shape[0]] = identical m = 3 diff --git a/tests/test_stumpi.py b/tests/test_stumpi.py index 09559f934..f4bb6e02a 100644 --- a/tests/test_stumpi.py +++ b/tests/test_stumpi.py @@ -6,7 +6,7 @@ import pandas as pd import pytest -from stumpy import config, core +from stumpy import config, core, rng from stumpy.stumpi import stumpi substitution_locations = [(slice(0, 0), 0, -1, slice(1, 3), [0, 3])] @@ -22,13 +22,12 @@ def test_stumpi_self_join(): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - T = np.random.rand(30) + T = rng.RNG.random(30) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -56,12 +55,12 @@ def test_stumpi_self_join(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(30) + rng.set_state(state) + T = rng.RNG.random(30) T = pd.Series(T) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -81,10 +80,9 @@ def test_stumpi_self_join(): def test_stumpi_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) ref_mp = naive.stumpi_egress(T, m) ref_P = ref_mp.P_.copy() @@ -110,7 +108,7 @@ def test_stumpi_self_join_egress(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -134,8 +132,8 @@ def test_stumpi_self_join_egress(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(n) + rng.set_state(state) + T = rng.RNG.random(n) T = pd.Series(T) ref_mp = naive.stumpi_egress(T, m) @@ -162,8 +160,8 @@ def test_stumpi_self_join_egress(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() - t = np.random.rand() + t = rng.RNG.random() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -194,19 +192,18 @@ def test_stumpi_init_nan_inf_self_join(substitute, substitution_locations): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) - # seed = 58638 + state = rng.get_state() for substitution_location in substitution_locations: - np.random.seed(seed) - T = np.random.rand(30) + rng.set_state(state) + T = rng.RNG.random(30) if substitution_location == -1: substitution_location = T.shape[0] - 1 T[substitution_location] = substitute stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -222,8 +219,8 @@ def test_stumpi_init_nan_inf_self_join(substitute, substitution_locations): npt.assert_almost_equal(ref_P, comp_P) npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) - T = np.random.rand(30) + rng.set_state(state) + T = rng.RNG.random(30) if substitution_location == -1: # pragma: no cover substitution_location = T.shape[0] - 1 @@ -231,7 +228,7 @@ def test_stumpi_init_nan_inf_self_join(substitute, substitution_locations): T = pd.Series(T) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -248,13 +245,12 @@ def test_stumpi_init_nan_inf_self_join(substitute, substitution_locations): def test_stumpi_init_nan_inf_self_join_egress(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) - # seed = 58638 + state = rng.get_state() for substitution_location in substitution_locations: - np.random.seed(seed) + rng.set_state(state) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) if substitution_location == -1: substitution_location = T.shape[0] - 1 @@ -284,7 +280,7 @@ def test_stumpi_init_nan_inf_self_join_egress(substitute, substitution_locations npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -308,8 +304,8 @@ def test_stumpi_init_nan_inf_self_join_egress(substitute, substitution_locations npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(n) + rng.set_state(state) + T = rng.RNG.random(n) if substitution_location == -1: # pragma: no cover substitution_location = T.shape[0] - 1 @@ -340,7 +336,7 @@ def test_stumpi_init_nan_inf_self_join_egress(substitute, substitution_locations npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -371,11 +367,11 @@ def test_stumpi_stream_nan_inf_self_join(substitute, substitution_locations): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) + state = rng.get_state() for substitution_location in substitution_locations: - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) stream = stumpi(T[:30], m, egress=False) if substitution_location == -1: @@ -398,8 +394,8 @@ def test_stumpi_stream_nan_inf_self_join(substitute, substitution_locations): npt.assert_almost_equal(ref_P, comp_P) npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) stream = stumpi(pd.Series(T[:30]), m, egress=False) if substitution_location == -1: # pragma: no cover @@ -422,11 +418,11 @@ def test_stumpi_stream_nan_inf_self_join(substitute, substitution_locations): def test_stumpi_stream_nan_inf_self_join_egress(substitute, substitution_locations): m = 3 - seed = np.random.randint(100000) + state = rng.get_state() for substitution_location in substitution_locations: - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) n = 30 ref_mp = naive.stumpi_egress(T[:n], m) @@ -479,8 +475,8 @@ def test_stumpi_stream_nan_inf_self_join_egress(substitute, substitution_locatio npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(64) + rng.set_state(state) + T = rng.RNG.random(64) ref_mp = naive.stumpi_egress(T[:n], m) ref_P = ref_mp.P_.copy() @@ -537,13 +533,12 @@ def test_stumpi_constant_subsequence_self_join(): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -559,12 +554,12 @@ def test_stumpi_constant_subsequence_self_join(): npt.assert_almost_equal(ref_P, comp_P) # npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) + rng.set_state(state) T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) T = pd.Series(T) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -579,8 +574,7 @@ def test_stumpi_constant_subsequence_self_join(): def test_stumpi_constant_subsequence_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) @@ -608,7 +602,7 @@ def test_stumpi_constant_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -632,7 +626,7 @@ def test_stumpi_constant_subsequence_self_join_egress(): npt.assert_almost_equal(ref_left_P, comp_left_P) # npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) + rng.set_state(state) T = np.concatenate((np.zeros(20, dtype=np.float64), np.ones(10, dtype=np.float64))) T = pd.Series(T) @@ -660,7 +654,7 @@ def test_stumpi_constant_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -689,16 +683,15 @@ def test_stumpi_identical_subsequence_self_join(): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -714,15 +707,15 @@ def test_stumpi_identical_subsequence_self_join(): npt.assert_almost_equal(ref_P, comp_P, decimal=config.STUMPY_TEST_PRECISION) # npt.assert_almost_equal(ref_I, comp_I) - np.random.seed(seed) - identical = np.random.rand(8) - T = np.random.rand(20) + rng.set_state(state) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical T = pd.Series(T) stream = stumpi(T, m, egress=False) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -737,11 +730,10 @@ def test_stumpi_identical_subsequence_self_join(): def test_stumpi_identical_subsequence_self_join_egress(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - identical = np.random.rand(8) - T = np.random.rand(20) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical @@ -771,7 +763,7 @@ def test_stumpi_identical_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -797,9 +789,9 @@ def test_stumpi_identical_subsequence_self_join_egress(): ) # npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - identical = np.random.rand(8) - T = np.random.rand(20) + rng.set_state(state) + identical = rng.RNG.random(8) + T = rng.RNG.random(20) T[1 : 1 + identical.shape[0]] = identical T[11 : 11 + identical.shape[0]] = identical T = pd.Series(T) @@ -829,7 +821,7 @@ def test_stumpi_identical_subsequence_self_join_egress(): # npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -857,7 +849,7 @@ def test_stumpi_identical_subsequence_self_join_egress(): def test_stumpi_profile_index_match(): - T_full = np.random.rand(64) + T_full = rng.RNG.random(64) m = 3 T_full_subseq = core.rolling_window(T_full, m) warm_start = 8 @@ -899,13 +891,12 @@ def test_stumpi_self_join_KNN(): zone = int(np.ceil(m / 4)) for k in range(2, 4): - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() - T = np.random.rand(30) + T = rng.RNG.random(30) stream = stumpi(T, m, egress=False, k=k) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -933,12 +924,12 @@ def test_stumpi_self_join_KNN(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(30) + rng.set_state(state) + T = rng.RNG.random(30) T = pd.Series(T) stream = stumpi(T, m, egress=False, k=k) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -959,10 +950,9 @@ def test_stumpi_self_join_egress_KNN(): m = 3 for k in range(2, 4): - seed = np.random.randint(100000) - np.random.seed(seed) + state = rng.get_state() n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) ref_mp = naive.stumpi_egress(T, m, k=k) ref_P = ref_mp.P_.copy() @@ -988,7 +978,7 @@ def test_stumpi_self_join_egress_KNN(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -1012,8 +1002,8 @@ def test_stumpi_self_join_egress_KNN(): npt.assert_almost_equal(ref_left_P, comp_left_P) npt.assert_almost_equal(ref_left_I, comp_left_I) - np.random.seed(seed) - T = np.random.rand(n) + rng.set_state(state) + T = rng.RNG.random(n) T = pd.Series(T) ref_mp = naive.stumpi_egress(T, m, k=k) @@ -1040,8 +1030,8 @@ def test_stumpi_self_join_egress_KNN(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() - t = np.random.rand() + t = rng.RNG.random() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -1069,10 +1059,8 @@ def test_stumpi_self_join_egress_KNN(): def test_stumpi_self_join_egress_passing_mp(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) mp = naive.stump(T, m) ref_mp = naive.stumpi_egress(T, m, mp=mp) @@ -1099,7 +1087,7 @@ def test_stumpi_self_join_egress_passing_mp(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t) @@ -1128,10 +1116,7 @@ def test_stumpi_self_join_with_isconstant(): m = 3 zone = int(np.ceil(m / 4)) - seed = np.random.randint(100000) - np.random.seed(seed) - - T = np.random.rand(30) + T = rng.RNG.random(30) quantile_threshold = 0.5 sliding_stddev = naive.rolling_nanstd(T, m) @@ -1143,7 +1128,7 @@ def test_stumpi_self_join_with_isconstant(): stream = stumpi(T, m, egress=False, T_subseq_isconstant_func=isconstant_custom_func) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -1189,7 +1174,7 @@ def test_stumpi_self_join_with_isconstant(): # npt.assert_almost_equal(ref_left_I, comp_left_I) # with passing `mp` - T = np.random.rand(30) + T = rng.RNG.random(30) quantile_threshold = 0.5 sliding_stddev = naive.rolling_nanstd(T, m) @@ -1204,7 +1189,7 @@ def test_stumpi_self_join_with_isconstant(): T, m, egress=False, mp=mp, T_subseq_isconstant_func=isconstant_custom_func ) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() stream.update(t) comp_P = stream.P_ @@ -1247,10 +1232,8 @@ def test_stumpi_self_join_with_isconstant(): def test_stumpi_self_join_egress_with_isconstant(): m = 3 - seed = np.random.randint(100000) - np.random.seed(seed) n = 30 - T = np.random.rand(n) + T = rng.RNG.random(n) quantile_threshold = 0.5 sliding_stddev = naive.rolling_nanstd(T, m) @@ -1284,7 +1267,7 @@ def test_stumpi_self_join_egress_with_isconstant(): npt.assert_almost_equal(ref_left_I, comp_left_I) for i in range(34): - t = np.random.rand() + t = rng.RNG.random() ref_mp.update(t) stream.update(t)