diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 8c88b83..8b285bb 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -11,7 +11,7 @@ jobs: runs-on: Ubuntu-latest strategy: matrix: - python-version: [3.9] + python-version: [3.12] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fe5df45..b9d2c54 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: runs-on: Ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.11, 3.12] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -41,7 +41,7 @@ jobs: runs-on: macOS-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.11, 3.12] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -70,7 +70,7 @@ jobs: runs-on: windows-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.11, 3.12] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/cryptorandom/sample.py b/cryptorandom/sample.py index 13bab45..54b8bbc 100644 --- a/cryptorandom/sample.py +++ b/cryptorandom/sample.py @@ -179,20 +179,20 @@ def random_allocation(a, sizes, replace=False, fast=False, p=None, method="sampl raise ValueError('sample sizes greater than population size') samples = [0] * len(sizes) - # sort sizes from smallest to largest - sizes.sort() - # get random samples for all the groups except the largest one - for i in range(len(sizes) - 1): + # get random samples for all the groups except the largest one. Work from smallest to largest for numerical stability + size_increasing_inx = np.argsort(sizes) + biggest = size_increasing_inx[-1] + for i in size_increasing_inx[:-1]: sam = random_sample(list(indices), sizes[i], replace, fast, p, method, prng) samples[i] = a[sam] if not replace: - indices = set(indices) - set(sam) + indices = list(set(indices) - set(sam)) # get the sample for the largest group - if not replace and N == np.sum(sizes): + if (not replace) and N == np.sum(sizes) and fast: sam = list(indices) else: - sam = random_sample(list(indices), sizes[-1], replace, fast, p, method, prng) - samples[-1] = a[sam] + sam = random_sample(list(indices), sizes[biggest], replace, fast, p, method, prng) + samples[biggest] = a[sam] return samples diff --git a/cryptorandom/tests/test_sample.py b/cryptorandom/tests/test_sample.py index 7ccce34..e1e2d2a 100644 --- a/cryptorandom/tests/test_sample.py +++ b/cryptorandom/tests/test_sample.py @@ -313,10 +313,14 @@ def test_permute_by_index(): def test_random_allocation(): # test random allocation without replacement - samples = random_allocation(10, [5, 5], replace = False) - assert all(x in np.arange(10) for x in samples[0]) - assert all(x in np.arange(10) for x in samples[1]) - assert np.sum(samples) == np.sum(np.arange(10)) + samples = random_allocation(15, [6, 4, 5], replace = False) + assert len(samples[0]) == 6 + assert len(samples[1]) == 4 + assert len(samples[2]) == 5 + assert all(x in np.arange(15) for x in samples[0]) + assert all(x in np.arange(15) for x in samples[1]) + assert all(x in np.arange(15) for x in samples[2]) + assert set(samples[0]) | set(samples[1]) | set(samples[2]) == set(np.arange(15)) # test with replacement a = [1, 2, 2, 3, 3] @@ -324,8 +328,6 @@ def test_random_allocation(): samples = random_allocation(a, sizes, replace = True) assert all(x in a for x in samples[0]) assert all(x in a for x in samples[1]) - # test that smallest sample is sample first - assert len(samples[0]) == np.min(sizes) # test when sum of sample sizes is less than population size a = [1, 2, 2, 3, 3] diff --git a/requirements/default.txt b/requirements/default.txt index 3f11151..af95058 100644 --- a/requirements/default.txt +++ b/requirements/default.txt @@ -1,2 +1,2 @@ -numpy>=1.20 -scipy>=1.6 +numpy>=2.0 +scipy>=1.12 diff --git a/requirements/doc.txt b/requirements/doc.txt index 2c4d2ac..0e7511a 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -1,2 +1,2 @@ -Sphinx~=4.0 +Sphinx>=5.0 numpydoc>=1.1