Generate Profiles

Sampling Profiles

We use the prefsampling package to sample profiles from standard probability functions. There is a single function, generate_profile, to interface with the prefsampling functions. The following are the available probability models for generating profiles:

  1. Impartial Culture Model: generate a profile by sampling from a uniform distribution over profiles with \(n\) candidates and \(m\) voters, where each voter is equally likely to have any of the \(n!\) linear orders on the candidates.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Impartial Culture model:

prof = generate_profile(3, 5) # the default is the IC model
prof = generate_profile(3, 5, probmodel="IC")
prof = generate_profile(3, 5, probmodel="impartial")
  1. Impartial Anonymous Culture: generate a profile by sampling from a uniform distribution over anonymous profiles.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Impartial Anonymous Culture model:

prof = generate_profile(3, 5, probmodel="IAC")
prof = generate_profile(3, 5, probmodel="impartial_anonymous")
  1. The Urn model: In the Polya-Eggenberger urn model, to generate a profile given a parameter \(\alpha\in [0,\infty)\), each voter in turn randomly draws a linear order from an urn. Initially the urn is the set of all linear orders on the \(n\) candidates. If a voter randomly chooses \(L\) from the urn, we return \(L\) to the urn plus \(\alpha n!\) copies of \(L\). IC is the special case where \(\alpha=0\). The Impartial Anonymous Culture (IAC) is the special case where \(\alpha=1/n!\).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Urn model:

# default is URN with alpha=0.0, which is equivalent to the IC model.
prof = generate_profile(3, 5, probmodel="urn")
prof = generate_profile(3, 5, probmodel="URN", alpha=5)
prof = generate_profile(3, 5, probmodel="urn", alpha=5)

# in addition, there is a pre-defined urn models

prof = generate_profile(3, 5, probmodel="URN-10") # URN with alpha=10
  1. Urn models where the \(\alpha\) parameter depends on the number of candidates: “URN-0.3” is the urn model with \(\alpha=n!*0.3\) where \(n\) is the number of candidates; and “URN-R” is the random URN model, where, following Boehmer et al. (“Putting a compass on the map of elections,” IJCAI-21), for each generated profile, we chose \(\alpha\) according to a Gamma distribution with shape parameter \(k=0.8\) and scale parameter \(\theta=1\).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Urn model:

prof = generate_profile(3, 5, probmodel="URN-0.3")
prof = generate_profile(3, 5, probmodel="URN-R")
  1. The Mallow’s model: generate a profile by fixing a reference linear ordering of the candidates (called the central_vote) and assign to each voter a ranking that is “close” to this reference ranking. Closeness to the reference ranking is defined using the Kendall-tau distance between rankings, depending on a dispersion parameter \(\phi\). Setting \(\phi= 0\) means that every voter is assigned the reference ranking, and setting \(\phi=1\) is equivalent to the IC model. Formally, to generate a profile given a reference ranking \(L_0\in\mathcal{L}(X)\) and \(\phi\in (0,1]\), the probability that a voter’s ballot is \(L\in\mathcal{L}(X)\) is \(Pr_{L_0,\phi}(L)=\phi^{\tau(L,L_0)}/C\) where \(\tau(L,L_0)= {{|X|}\choose{2}} - |L\cap L_0|\), the Kendell-tau distance of \(L\) to \(L_0\), and \(C\) is a normalization constant.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Mallow's model:

# default is phi = 1.0, which is equivalent to the IC model.
prof = generate_profile(3, 5, probmodel="MALLOWS")
prof = generate_profile(3, 5, probmodel="mallows")

prof = generate_profile(3, 5, probmodel="mallows", phi=0.5)

# in addition, you can fix the central ranking

prof = generate_profile(3, 5,
                        probmodel="mallows",
                        central_vote=[2, 1, 0],
                        phi=0.5)
  1. The Mallow’s model with a parameter that Boehmer et al. (2021) call rel-\(\phi\), which together with the number of candidates determines the \(\phi\) value.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Mallow's model:

# default is relphi is generated randomly from the interval (0,1).
prof = generate_profile(3, 5, probmodel="MALLOWS-RELPHI")

prof = generate_profile(3, 5, probmodel="MALLOWS-RELPHI", relphi=0.5)

# the following are pre-defined Mallow's models with relphi=0.375
prof = generate_profile(3, 5, probmodel="MALLOWS-RELPHI-0.375")

