Skip to content

Commit 9349864

Browse files
committed
Special handling of comb for python 3.7
1 parent 40f67bf commit 9349864

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

prefsampling/approval/noise.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import numpy as np
77

88
from prefsampling.inputvalidators import validate_num_voters_candidates
9+
from prefsampling.utils import comb
910

1011

1112
class NoiseType(Enum):
@@ -91,9 +92,9 @@ def noise(
9192

9293
# Prepare buckets
9394
for x in range(len(A) + 1):
94-
num_options_in = math.comb(len(A), x)
95+
num_options_in = comb(len(A), x)
9596
for y in range(len(B) + 1):
96-
num_options_out = math.comb(len(B), y)
97+
num_options_out = comb(len(B), y)
9798

9899
if noise_type == NoiseType.HAMMING:
99100
factor = phi ** (len(A) - x + y)

prefsampling/ordinal/groupseparable.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from prefsampling.tree.caterpillar import caterpillar_tree
1515
from prefsampling.tree.balanced import balanced_tree
1616
from prefsampling.inputvalidators import validate_num_voters_candidates
17+
from prefsampling.utils import comb
1718

1819

1920
class TreeSampler(Enum):
@@ -161,7 +162,7 @@ def _number_group_separable_profiles(m: int, r: int, n: int) -> float:
161162
of internal nodes `r` based on the formula from `Karpov (2019)
162163
<https://link.springer.com/article/10.1007/s10726-019-09621-w>`_
163164
"""
164-
return math.comb(m - 1, r) * math.comb(m - 1 + r, m) * (2 ** (n - 1) - 1) ** (r - 1)
165+
return comb(m - 1, r) * comb(m - 1 + r, m) * (2 ** (n - 1) - 1) ** (r - 1)
165166

166167

167168
def _sample_a_vote(node, reverse=False):

prefsampling/tree/schroeder.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from prefsampling.inputvalidators import validate_int
99
from prefsampling.tree.node import Node
10+
from prefsampling.utils import comb
1011

1112

1213
def validate_num_leaves_nodes(num_leaves: int, num_internal_nodes: int | None):
@@ -52,8 +53,8 @@ def _random_num_internal_nodes(num_leaves: int, rng: np.random.Generator) -> int
5253

5354
def _num_schroeder_tree(num_internal_nodes, num_leaves):
5455
return (
55-
math.comb(num_leaves - 1, num_internal_nodes)
56-
* math.comb(num_leaves - 1 + num_internal_nodes, num_leaves)
56+
comb(num_leaves - 1, num_internal_nodes)
57+
* comb(num_leaves - 1 + num_internal_nodes, num_leaves)
5758
/ (num_leaves - 1)
5859
)
5960

prefsampling/utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import math
2+
3+
4+
def comb(n: int, k: int):
5+
"""
6+
Function to compute the binomial coefficient. It uses math.comb if available (i.e., if Python >=
7+
3.8), otherwise computes it by hand.
8+
9+
Parameters
10+
----------
11+
n
12+
k
13+
14+
Returns
15+
-------
16+
17+
"""
18+
if hasattr(math, "comb"):
19+
return math.comb(n, k)
20+
return _comb(n, k)
21+
22+
23+
def _comb(n, k):
24+
try:
25+
return math.factorial(n) // math.factorial(k) // math.factorial(n - k)
26+
except ValueError:
27+
return 0

0 commit comments

Comments
 (0)