Skip to content

Commit 3787ed2

Browse files
committed
Continue updating the docs
1 parent 7594a7c commit 3787ed2

File tree

9 files changed

+200
-30
lines changed

9 files changed

+200
-30
lines changed

prefsampling/approval/identity.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,20 @@ def identity(
2828
list[set[int]]
2929
Approval votes.
3030
31-
Raises
32-
------
33-
ValueError
34-
When `rel_num_approvals` is not in the [0, 1] interval.
31+
Examples
32+
--------
33+
34+
.. testcode::
35+
36+
from prefsampling.approval import identity
37+
38+
# Sample a unanimous profile with 2 voters and 3 candidates.
39+
# Voters approve 60% of the candidates (1 in this case).
40+
identity(2, 3, 0.6)
41+
42+
# The seed will not change anything here, but you can still set it.
43+
identity(2, 3, seed=1002)
44+
3545
"""
3646

3747
if rel_num_approvals < 0 or 1 < rel_num_approvals:

prefsampling/approval/impartial.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ def impartial(
1919
A collection of `num_voters` vote is generated independently and identically following the
2020
process described above.
2121
22+
See :py:func:`prefsampling.approval.impartial.impartial_constant_size` for a version in which
23+
all voters approve of the same number of candidates.
24+
2225
Parameters
2326
----------
2427
num_voters : int
@@ -35,10 +38,19 @@ def impartial(
3538
list[set]
3639
Approval votes.
3740
38-
Raises
39-
------
40-
ValueError
41-
When `p` not in [0,1] interval.
41+
Examples
42+
--------
43+
44+
.. testcode::
45+
46+
from prefsampling.approval import impartial
47+
48+
# Sample from an impartial culture with 2 voters and 3 candidates where
49+
# a candidate is approved with 60% probability.
50+
impartial(2, 3, 0.6)
51+
52+
# For reproducibility, you can set the seed.
53+
impartial(2, 3, 0.6, seed=1002)
4254
"""
4355

4456
if p < 0 or 1 < p:
@@ -67,6 +79,9 @@ def impartial_constant_size(
6779
A collection of `num_voters` vote is generated independently and identically following the
6880
process described above.
6981
82+
See :py:func:`prefsampling.approval.impartial.impartial` for a version in the probability of
83+
approving any candidate is constant and independent.
84+
7085
Parameters
7186
----------
7287
num_voters : int
@@ -83,10 +98,19 @@ def impartial_constant_size(
8398
list[set]
8499
Approval votes.
85100
86-
Raises
87-
------
88-
ValueError
89-
When `rel_num_approvals` is not in [0, 1] interval.
101+
Examples
102+
--------
103+
104+
.. testcode::
105+
106+
from prefsampling.approval import impartial_constant_size
107+
108+
# Sample from an impartial culture with 2 voters and 3 candidates where
109+
# all voters approve of 60% of the candidates (in this case 1).
110+
impartial_constant_size(2, 3, 0.6)
111+
112+
# For reproducibility, you can set the seed.
113+
impartial_constant_size(2, 3, 0.6, seed=1002)
90114
"""
91115

92116
if rel_num_approvals < 0 or 1 < rel_num_approvals:

prefsampling/approval/urn.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ def urn(
1111
num_voters: int, num_candidates: int, p: float, alpha: float, seed: int = None
1212
) -> list[set]:
1313
"""
14-
1514
Generates votes following the Pólya-Eggenberger urn culture. The process is as follows. The urn
1615
is initially empty and votes are generated one after the other, in turns. When generating a
1716
vote, the following happens. With a probability of 1/(urn_size + 1),an approval ballots in

prefsampling/core/composition.py

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,45 @@ def mixture(
4444
Note that this is only the seed for this function.
4545
If you want to use particular seed for the functions generating votes,
4646
you should pass it as parameter within the :code:`sampler_parameters` list.
47+
48+
Examples
49+
--------
50+
51+
.. testcode::
52+
53+
from prefsampling.core import mixture
54+
from prefsampling.ordinal import mallows
55+
56+
# A mixture of two Mallows' models with different phi and central votes.
57+
# The first model has weight 0.7 and the second 0.3.
58+
# There are 10 voters and 5 candidates.
59+
60+
mixture(
61+
10,
62+
5,
63+
[mallows, mallows],
64+
[0.7, 0.3],
65+
[
66+
{'phi': 0.2, 'central_vote': range(5)},
67+
{'phi': 0.9, 'central_vote': [4, 3, 2, 1, 0]}
68+
],
69+
)
70+
71+
# The weights are re-normalised if they don't add up to one.
72+
# The real weights here would be 3/4, 1/4.
73+
74+
from prefsampling.approval import noise, identity
75+
76+
mixture(
77+
10,
78+
5,
79+
[noise, identity],
80+
[0.3, 0.1],
81+
[
82+
{'p': 0.2, 'phi': 0.4},
83+
{'rel_num_approvals': 0.6}
84+
],
85+
)
4786
"""
4887
if len(samplers) != len(weights):
4988
raise ValueError(
@@ -103,10 +142,28 @@ def concatenation(
103142
List of dictionaries passed as keyword parameters of the samplers. Number of voters and
104143
number of candidates of these dictionaries are not taken into account.
105144
106-
Returns
107-
-------
108-
np.ndarray
109-
Ordinal votes.
145+
Examples
146+
--------
147+
148+
.. testcode::
149+
150+
from prefsampling.core import concatenation
151+
from prefsampling.ordinal import mallows
152+
153+
# A concatenation of two Mallows' models with different phi and central votes.
154+
# 4 votes are sampled from the first model and 6 votes from the second.
155+
# There are 5 candidates
156+
157+
mixture(
158+
[4, 6],
159+
5,
160+
[mallows, mallows],
161+
[0.7, 0.3],
162+
[
163+
{'phi': 0.2, 'central_vote': range(5)},
164+
{'phi': 0.9, 'central_vote': [4, 3, 2, 1, 0]}
165+
],
166+
)
110167
"""
111168

112169
if len(num_voters_per_sampler) != len(samplers):

prefsampling/core/filters.py

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,32 @@ def permute_voters(
2727
-------
2828
np.ndarray
2929
Ordinal votes.
30+
31+
Examples
32+
--------
33+
34+
.. testcode::
35+
36+
from prefsampling.ordinal import didi
37+
from prefsampling.core import permute_voters
38+
39+
# Get some votes
40+
ordinal_votes = didi(2, 3, (0.5, 0.2, 0.1))
41+
42+
# Randomly permute the voters
43+
permute_voters(ordinal_votes)
44+
45+
# The syntax is the same with approval votes
46+
47+
from prefsampling.approval import resampling
48+
49+
approval_votes = resampling(2, 3, 0.5, 0.2)
50+
permute_voters(approval_votes)
51+
52+
# You can set the seed for reproducibility
53+
54+
permute_voters(approval_votes, seed=234)
55+
3056
"""
3157
rng = np.random.default_rng(seed)
3258
rng.shuffle(votes)
@@ -59,6 +85,31 @@ def rename_candidates(
5985
-------
6086
list[set[int]] or np.ndarray
6187
Votes with renamed candidates.
88+
89+
Examples
90+
--------
91+
92+
.. testcode::
93+
94+
from prefsampling.ordinal import didi
95+
from prefsampling.core import rename_candidates
96+
97+
# Get some votes
98+
ordinal_votes = didi(2, 3, (0.5, 0.2, 0.1))
99+
100+
# Randomly permute the voters
101+
rename_candidates(ordinal_votes)
102+
103+
# With approval votes, you need to give the number of candidates
104+
105+
from prefsampling.approval import resampling
106+
107+
approval_votes = resampling(2, 3, 0.5, 0.2)
108+
rename_candidates(approval_votes, num_candidates=3)
109+
110+
# You can set the seed for reproducibility
111+
112+
permute_voters(approval_votes, num_candidates=3, seed=234)
62113
"""
63114
rng = np.random.default_rng(seed)
64115

@@ -85,8 +136,11 @@ def resample_as_central_vote(
85136
votes: np.ndarray | list[set[int]], sampler: Callable, sampler_parameters: dict
86137
) -> np.ndarray | list[set[int]]:
87138
"""
88-
Resamples the votes by using them as the central vote of a given sampler. Only samplers that
89-
accept a :code:`central_vote` argument can be used.
139+
Resamples the votes by using them as the central vote of a given sampler. The outcome is
140+
obtained as follows: for each input vote, we pass it to the sampler as central vote; a single
141+
vote is then resampled and added to the outcome.
142+
143+
Only samplers that accept a :code:`central_vote` argument can be used.
90144
91145
Votes are copied before being returned to avoid loss of data.
92146
@@ -104,6 +158,36 @@ def resample_as_central_vote(
104158
-------
105159
list[set[int]] or np.ndarray
106160
Votes resampled.
161+
162+
Examples
163+
--------
164+
165+
.. testcode::
166+
167+
from prefsampling.ordinal import urn, mallows
168+
from prefsampling.core import rename_candidates
169+
170+
# Get some votes
171+
ordinal_votes = urn(2, 3, 0.2)
172+
173+
# We resample them by passing them as central vote to a Mallows' model
174+
resample_as_central_vote(ordinal_votes, mallows, {'phi': 0.3})
175+
176+
# The syntax is the same with approval votes
177+
178+
from prefsampling.approval import urn, resampling
179+
180+
approval_votes = urn(2, 3, 0.5, 0.2)
181+
resample_as_central_vote(approval_votes, resampling, {'phi': 0.4, 'p': 0.8})
182+
183+
# To ensure reproducibility, you need to pass the seed everywhere
184+
seed = 4234
185+
approval_votes = urn(2, 3, 0.5, 0.2, seed=seed)
186+
resample_as_central_vote(
187+
approval_votes,
188+
resampling,
189+
{'phi': 0.4, 'p': 0.8, 'seed':seed}
190+
)
107191
"""
108192
res = deepcopy(votes)
109193
sampler_parameters["num_voters"] = 1

prefsampling/ordinal/identity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def identity(num_voters: int, num_candidates: int, seed: int = None) -> np.ndarr
3737
3838
from prefsampling.ordinal import identity
3939
40-
# Sample from a unanimous profile with 2 voters and 3 candidates
40+
# Sample a unanimous profile with 2 voters and 3 candidates
4141
identity(2, 3)
4242
4343
# The seed will not change anything here, but you can still set it.

prefsampling/tree/schroeder.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ def schroeder_tree_lescanne(
172172
) -> Node:
173173
"""
174174
Samples a random Schröder tree following the algorithm provided by `Lescanne (2022)
175-
<https://arxiv.org/abs/2205.11982>`_. The sampler is directcly taken from the `corresponding
175+
<https://arxiv.org/abs/2205.11982>`_. The sampler is directly taken from the `corresponding
176176
GitHub repository <https://github.com/PierreLescanne/Motzkin>`_ (no licence available).
177177
178178
If a specific number of internal nodes is given, trees are sampled at random until the required
@@ -308,7 +308,9 @@ def schroeder_tree_brute_force(
308308
"""
309309
all_trees = all_schroeder_tree(num_leaves, num_internal_nodes=num_internal_nodes)
310310
rng = np.random.default_rng(seed)
311-
return rng.choice(all_trees)
311+
res = rng.choice(all_trees)
312+
res.rename_frontier()
313+
return res
312314

313315

314316
def _partition_schroeder_nodes(num_nodes: int, num_leaves: int) -> list[list[int]]:

tests/test_samplers/ordinal/test_all_ordinal_samplers.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22

33
import numpy as np
44

5-
from prefsampling.core import (
6-
permute_voters,
7-
rename_candidates,
8-
resample_as_central_vote,
9-
mixture,
10-
)
115
from prefsampling.ordinal import mallows
126
from tests.test_samplers.ordinal.test_ordinal_didi import (
137
all_test_samplers_ordinal_didi,

tests/test_samplers/test_all_samplers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66

77
def all_random_samplers():
8-
samplers = all_test_samplers_approval()
9-
samplers += all_test_samplers_ordinal()
8+
samplers = all_test_samplers_ordinal()
9+
samplers += all_test_samplers_approval()
1010
return samplers
1111

1212

0 commit comments

Comments
 (0)