# the relphi parameter is chosen uniformly from the interval (0,1)
prof = generate_profile(3, 5, probmodel="MALLOWS-RELPHI-R")
  1. The Mallow’s model with the phi parameter normalized as discussed in Boehmer, Faliszewski and Kraiczy (2023).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Mallow's model:

prof = generate_profile(3, 5,
                        probmodel="mallows",
                        phi=0.5,
                        normalise_phi=True)
  1. SinglePeaked - a profile \(\mathbf{P}\) is single peaked if there exists a strict linear order \(<\) of \(X(\mathbf{P})\) such that for every \(i\in V(\mathbf{P})\) and \(x,y\in X(\mathbf{P})\), \(x<y < max(\mathbf{P}_i)\) implies \(y\mathbf{P}_ix\), and \(max(\mathbf{P}_i)< x<y\) implies \(x\mathbf{P}_iy\). The probability model called single peaked assigns zero probability to any profile that is not single peaked and equal probability to any two single-peaked profiles.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Single Peaked probability model:

prof = generate_profile(3, 5,
                        probmodel="SinglePeaked")
prof = generate_profile(3, 5,
                        probmodel="single_peaked_walsh")
prof = generate_profile(3, 5,
                        probmodel="single_peaked_conitzer")
  1. There are a number of variations of the Single Peaked model available.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Single Crossing and Single Peaked Circle probability models:

prof = generate_profile(3, 5,
                        probmodel="single_crossing")
prof = generate_profile(3, 5,
                        probmodel="single_peaked_circle")
  1. Euclidean - In the Euclidean model voters and candidates are assigned random positions in a Euclidean space. A voter then ranks the candidates according to their distance: their most preferred candidate is the closest one to them, etc.

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Euclidean probability model.  The default is 2 dimensions
# in a uniform space.

prof = generate_profile(3, 5,
                        probmodel="euclidean")

# you can specify the number of dimensions and the type of space.

prof = generate_profile(3, 5,
                        probmodel="euclidean",
                        dimensions=3,
                        space="uniform")

prof = generate_profile(3, 5,
                        probmodel="euclidean",
                        dimensions=3,
                        space="ball")

prof = generate_profile(3, 5,
                        probmodel="euclidean",
                        dimensions=3,
                        space="gaussian")

prof = generate_profile(3, 5,
                        probmodel="euclidean",
                        dimensions=3,
                        space="sphere")
  1. Plackett-Luce - In the Plackett-Luce model, each candidate is assigned a value representing the candidate’s “quality”. The voters rank the candidates according to their quality (the higher quality candidate has a higher chance of being ranked first, etc.).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Plackett Luce probability model.


prof = generate_profile(3, 5,
                        probmodel="plackett_luce",
                        alphas=[2, 1, 1])
  1. Direct Dirichlet - The Direct Dirichlet model is very similar to the Plackett-Luce model, but the quality of the candidates is drawn from a Dirichlet distribution. The key difference is that the higher the sum of the alphas, the more correlated the votes are (the more concentrated the Dirichlet distribution is).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Didi probability model.

prof = generate_profile(3, 5,
                        probmodel="didi",
                        alphas=[20, 10, 10])
  1. Stratification - In the Stratification model, the candidates are dividing into groups with the first group being ranked above the second group. The size of the top group is defined by the weight parameter (a number between 0 and 1).

from pref_voting.generate_profiles import generate_profile

# the following all generate a profile with 3 candidates and 5 voters
# using the Stratification probability model.

prof = generate_profile(3, 5,
                        probmodel="stratification",
                        weight=0.3)
  1. Groups of Voters - In the Groups of Voters model, the voters are divided into groups and each group ranks the candidates according to a different probability model. The weights parameter specifies how likely each voter will be in each group.

from pref_voting.generate_profiles import generate_profile_with_groups

# the following all generate a profile with 3 candidates and 5 voters
# and two groups of voters drawn from  Mallow's models with different
# reference rankings.

prof = generate_profile_with_groups(4, 3,
                                    [{"probmodel":"mallows",
                                      "central_vote":[0, 1, 2, 3],
                                      "phi":0.5},
                                     {"probmodel":"mallows",
                                      "central_vote":[3, 2, 1, 0],
                                      "phi":0.5}],
                                    weights=[1, 2])

Generate a Profile

pref_voting.generate_profiles.get_rankings(num_candidates, num_voters, **kwargs)[source]

