Skip to content
Merged
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: Ubuntu-latest
strategy:
matrix:
python-version: [3.9]
python-version: [3.12]
steps:
- uses: actions/checkout@v2

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down Expand Up @@ -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 }}
Expand Down Expand Up @@ -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 }}
Expand Down
16 changes: 8 additions & 8 deletions cryptorandom/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 8 additions & 6 deletions cryptorandom/tests/test_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,19 +313,21 @@ 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]
sizes = [2, 3]
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]
Expand Down
4 changes: 2 additions & 2 deletions requirements/default.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
numpy>=1.20
scipy>=1.6
numpy>=2.0
scipy>=1.12
2 changes: 1 addition & 1 deletion requirements/doc.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Sphinx~=4.0
Sphinx>=5.0
numpydoc>=1.1