Skip to content

Plurality veto major rework#325

Merged
peterrrock2 merged 12 commits intomggg:3.4.0from
ross-i:plurality-veto
Feb 28, 2026
Merged

Plurality veto major rework#325
peterrrock2 merged 12 commits intomggg:3.4.0from
ross-i:plurality-veto

Conversation

@ross-i
Copy link
Copy Markdown
Contributor

@ross-i ross-i commented Feb 11, 2026

Overhauled PluralityVeto.
Bug fix: now considers unranked candidates as tied for last place, and thus able to be vetoed.
Various optimizations, most importantly relying on profile.df instead of duplicated Ballot objects to conduct election. For deterministic tiebreak, approximately 50-60x faster than previous implementation (testing on a 3-candidate election with 26k voters; was ~2.8s, now <0.05s). For random tiebreak, only about 8-10x faster.
Refactored significantly for readability. Corrected existing documentation and added thorough documentation and comments.
Updated tests for PluralityVeto.

m (number of seats) now defaults to 1.
Now supports tiebreak = 'random', 'first_place', 'borda', and 'lex'.
tiebreak is no longer permitted to be None. The default value is 'first_place', and the backup tiebreak is always 'lex', i.e., lexicographic/alphabetical.
Because PluralityVeto requires tiebreaking at the ballot level (rather than round level), PluralityVeto does not report tiebreaks to ElectionState. However, a new attribute tiebreak_order allows users to inspect the tiebreak order when using a non-random tiebreak method.

Matthew Rossi added 4 commits February 11, 2026 11:00
Bug fix: now considers unranked candidates as tied for last place, and thus able to be vetoed.
Various optimizations, most importantly relying on profile.df instead of duplicated Ballot objects
to conduct election. For deterministic tiebreak, approximately 50-60x faster than previous
implementation (testing on a 3-candidate election with 26k voters; was ~2.8s, now <0.05s). For
random tiebreak, only about 8-10x faster.
Now supports `tiebreak` = 'random', 'first_place', 'borda', and 'lex'.
`tiebreak` is no longer permitted to be `None`. The default value is 'first_place', and the backup
tiebreak is always 'lex', i.e., lexicographic/alphabetical.
Because PluralityVeto requires tiebreaking at the ballot level (rather than round level),
PluralityVeto does not report tiebreaks to ElectionState. However, a new attribute `tiebreak_order`
allows users to inspect the tiebreak order when using a non-random tiebreak method.
Refactored significantly for readability. Corrected existing documentation and added thorough
documentation and comments.
@ross-i ross-i marked this pull request as draft February 13, 2026 18:29
@ross-i ross-i marked this pull request as ready for review February 26, 2026 21:29
Copy link
Copy Markdown
Collaborator

@peterrrock2 peterrrock2 left a comment

Choose a reason for hiding this comment

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

This is looking great!

Small nit: I am trying to unify the doc string style accoss the repository. Can you modify the doc strings to look more like:

def  foo( arg1: str | None, arg2: int = 3) -> str:
    """
    Brief description (max 100 chars including indents)

    More details (max 100 chars per line, but as many lines as you would like)

    Example: 
        <Stuff goes here. This section is optional>

    Args:
        arg1 (str | None): description
        arg2 (int, optional): description. Defaults to 3.

    Returns:
        str: The string "baz"
    """
   ...

This is a mild modification of the Google-style doc string and adheres to the PEP 257 recommendation but with the line width modified to 100 chars rather than 80 (better for 16:9 screens IMO)

@ross-i
Copy link
Copy Markdown
Contributor Author

ross-i commented Feb 28, 2026

This is looking great!

Small nit: I am trying to unify the doc string style accoss the repository. Can you modify the doc strings to look more like:

def  foo( arg1: str | None, arg2: int = 3) -> str:
    """
    Brief description (max 100 chars including indents)

    More details (max 100 chars per line, but as many lines as you would like)

    Example: 
        <Stuff goes here. This section is optional>

    Args:
        arg1 (str | None): description
        arg2 (int, optional): description. Defaults to 3.

    Returns:
        str: The string "baz"
    """
   ...

This is a mild modification of the Google-style doc string and adheres to the PEP 257 recommendation but with the line width modified to 100 chars rather than 80 (better for 16:9 screens IMO)

Not a small nit at all: the docstrings definitely needed some love! Check it out now.

Copy link
Copy Markdown
Collaborator

@peterrrock2 peterrrock2 left a comment

Choose a reason for hiding this comment

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

Looks good!

@peterrrock2 peterrrock2 merged commit 4027651 into mggg:3.4.0 Feb 28, 2026
4 of 5 checks passed
@peterrrock2 peterrrock2 mentioned this pull request Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants