Last active
December 27, 2020 18:57
-
-
Save endolith/fa1d19767e5c2e9d4bd15e391ba79f91 to your computer and use it in GitHub Desktop.
Revisions
-
endolith revised this gist
Jun 10, 2017 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,10 @@ See also: - 1D: - http://zesty.ca/voting/voteline/ - 2D: - http://bolson.org/voting/sim_one_seat/www/spacegraph.html - http://zesty.ca/voting/sim/ - http://rangevoting.org/IEVS/Pictures.html - ND: - https://github.com/electology/vse-sim -
endolith revised this gist
Jun 10, 2017 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,8 @@ See also: - 2D: - http://bolson.org/voting/sim_one_seat/www/spacegraph.html - http://zesty.ca/voting/sim/ - http://rangevoting.org/IEVS/Pictures.html - 1D: - http://zesty.ca/voting/voteline/ -
endolith created this gist
Dec 23, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,125 @@ # -*- coding: utf-8 -*- """ Created on Sat Dec 17 11:33:35 2016 """ from __future__ import division, print_function from numpy.random import multivariate_normal import matplotlib.pyplot as plt from scipy.spatial.distance import cdist import numpy as np # Polarization between the two main factions pol = np.random.randn(1)[0] voters = np.concatenate((multivariate_normal(mean=(-pol, -pol), cov=((1, 0), (0, 1)), size=500), multivariate_normal(mean=(+pol, +pol), cov=((1, 0), (0, 1)), size=500) )) # Candidates distributed similarly to voters candidates = multivariate_normal(mean=(0, 0), cov=np.cov(voters, rowvar=False), size=9 ) plt.figure() plt.scatter(voters[:, 0], voters[:, 1], color='b', marker='.', alpha=0.2, label='voters') plt.scatter(candidates[:, 0], candidates[:, 1], color='r', marker='o', alpha=0.7, label='candidates') centroid = np.mean(voters, axis=0) plt.plot(centroid[0], centroid[1], color='k', marker='+', markersize=10, ls='none', label='centroid') dists = cdist(voters, candidates) def plurality(dists): """ Honest plurality voting """ # Voters choose the nearest candidate ballots = np.argmin(dists, axis=1) # Winner is the candidate with the most votes winner = np.argmax(np.bincount(ballots)) return ballots, winner def approval_nearest(dists, n=3): """ Honest approval voting of the nearest `n` candidates """ # Voters choose the n nearest candidates ballots = np.argsort(dists, axis=1)[:, :n] # Winner is the candidate with the most votes winner = np.argmax(np.bincount(ballots.flat)) return ballots, winner def approval_half(dists): """ Honest approval voting of the nearest 50% of candidates """ n_cands = dists.shape[1] return approval_nearest(dists, n=int(0.5 * n_cands)) def score_normed(dists, levels=None): """ Honest score voting, normalized to min and max for worst and best, optionally quantized to number of `levels`. All candidates are scored, so total vs average is irrelevant. """ # Normalize from 0 to 1 for nearest to farthest normed = dists - np.amin(dists, axis=1)[:, np.newaxis] normed /= np.amax(normed, axis=1)[:, np.newaxis] # Farthest candidates get the lowest scores normed = 1 - normed # Optionally quantize to discrete scale if levels is not None: normed = np.around(normed * levels) # Total scores for each candidate scores = np.sum(normed, axis=0) # Winner is the candidate with the highest total/average score winner = np.argmax(scores) return ballots, winner def next_color(): ax = plt.gca() while True: color = next(ax._get_lines.prop_cycler)['color'] if color not in {'r', }: # , 'b'}: return color def next_size(): s = 6 while True: yield s s += 2 sizes = next_size() for func in plurality, approval_nearest, approval_half, score_normed: name = func.__name__.replace('_', ' ') ballots, winner = func(dists) winner_loc = candidates[winner] plt.plot(winner_loc[0], winner_loc[1], marker='o', markersize=sizes.next(), ls='none', markeredgewidth=1, markeredgecolor=next_color(), color='none', # don't increment color cycle for invisible face markerfacecolor='none', label=name) plt.legend(loc='lower right', numpoints=1, fontsize='small') plt.axis('square') plt.grid(True) plt.tight_layout() This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,8 @@ See also: - 2D: - http://bolson.org/voting/sim_one_seat/www/spacegraph.html - http://zesty.ca/voting/sim/ - http://rangevoting.org/IEVS/Pictures.html - 1D: - http://zesty.ca/voting/voteline/