Subversion Repositories Remote Hare Voting

Rev

Rev 53 | Rev 55 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 53 Rev 54
Line 29... Line 29...
29
fdOut = None
29
fdOut = None
30
fTrace = 1
30
fTrace = 1
31
randcalls = 0
31
randcalls = 0
32
 
32
 
33
class Universe:
33
class Universe:
34
    p = 1               # probability of this universe existing
34
    id = 0                              # id of last create Universe
-
 
35
 
-
 
36
    def __init__(self, p, nWinners, nBallots, quota):
-
 
37
        Universe.id += 1
-
 
38
        self.id = Universe.id
-
 
39
        self.p = p
-
 
40
        self.nBallots = nBallots
-
 
41
	self.nWinners = nWinners
-
 
42
        self.quota = quota
35
    winners = None
43
        self.winners = []
36
    losers = None
44
        self.losers = []
37
    tally = None
45
        self.tally = {}
38
 
46
 
39
    def getP(self):
47
    def getP(self):
40
        print "instance p =", self.p
48
        print "instance p =", self.p
41
        print "class p =", Universe.p
49
        print "class p =", Universe.p
42
 
50
 
43
print Universe.p
-
 
44
x = Universe()
-
 
45
print x.p
-
 
46
x.p = 5
-
 
47
print Universe.p
-
 
48
print x.p
-
 
49
x.getP()
-
 
50
 
-
 
51
def trace(s):
51
def trace(s):
52
    global fTrace, fdOut
52
    global fTrace, fdOut
53
    if fTrace: print >>fdOut, s
53
    if fTrace: print >>fdOut, s
54
    return
54
    return
55
 
55
 
Line 177... Line 177...
177
#       redistribute wasted votes to next priority candidate
177
#       redistribute wasted votes to next priority candidate
178
#
178
#
179
def dotally(nWinners, ballots):
179
def dotally(nWinners, ballots):
180
    global randcalls
180
    global randcalls
181
    randcalls = 0
181
    randcalls = 0
182
    nBallots = len(ballots)
-
 
183
    quota = int(math.ceil((nBallots + 1.0)/(nWinners + 1)))
-
 
184
 
182
 
-
 
183
    nBallots=len(ballots)
-
 
184
    quota=int(math.ceil((nBallots + 1.0)/(nWinners + 1)))
-
 
185
 
-
 
186
    universe = Universe(1.0, nWinners, nBallots, quota)
-
 
187
 
185
    trace("INPUT SUMMARY AND SINGLE RUN TRACE")
188
    trace("INPUT SUMMARY AND RUN TRACE")
186
    trace("\t%d ballots" % nBallots)
189
    trace("\t%d ballots" % universe.nBallots)
187
    trace("\tChoosing %s winners" % nWinners)
190
    trace("\tChoosing %s winners" % universe.nWinners)
188
    trace("\tNeed ceil((%d + 1)/(%d + 1)) = %d ballots to win" %
191
    trace("\tNeed ceil((%d + 1)/(%d + 1)) = %d ballots to win" %
189
          (nBallots, nWinners, quota))
192
          (universe.nBallots, universe.nWinners, universe.quota))
190
 
193
 
191
    # Create initial tally and statistics
194
    # Create initial tally and statistics
192
    #
195
    #
193
    tally = {}
-
 
194
    for ballot in ballots:
196
    for ballot in ballots:
195
        candidate = ballot[0]
197
        candidate = ballot[0]
196
        if not tally.has_key(candidate):
198
        if not universe.tally.has_key(candidate):
197
            tally[candidate] = []
199
            universe.tally[candidate] = []
198
        tally[candidate].append(ballot)
200
        universe.tally[candidate].append(ballot)
199
 
201
 
200
    total1st = {}
202
    total1st = {}
201
    total2nd = {}
203
    total2nd = {}
202
    totalMrk = {}
204
    totalMrk = {}
203
 
205
 
Line 217... Line 219...
217
    trace("\n\tBALLOT MARKS\t1ST\t2ND\tNONE")
219
    trace("\n\tBALLOT MARKS\t1ST\t2ND\tNONE")
218
    candidates = totalMrk.keys()
220
    candidates = totalMrk.keys()
219
    candidates.sort()
221
    candidates.sort()
220
    for c in candidates:
222
    for c in candidates:
221
        trace("\t%-16s%3d\t%3d\t%4d" % (c, total1st[c], total2nd[c], len(ballots)-totalMrk[c]))
223
        trace("\t%-16s%3d\t%3d\t%4d" % (c, total1st[c], total2nd[c], len(ballots)-totalMrk[c]))
222
    traceTally(quota, tally)
224
    traceTally(universe.quota, universe.tally)
223
    
225
 
224
    winners = []
226
    continueTally(universe)
225
    losers = []
227
    return universe.winners
226
 
228
 
-
 
229
def continueTally(universe):
227
    while len(winners) < nWinners:
230
    while len(universe.winners) < universe.nWinners:
228
        winner = findWinner(winners, losers, tally, quota, nWinners)
231
        winner = findWinner(universe.winners, universe.losers, universe.tally, universe.quota, universe.nWinners)
229
        if winner:
232
        if winner:
230
            winners.append(winner)
233
            universe.winners.append(winner)
231
            trace("\nSELECTION #%d: %s" % (len(winners), winner))
234
            trace("\nSELECTION #%d: %s" % (len(universe.winners), winner))
232
            redistributeWinner(winner, winners, losers, tally, quota)
235
            redistributeWinner(winner, universe.winners, universe.losers, universe.tally, universe.quota)
233
        else:
236
        else:
234
            loser = findLoser(losers, winners, tally)
237
            loser = findLoser(universe.losers, universe.winners, universe.tally)
235
            if loser:
238
            if loser:
236
                losers.append(loser)
239
                universe.losers.append(loser)
237
                trace("\nELIMINATED: %s" % loser)
240
                trace("\nELIMINATED: %s" % loser)
238
                redistributeLoser(loser, losers, winners, tally, quota)
241
                redistributeLoser(loser, universe.losers, universe.winners, universe.tally, universe.quota)
239
            else:
242
            else:
240
                trace("Not enough chosen candidates to fill all positions")
243
                trace("Not enough chosen candidates to fill all positions")
241
                break
244
                break
242
    trace("\nNumber of random choices made: %d" % randcalls)
245
    trace("\nNumber of random choices made: %d" % randcalls)
243
 
-
 
244
    return winners
-
 
245
 
-