def func(): count = defaultdict(dict) for n_cands in n_cands_list: utilities = random_utilities(n_voters, n_cands) # Find the social utility winner and accumulate utilities UW = utility_winner(utilities) count['UW'][n_cands] = utilities.sum(axis=0)[UW] for name, method in rated_methods.items(): try: winner = method(utilities, tiebreaker='random') count[name][n_cands] = utilities.sum(axis=0)[winner] except ValueError: # Skip junk cases like vote-for-2 with 2 candidates count[name][n_cands] = np.nan rankings = honest_rankings(utilities) for name, method in ranked_methods.items(): winner = method(rankings, tiebreaker='random') count[name][n_cands] = utilities.sum(axis=0)[winner] return count
start_time = time.monotonic() for iteration in range(n): for n_cands in n_cands_list: utilities = random_utilities(n_voters, n_cands) # Find the social utility winner and accumulate utilities UW = utility_winner(utilities) count['UW'][n_cands] += utilities.sum(axis=0)[UW] for name, method in rated_methods.items(): winner = method(utilities, tiebreaker='random') count[name][n_cands] += utilities.sum(axis=0)[winner] rankings = honest_rankings(utilities) for name, method in ranked_methods.items(): winner = method(rankings, tiebreaker='random') count[name][n_cands] += utilities.sum(axis=0)[winner] elapsed_time = time.monotonic() - start_time print('Elapsed:', time.strftime("%H:%M:%S", time.gmtime(elapsed_time)), '\n') plt.figure(f'Effectiveness, {n_voters} voters, {n} iterations') plt.title('The Effectiveness of Several Voting Systems') for name, method in (('Standard', eff_standard), ('Vote-for-half', eff_vote_for_half), ('Borda', eff_borda)): plt.plot(n_cands_list, method(np.array(n_cands_list))*100, ':', lw=0.8) # Restart color cycle, so result colors match
def impartial_culture(n_voters, n_cands, random_state=None): """ Generate ranked ballots using the impartial culture / random society model. The impartial culture model selects complete preference rankings from the set of all possible preference rankings using a uniform distribution. This model is unrealistic, but is commonly used because it has some worst-case properties and is comparable between researchers.[2]_ Parameters ---------- n_voters : int Number of voters n_cands : int Number of candidates random_state : {None, int, np.random.Generator}, optional Initializes the random number generator. If `random_state` is int, a new Generator instance is used, seeded with its value. (If the same int is given twice, the function will return the same values.) If None (default), an existing Generator is used. If `random_state` is already a Generator instance, then that object is used. Returns ------- election : numpy.ndarray A collection of ranked ballots. Rows represent voters and columns represent rankings, from best to worst, with no tied rankings. Each cell contains the ID number of a candidate, starting at 0. For example, if a voter ranks Curie > Avogadro > Bohr, the ballot line would read ``[2, 0, 1]`` (with IDs in alphabetical order). Notes ----- This implementation first generates a set of independent, uniformly distributed random utilities, which are then converted into rankings.[1]_ It can (extremely rarely) generate tied utilities, which are always ranked in order from lowest to highest, so there is a very slight bias in favor of lower-numbered candidates? References ---------- .. [1] S. Merrill III, "A Comparison of Efficiency of Multicandidate Electoral Systems", American Journal of Political Science, vol. 28, no. 1, p. 26, 1984. :doi:`10.2307/2110786` .. [2] A. Lehtinen and J. Kuorikoski, "Unrealistic Assumptions in Rational Choice Theory", Philosophy of the Social Sciences vol. 37, no. 2, p 132. 2007. :doi:`10.1177/0048393107299684` Examples -------- Generate an election with 4 voters and 3 candidates: >>> impartial_culture(4, 3) array([[0, 1, 2], [2, 0, 1], [2, 1, 0], [1, 0, 2]], dtype=uint8) Here, Voter 1 prefers Candidate 2, then Candidate 0, then Candidate 1. """ # This method is much faster than generating integer sequences and then # shuffling them. utilities = random_utilities(n_voters, n_cands, random_state) rankings = honest_rankings(utilities) return rankings