Skip to content

Commit f81633c

Browse files
committed
Add "hash-random" method.
This method takes all the ballot data and runs it through a hash function, ordering candidates according to the hash value when setting the first double of the data to the candidate number. In essence, it's a reproducible version of random candidate, and as such extremely manipulable. It's useful for finding bounds on manipulability of certain sets or other methods over all possible ways to break ties.
1 parent f03c581 commit f81633c

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ add_library(qe_singlewinner_methods
136136
src/singlewinner/experimental/rmr1.cc
137137
src/singlewinner/fpc.cc
138138
src/singlewinner/gradual_c_b.cc
139+
src/singlewinner/hash.cc
139140
src/singlewinner/meta/chain_climbing.cc
140141
src/singlewinner/meta/benham.cc
141142
src/singlewinner/meta/comma.cc

src/lib/spookyhash/SpookyV2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
// slower than MD5.
2727
//
2828

29+
#pragma once
30+
2931
#include <stddef.h>
3032

3133
#ifdef _MSC_VER

src/singlewinner/all.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "fpc.h"
77
#include "gradual_c_b.h"
8+
#include "hash.h"
89
#include "no_elimination_irv.h"
910
#include "quick_runoff.h"
1011
#include "young.h"

src/singlewinner/hash.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "hash.h"
2+
3+
std::pair<ordering, bool> hash_random_cand::elect_inner(
4+
const election_t & papers,
5+
const std::vector<bool> & hopefuls, int num_candidates,
6+
cache_map * cache, bool winner_only) const {
7+
8+
// Dump the ballot data to a double vector that
9+
// we'll later read into the hash function.
10+
std::vector<double> ballot_byte_rep;
11+
// Reserve a spot for the candidate number.
12+
ballot_byte_rep.push_back(-1);
13+
14+
for (const ballot_group & bg: papers) {
15+
ballot_byte_rep.push_back(bg.get_weight());
16+
for (const candscore & cs: bg.contents) {
17+
ballot_byte_rep.push_back(cs.get_score());
18+
ballot_byte_rep.push_back(cs.get_candidate_num());
19+
}
20+
}
21+
22+
// Get the "score" of each candidate by setting the first
23+
// element to the candidate number. Highest score wins.
24+
25+
ordering out;
26+
27+
for (size_t candidate = 0; candidate < (size_t)num_candidates;
28+
++candidate) {
29+
30+
ballot_byte_rep[0] = candidate;
31+
32+
size_t score = hasher.Hash64(
33+
ballot_byte_rep.data(),
34+
sizeof(double) * ballot_byte_rep.size(),
35+
0);
36+
37+
out.insert(candscore(candidate, score));
38+
}
39+
40+
return (std::pair<ordering, bool>(out, false));
41+
}

src/singlewinner/hash.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This method performs a hashing operation on the input ballot set, and
2+
// orders the winners according to the output.
3+
// It thus fails just about every property (as well as neutrality and
4+
// symmetry) and is maximally manipulable. It's basically random
5+
// candidate without actual randomness.
6+
// The only point of the method is to prove lower bounds about
7+
// compositions, e.g. the maximal manipulability of something that
8+
// elects from the resistant set.
9+
10+
#pragma once
11+
12+
#include "method.h"
13+
#include "lib/spookyhash/SpookyV2.h"
14+
15+
class hash_random_cand : public election_method {
16+
17+
private:
18+
mutable SpookyHash hasher;
19+
20+
std::pair<ordering, bool> elect_inner(
21+
const election_t & papers,
22+
const std::vector<bool> & hopefuls,
23+
int num_candidates, cache_map * cache,
24+
bool winner_only) const;
25+
26+
public:
27+
std::string name() const {
28+
return "Hash-random candidate";
29+
}
30+
};

0 commit comments

Comments
 (0)