def test_all_adj(self): #Arrange election = voting.Election(self.e_rules, self.votes) comparison_rules = simulate.generate_all_adj_ruleset(self.e_rules) comparison_election = voting.Election(comparison_rules, self.votes) sim = simulate.Simulation(self.s_rules, [self.e_rules], self.votes) #Act base_results = election.run() comparison_results = comparison_election.run() sim.simulate() sim_result = sim.get_results_dict() #Assert list_measures = sim_result['data'][0]['list_measures'] self.assertEqual(list_measures["total_seats"]['avg'], util.add_totals(base_results)) self.assertEqual(base_results, [[0, 1], [0, 1], [0, 1]]) self.assertEqual(comparison_results, [[1, 0], [0, 1], [0, 1]]) deviation = simulate.dev(base_results, comparison_results) self.assertEqual(deviation, 2) measures = sim_result['data'][0]['measures'] self.assertEqual(measures['dev_all_adj']['avg'], deviation)
def handle_election(): data = request.get_json(force=True) rules = voting.ElectionRules() for k, v in data["rules"].items(): rules[k] = v for x in [ "constituency_names", "constituency_seats", "parties", "constituency_adjustment_seats" ]: if x in data and data[x]: rules[x] = data[x] else: return {"error": "Missing data ('%s')" % x} if not "votes" in data: return {"error": "Votes missing."} for const in data["votes"]: for party in const: if type(party) != int: return {"error": "Votes must be numbers."} try: election = voting.Election(rules, data["votes"]) election.run() except ZeroDivisionError: return {"error": "Need to have more votes."} except AssertionError: return {"error": "The data is malformed."} return election
def apportion(votes, **kwargs): """Do regular apportionment based on votes and constituency data.""" rules = voting.ElectionRules() kwargs["primary_divider"] = kwargs["divider"] kwargs["adj_determine_divider"] = kwargs[ "adj_determine_divider"] or kwargs["divider"] kwargs["adj_alloc_divider"] = kwargs["adj_alloc_divider"] or kwargs[ "adj_determine_divider"] kwargs["adjustment_threshold"] = kwargs["threshold"] * 0.01 try: for arg, val in kwargs.iteritems(): rules[arg] = val except AttributeError: for arg, val in kwargs.items(): rules[arg] = val parties, votes = util.load_votes(votes, rules["constituencies"]) rules["parties"] = parties election = voting.Election(rules, votes) election.run() if rules["show_details"]: util.print_steps_election(election) else: util.pretty_print_election(election) if rules["to_xlsx"]: util.election_to_xlsx(election, rules["to_xlsx"])
def apportion(votes, **kwargs): """Do regular apportionment based on votes and constituency data.""" rules = voting.Rules() kwargs["adjustment_divider"] = kwargs["adjustment_divider"] or kwargs[ "divider"] try: for arg, val in kwargs.iteritems(): rules[arg] = val except AttributeError: for arg, val in kwargs.items(): rules[arg] = val parties, votes = util.load_votes(votes, rules["constituencies"]) rules["parties"] = parties election = voting.Election(rules, votes) election.run() if rules['output'] == "simple": click.secho( "Warning: When loading votes, no attempt is currently " "made to guarantee that the vote file lists " "constituencies in the same order as they are declared in " "the constituency file.\n\n", fg="red") util.pretty_print_election(rules, election)
def collect_measures(self, votes): self.collect_votes(votes) for ruleset in range(self.num_rulesets): election = voting.Election(self.e_rules[ruleset], votes) results = election.run() self.collect_list_measures(ruleset, results, election) self.collect_general_measures(ruleset, votes, results, election)
def entropy(self, ruleset, votes, entropy): opt_rules = generate_opt_ruleset(self.e_rules[ruleset]) opt_election = voting.Election(opt_rules, votes) opt_results = opt_election.run() entropy_deviation_ratio = 1 - exp(entropy - opt_election.entropy()) self.aggregate_measure(ruleset, "entropy_ratio", entropy_deviation_ratio) self.aggregate_measure(ruleset, "entropy", entropy) return opt_results
def test_norwegian_icelandic_6c(self): self.rules_6c["adjustment_method"] = "norwegian-icelandic" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[1,3,2,0,0,0,0,0,0,0,0,1,0,1,0], [0,4,3,0,0,0,0,0,0,0,0,1,0,2,0], [2,4,3,0,0,0,0,0,0,0,0,1,0,0,0], [1,3,5,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def votes_to_change(election): """ Find how many additional votes each individual list must receive for the results of the given election to change. """ ref_results = election.results ref_votes = election.m_votes votes_to_change = [] votes = deepcopy(ref_votes) for c in range(len(ref_results)): votes_to_change.append([]) for p in range(len(ref_results[c])): if ref_votes[c][p] == 0: votes_to_change[c].append(None) continue a = 0 b = int(0.1 * votes[c][p]) d = 0 while d == 0: votes[c][p] = ref_votes[c][p] + b election = voting.Election(election.rules, votes) results = election.run() d = dev(results, ref_results) if d == 0: a = copy(b) b = int(sqrt(2) * b) m = b - a x = 0 while m > 1: x = int(m * sqrt(0.5) + a) votes[c][p] = ref_votes[c][p] + x election = voting.Election(election.rules, votes) results = election.run() d = dev(results, ref_results) if d == 0: a = copy(x) else: b = copy(x) m = b - a votes_to_change[c].append(b) votes[c][p] = ref_votes[c][p] return votes_to_change
def test_var_alt_scal_6c(self): self.rules_6c["adjustment_method"] = "var-alt-scal" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[0,3,3,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [0,4,4,0,0,0,0,0,0,0,0,1,0,1,0], [2,3,4,0,0,0,0,0,0,0,0,2,0,1,1], [2,2,3,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def test_switching_6c(self): self.rules_6c["adjustment_method"] = "switching" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[0,4,2,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [1,4,4,0,0,0,0,0,0,0,0,1,0,0,0], [2,2,5,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def test_nearest_neighbor_6c(self): self.rules_6c["adjustment_method"] = "nearest-neighbor" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[1,3,2,0,0,0,0,0,0,0,0,1,0,0,1], [1,3,2,0,0,0,0,0,0,0,0,1,0,3,0], [0,5,4,0,0,0,0,0,0,0,0,1,0,0,0], [1,4,5,0,0,0,0,0,0,0,0,2,0,1,0], [1,2,4,0,0,0,0,0,0,0,0,2,0,1,1], [2,1,2,0,0,0,0,0,0,0,0,2,0,3,1]])
def test_icelandic_law_6c(self): self.rules_6c["adjustment_method"] = "icelandic-law" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[0,4,2,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [0,4,4,0,0,0,0,0,0,0,0,1,0,1,0], [1,3,5,0,0,0,0,0,0,0,0,2,0,1,1], [2,2,3,0,0,0,0,0,0,0,0,2,0,1,1], [2,1,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def test_relative_superiority_6c(self): self.rules_6c["adjustment_method"] = "relative-superiority" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[0,3,3,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [0,4,4,0,0,0,0,0,0,0,0,1,0,1,0], [2,3,4,0,0,0,0,0,0,0,0,2,0,1,1], [2,2,3,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def test_alternating_scaling(self): self.rules["adjustment_method"] = "alternating-scaling" election = voting.Election(self.rules, self.votes) results = election.run() self.assertEqual(results, [[0,4,2,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [1,4,4,0,0,0,0,0,0,0,0,1,0,0,0], [1,3,5,0,0,0,0,0,0,0,0,2,0,1,1], [2,2,3,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def deviation(self, ruleset, option, votes, reference_results, results=None): if results == None: rules = generate_comparison_rules(self.e_rules[ruleset], option) results = voting.Election(rules, votes).run() deviation = dev(reference_results, results) self.aggregate_measure(ruleset, "dev_" + option, deviation)
def fn(self): rules = voting.ElectionRules() votes_file = "../data/elections/iceland_2013_landskjorstjorn.csv" const_file = "../data/constituencies/constituencies_iceland_2013.csv" rules["constituencies"] = const_file parties, votes = util.load_votes(votes_file, rules["constituencies"]) rules["parties"] = parties rules["adjustment_method"] = method election = voting.Election(rules, votes) election.run()
def test_alternating_scaling_lague(self): self.rules["primary_divider"] = "sainte-lague" self.rules["adj_determine_divider"] = "sainte-lague" self.rules["adj_alloc_divider"] = "sainte-lague" self.rules["adjustment_method"] = "alternating-scaling" election = voting.Election(self.rules, self.votes) results = election.run() self.assertEqual(results, [[1,3,2,0,0,0,0,0,0,0,0,1,0,1,0], [1,3,3,0,0,0,0,0,0,0,0,1,0,2,0], [0,4,3,0,0,0,0,0,0,0,0,1,0,1,1], [1,3,5,0,0,0,0,0,0,0,0,2,0,1,1], [2,2,3,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def test_norwegian_law_6c(self): self.rules_6c["adjustment_method"] = "norwegian-law" self.rules_6c["primary_divider"] = "nordic" self.rules_6c["adj_determine_divider"] = "dhondt" self.rules_6c["adj_alloc_divider"] = "sainte-lague" election = voting.Election(self.rules_6c, self.votes) results = election.run() self.assertEqual(results, [[1,3,2,0,0,0,0,0,0,0,0,1,0,1,0], [1,4,2,0,0,0,0,0,0,0,0,1,0,2,0], [1,4,3,0,0,0,0,0,0,0,0,1,0,1,0], [1,3,5,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,4,0,0,0,0,0,0,0,0,2,0,1,1], [1,2,3,0,0,0,0,0,0,0,0,2,0,2,1]])
def apportion(votes, **kwargs): """Do regular apportionment based on votes and constituency data.""" rules = voting.Rules() kwargs["adjustment_divider"] = kwargs["adjustment_divider"] or kwargs[ "divider"] for arg, val in kwargs.iteritems(): rules[arg] = val parties, votes = util.load_votes(votes, rules["constituencies"]) rules["parties"] = parties election = voting.Election(rules, votes) election.run() util.pretty_print_election(rules, election)
def run_initial_elections(self): self.base_allocations = [] for r in range(self.num_rulesets): election = voting.Election(self.e_rules[r], self.base_votes) xtd_total_seats = add_totals(election.run()) xtd_const_seats = add_totals(election.m_const_seats_alloc) xtd_adj_seats = matrix_subtraction(xtd_total_seats, xtd_const_seats) xtd_seat_shares = find_xtd_shares(xtd_total_seats) self.base_allocations.append({ "xtd_const_seats": xtd_const_seats, "xtd_adj_seats": xtd_adj_seats, "xtd_total_seats": xtd_total_seats, "xtd_seat_shares": xtd_seat_shares, "step_info": election.adj_seats_info, })
def run_script_simulation(rules): srs = SimulationRules() srs.update(rules["simulation_rules"]) rs = voting.ElectionRules() rs.update(rules["election_rules"]) if not "ref_votes" in rules: return {"error": "No reference votes supplied."} election = voting.Election(rs, rules["ref_votes"]) sim = Simulation(srs, election, rules["ref_votes"]) sim.simulate() return sim
def simulate(self): """Simulate many elections.""" gen = self.gen_votes() for i in range(self.num_total_simulations): round_start = datetime.now() if self.terminate: break self.iteration = i + 1 votes = next(gen) for ruleset in range(self.num_rulesets): election = voting.Election(self.e_rules[ruleset], votes) results = election.run() self.collect_list_measures(ruleset, results, election) self.collect_general_measures(ruleset, votes, results, election) round_end = datetime.now() self.iteration_time = round_end - round_start self.analysis() self.test_generated()
def calculate_bi_seat_shares(self, ruleset, votes, opt_results): election = voting.Election(self.e_rules[ruleset], self.base_votes) election.run() v_total_seats = election.v_total_seats bi_seat_shares = deepcopy(votes) seats_party_opt = [sum(x) for x in zip(*opt_results)] rein = 0 error = 1 while round(error, 5) != 0.0: error = 0 for c in range(self.num_constituencies): s = sum(bi_seat_shares[c]) if s != 0: mult = float(v_total_seats[c]) / s error += abs(1 - mult) for p in range(self.num_parties): bi_seat_shares[c][p] *= rein + mult * (1 - rein) for p in range(self.num_parties): s = sum([c[p] for c in bi_seat_shares]) if s != 0: mult = float(seats_party_opt[p]) / s error += abs(1 - mult) for c in range(self.num_constituencies): bi_seat_shares[c][p] *= rein + mult * (1 - rein) try: assert (all([ sum([c[p] for c in bi_seat_shares]) == seats_party_opt[p] for p in range(self.num_parties) ])) except AssertionError: pass try: assert (all([ sum(bi_seat_shares[c]) == v_total_seats[c] for c in range(self.num_constituencies) ])) except AssertionError: pass return bi_seat_shares
def fn(self): self.rules["primary_divider"] = rule self.rules["adjustment_divider"] = rule election = voting.Election(self.rules, self.votes) election.run()
def test_monge(self): self.rules["adjustment_method"] = "monge" election = voting.Election(self.rules, self.votes) results = election.run() self.assertEqual(0, 0)