From b4f56e2ab72b9d1563835067136911c0cd3ab417 Mon Sep 17 00:00:00 2001 From: endolith Date: Sat, 1 Aug 2026 16:05:53 -0400 Subject: [PATCH] feat(studies): promote approval_at_optimal to a public rated-method helper Rename the private _approval_at_optimal wrapper to public approval_at_optimal with a default tiebreaker, so scripts can reference it directly in rated_methods mappings instead of repeating a lambda. Split 2 of 3 from #56, stacked on #52. --- elsim/studies/__init__.py | 7 ++++++- elsim/studies/condorcet_metrics.py | 13 ++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/elsim/studies/__init__.py b/elsim/studies/__init__.py index 918e04a6..5f7f5dad 100644 --- a/elsim/studies/__init__.py +++ b/elsim/studies/__init__.py @@ -13,7 +13,11 @@ """ from .backends import JoblibBackend, SerialBackend -from .condorcet_metrics import merrill_1984_comparison_methods, tally_condorcet_agreement +from .condorcet_metrics import ( + approval_at_optimal, + merrill_1984_comparison_methods, + tally_condorcet_agreement, +) from .parameters import expand_product, expand_rows, expand_zip from .runner import merge_counters, run_batched from .social_utility import ( @@ -31,6 +35,7 @@ "merge_counters", "run_batched", "merrill_1984_comparison_methods", + "approval_at_optimal", "tally_condorcet_agreement", "spatial_random_reference_utility_updates", "random_society_utility_updates", diff --git a/elsim/studies/condorcet_metrics.py b/elsim/studies/condorcet_metrics.py index 6916a5b9..344dc54f 100644 --- a/elsim/studies/condorcet_metrics.py +++ b/elsim/studies/condorcet_metrics.py @@ -19,7 +19,14 @@ RatedMethod = Callable[..., Optional[int]] -def _approval_at_optimal(utilities: np.ndarray, tiebreaker: str) -> Optional[int]: # noqa: UP045 +def approval_at_optimal(utilities: np.ndarray, tiebreaker: str = "random") -> Optional[int]: # noqa: UP045 + """ + Rated-method helper: build an optimal approval ballot, then apply :func:`elsim.methods.approval`. + + Intended for use in a ``rated_methods`` mapping passed to + :func:`tally_condorcet_agreement` or the spatial sweep helpers, so scripts + stay declarative without repeating lambdas. + """ return approval(approval_optimal(utilities), tiebreaker) @@ -44,7 +51,7 @@ def merrill_1984_comparison_methods() -> tuple[dict[str, RankedMethod], dict[str } rated_methods: dict[str, RatedMethod] = { "SU max": utility_winner, - "Approval": _approval_at_optimal, + "Approval": approval_at_optimal, } return ranked_methods, rated_methods @@ -76,7 +83,7 @@ def tally_condorcet_agreement( Returns ------- collections.Counter - Includes key ``\"CW\"`` when a Condorcet winner exists, plus one key per + Includes key ``"CW"`` when a Condorcet winner exists, plus one key per supplied method name when that method's winner matches the Condorcet winner. """