Skip to content

Commit

Permalink
Merge pull request #93 from wesholliday/main
Browse files Browse the repository at this point in the history
Fixed bugs in positive involvement and smith axioms. Added Preliminary Weighted Condorcet
  • Loading branch information
epacuit authored May 3, 2024
2 parents 6610bd2 + 5c28732 commit 05fcaae
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 4 deletions.
9 changes: 8 additions & 1 deletion docs/source/other_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ Other Methods
```



## Kemeny-Young

```{eval-rst}
Expand All @@ -28,6 +27,14 @@ Other Methods
```

## Preliminary Weighted Condorcet

```{eval-rst}
.. autofunction:: pref_voting.other_methods.preliminary_weighted_condorcet
```

## Bucklin

```{eval-rst}
Expand Down
4 changes: 2 additions & 2 deletions pref_voting/dominance_axioms.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def has_smith_violation(edata, vm, verbose=False):
s_set = smith_set(edata)
ws = vm(edata)

winners_not_in_smith = [w not in s_set for w in ws]
winners_not_in_smith = [w for w in ws if w not in s_set]
if len(winners_not_in_smith) > 0:
if verbose:
if type(edata) == Profile or type(edata) == ProfileWithTies:
Expand Down Expand Up @@ -259,7 +259,7 @@ def find_all_smith_violations(edata, vm, verbose=False):
s_set = smith_set(edata)
ws = vm(edata)

winners_not_in_smith = [w not in s_set for w in ws]
winners_not_in_smith = [w for w in ws if w not in s_set]
if len(winners_not_in_smith) > 0:
if verbose:
if type(edata) == Profile or type(edata) == ProfileWithTies:
Expand Down
49 changes: 49 additions & 0 deletions pref_voting/other_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,53 @@ def kemeny_young(profile, curr_cands = None):

return sorted(list(set([r[0] for r in ky_rankings])))


@vm("Preliminary Weighted Condorcet")
def preliminary_weighted_condorcet(prof, curr_cands = None, show_orders = False, require_positive_plurality_score = False):
"""The preliminary version of the Weighted Condorcet Rule in Tideman's book, Collective Decisions and Voting (p. 223). The winners are the candidates ranked first by some linear order of the candidates with highest score, where the score of an order (c_1,...,c_n) is the sum over all i<j of the margin of c_i vs. c_j multiplied by the plurality scores of c_i and c_j.
The multiplication by plurality scores is what distinguishes this method from the Kemeny-Young method.
Tideman (p. 224) defines a more complicated Weighted Condorcet rule that is intended to be used when some candidates receive zero first-place votes.
Args:
prof (Profile): An anonymous profile of linear orders on a set of candidates
curr_cands (List[int], optional): If set, then find the winners for the profile restricted to the candidates in ``curr_cands``
show_orders (bool): If True, then print the set of best orders.
require_positive_plurality_score (bool): If True, then require that all candidates have a positive plurality score.
Returns:
A sorted list of candidates
"""

cands = curr_cands if curr_cands is not None else prof.candidates

if require_positive_plurality_score:
assert all([prof.plurality_scores(curr_cands=curr_cands)[c] > 0 for c in cands]), "All candidates must have a positive plurality score."

best_order_score = 0
best_orders = []

for r in permutations(cands):

score_of_r = 0
for i in r[:-1]:
for j in r[r.index(i)+1:]:
score_of_r += (prof.plurality_scores(curr_cands=curr_cands)[i] * prof.plurality_scores(curr_cands=curr_cands)[j] * prof.margin(i,j))

if score_of_r > best_order_score:
best_order_score = score_of_r
best_orders = [r]
if score_of_r == best_order_score:
best_orders.append(r)

if show_orders == True:
print(f"Best orders: {set(best_orders)}")

winners = [r[0] for r in best_orders]

return list(set(winners))

### Bucklin

@vm(name = "Bucklin")
Expand Down Expand Up @@ -558,6 +605,8 @@ def superior_voting(profile, curr_cands = None):

other_vms = [
kemeny_young,
pareto,
preliminary_weighted_condorcet,
majority,
bucklin,
simplified_bucklin,
Expand Down
2 changes: 1 addition & 1 deletion pref_voting/variable_voter_axioms.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def has_positive_involvement_violation(prof, vm, verbose=False, violation_type="
if uniform_coalition:
for loser in losers:

relevant_ranking_types = [r for r in prof.ranking_types if prof.rankings.count(r) >= coalition_size]
relevant_ranking_types = [r for r in prof.ranking_types if r[0] == loser and prof.rankings.count(r) >= coalition_size]

for r in relevant_ranking_types:

Expand Down

0 comments on commit 05fcaae

Please sign in to comment.