Get the rankings for a given number of candidates and voters using the [prefsampling library](https://comsoc-community.github.io/prefsampling/index.html).

Parameters:
  • num_candidates (int) – The number of candidates.

  • num_voters (int) – The number of voters.

  • kwargs (dict) – Any parameters for the probability model.

Returns:

A list of rankings.

Return type:

list

pref_voting.generate_profiles.generate_profile(num_candidates, num_voters, anonymize=False, num_profiles=1, **kwargs)[source]

Generate profiles using the prefsampling library.

Parameters:
  • num_candidates (int) – The number of candidates.

  • num_voters (int) – The number of voters.

  • anonymize (bool) – If True, anonymize the profiles.

  • num_profiles (int) – The number of profiles to generate.

  • kwargs (dict) – Any parameters for the probability model.

Returns:

A list of profiles or a single profile if num_profiles is 1.

Return type:

list

Generate a Profile with groups

pref_voting.generate_profiles.generate_profile_with_groups(num_candidates, num_voters, probmodels, weights=None, seed=None, num_profiles=1, anonymize=False)[source]

Generate profiles with groups of voters generated from different probability models. The probability of selecting a probability model is proportional its weight in the list weight.

Parameters:
  • num_candidates (int) – The number of candidates.

  • num_voters (int) – The number of voters.

  • probmodels (list) – A list of dictionaries specifying a probability model.

  • weights (list) – A list of weights for each probability model.

  • seed (int) – The random seed.

  • num_profiles (int) – The number of profiles to generate.

  • anonymize (bool) – If True, anonymize the profiles.

Generate a Profile with truncated linear orders

pref_voting.generate_profiles.generate_truncated_profile(num_cands, num_voters, max_num_ranked=3, probmod='IC')[source]

Generate a ProfileWithTies with num_cands candidates and num_voters. The ballots will be truncated linear orders of the candidates. Returns a ProfileWithTies that uses extended strict preference (so all ranked candidates are strictly preferred to any candidate that is not ranked).

Parameters:
  • num_cands (int) – The number of candidates to include in the profile.

  • num_voters (int) – The number of voters to include in the profile.

  • max_num_ranked (int, default=3) – The maximum level to truncate the linear ranking.

  • probmod (str) – optional (default “IC”)

Returns:

ProfileWithTies

Example:
from pref_voting.generate_profiles import generate_truncated_profile

prof = generate_truncated_profile(6, 7)
prof.display()

prof = generate_truncated_profile(6, 7, max_num_ranked=6)
prof.display()
+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+---+---+---+---+---+---+---+
| 4 | 5 | 0 | 3 | 3 | 2 | 5 |
| 1 | 0 | 3 | 2 | 4 | 1 | 4 |
|   | 1 | 4 |   |   |   | 2 |
|   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+
+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+---+---+---+---+---+---+---+
| 5 | 1 | 1 | 2 | 4 | 2 | 5 |
| 3 | 2 | 2 | 0 | 1 | 3 | 1 |
| 4 | 0 | 0 | 5 | 3 | 5 | 4 |
| 2 | 5 | 3 | 1 | 2 | 4 | 0 |
| 0 | 4 | 5 |   | 0 | 1 | 2 |
| 1 | 3 |   |   | 5 |   |   |
+---+---+---+---+---+---+---+
Possible Values of probmod:

  • “IC” (Impartial Culture): each randomly generated linear order of all candidates is truncated at a level from 1 to max_num_ranked, where the probability of truncating at level t is the number of truncated linear orders of length t divided by the number of truncated linear orders of length from 1 to max_num_ranked. Then a voter is equally likely to get any of the truncated linear orders of length from 1 to max_num_ranked.

  • “RT” (Random Truncation): each randomly generated linear order of all candidates is truncated at a level that is randomly chosen from 1 to max_num_ranked.

Generate a Profile for a given ordinal margin graph

pref_voting.generate_profiles.minimal_profile_from_edge_order(cands, edge_order)[source]

Given a list of candidates and a list of edges (positive margin edges only) in order of descending strength, find a minimal profile whose qualitative margin graph has that edge order.

Parameters:
  • cands (list) – list of candidates

  • edge_order (list) – list of edges in order of descending strength

Returns:

a profile whose qualitative margin graph has the given edge order

Return type:

Profile

Enumerating profiles

Enumerate anonymous profiles

Enumerate anonymous profiles with ties