Skip to content

Commit

Permalink
mixture model
Browse files Browse the repository at this point in the history
  • Loading branch information
szufix committed Feb 6, 2024
1 parent d60fc61 commit e61ac00
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
6 changes: 6 additions & 0 deletions prefsampling/approval/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
from prefsampling.approval.euclidean import euclidean
from prefsampling.approval.partylist import urn_partylist
from prefsampling.approval.truncated_urn import truncated_urn
from prefsampling.approval.mixture import (
mixture,
concat,
)


__all__ = [
Expand All @@ -29,4 +33,6 @@
"euclidean",
"urn_partylist",
"truncated_urn",
"mixture",
"concat"
]
81 changes: 81 additions & 0 deletions prefsampling/approval/mixture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import numpy as np


def mixture(
num_voters: int,
num_candidates: int,
weights: list,
list_of_cultures: list,
list_of_params: list,
seed: int = None,
) -> list[set[int]]:
"""
Generates a mixture of approval votes from different cultures.
Parameters
----------
num_voters : int
Number of Voters.
num_candidates : int
Number of Candidates.
weights: list
Probability of being sampled from a given culture
list_of_cultures: list,
List of the cultures.
list_of_params: list,
List of params for each considered culture
(excluding the number of voters and the number of candidates).
seed : int
Seed for numpy random number generator.
Note that this is only the seed for this function.
If you want to use particular seed for the functions generating votes,
you should pass it as argument within the list of params.
Returns
-------
list[set[int]]
Approval votes.
"""
rng = np.random.default_rng(seed)

options = [i for i in range(len(weights))]
sum_weights = sum(weights)
norm_weights = [w / sum_weights for w in weights]
samples = list(rng.choice(options, size=num_voters, replace=True, p=norm_weights))
list_of_num_voters = [samples.count(i) for i in range(len(weights))]
return concat(list_of_num_voters, num_candidates, list_of_cultures, list_of_params)


def concat(
list_of_num_voters: list,
num_candidates: int,
list_of_cultures: list,
list_of_params: list
) -> list[set[int]]:
"""
Generates a concatenation of approval votes from different cultures.
Parameters
----------
list_of_num_voters : int
List of numbers of voters to be sampled from each culture.
num_candidates : int
Number of Candidates.
list_of_cultures: list,
List of the cultures.
list_of_params: list,
List of params for each considered culture
(excluding the number of voters and the number of candidates).
Returns
-------
list[set[int]]
Approval votes.
"""
all_votes = []
for num_voters, culture, params in zip(list_of_num_voters, list_of_cultures, list_of_params):
if num_voters > 0:
votes = culture(num_voters, num_candidates, **params)
for vote in votes:
all_votes.append(vote)
return all_votes
6 changes: 6 additions & 0 deletions prefsampling/ordinal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
from prefsampling.ordinal.identity import identity
from prefsampling.ordinal.didi import didi
from prefsampling.ordinal.identity import identity
from prefsampling.ordinal.mixture import (
mixture,
concat,
)

__all__ = [
"urn",
Expand All @@ -47,4 +51,6 @@
"TreeSampler",
"identity",
"didi",
"mixture",
"concat",
]
80 changes: 80 additions & 0 deletions prefsampling/ordinal/mixture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import numpy as np


def mixture(
num_voters: int,
num_candidates: int,
weights: list,
list_of_cultures: list,
list_of_params: list,
seed: int = None,
) -> np.ndarray:
"""
Generates a mixture of ordinal votes from different cultures.
Parameters
----------
num_voters : int
Number of Voters.
num_candidates : int
Number of Candidates.
weights: list
Probability of being sampled from a given culture
list_of_cultures: list,
List of the cultures.
list_of_params: list,
List of params for each considered culture
(excluding the number of voters and the number of candidates).
seed : int
Seed for numpy random number generator.
Note that this is only the seed for this function.
If you want to use particular seed for the functions generating votes,
you should pass it as argument within the list of params.
Returns
-------
np.ndarray
Ordinal votes.
"""
rng = np.random.default_rng(seed)

options = [i for i in range(len(weights))]
sum_weights = sum(weights)
norm_weights = [w / sum_weights for w in weights]
samples = list(rng.choice(options, size=num_voters, replace=True, p=norm_weights))
list_of_num_voters = [samples.count(i) for i in range(len(weights))]
return concat(list_of_num_voters, num_candidates, list_of_cultures, list_of_params)


def concat(
list_of_num_voters: list,
num_candidates: int,
list_of_cultures: list,
list_of_params: list
) -> np.ndarray:
"""
Generates a concatenation of ordinal votes from different cultures.
Parameters
----------
list_of_num_voters : int
List of numbers of voters to be sampled from each culture.
num_candidates : int
Number of Candidates.
list_of_cultures: list,
List of the cultures.
list_of_params: list,
List of params for each considered culture
(excluding the number of voters and the number of candidates).
Returns
-------
np.ndarray
Ordinal votes.
"""
all_votes = np.empty(shape=(0, num_candidates), dtype=int)
for num_voters, culture, params in zip(list_of_num_voters, list_of_cultures, list_of_params):
if num_voters > 0:
votes = culture(num_voters, num_candidates, **params)
all_votes = np.concatenate((all_votes, votes), axis=0)
return all_votes

0 comments on commit e61ac00

Please sign in to comment.