def preCount(self): "QPQ pre-count" Iterative.preCount(self) QX.set_precision(self, self.prec) QX.set_guard(self, self.prec) self.R = 0 # current round self.numRounds = 0 # total number of rounds self.msg = [] # msg[r] contains text describing round r self.count = [] # count[r][c] is candidate c's quotient qc at round r for c in range(self.b.numCandidates): self.votes.append([])
def updateCount(self): "Update quotients." # Count contribution of all ballots (will eventually subtract active contributions) for i in range(self.b.numWeightedBallots): self.tx[self.R] += self.b.contrib[i] # Count number (vc) and contribution (tc) of active ballots (ranking hopeful candidates); # Calculate quotient for each hopeful candidate (qc=count) # Count total number of active ballots (va) # Adjust tx. for c in range(self.b.numCandidates): for i in self.votes[c]: self.vc[self.R][c] += QX.fix(self.b.getWeight(i)) self.tc[self.R][c] += self.b.contrib[i] self.count[self.R][c] = QX.div(self.vc[self.R][c], QX.One + self.tc[self.R][c]) self.va[self.R] += self.vc[self.R][c] self.tx[self.R] -= self.tc[self.R][c] # Calculate quota for current round self.thresh[self.R] = QX.div(self.va[self.R], QX.fix(1 + self.numSeats) - self.tx[self.R])
def updateWinners(self): "Find best winning candidate." desc = "" best = 0 winners = set() self.restart = False for c in self.continuing: if QX.gt(self.count[self.R][c], best): winners = set([c]) best = self.count[self.R][c] elif self.count[self.R][c] == best: winners.add(c) if (len(winners) != 0 and QX.gt(best, self.thresh[self.R])): # determine single winner (cWin, desc) = self.breakWeakTie(self.R, winners, "most", "winner") desc = self.newWinners([cWin]) self.roundInfo[self.R]["action"] = ("surplus", [cWin]) # distribute ballots to next choice for i in self.votes[cWin][:]: self.b.contrib[i] = self.b.getWeight(i) * QX.div( QX.One, self.count[self.R][cWin]) c = self.b.getTopChoiceFromWeightedBallot(i, self.continuing) if c is not None: self.votes[c].append(i) self.votes[cWin] = [] else: # if no winner, exclude one candidate (elimList, desc) = self.selectCandidatesToEliminate() self.roundInfo[self.R]["action"] = ("eliminate", elimList) cLose = elimList[0] # distribute ballots to next choice for i in self.votes[cLose][:]: c = self.b.getTopChoiceFromWeightedBallot(i, self.continuing) if c is not None: self.votes[c].append(i) self.votes[cLose] = [] self.restart = self.optRestart return desc
def updateWinners(self): "Find best winning candidate." desc = "" best = 0 winners = set() self.restart = False for c in self.continuing: if QX.gt(self.count[self.R][c], best): winners = set([c]) best = self.count[self.R][c] elif self.count[self.R][c] == best: winners.add(c) if (len(winners) != 0 and QX.gt(best, self.thresh[self.R])): # determine single winner (cWin, desc) = self.breakWeakTie(self.R, winners, "most", "winner") desc = self.newWinners([cWin]) self.roundInfo[self.R]["action"] = ("surplus", [cWin]) # distribute ballots to next choice for i in self.votes[cWin][:]: self.b.contrib[i] = self.b.getWeight(i) * QX.div(QX.One, self.count[self.R][cWin]) c = self.b.getTopChoiceFromWeightedBallot(i, self.continuing) if c is not None: self.votes[c].append(i) self.votes[cWin] = [] else: # if no winner, exclude one candidate (elimList, desc) = self.selectCandidatesToEliminate() self.roundInfo[self.R]["action"] = ("eliminate", elimList) cLose = elimList[0] # distribute ballots to next choice for i in self.votes[cLose][:]: c = self.b.getTopChoiceFromWeightedBallot(i, self.continuing) if c is not None: self.votes[c].append(i) self.votes[cLose] = [] self.restart = self.optRestart return desc
def updateCount(self): "Update quotients." # Count contribution of all ballots (will eventually subtract active contributions) for i in xrange(self.b.numWeightedBallots): self.tx[self.R] += self.b.contrib[i] # Count number (vc) and contribution (tc) of active ballots (ranking hopeful candidates); # Calculate quotient for each hopeful candidate (qc=count) # Count total number of active ballots (va) # Adjust tx. for c in range(self.b.numCandidates): for i in self.votes[c]: self.vc[self.R][c] += QX.fix(self.b.getWeight(i)) self.tc[self.R][c] += self.b.contrib[i] self.count[self.R][c] = QX.div(self.vc[self.R][c], QX.One + self.tc[self.R][c]) self.va[self.R] += self.vc[self.R][c] self.tx[self.R] -= self.tc[self.R][c] # Calculate quota for current round self.thresh[self.R] = QX.div( self.va[self.R], QX.fix(1 + self.numSeats) - self.tx[self.R])
def findTiedCand(self, cList, mostfewest, function): "Return a list of candidates tied for first or last." assert(mostfewest in ["most", "fewest"]) assert(len(cList) > 0) cList = list(cList) tiedCand = [] # Find a candidate who is winning/losing. He may be tied with others. if mostfewest == "most": cList.sort(key=lambda a, f=function: -f[a]) elif mostfewest == "fewest": cList.sort(key=lambda a, f=function: f[a]) top = cList[0] # first/last place candidate # Find the number of candidates who are tied with him. for c in cList: if QX.eq(function[c], function[top]): tiedCand.append(c) return tiedCand
def findTiedCand(self, cList, mostfewest, function): "Return a list of candidates tied for first or last." assert (mostfewest in ["most", "fewest"]) assert (len(cList) > 0) cList = list(cList) tiedCand = [] # Find a candidate who is winning/losing. He may be tied with others. if mostfewest == "most": cList.sort(key=lambda a, f=function: -f[a]) elif mostfewest == "fewest": cList.sort(key=lambda a, f=function: f[a]) top = cList[0] # first/last place candidate # Find the number of candidates who are tied with him. for c in cList: if QX.eq(function[c], function[top]): tiedCand.append(c) return tiedCand
def displayValue(self, value): "Format a value with specified precision." return QX.str(value)
def postCount(self): "Report QX stats if enabled" self.numRounds = self.R if False: QX.postCount(self, self.R)