diff --git a/elect.py b/elect.py index 7ebcd12a14c92b64eb70de01dc937c51278363c2..0341a47df5985793732e42a42f83d4d6154857f6 100755 --- a/elect.py +++ b/elect.py @@ -39,13 +39,24 @@ def weak_condorcet_winners(n, candidates): return weak_winners # As defined in section 4 https://citizensassembly.arts.ubc.ca/resources/submissions/csharman-10_0409201706-143.pdf -def schulze_winners(n, candidates): +# + other link strength methods defined in https://arxiv.org/pdf/1804.02973.pdf +def schulze_winners(n, candidates, link_strength_method='margin'): nb_candidates = len(candidates) - p = np.zeros((nb_candidates, nb_candidates), dtype=np.int8) - for i in range(nb_candidates): - for j in range(nb_candidates): - if i != j: - p[i][j] = n[i][j] - n[j][i] + + if link_strength_method == 'margin': + p = np.zeros((nb_candidates, nb_candidates), dtype=np.int8) + for i in range(nb_candidates): + for j in range(nb_candidates): + if i != j: + p[i][j] = n[i][j] - n[j][i] + elif link_strength_method == 'ratio': + p = np.ones((nb_candidates, nb_candidates), dtype=np.int8) * np.Inf + for i in range(nb_candidates): + for j in range(nb_candidates): + if i != j and n[j][i] > 0: + p[i][j] = n[i][j] / n[j][i] + else: + raise ValueError(f"link_strength_method '{link_strength_method}' is not implemented") for i in range(nb_candidates): for j in range(nb_candidates): diff --git a/test_schulze_examples.py b/test_schulze_examples.py index 1272428ce63e528471beacc15e2619d049193d79..13b7aedc564875e57707edef419efed35662f1bf 100644 --- a/test_schulze_examples.py +++ b/test_schulze_examples.py @@ -27,7 +27,8 @@ def test_example1(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['d'] def test_example2(): @@ -50,7 +51,8 @@ def test_example2(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['c'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['c'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['c'] def test_example3(): @@ -77,7 +79,8 @@ def test_example3(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['e'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['e'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['e'] def test_example4(): @@ -99,7 +102,8 @@ def test_example4(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['b', 'd'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['b', 'd'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['b', 'd'] def test_example5(): @@ -122,7 +126,8 @@ def test_example5(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['d'] def test_example6(): @@ -147,7 +152,8 @@ def test_example6(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a', 'c'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a', 'c'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['a', 'c'] def test_example7(): # situation 1 @@ -174,7 +180,8 @@ def test_example7(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['a'] # situation 2 candidates = ['a', 'b', 'c', 'd', 'e', 'f'] @@ -194,7 +201,8 @@ def test_example7(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['d'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['d'] def test_example8(): @@ -222,7 +230,8 @@ def test_example8(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['a'] # situation 2 candidates = ['a', 'b', 'c', 'd', 'e'] @@ -249,7 +258,8 @@ def test_example8(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['b'] def test_example9(): @@ -272,7 +282,8 @@ def test_example9(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['a'] # situation 2 candidates = ['a', 'b', 'c', 'd', 'e'] @@ -294,7 +305,8 @@ def test_example9(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['b'] def test_example10(): candidates = ['a', 'b', 'c', 'd'] @@ -323,7 +335,8 @@ def test_example10(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['b'] #assert False, "TODO: implement other methods to compute strength of link" @@ -352,7 +365,8 @@ def test_example11(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['b'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['b'] def test_example12(): @@ -379,7 +393,8 @@ def test_example12(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['e'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['e'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['e'] def test_example13(): @@ -399,4 +414,5 @@ def test_example13(): assert elect.condorcet_winner(n, candidates) is None assert len(elect.weak_condorcet_winners(n, candidates)) == 0 - assert elect.schulze_winners(n, candidates) == ['a', 'b'] + assert elect.schulze_winners(n, candidates, link_strength_method='margin') == ['a', 'b'] + assert elect.schulze_winners(n, candidates, link_strength_method='ratio') == ['a', 'b']