Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/vse_sim/methods/borda.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@


class Borda(Method):
"""Implement Borda count with larger rank values representing preference.

Honest ballots assign consecutive scores from least to most preferred.
Comment on lines +8 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Clarify how ranks map to preferences and scores to avoid confusion with conventional Borda.

The phrases "larger rank values representing preference" and "consecutive scores from least to most preferred" are unclear, especially since classical Borda typically treats smaller ranks as more preferred. If this implementation reverses that convention (e.g., 0 = least preferred and higher values = more preferred), please state that explicitly and add a brief example ballot to illustrate the ranking and scoring direction for readers familiar with standard Borda.

Ranked methods also inherit this class's ballot construction and strategy
helpers.
"""

candScore = staticmethod(mean)

nRanks = 999 # infinity
Expand Down
7 changes: 6 additions & 1 deletion src/vse_sim/methods/bullety_approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@


def BulletyApprovalWith(bullets=0.5, asClass=False):
"""Create approval voting with a configurable share of bullet voters.


Each honest ballot is either ordinary normalized approval or a bullet vote
for all utility-maximizing candidates. ``bullets`` is the probability of
Comment on lines 8 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Tighten the description of how bullets is interpreted and any expected range.

The current docstring doesn’t specify the expected range for bullets or how the probability is applied. Please clarify that bullets is a float in [0, 1] and that it’s applied independently per honest ballot (e.g., “bullets is the independent probability that an honest voter casts a bullet ballot rather than a normalized approval ballot”). This will help avoid misconfiguration.

bullet voting.
"""

class BulletyApproval((Score(1,True))):
"""Implement the configured mixture of approval and bullet voting."""

bulletiness = bullets

Expand Down
7 changes: 7 additions & 0 deletions src/vse_sim/methods/irnr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@


class IRNR(RankedMethod):
"""Implement Instant Runoff Normalized Ratings.

In each round, every ballot is normalized by the absolute ratings of its
remaining candidates. The candidate with the lowest normalized total is
eliminated until one remains.
"""

stratMax = 10

stratTargetFor = Method.stratTarget3 # strategize in favor of third place, because second place is pointless (can't change pairwise)
Expand Down
8 changes: 5 additions & 3 deletions src/vse_sim/methods/irv.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@


class Irv(Method):
"""
IRV.
"""Implement Instant-Runoff Voting over complete ranked ballots.

High numbers are good for both results and votes (pretty sure).
Ballots are candidate-aligned rank vectors where larger values indicate
stronger preference. Tabulation repeatedly eliminates the candidate with
the fewest active first preferences and returns candidate-aligned finish
scores, again with larger values preferred.
"""

stratTargetFor = Method.stratTarget3
Expand Down
7 changes: 4 additions & 3 deletions src/vse_sim/methods/irv_prime.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@


class IrvPrime(Irv):
"""
IRV Prime.
"""Implement IRV Prime, preserving pairwise challengers during elimination.

See https://electowiki.org/wiki/IRV_Prime
The classic IRV winner and candidates that defeat it pairwise are protected
until all other candidates have been eliminated. See
https://electowiki.org/wiki/IRV_Prime.
"""

stratTargetFor = Method.stratTarget3
Expand Down
6 changes: 5 additions & 1 deletion src/vse_sim/methods/mav.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ def toVote(cutoffs, util):


class Mav(Method):
"""Majority Approval Voting.
"""Implement Majority Approval Voting with five ordered grades.

Honest ballots map utilities through election-scoped percentile cutoffs.
Candidates are ordered by their median grade with a fractional tiebreak
derived from support above that grade.
"""

bias5 = 1.0970202515275356
Expand Down
6 changes: 6 additions & 0 deletions src/vse_sim/methods/mj.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@


class Mj(Mav):
"""Implement Majority Judgment using Mav's five-grade ballots.

Candidate scores refine the median grade according to the balance of
grades immediately above and below the median.
"""

def candScore(self, scores):
"""This formula will always give numbers within 0.5 of the raw median.
Unfortunately, with 5 grade levels, these will tend to be within 0.1 of
Expand Down
5 changes: 5 additions & 0 deletions src/vse_sim/methods/plurality.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@


class Plurality(RankedMethod):
"""Implement plurality voting with one vote for each voter's favorite.

Ballots are binary candidate-aligned vectors: the favorite receives one
and every other candidate receives zero.
"""

nRanks = 2

Expand Down
6 changes: 6 additions & 0 deletions src/vse_sim/methods/ranked_pairs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@


class Rp(Schulze):
"""Implement Ranked Pairs using Schulze's pairwise tallying interface.

Pairwise victories are considered from strongest to weakest and locked
unless doing so would contradict an already locked path.
"""

def resolveCycle(self, cmat, n):
"""Note: mutates cmat destructively.

Expand Down
7 changes: 7 additions & 0 deletions src/vse_sim/methods/schulze.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@


class Schulze(RankedMethod):
"""Implement the Schulze strongest-path Condorcet method.

Candidate pairs are compared by ballot rank, then cycles are resolved by
comparing the strongest paths through the pairwise preference graph.
Deterministic candidate-index tiebreaks produce candidate-aligned scores.
"""

def resolveCycle(self, cmat, n):

beatStrength = [[0] * n for _ in range(n)]
Expand Down
8 changes: 7 additions & 1 deletion src/vse_sim/methods/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@


def Score(topRank=10, asClass=False):
"""Create a score voting method with ratings from zero through ``topRank``.

Honest ballots linearly normalize each voter's utilities to the configured
scale. By default the factory returns a method instance; ``asClass=True``
returns the generated class for use by related method factories.
"""

class Score0to(Method):
"""Score voting, 0-10.
"""Implement score voting on the scale configured by :func:`Score`.


Strategy establishes pivots
Expand Down
8 changes: 7 additions & 1 deletion src/vse_sim/methods/srv.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@


def Srv(topRank=10):
"""Score Runoff Voting
"""Create Score Runoff Voting on a zero-through-``topRank`` scale.

The two highest score totals advance to a pairwise runoff. Candidate
results remain candidate-aligned scores, with a runoff upset represented
by placing the pairwise winner just above the score winner.

>>> Srv().resultsFor(DeterministicModel(3)(5,3),Irv().honBallot)["results"]
[0.8, 1.2, 1.21]
>>> Srv().results([[0,1,2]])[2]
Expand All @@ -27,6 +32,7 @@ def Srv(topRank=10):
score0to = Score(topRank,True)

class Srv0to(score0to):
"""Implement Score Runoff Voting on the factory's configured scale."""

stratTargetFor = Method.stratTarget3

Expand Down
8 changes: 8 additions & 0 deletions src/vse_sim/methods/v321.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@


class V321(Mav):
"""Implement 3-2-1 Voting with three-level candidate ratings.

The three candidates with the most top ratings advance, the candidate with
the most bottom ratings is removed, and the remaining pair is compared
head-to-head. Result values encode the complete candidate ordering used by
the simulator.
"""

baseCuts = [-.1,.8]
specificPercentiles = [45, 75]

Expand Down