From 6194c0c1c8366a14d4715371cf1ac75c391a4988 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 22 Feb 2019 13:18:16 +0100 Subject: [PATCH 1/5] First draft of fixing styles --- .gitignore | 1 + "NPoS/simplePhragm\303\251n.py" | 257 ++++++++++++++++++-------------- 2 files changed, 150 insertions(+), 108 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..600d2d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git "a/NPoS/simplePhragm\303\251n.py" "b/NPoS/simplePhragm\303\251n.py" index ff3140e..289235c 100644 --- "a/NPoS/simplePhragm\303\251n.py" +++ "b/NPoS/simplePhragm\303\251n.py" @@ -1,125 +1,148 @@ -#from itertools import count +import unittest +import math +import sys +import random + + class edge: - def __init__(self,nomid,valiid): - self.nomid=nomid - self.valiid=valiid - #self.validator - self.load=0 + def __init__(self, nomid, valiid): + self.nomid = nomid + self.valiid = valiid + self.load = 0 + class nominator: - def __init__(self,votetuple): - self.nomid=votetuple[0] - self.budget=votetuple[1] - self.edges=[edge(self.nomid,valiid) for valiid in votetuple[2]] - self.load=0 + def __init__(self, votetuple): + self.nomid = votetuple[0] + self.budget = votetuple[1] + self.edges = [edge(self.nomid, valiid) for valiid in votetuple[2]] + self.load = 0 + class candidate: - def __init__(self,valiid,valindex): + def __init__(self, valiid, valindex): self.valiid = valiid - self.valindex=valindex - self.approvalstake=0 - self.elected=False - self.backedstake=0 - self.score=0 + self.valindex = valindex + self.approvalstake = 0 + self.elected = False + self.backedstake = 0 + self.score = 0 + def setuplists(votelist): - #Instead of Python's dict here, you can use anything with O(log n) addition and lookup. - #We can also use a hashmap like dict, by generating a random constant r and useing H(canid+r) - #since the naive thing is obviously attackable. + ''' + Instead of Python's dict here, you can use anything with O(log n) + addition and lookup.We can also use a hashmap like dict, by generating + a random constant r and useing H(canid+r) + since the naive thing is obviously attackable. + ''' nomlist = [nominator(votetuple) for votetuple in votelist] - candidatedict=dict() - candidatearray=list() - numcandidates=0 - #Get an array of candidates. ]#We could reference these by index - #rather than pointer + candidatedict = dict() + candidatearray = list() + numcandidates = 0 + + # Get an array of candidates. ]#We could reference these by index + # rather than pointer + for nom in nomlist: for edge in nom.edges: valiid = edge.valiid if valiid in candidatedict: - edge.candidate=candidatearray[candidatedict[valiid]] + edge.candidate = candidatearray[candidatedict[valiid]] else: - candidatedict[valiid]=numcandidates - newcandidate=candidate(valiid,numcandidates) + candidatedict[valiid] = numcandidates + newcandidate = candidate(valiid, numcandidates) candidatearray.append(newcandidate) - edge.candidate=newcandidate + edge.candidate = newcandidate numcandidates += 1 - return(nomlist,candidatearray) - + return(nomlist, candidatearray) -def seqPhragmén(votelist,numtoelect): - nomlist,candidates=setuplists(votelist) - #Compute the total possible stake for each candidate + +def seqPhragmén(votelist, numtoelect): + nomlist, candidates = setuplists(votelist) + # Compute the total possible stake for each candidate for nom in nomlist: for edge in nom.edges: edge.candidate.approvalstake += nom.budget - - electedcandidates=list() + + electedcandidates = list() for round in range(numtoelect): for candidate in candidates: if not candidate.elected: - candidate.score=1/candidate.approvalstake + candidate.score = 1/candidate.approvalstake for nom in nomlist: for edge in nom.edges: if not edge.candidate.elected: - edge.candidate.score +=nom.budget * nom.load / edge.candidate.approvalstake - bestcandidate=0 - bestscore = 1000 #should be infinite but I'm lazy + edge.candidate.score += nom.budget * nom.load / edge.candidate.approvalstake + + bestcandidate = 0 + bestscore = math.inf + for candidate in candidates: if not candidate.elected and candidate.score < bestscore: - bestscore=candidate.score - bestcandidate=candidate.valindex - electedcandidate=candidates[bestcandidate] - electedcandidate.elected=True - electedcandidate.electedpos=round + bestscore = candidate.score + bestcandidate = candidate.valindex + + electedcandidate = candidates[bestcandidate] + electedcandidate.elected = True + electedcandidate.electedpos = round electedcandidates.append(electedcandidate) + for nom in nomlist: for edge in nom.edges: if edge.candidate.valindex == bestcandidate: - edge.load=electedcandidate.score - nom.load - nom.load=electedcandidate.score + edge.load = electedcandidate.score - nom.load + nom.load = electedcandidate.score for candidate in electedcandidates: - candidate.backedstake=0 + candidate.backedstake = 0 for nom in nomlist: for edge in nom.edges: - edge.backingstake = nom.budget * edge.load/nom.load - edge.candidate.backedstake += edge.backingstake - return (nomlist,electedcandidates) + edge.backingstake = nom.budget * edge.load/nom.load + edge.candidate.backedstake += edge.backingstake + return nomlist, electedcandidates + + +def approvalvoting(votelist, numtoelect): + nomlist, candidates = setuplists(votelist) -def approvalvoting(votelist,numtoelect): - nomlist,candidates=setuplists(votelist) - #Compute the total possible stake for each candidate + # Compute the total possible stake for each candidate for nom in nomlist: for edge in nom.edges: edge.candidate.approvalstake += nom.budget - edge.backingstake = nom.budget/min(len(nom.edges),numtoelect) + edge.backingstake = nom.budget/min(len(nom.edges), numtoelect) edge.candidate.backedstake += edge.backingstake - candidates.sort( key = lambda x : x.approvalstake, reverse=True) - electedcandidates=candidates[0:numtoelect] - return nomlist,electedcandidates -def printresult(nomlist,electedcandidates): + candidates.sort(key=lambda x: x.approvalstake, reverse=True) + + electedcandidates = candidates[0:numtoelect] + return nomlist, electedcandidates + + +def printresult(nomlist, electedcandidates): for candidate in electedcandidates: - print(candidate.valiid," is elected with stake ",candidate.backedstake, "and score ",candidate.score) + print(candidate.valiid, " is elected with stake ", candidate.backedstake, "and score ", candidate.score) + print() for nom in nomlist: - print(nom.nomid," has load ",nom.load, "and supported ") + print(nom.nomid, " has load ", nom.load, "and supported ") for edge in nom.edges: - print(edge.valiid," with stake ",edge.backingstake, end=" ") + print(edge.valiid, " with stake ", edge.backingstake, end=" ") print() + def equalise(nom, tolerance): # Attempts to redistribute the nominators budget between elected validators # Assumes that all elected validators have backedstake set correctly # returns the max difference in stakes between sup - electededges=[edge for edge in nom.edges if edge.candidate.elected] - if len(electededges)==0: + electededges = [edge for edge in nom.edges if edge.candidate.elected] + if len(electededges) == 0: return 0.0 stakeused = sum([edge.backingstake for edge in electededges]) - backedstakes=[edge.candidate.backedstake for edge in electededges] - backingbackedstakes=[edge.candidate.backedstake for edge in electededges if edge.backingstake > 0.0] + backedstakes = [edge.candidate.backedstake for edge in electededges] + backingbackedstakes = [edge.candidate.backedstake for edge in electededges if edge.backingstake > 0.0] if len(backingbackedstakes) > 0: difference = max(backingbackedstakes)-min(backedstakes) difference += nom.budget-stakeused @@ -127,53 +150,61 @@ def equalise(nom, tolerance): return difference else: difference = nom.budget + #remove all backing for edge in nom.edges: edge.candidate.backedstake -= edge.backingstake - edge.backingstake=0 + edge.backingstake = 0 + electededges.sort(key=lambda x: x.candidate.backedstake) - cumulativebackedstake=0 - lastcandidateindex=len(electededges)-1 + cumulativebackedstake = 0 + lastcandidateindex = len(electededges)-1 + for i in range(len(electededges)): - backedstake=electededges[i].candidate.backedstake - #print(nom.nomid,electededges[i].valiid,backedstake,cumulativebackedstake,i) + backedstake = electededges[i].candidate.backedstake if backedstake * i - cumulativebackedstake > nom.budget: - lastcandidateindex=i-1 + lastcandidateindex = i-1 break - cumulativebackedstake +=backedstake - laststake=electededges[lastcandidateindex].candidate.backedstake - waystosplit=lastcandidateindex+1 - excess = nom.budget + cumulativebackedstake - laststake*waystosplit + cumulativebackedstake += backedstake + + laststake = electededges[lastcandidateindex].candidate.backedstake + waystosplit = lastcandidateindex+1 + excess = nom.budget + cumulativebackedstake - laststake*waystosplit for edge in electededges[0:waystosplit]: edge.backingstake = excess / waystosplit + laststake - edge.candidate.backedstake edge.candidate.backedstake += edge.backingstake return difference -import random -def equaliseall(nomlist,maxiterations,tolerance): + +def equaliseall(nomlist, maxiterations, tolerance): for i in range(maxiterations): for j in range(len(nomlist)): - nom=random.choice(nomlist) - equalise(nom,tolerance/10) - maxdifference=0 + nom = random.choice(nomlist) + equalise(nom, tolerance/10) + maxdifference = 0 for nom in nomlist: - difference=equalise(nom,tolerance/10) - maxdifference=max(difference,maxdifference) + difference = equalise(nom, tolerance/10) + maxdifference = max(difference, maxdifference) if maxdifference < tolerance: return -def seqPhragménwithpostprocessing(votelist,numtoelect): - nomlist,electedcandidates = seqPhragmén(votelist,numtoelect) - equaliseall(nomlist,2,0.1) - return nomlist,electedcandidates + +def seqPhragménwithpostprocessing(votelist, numtoelect): + nomlist, electedcandidates = seqPhragmén(votelist, numtoelect) + equaliseall(nomlist, 2, 0.1) + return nomlist, electedcandidates + def example1(): - votelist=[("A",10.0,["X","Y"]),("B",20.0,["X","Z"]),("C",30.0,["Y","Z"])] - print("Votes ",votelist) - nomlist, electedcandidates = seqPhragmén(votelist,2) + votelist = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + print("Votes ", votelist) + nomlist, electedcandidates = seqPhragmén(votelist, 2) print("Sequential Phragmén gives") printresult(nomlist, electedcandidates) - nomlist, electedcandidates = approvalvoting(votelist,2) + nomlist, electedcandidates = approvalvoting(votelist, 2) print() print("Approval voting gives") printresult(nomlist, electedcandidates) @@ -181,26 +212,36 @@ def example1(): print("Sequential Phragmén with post processing gives") printresult(nomlist, electedcandidates) -import unittest + class electiontests(unittest.TestCase): def testexample1Phragmén(self): - votelist=[("A",10.0,["X","Y"]),("B",20.0,["X","Z"]),("C",30.0,["Y","Z"])] - nomlist, electedcandidates = seqPhragmén(votelist,2) - self.assertEqual(electedcandidates[0].valiid,"Z") - self.assertAlmostEqual(electedcandidates[0].score,0.02) - self.assertEqual(electedcandidates[1].valiid,"Y") - self.assertAlmostEqual(electedcandidates[1].score,0.04) + votelist = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + nomlist, electedcandidates = seqPhragmén(votelist, 2) + self.assertEqual(electedcandidates[0].valiid, "Z") + self.assertAlmostEqual(electedcandidates[0].score, 0.02) + self.assertEqual(electedcandidates[1].valiid, "Y") + self.assertAlmostEqual(electedcandidates[1].score, 0.04) + def testexample1approval(self): - votelist=[("A",10.0,["X","Y"]),("B",20.0,["X","Z"]),("C",30.0,["Y","Z"])] - nomlist, electedcandidates = approvalvoting(votelist,2) - self.assertEqual(electedcandidates[0].valiid,"Z") - self.assertAlmostEqual(electedcandidates[0].approvalstake,50.0) - self.assertEqual(electedcandidates[1].valiid,"Y") - self.assertAlmostEqual(electedcandidates[1].approvalstake,40.0) -def dotests(): - unittest.main() - - + votelist = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + nomlist, electedcandidates = approvalvoting(votelist, 2) + self.assertEqual(electedcandidates[0].valiid, "Z") + self.assertAlmostEqual(electedcandidates[0].approvalstake, 50.0) + self.assertEqual(electedcandidates[1].valiid, "Y") + self.assertAlmostEqual(electedcandidates[1].approvalstake, 40.0) + + +if __name__ == "__main__": + if len(sys.argv) == 3 and sys.argv[2] == "test": + unittest.main() + else: + example1() From 01c9839fede2bc247fc4dc76d8a22f64a755d8bf Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 22 Feb 2019 13:22:16 +0100 Subject: [PATCH 2/5] rename functions to snake_case --- "NPoS/simplePhragm\303\251n.py" | 73 ++++++++++----------------------- 1 file changed, 22 insertions(+), 51 deletions(-) diff --git "a/NPoS/simplePhragm\303\251n.py" "b/NPoS/simplePhragm\303\251n.py" index 289235c..314efc8 100644 --- "a/NPoS/simplePhragm\303\251n.py" +++ "b/NPoS/simplePhragm\303\251n.py" @@ -29,7 +29,7 @@ def __init__(self, valiid, valindex): self.score = 0 -def setuplists(votelist): +def setup_lists(votelist): ''' Instead of Python's dict here, you can use anything with O(log n) addition and lookup.We can also use a hashmap like dict, by generating @@ -58,8 +58,8 @@ def setuplists(votelist): return(nomlist, candidatearray) -def seqPhragmén(votelist, numtoelect): - nomlist, candidates = setuplists(votelist) +def seq_phragmén(votelist, numtoelect): + nomlist, candidates = setup_lists(votelist) # Compute the total possible stake for each candidate for nom in nomlist: for edge in nom.edges: @@ -74,7 +74,7 @@ def seqPhragmén(votelist, numtoelect): for edge in nom.edges: if not edge.candidate.elected: edge.candidate.score += nom.budget * nom.load / edge.candidate.approvalstake - + bestcandidate = 0 bestscore = math.inf @@ -104,8 +104,8 @@ def seqPhragmén(votelist, numtoelect): return nomlist, electedcandidates -def approvalvoting(votelist, numtoelect): - nomlist, candidates = setuplists(votelist) +def approval_voting(votelist, numtoelect): + nomlist, candidates = setup_lists(votelist) # Compute the total possible stake for each candidate for nom in nomlist: @@ -120,7 +120,7 @@ def approvalvoting(votelist, numtoelect): return nomlist, electedcandidates -def printresult(nomlist, electedcandidates): +def print_result(nomlist, electedcandidates): for candidate in electedcandidates: print(candidate.valiid, " is elected with stake ", candidate.backedstake, "and score ", candidate.score) @@ -151,7 +151,7 @@ def equalise(nom, tolerance): else: difference = nom.budget - #remove all backing + # remove all backing for edge in nom.edges: edge.candidate.backedstake -= edge.backingstake edge.backingstake = 0 @@ -176,7 +176,7 @@ def equalise(nom, tolerance): return difference -def equaliseall(nomlist, maxiterations, tolerance): +def equalise_all(nomlist, maxiterations, tolerance): for i in range(maxiterations): for j in range(len(nomlist)): nom = random.choice(nomlist) @@ -189,9 +189,9 @@ def equaliseall(nomlist, maxiterations, tolerance): return -def seqPhragménwithpostprocessing(votelist, numtoelect): - nomlist, electedcandidates = seqPhragmén(votelist, numtoelect) - equaliseall(nomlist, 2, 0.1) +def seq_phragmén_with_postprocessing(votelist, numtoelect): + nomlist, electedcandidates = seq_phragmén(votelist, numtoelect) + equalise_all(nomlist, 2, 0.1) return nomlist, electedcandidates @@ -201,36 +201,36 @@ def example1(): ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] print("Votes ", votelist) - nomlist, electedcandidates = seqPhragmén(votelist, 2) + nomlist, electedcandidates = seq_phragmén(votelist, 2) print("Sequential Phragmén gives") - printresult(nomlist, electedcandidates) - nomlist, electedcandidates = approvalvoting(votelist, 2) + print_result(nomlist, electedcandidates) + nomlist, electedcandidates = approval_voting(votelist, 2) print() print("Approval voting gives") - printresult(nomlist, electedcandidates) - nomlist, electedcandidates = seqPhragménwithpostprocessing(votelist,2) + print_result(nomlist, electedcandidates) + nomlist, electedcandidates = seq_phragmén_with_postprocessing(votelist, 2) print("Sequential Phragmén with post processing gives") - printresult(nomlist, electedcandidates) + print_result(nomlist, electedcandidates) class electiontests(unittest.TestCase): - def testexample1Phragmén(self): + def testexample1_phragmén(self): votelist = [ ("A", 10.0, ["X", "Y"]), ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] - nomlist, electedcandidates = seqPhragmén(votelist, 2) + nomlist, electedcandidates = seq_phragmén(votelist, 2) self.assertEqual(electedcandidates[0].valiid, "Z") self.assertAlmostEqual(electedcandidates[0].score, 0.02) self.assertEqual(electedcandidates[1].valiid, "Y") self.assertAlmostEqual(electedcandidates[1].score, 0.04) - def testexample1approval(self): + def test_example1_approval(self): votelist = [ ("A", 10.0, ["X", "Y"]), ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] - nomlist, electedcandidates = approvalvoting(votelist, 2) + nomlist, electedcandidates = approval_voting(votelist, 2) self.assertEqual(electedcandidates[0].valiid, "Z") self.assertAlmostEqual(electedcandidates[0].approvalstake, 50.0) self.assertEqual(electedcandidates[1].valiid, "Y") @@ -242,32 +242,3 @@ def testexample1approval(self): unittest.main() else: example1() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From fe99e907167bf40680f5eb68faea1ce1d5ef4ae1 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 22 Feb 2019 13:52:52 +0100 Subject: [PATCH 3/5] renames vriables and attributes to sname_case and adds some docs --- .gitignore | 3 +- "NPoS/simplePhragm\303\251n.py" | 125 +++++++++++++++++--------------- 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 600d2d3..cc06c53 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.vscode \ No newline at end of file +.vscode +.idea/ diff --git "a/NPoS/simplePhragm\303\251n.py" "b/NPoS/simplePhragm\303\251n.py" index 314efc8..72db194 100644 --- "a/NPoS/simplePhragm\303\251n.py" +++ "b/NPoS/simplePhragm\303\251n.py" @@ -13,8 +13,11 @@ def __init__(self, nomid, valiid): class nominator: def __init__(self, votetuple): + # id of the current nominator self.nomid = votetuple[0] + # staked value of the nominator self.budget = votetuple[1] + # edges to candidates being voted self.edges = [edge(self.nomid, valiid) for valiid in votetuple[2]] self.load = 0 @@ -23,23 +26,23 @@ class candidate: def __init__(self, valiid, valindex): self.valiid = valiid self.valindex = valindex - self.approvalstake = 0 + self.approval_stake = 0 self.elected = False - self.backedstake = 0 + self.backed_stake = 0 self.score = 0 -def setup_lists(votelist): +def setup_lists(vote_list): ''' Instead of Python's dict here, you can use anything with O(log n) addition and lookup.We can also use a hashmap like dict, by generating a random constant r and useing H(canid+r) since the naive thing is obviously attackable. ''' - nomlist = [nominator(votetuple) for votetuple in votelist] - candidatedict = dict() - candidatearray = list() - numcandidates = 0 + nomlist = [nominator(vote_tuple) for vote_tuple in vote_list] + candidate_dict = dict() + candidate_array = list() + num_candidates = 0 # Get an array of candidates. ]#We could reference these by index # rather than pointer @@ -47,61 +50,69 @@ def setup_lists(votelist): for nom in nomlist: for edge in nom.edges: valiid = edge.valiid - if valiid in candidatedict: - edge.candidate = candidatearray[candidatedict[valiid]] + if valiid in candidate_dict: + edge.candidate = candidate_array[candidate_dict[valiid]] else: - candidatedict[valiid] = numcandidates - newcandidate = candidate(valiid, numcandidates) - candidatearray.append(newcandidate) + candidate_dict[valiid] = num_candidates + newcandidate = candidate(valiid, num_candidates) + candidate_array.append(newcandidate) edge.candidate = newcandidate - numcandidates += 1 - return(nomlist, candidatearray) + num_candidates += 1 + return nomlist, candidate_array -def seq_phragmén(votelist, numtoelect): - nomlist, candidates = setup_lists(votelist) +def seq_phragmén(vote_list, num_to_elect): + nomlist, candidates = setup_lists(vote_list) # Compute the total possible stake for each candidate + # e.g. sum of the stake of all the nominators voting to each candidate. for nom in nomlist: for edge in nom.edges: - edge.candidate.approvalstake += nom.budget + edge.candidate.approval_stake += nom.budget - electedcandidates = list() - for round in range(numtoelect): + elected_candidates = list() + for round in range(num_to_elect): + # note that the candidates[i] list and the nominator.edge.candidate[i] are mutably linked, + # changing one will affect the other one. + # in the following two loops this applies to edge.candidate.score and candidate.score for candidate in candidates: if not candidate.elected: - candidate.score = 1/candidate.approvalstake + candidate.score = 1/candidate.approval_stake for nom in nomlist: for edge in nom.edges: if not edge.candidate.elected: - edge.candidate.score += nom.budget * nom.load / edge.candidate.approvalstake + edge.candidate.score += nom.budget * nom.load / edge.candidate.approval_stake - bestcandidate = 0 - bestscore = math.inf + best_candidate_index = 0 + best_score = math.inf + # choose the best based on the computed 'approval_stake' for candidate in candidates: - if not candidate.elected and candidate.score < bestscore: - bestscore = candidate.score - bestcandidate = candidate.valindex + if not candidate.elected and candidate.score < best_score: + best_score = candidate.score + best_candidate_index = candidate.valindex - electedcandidate = candidates[bestcandidate] - electedcandidate.elected = True - electedcandidate.electedpos = round - electedcandidates.append(electedcandidate) + elected_candidate = candidates[best_candidate_index] + elected_candidate.elected = True + elected_candidate.elected_pos = round + elected_candidates.append(elected_candidate) + # change the load of all nominators who voted for the winner for nom in nomlist: for edge in nom.edges: - if edge.candidate.valindex == bestcandidate: - edge.load = electedcandidate.score - nom.load - nom.load = electedcandidate.score + if edge.candidate.valindex == best_candidate_index: + edge.load = elected_candidate.score - nom.load + nom.load = elected_candidate.score - for candidate in electedcandidates: - candidate.backedstake = 0 + # reset the backed_stake of the winners + for candidate in elected_candidates: + candidate.backed_stake = 0 + # set the new real backed stake value of the winners for nom in nomlist: for edge in nom.edges: - edge.backingstake = nom.budget * edge.load/nom.load - edge.candidate.backedstake += edge.backingstake - return nomlist, electedcandidates + edge.backing_stake = nom.budget * edge.load / nom.load + edge.candidate.backed_stake += edge.backing_stake + return nomlist, elected_candidates def approval_voting(votelist, numtoelect): @@ -110,11 +121,11 @@ def approval_voting(votelist, numtoelect): # Compute the total possible stake for each candidate for nom in nomlist: for edge in nom.edges: - edge.candidate.approvalstake += nom.budget - edge.backingstake = nom.budget/min(len(nom.edges), numtoelect) - edge.candidate.backedstake += edge.backingstake + edge.candidate.approval_stake += nom.budget + edge.backing_stake = nom.budget/min(len(nom.edges), numtoelect) + edge.candidate.backed_stake += edge.backing_stake - candidates.sort(key=lambda x: x.approvalstake, reverse=True) + candidates.sort(key=lambda x: x.approval_stake, reverse=True) electedcandidates = candidates[0:numtoelect] return nomlist, electedcandidates @@ -122,27 +133,27 @@ def approval_voting(votelist, numtoelect): def print_result(nomlist, electedcandidates): for candidate in electedcandidates: - print(candidate.valiid, " is elected with stake ", candidate.backedstake, "and score ", candidate.score) + print(candidate.valiid, " is elected with stake ", candidate.backed_stake, "and score ", candidate.score) print() for nom in nomlist: print(nom.nomid, " has load ", nom.load, "and supported ") for edge in nom.edges: - print(edge.valiid, " with stake ", edge.backingstake, end=" ") + print(edge.valiid, " with stake ", edge.backing_stake, end=" ") print() def equalise(nom, tolerance): # Attempts to redistribute the nominators budget between elected validators - # Assumes that all elected validators have backedstake set correctly + # Assumes that all elected validators have backed_stake set correctly # returns the max difference in stakes between sup electededges = [edge for edge in nom.edges if edge.candidate.elected] if len(electededges) == 0: return 0.0 - stakeused = sum([edge.backingstake for edge in electededges]) - backedstakes = [edge.candidate.backedstake for edge in electededges] - backingbackedstakes = [edge.candidate.backedstake for edge in electededges if edge.backingstake > 0.0] + stakeused = sum([edge.backing_stake for edge in electededges]) + backedstakes = [edge.candidate.backed_stake for edge in electededges] + backingbackedstakes = [edge.candidate.backed_stake for edge in electededges if edge.backing_stake > 0.0] if len(backingbackedstakes) > 0: difference = max(backingbackedstakes)-min(backedstakes) difference += nom.budget-stakeused @@ -153,26 +164,26 @@ def equalise(nom, tolerance): # remove all backing for edge in nom.edges: - edge.candidate.backedstake -= edge.backingstake - edge.backingstake = 0 + edge.candidate.backed_stake -= edge.backing_stake + edge.backing_stake = 0 - electededges.sort(key=lambda x: x.candidate.backedstake) + electededges.sort(key=lambda x: x.candidate.backed_stake) cumulativebackedstake = 0 lastcandidateindex = len(electededges)-1 for i in range(len(electededges)): - backedstake = electededges[i].candidate.backedstake + backedstake = electededges[i].candidate.backed_stake if backedstake * i - cumulativebackedstake > nom.budget: lastcandidateindex = i-1 break cumulativebackedstake += backedstake - laststake = electededges[lastcandidateindex].candidate.backedstake + laststake = electededges[lastcandidateindex].candidate.backed_stake waystosplit = lastcandidateindex+1 excess = nom.budget + cumulativebackedstake - laststake*waystosplit for edge in electededges[0:waystosplit]: - edge.backingstake = excess / waystosplit + laststake - edge.candidate.backedstake - edge.candidate.backedstake += edge.backingstake + edge.backing_stake = excess / waystosplit + laststake - edge.candidate.backed_stake + edge.candidate.backed_stake += edge.backing_stake return difference @@ -232,9 +243,9 @@ def test_example1_approval(self): ("C", 30.0, ["Y", "Z"])] nomlist, electedcandidates = approval_voting(votelist, 2) self.assertEqual(electedcandidates[0].valiid, "Z") - self.assertAlmostEqual(electedcandidates[0].approvalstake, 50.0) + self.assertAlmostEqual(electedcandidates[0].approval_stake, 50.0) self.assertEqual(electedcandidates[1].valiid, "Y") - self.assertAlmostEqual(electedcandidates[1].approvalstake, 40.0) + self.assertAlmostEqual(electedcandidates[1].approval_stake, 40.0) if __name__ == "__main__": From 01fa94d3afc629c824efe8fc084f26527e0aa128 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 22 Feb 2019 15:41:17 +0100 Subject: [PATCH 4/5] finalize refactoring --- "NPoS/simplePhragm\303\251n.py" | 98 ++++++++++++++++----------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git "a/NPoS/simplePhragm\303\251n.py" "b/NPoS/simplePhragm\303\251n.py" index 72db194..3fc32ed 100644 --- "a/NPoS/simplePhragm\303\251n.py" +++ "b/NPoS/simplePhragm\303\251n.py" @@ -54,9 +54,9 @@ def setup_lists(vote_list): edge.candidate = candidate_array[candidate_dict[valiid]] else: candidate_dict[valiid] = num_candidates - newcandidate = candidate(valiid, num_candidates) - candidate_array.append(newcandidate) - edge.candidate = newcandidate + new_candidate = candidate(valiid, num_candidates) + candidate_array.append(new_candidate) + edge.candidate = new_candidate num_candidates += 1 return nomlist, candidate_array @@ -127,8 +127,8 @@ def approval_voting(votelist, numtoelect): candidates.sort(key=lambda x: x.approval_stake, reverse=True) - electedcandidates = candidates[0:numtoelect] - return nomlist, electedcandidates + elected_candidates = candidates[0:numtoelect] + return nomlist, elected_candidates def print_result(nomlist, electedcandidates): @@ -148,15 +148,15 @@ def equalise(nom, tolerance): # Assumes that all elected validators have backed_stake set correctly # returns the max difference in stakes between sup - electededges = [edge for edge in nom.edges if edge.candidate.elected] - if len(electededges) == 0: + elected_edges = [edge for edge in nom.edges if edge.candidate.elected] + if len(elected_edges) == 0: return 0.0 - stakeused = sum([edge.backing_stake for edge in electededges]) - backedstakes = [edge.candidate.backed_stake for edge in electededges] - backingbackedstakes = [edge.candidate.backed_stake for edge in electededges if edge.backing_stake > 0.0] - if len(backingbackedstakes) > 0: - difference = max(backingbackedstakes)-min(backedstakes) - difference += nom.budget-stakeused + stake_used = sum([edge.backing_stake for edge in elected_edges]) + backed_stakes = [edge.candidate.backed_stake for edge in elected_edges] + backing_backed_stakes = [edge.candidate.backed_stake for edge in elected_edges if edge.backing_stake > 0.0] + if len(backing_backed_stakes) > 0: + difference = max(backing_backed_stakes)-min(backed_stakes) + difference += nom.budget-stake_used if difference < tolerance: return difference else: @@ -167,22 +167,22 @@ def equalise(nom, tolerance): edge.candidate.backed_stake -= edge.backing_stake edge.backing_stake = 0 - electededges.sort(key=lambda x: x.candidate.backed_stake) - cumulativebackedstake = 0 - lastcandidateindex = len(electededges)-1 + elected_edges.sort(key=lambda x: x.candidate.backed_stake) + cumulative_backed_stake = 0 + last_candidate_index = len(elected_edges)-1 - for i in range(len(electededges)): - backedstake = electededges[i].candidate.backed_stake - if backedstake * i - cumulativebackedstake > nom.budget: - lastcandidateindex = i-1 + for i in range(len(elected_edges)): + backed_stake = elected_edges[i].candidate.backed_stake + if backed_stake * i - cumulative_backed_stake > nom.budget: + last_candidate_index = i-1 break - cumulativebackedstake += backedstake + cumulative_backed_stake += backed_stake - laststake = electededges[lastcandidateindex].candidate.backed_stake - waystosplit = lastcandidateindex+1 - excess = nom.budget + cumulativebackedstake - laststake*waystosplit - for edge in electededges[0:waystosplit]: - edge.backing_stake = excess / waystosplit + laststake - edge.candidate.backed_stake + last_stake = elected_edges[last_candidate_index].candidate.backed_stake + ways_to_split = last_candidate_index+1 + excess = nom.budget + cumulative_backed_stake - last_stake*ways_to_split + for edge in elected_edges[0:ways_to_split]: + edge.backing_stake = excess / ways_to_split + last_stake - edge.candidate.backed_stake edge.candidate.backed_stake += edge.backing_stake return difference @@ -192,18 +192,18 @@ def equalise_all(nomlist, maxiterations, tolerance): for j in range(len(nomlist)): nom = random.choice(nomlist) equalise(nom, tolerance/10) - maxdifference = 0 + max_difference = 0 for nom in nomlist: difference = equalise(nom, tolerance/10) - maxdifference = max(difference, maxdifference) - if maxdifference < tolerance: + max_difference = max(difference, max_difference) + if max_difference < tolerance: return def seq_phragmén_with_postprocessing(votelist, numtoelect): - nomlist, electedcandidates = seq_phragmén(votelist, numtoelect) + nomlist, elected_candidates = seq_phragmén(votelist, numtoelect) equalise_all(nomlist, 2, 0.1) - return nomlist, electedcandidates + return nomlist, elected_candidates def example1(): @@ -212,40 +212,40 @@ def example1(): ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] print("Votes ", votelist) - nomlist, electedcandidates = seq_phragmén(votelist, 2) + nomlist, elected_candidates = seq_phragmén(votelist, 2) print("Sequential Phragmén gives") - print_result(nomlist, electedcandidates) - nomlist, electedcandidates = approval_voting(votelist, 2) + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = approval_voting(votelist, 2) print() print("Approval voting gives") - print_result(nomlist, electedcandidates) - nomlist, electedcandidates = seq_phragmén_with_postprocessing(votelist, 2) + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) print("Sequential Phragmén with post processing gives") - print_result(nomlist, electedcandidates) + print_result(nomlist, elected_candidates) class electiontests(unittest.TestCase): def testexample1_phragmén(self): - votelist = [ + vote_list = [ ("A", 10.0, ["X", "Y"]), ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] - nomlist, electedcandidates = seq_phragmén(votelist, 2) - self.assertEqual(electedcandidates[0].valiid, "Z") - self.assertAlmostEqual(electedcandidates[0].score, 0.02) - self.assertEqual(electedcandidates[1].valiid, "Y") - self.assertAlmostEqual(electedcandidates[1].score, 0.04) + nomlist, elected_candidates = seq_phragmén(vote_list, 2) + self.assertEqual(elected_candidates[0].valiid, "Z") + self.assertAlmostEqual(elected_candidates[0].score, 0.02) + self.assertEqual(elected_candidates[1].valiid, "Y") + self.assertAlmostEqual(elected_candidates[1].score, 0.04) def test_example1_approval(self): - votelist = [ + vote_list = [ ("A", 10.0, ["X", "Y"]), ("B", 20.0, ["X", "Z"]), ("C", 30.0, ["Y", "Z"])] - nomlist, electedcandidates = approval_voting(votelist, 2) - self.assertEqual(electedcandidates[0].valiid, "Z") - self.assertAlmostEqual(electedcandidates[0].approval_stake, 50.0) - self.assertEqual(electedcandidates[1].valiid, "Y") - self.assertAlmostEqual(electedcandidates[1].approval_stake, 40.0) + nomlist, elected_candidates = approval_voting(vote_list, 2) + self.assertEqual(elected_candidates[0].valiid, "Z") + self.assertAlmostEqual(elected_candidates[0].approval_stake, 50.0) + self.assertEqual(elected_candidates[1].valiid, "Y") + self.assertAlmostEqual(elected_candidates[1].approval_stake, 40.0) if __name__ == "__main__": From ed7cd73c1a6771b8668884f1022737813c5564f7 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 18 Mar 2019 11:41:21 +0100 Subject: [PATCH 5/5] adds new test cases --- "NPoS/simplePhragm\303\251n.py" | 485 ++++++++++++++++++-------------- 1 file changed, 276 insertions(+), 209 deletions(-) diff --git "a/NPoS/simplePhragm\303\251n.py" "b/NPoS/simplePhragm\303\251n.py" index 3fc32ed..c39aee8 100644 --- "a/NPoS/simplePhragm\303\251n.py" +++ "b/NPoS/simplePhragm\303\251n.py" @@ -5,251 +5,318 @@ class edge: - def __init__(self, nomid, valiid): - self.nomid = nomid - self.valiid = valiid - self.load = 0 + def __init__(self, nomid, valiid): + self.nomid = nomid + self.valiid = valiid + self.load = 0 class nominator: - def __init__(self, votetuple): - # id of the current nominator - self.nomid = votetuple[0] - # staked value of the nominator - self.budget = votetuple[1] - # edges to candidates being voted - self.edges = [edge(self.nomid, valiid) for valiid in votetuple[2]] - self.load = 0 + def __init__(self, votetuple): + # id of the current nominator + self.nomid = votetuple[0] + # staked value of the nominator + self.budget = votetuple[1] + # edges to candidates being voted + self.edges = [edge(self.nomid, valiid) for valiid in votetuple[2]] + self.load = 0 class candidate: - def __init__(self, valiid, valindex): - self.valiid = valiid - self.valindex = valindex - self.approval_stake = 0 - self.elected = False - self.backed_stake = 0 - self.score = 0 + def __init__(self, valiid, valindex): + self.valiid = valiid + self.valindex = valindex + self.approval_stake = 0 + self.elected = False + self.backed_stake = 0 + self.score = 0 def setup_lists(vote_list): - ''' - Instead of Python's dict here, you can use anything with O(log n) - addition and lookup.We can also use a hashmap like dict, by generating - a random constant r and useing H(canid+r) - since the naive thing is obviously attackable. - ''' - nomlist = [nominator(vote_tuple) for vote_tuple in vote_list] - candidate_dict = dict() - candidate_array = list() - num_candidates = 0 - - # Get an array of candidates. ]#We could reference these by index - # rather than pointer - - for nom in nomlist: - for edge in nom.edges: - valiid = edge.valiid - if valiid in candidate_dict: - edge.candidate = candidate_array[candidate_dict[valiid]] - else: - candidate_dict[valiid] = num_candidates - new_candidate = candidate(valiid, num_candidates) - candidate_array.append(new_candidate) - edge.candidate = new_candidate - num_candidates += 1 - return nomlist, candidate_array + ''' + Instead of Python's dict here, you can use anything with O(log n) + addition and lookup.We can also use a hashmap like dict, by generating + a random constant r and useing H(canid+r) + since the naive thing is obviously attackable. + ''' + nomlist = [nominator(vote_tuple) for vote_tuple in vote_list] + candidate_dict = dict() + candidate_array = list() + num_candidates = 0 + + # Get an array of candidates. ]#We could reference these by index + # rather than pointer + + for nom in nomlist: + for edge in nom.edges: + valiid = edge.valiid + if valiid in candidate_dict: + edge.candidate = candidate_array[candidate_dict[valiid]] + else: + candidate_dict[valiid] = num_candidates + new_candidate = candidate(valiid, num_candidates) + candidate_array.append(new_candidate) + edge.candidate = new_candidate + num_candidates += 1 + return nomlist, candidate_array def seq_phragmén(vote_list, num_to_elect): - nomlist, candidates = setup_lists(vote_list) - # Compute the total possible stake for each candidate - # e.g. sum of the stake of all the nominators voting to each candidate. - for nom in nomlist: - for edge in nom.edges: - edge.candidate.approval_stake += nom.budget - - elected_candidates = list() - for round in range(num_to_elect): - # note that the candidates[i] list and the nominator.edge.candidate[i] are mutably linked, - # changing one will affect the other one. - # in the following two loops this applies to edge.candidate.score and candidate.score - for candidate in candidates: - if not candidate.elected: - candidate.score = 1/candidate.approval_stake - for nom in nomlist: - for edge in nom.edges: - if not edge.candidate.elected: - edge.candidate.score += nom.budget * nom.load / edge.candidate.approval_stake - - best_candidate_index = 0 - best_score = math.inf - - # choose the best based on the computed 'approval_stake' - for candidate in candidates: - if not candidate.elected and candidate.score < best_score: - best_score = candidate.score - best_candidate_index = candidate.valindex - - elected_candidate = candidates[best_candidate_index] - elected_candidate.elected = True - elected_candidate.elected_pos = round - elected_candidates.append(elected_candidate) - - # change the load of all nominators who voted for the winner - for nom in nomlist: - for edge in nom.edges: - if edge.candidate.valindex == best_candidate_index: - edge.load = elected_candidate.score - nom.load - nom.load = elected_candidate.score - - # reset the backed_stake of the winners - for candidate in elected_candidates: - candidate.backed_stake = 0 - - # set the new real backed stake value of the winners - for nom in nomlist: - for edge in nom.edges: - edge.backing_stake = nom.budget * edge.load / nom.load - edge.candidate.backed_stake += edge.backing_stake - return nomlist, elected_candidates + nomlist, candidates = setup_lists(vote_list) + # Compute the total possible stake for each candidate + # e.g. sum of the stake of all the nominators voting to each candidate. + for nom in nomlist: + for edge in nom.edges: + edge.candidate.approval_stake += nom.budget + + elected_candidates = list() + for round in range(num_to_elect): + # note that the candidates[i] list and the nominator.edge.candidate[i] are mutably linked, + # changing one will affect the other one. + # in the following two loops this applies to edge.candidate.score and candidate.score + for candidate in candidates: + if not candidate.elected: + candidate.score = 1/candidate.approval_stake + for nom in nomlist: + for edge in nom.edges: + if not edge.candidate.elected: + edge.candidate.score += nom.budget * nom.load / edge.candidate.approval_stake + + best_candidate_index = 0 + best_score = math.inf + + # choose the best based on the computed 'approval_stake' + for candidate in candidates: + if not candidate.elected and candidate.score < best_score: + best_score = candidate.score + best_candidate_index = candidate.valindex + + elected_candidate = candidates[best_candidate_index] + elected_candidate.elected = True + elected_candidate.elected_pos = round + elected_candidates.append(elected_candidate) + + # change the load of all nominators who voted for the winner + for nom in nomlist: + for edge in nom.edges: + if edge.candidate.valindex == best_candidate_index: + edge.load = elected_candidate.score - nom.load + nom.load = elected_candidate.score + + # reset the backed_stake of the winners + for candidate in elected_candidates: + candidate.backed_stake = 0 + + # set the new real backed stake value of the winners + for nom in nomlist: + for edge in nom.edges: + if nom.load > 0.0: + edge.backing_stake = nom.budget * edge.load/nom.load + edge.candidate.backed_stake += edge.backing_stake + else: + edge.backing_stake = 0 + return nomlist, elected_candidates def approval_voting(votelist, numtoelect): - nomlist, candidates = setup_lists(votelist) + nomlist, candidates = setup_lists(votelist) - # Compute the total possible stake for each candidate - for nom in nomlist: - for edge in nom.edges: - edge.candidate.approval_stake += nom.budget - edge.backing_stake = nom.budget/min(len(nom.edges), numtoelect) - edge.candidate.backed_stake += edge.backing_stake + # Compute the total possible stake for each candidate + for nom in nomlist: + for edge in nom.edges: + edge.candidate.approval_stake += nom.budget + edge.backing_stake = nom.budget/min(len(nom.edges), numtoelect) + edge.candidate.backed_stake += edge.backing_stake - candidates.sort(key=lambda x: x.approval_stake, reverse=True) + candidates.sort(key=lambda x: x.approval_stake, reverse=True) - elected_candidates = candidates[0:numtoelect] - return nomlist, elected_candidates + elected_candidates = candidates[0:numtoelect] + return nomlist, elected_candidates def print_result(nomlist, electedcandidates): - for candidate in electedcandidates: - print(candidate.valiid, " is elected with stake ", candidate.backed_stake, "and score ", candidate.score) - - print() - for nom in nomlist: - print(nom.nomid, " has load ", nom.load, "and supported ") - for edge in nom.edges: - print(edge.valiid, " with stake ", edge.backing_stake, end=" ") - print() + for candidate in electedcandidates: + print(candidate.valiid, " is elected with stake ", candidate.backed_stake, "and score ", candidate.score) + + print() + for nom in nomlist: + print(nom.nomid, " has load ", nom.load, "and supported ") + for edge in nom.edges: + print(edge.valiid, " with stake ", edge.backing_stake, end=" ") + print() def equalise(nom, tolerance): - # Attempts to redistribute the nominators budget between elected validators - # Assumes that all elected validators have backed_stake set correctly - # returns the max difference in stakes between sup - - elected_edges = [edge for edge in nom.edges if edge.candidate.elected] - if len(elected_edges) == 0: - return 0.0 - stake_used = sum([edge.backing_stake for edge in elected_edges]) - backed_stakes = [edge.candidate.backed_stake for edge in elected_edges] - backing_backed_stakes = [edge.candidate.backed_stake for edge in elected_edges if edge.backing_stake > 0.0] - if len(backing_backed_stakes) > 0: - difference = max(backing_backed_stakes)-min(backed_stakes) - difference += nom.budget-stake_used - if difference < tolerance: - return difference - else: - difference = nom.budget - - # remove all backing - for edge in nom.edges: - edge.candidate.backed_stake -= edge.backing_stake - edge.backing_stake = 0 - - elected_edges.sort(key=lambda x: x.candidate.backed_stake) - cumulative_backed_stake = 0 - last_candidate_index = len(elected_edges)-1 - - for i in range(len(elected_edges)): - backed_stake = elected_edges[i].candidate.backed_stake - if backed_stake * i - cumulative_backed_stake > nom.budget: - last_candidate_index = i-1 - break - cumulative_backed_stake += backed_stake - - last_stake = elected_edges[last_candidate_index].candidate.backed_stake - ways_to_split = last_candidate_index+1 - excess = nom.budget + cumulative_backed_stake - last_stake*ways_to_split - for edge in elected_edges[0:ways_to_split]: - edge.backing_stake = excess / ways_to_split + last_stake - edge.candidate.backed_stake - edge.candidate.backed_stake += edge.backing_stake - return difference + # Attempts to redistribute the nominators budget between elected validators + # Assumes that all elected validators have backed_stake set correctly + # returns the max difference in stakes between sup + + elected_edges = [edge for edge in nom.edges if edge.candidate.elected] + if len(elected_edges) == 0: + return 0.0 + stake_used = sum([edge.backing_stake for edge in elected_edges]) + backed_stakes = [edge.candidate.backed_stake for edge in elected_edges] + backing_backed_stakes = [edge.candidate.backed_stake for edge in elected_edges if edge.backing_stake > 0.0] + if len(backing_backed_stakes) > 0: + difference = max(backing_backed_stakes)-min(backed_stakes) + difference += nom.budget-stake_used + if difference < tolerance: + return difference + else: + difference = nom.budget + + # remove all backing + for edge in nom.edges: + edge.candidate.backed_stake -= edge.backing_stake + edge.backing_stake = 0 + + elected_edges.sort(key=lambda x: x.candidate.backed_stake) + cumulative_backed_stake = 0 + last_candidate_index = len(elected_edges)-1 + + for i in range(len(elected_edges)): + backed_stake = elected_edges[i].candidate.backed_stake + if backed_stake * i - cumulative_backed_stake > nom.budget: + last_candidate_index = i-1 + break + cumulative_backed_stake += backed_stake + + last_stake = elected_edges[last_candidate_index].candidate.backed_stake + ways_to_split = last_candidate_index+1 + excess = nom.budget + cumulative_backed_stake - last_stake*ways_to_split + for edge in elected_edges[0:ways_to_split]: + edge.backing_stake = excess / ways_to_split + last_stake - edge.candidate.backed_stake + edge.candidate.backed_stake += edge.backing_stake + return difference def equalise_all(nomlist, maxiterations, tolerance): - for i in range(maxiterations): - for j in range(len(nomlist)): - nom = random.choice(nomlist) - equalise(nom, tolerance/10) - max_difference = 0 - for nom in nomlist: - difference = equalise(nom, tolerance/10) - max_difference = max(difference, max_difference) - if max_difference < tolerance: - return + for i in range(maxiterations): + for j in range(len(nomlist)): + nom = random.choice(nomlist) + equalise(nom, tolerance/10) + max_difference = 0 + for nom in nomlist: + difference = equalise(nom, tolerance/10) + max_difference = max(difference, max_difference) + if max_difference < tolerance: + return def seq_phragmén_with_postprocessing(votelist, numtoelect): - nomlist, elected_candidates = seq_phragmén(votelist, numtoelect) - equalise_all(nomlist, 2, 0.1) - return nomlist, elected_candidates + nomlist, elected_candidates = seq_phragmén(votelist, numtoelect) + equalise_all(nomlist, 2, 0.1) + return nomlist, elected_candidates def example1(): - votelist = [ - ("A", 10.0, ["X", "Y"]), - ("B", 20.0, ["X", "Z"]), - ("C", 30.0, ["Y", "Z"])] - print("Votes ", votelist) - nomlist, elected_candidates = seq_phragmén(votelist, 2) - print("Sequential Phragmén gives") - print_result(nomlist, elected_candidates) - nomlist, elected_candidates = approval_voting(votelist, 2) - print() - print("Approval voting gives") - print_result(nomlist, elected_candidates) - nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) - print("Sequential Phragmén with post processing gives") - print_result(nomlist, elected_candidates) + votelist = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + print("Votes ", votelist) + nomlist, elected_candidates = seq_phragmén(votelist, 2) + print("Sequential Phragmén gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = approval_voting(votelist, 2) + print() + print("Approval voting gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) + print("Sequential Phragmén with post processing gives") + print_result(nomlist, elected_candidates) + + +def example2(): + votelist = [ + ("10", 1000, ["10"]), + ("20", 1000, ["20"]), + ("30", 1000, ["30"]), + ("40", 1000, ["40"]), + ('2', 500, ['10', '20', '30']), + ('4', 500, ['10', '20', '40']) + ] + print("Votes ", votelist) + nomlist, elected_candidates = seq_phragmén(votelist, 2) + print("Sequential Phragmén gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = approval_voting(votelist, 2) + print() + print("Approval voting gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) + print("Sequential Phragmén with post processing gives") + print_result(nomlist, elected_candidates) + +def example3(): + votelist = [ + ("10", 1000, ["10"]), + ("20", 1000, ["20"]), + ("30", 1000, ["30"]), + ('2', 50, ['10', '20']), + ('4', 1000, ['10', '30']) + ] + print("Votes ", votelist) + nomlist, elected_candidates = seq_phragmén(votelist, 2) + print("Sequential Phragmén gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = approval_voting(votelist, 2) + print() + print("Approval voting gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) + print("Sequential Phragmén with post processing gives") + print_result(nomlist, elected_candidates) + + +def nominating_and_rewards(): + votelist = [ + ("10", 1000, ["10"]), + ("20", 1000, ["20"]), + ("30", 1000, ["30"]), + ("40", 1000, ["40"]), + ('2', 1000, ['10', '20', '30']), + ('4', 1000, ['10', '20', '40']), + ] + print("Votes ", votelist) + nomlist, elected_candidates = seq_phragmén(votelist, 2) + print("Sequential Phragmén gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = approval_voting(votelist, 2) + print() + print("Approval voting gives") + print_result(nomlist, elected_candidates) + nomlist, elected_candidates = seq_phragmén_with_postprocessing(votelist, 2) + print("Sequential Phragmén with post processing gives") + print_result(nomlist, elected_candidates) class electiontests(unittest.TestCase): - def testexample1_phragmén(self): - vote_list = [ - ("A", 10.0, ["X", "Y"]), - ("B", 20.0, ["X", "Z"]), - ("C", 30.0, ["Y", "Z"])] - nomlist, elected_candidates = seq_phragmén(vote_list, 2) - self.assertEqual(elected_candidates[0].valiid, "Z") - self.assertAlmostEqual(elected_candidates[0].score, 0.02) - self.assertEqual(elected_candidates[1].valiid, "Y") - self.assertAlmostEqual(elected_candidates[1].score, 0.04) - - def test_example1_approval(self): - vote_list = [ - ("A", 10.0, ["X", "Y"]), - ("B", 20.0, ["X", "Z"]), - ("C", 30.0, ["Y", "Z"])] - nomlist, elected_candidates = approval_voting(vote_list, 2) - self.assertEqual(elected_candidates[0].valiid, "Z") - self.assertAlmostEqual(elected_candidates[0].approval_stake, 50.0) - self.assertEqual(elected_candidates[1].valiid, "Y") - self.assertAlmostEqual(elected_candidates[1].approval_stake, 40.0) + def testexample1_phragmén(self): + vote_list = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + nomlist, elected_candidates = seq_phragmén(vote_list, 2) + self.assertEqual(elected_candidates[0].valiid, "Z") + self.assertAlmostEqual(elected_candidates[0].score, 0.02) + self.assertEqual(elected_candidates[1].valiid, "Y") + self.assertAlmostEqual(elected_candidates[1].score, 0.04) + + def test_example1_approval(self): + vote_list = [ + ("A", 10.0, ["X", "Y"]), + ("B", 20.0, ["X", "Z"]), + ("C", 30.0, ["Y", "Z"])] + nomlist, elected_candidates = approval_voting(vote_list, 2) + self.assertEqual(elected_candidates[0].valiid, "Z") + self.assertAlmostEqual(elected_candidates[0].approval_stake, 50.0) + self.assertEqual(elected_candidates[1].valiid, "Y") + self.assertAlmostEqual(elected_candidates[1].approval_stake, 40.0) if __name__ == "__main__": - if len(sys.argv) == 3 and sys.argv[2] == "test": - unittest.main() - else: - example1() + if len(sys.argv) == 3 and sys.argv[2] == "test": + unittest.main() + else: + example3() \ No newline at end of file