### Install Development Dependencies Source: https://github.com/comsoc-community/trivoting/blob/main/README.md Install the necessary dependencies for developing the trivoting package. This command ensures all required tools and libraries are available in your environment. ```shell pip install -e ".[dev]" ``` -------------------------------- ### Install Trivoting using pip Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/installation.rst Use this command to install the Trivoting package from PyPI. Ensure you are using pip3. ```shell pip3 install trivoting ``` -------------------------------- ### Get Support Dictionary Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns a dictionary mapping each alternative to its net support score across all ballots in the profile. ```python def support_dict(self) -> dict[Alternative, int]: res = dict() for ballot, count in self.items(): for alt in ballot.approved: if alt in res: res[alt] += count else: res[alt] = count for alt in ballot.disapproved: if alt in res: res[alt] -= count else: res[alt] = -count return res ``` -------------------------------- ### DisapprovalLinearTax Initialization Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/tax_rules.html Demonstrates how to initialize the DisapprovalLinearTax using its class method. This ensures proper setup with the required weight parameter. ```python class DisapprovalLinearTax(TaxFunction): """ Disapproval linear tax function for which the cost of a project is equal to its disapproval multiplied by a fixed factor. """ def __init__( self, profile: AbstractTrichotomousProfile, max_size_selection: int, weight=None, class_method_call=False, ): if not class_method_call: raise RuntimeError( "To create a disapproval linear tax, use the initialize() class method instead of using the class itself." ) TaxFunction.__init__(self, profile, max_size_selection) self.weight = weight @classmethod def initialize( cls, weight: Numeric ) -> Callable[AbstractTrichotomousProfile, int, DisapprovalLinearTax]: def constructor( profile: AbstractTrichotomousProfile, max_size_selection: int ) -> DisapprovalLinearTax: return cls( profile, max_size_selection, weight=weight, class_method_call=True ) return constructor def preprocess(self) -> None: self.preprocessed_data["disapp_scores"] = self.profile.disapproval_score_dict() def tax_alternative(self, alternative: Alternative) -> Numeric | None: return 1 + self.weight * self.preprocessed_data["disapp_scores"][alternative] ``` -------------------------------- ### Tie-Breaking Rule Examples Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Demonstrates the usage of different tie-breaking rules for ordering alternatives or selecting a single alternative. ```python from trivoting.tiebreaking import lexico_tie_breaking, support_tie_breaking, app_score_tie_breaking # Offers order() or untie() to either order alternatives # or single out an alternative # Lexicographic tie-breaking based on name order_alts = lexico_tie_breaking.order(profile, alt_set) alt = lexico_tie_breaking.untie(profile, alt_set) # Tie-breaking based on support of an alternative order_alts = support_tie_breaking.order(profile, alt_set) # Tie-breaking based on the approval score of an alternative alt = app_score_tie_breaking.untie(profile, alt_set) ``` -------------------------------- ### Get Selection Size Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Demonstrates how to get the count of selected alternatives and the total count of selected and rejected alternatives from a Selection object. ```python # Count how many alternatives are selected len(selection) # Count total number of selected + rejected alternatives selection.total_len() ``` -------------------------------- ### Tax Calculation Example Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/tax_rules.html Illustrates a basic tax calculation where the support for an alternative is determined by subtracting disapproval scores from approval scores. Returns a fraction if support is positive, otherwise None. ```python app_score = self.preprocessed_data["app_scores"][alternative] disapp_score = self.preprocessed_data["disapp_scores"][alternative] support = app_score - disapp_score if support > 0: return frac(app_score, support) return None ``` -------------------------------- ### Create Fractions Source: https://github.com/comsoc-community/trivoting/blob/main/docs/usage.html Demonstrates how to create fractions using the `frac` and `str_as_frac` functions. It shows defining fractions from integers, floats, and strings. Ensure fractions are defined using `frac()` to avoid potential errors. ```python from trivoting.fractions import frac, str_as_frac # Define a fraction fraction = frac(1, 4) # Define a fraction from an integer fraction_from_int = frac(2) # Define a fraction from a float fraction_from_float = frac(2.6) # Define a fraction from a string fraction_from_str = str_as_frac("2.3") ``` -------------------------------- ### Creating and Comparing Alternatives Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Demonstrates how to create Alternative objects and how their equality and comparison are based on their names. Useful for representing election options. ```python from trivoting.election import Alternative # Creating alternatives a1 = Alternative("Option A") a2 = Alternative("Option B") a3 = Alternative("Option C") # Alternatives are compared based on their names print(a1 == "Option A") # True print(a1 == a2) # False # They can be used in sets and as dictionary keys alternatives_set = {a1, a2} print(a3 in alternatives_set) # False # Sorting alternatives is based on name sorted_alts = sorted([a2, a1, a3]) print(sorted_alts) # ['Option A', 'Option B', 'Option C'] ``` -------------------------------- ### Max Net Support ILP Builder Initialization Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/max_net_support.html This snippet demonstrates the initialization of the MaxNetSupportILPBuilder, which is used for optimizing selections with the Integer Linear Programming (ILP) solver. It takes various parameters to configure the optimization process. ```python ilp_builder = MaxNetSupportILPBuilder( profile, max_size_selection, initial_selection, max_seconds=max_seconds, verbose=verbose, ) try: return ilp_optimiser_rule(ilp_builder, resoluteness=resoluteness) except ILPNotOptimalError as e: raise RuntimeError("Max Net Support ILP did not converge.") from e ``` -------------------------------- ### Create and Inspect a Selection (Implicit Rejection) Source: https://github.com/comsoc-community/trivoting/blob/main/docs/usage.html Demonstrates creating a Selection object with implicit rejection and checking the number of selected and total alternatives. ```python from trivoting.election import Alternative, Selection a1 = Alternative("a1") a2 = Alternative("a2") a3 = Alternative("a3") # Implicit rejection (default): everything not selected is rejected selection = Selection(selected=[a1]) # Count how many alternatives are selected len(selection) # Count total number of selected + rejected alternatives selection.total_len() ``` -------------------------------- ### Getting the length of TrichotomousProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns the number of ballots in the profile. ```python def __len__(self): return len(self._ballots_list) ``` -------------------------------- ### Build GitHub Documentation Source: https://github.com/comsoc-community/trivoting/blob/main/README.md Build documentation specifically for GitHub deployment. This command prepares the documentation files to be pushed to the GitHub repository. ```shell make github ``` -------------------------------- ### Get Total Number of Alternatives Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/selection.html Calculates and returns the combined count of both selected and rejected alternatives. ```python def total_len(self) -> int: """ Get the total number of alternatives (selected and rejected). Returns ------- int Total count of selected and rejected alternatives. """ return len(self.selected) + len(self.rejected) ``` -------------------------------- ### Fraction Definition and Conversion Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Shows how to define fractions using the `frac` function and convert them from integers, floats, or strings. ```python from trivoting.fractions import frac, str_as_frac # Define a fraction fraction = frac(1, 4) # Define a fraction from an integer fraction_from_int = frac(2) # Define a fraction from a float fraction_from_int = frac(2.6) # Define a fraction from a string ``` -------------------------------- ### Get Number of Ballots Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns the total number of ballots in the profile. This is a simple utility function for profile size. ```python def num_ballots(self) -> int: return len(self) ``` -------------------------------- ### Create and Inspect a Selection (Explicit Rejection) Source: https://github.com/comsoc-community/trivoting/blob/main/docs/usage.html Demonstrates creating a Selection object with explicit rejection and checking selection/rejection status. ```python from trivoting.election import Alternative, Selection a1 = Alternative("a1") a2 = Alternative("a2") a3 = Alternative("a3") # Explicit rejection selection_explicit = Selection(selected=[a1], rejected=[a2, a3], implicit_reject=False) selection_explicit.is_selected(a1) # True selection_explicit.is_rejected(a2) # True selection_explicit.is_rejected(a3) # True ``` -------------------------------- ### Selection.total_len Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/selection.html Gets the total number of alternatives, including both selected and rejected ones. This method is part of the Selection class. ```APIDOC ## Selection.total_len ### Description Gets the total number of alternatives (selected and rejected). ### Method (Not specified, likely a Python method call) ### Returns * **int** - Total count of selected and rejected alternatives. ``` -------------------------------- ### Calculate Support for All Alternatives Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Generates a dictionary mapping each alternative to its net support score. This is useful for comparing support across multiple alternatives efficiently. ```python def support_dict(self) -> defaultdict[Alternative, int]: res = defaultdict(int) for ballot in self: for alt in ballot.approved: res[alt] += 1 for alt in ballot.disapproved: res[alt] -= 1 return res ``` -------------------------------- ### Build HTML Documentation Source: https://github.com/comsoc-community/trivoting/blob/main/README.md Generate the HTML documentation locally. This command compiles the Sphinx source files into a browsable HTML format. ```shell make html ``` -------------------------------- ### Get Number of Ballots (Alias) Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html An alias for the `total` method, returning the total number of ballots in the profile, including multiplicities. ```python def num_ballots(self) -> int: return self.total() ``` -------------------------------- ### Get Disapproval Score Dictionary Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns a defaultdict mapping each alternative to its total disapproval score across all ballots in the profile. ```python def disapproval_score_dict(self) -> defaultdict[Alternative, int]: res = defaultdict(int) for ballot, count in self.items(): for alt in ballot.disapproved: res[alt] += count return res ``` -------------------------------- ### Initialize Selection Variables Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/ilp_schemes.html Initializes binary variables for each alternative, indicating whether it is selected. Assumes self.vars['selection'] exists. ```python def init_selection_vars(self): """Initialises the selections variables. Other function assumes that self.vars["selection"] exists and correspond to the variables indicating whether an alternative is selected or not. """ self.vars["selection"] = { alt: LpVariable(f"y_{alt.name}", cat=LpBinary) for alt in self.profile.alternatives } ``` -------------------------------- ### Get Approval Score Dictionary Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns a defaultdict mapping each alternative to its total approval score across all ballots in the profile. ```python def approval_score_dict(self) -> defaultdict[Alternative, int]: res = defaultdict(int) for ballot, count in self.items(): for alt in ballot.approved: res[alt] += count return res ``` -------------------------------- ### Initialize and Use TrichotomousProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Demonstrates initializing a TrichotomousProfile with multiple ballots and alternatives. Shows how to access, append, extend, and iterate over the ballots within the profile. ```python from trivoting.election.alternative import Alternative from trivoting.election.trichotomous_ballot import TrichotomousBallot from trivoting.election.trichotomous_profile import TrichotomousProfile # Define alternatives a = Alternative("a") b = Alternative("b") c = Alternative("c") # Create ballots ballot1 = TrichotomousBallot(approved=[a, b], disapproved=[c]) ballot2 = TrichotomousBallot(approved=[b], disapproved=[a]) # Initialize profile profile = TrichotomousProfile([ballot1, ballot2, ballot1, ballot2], alternatives=[a, b, c]) # Access ballots (behaves like a list) b_at_pos_1 = profile[1] b_at_pos_1_to_3 = profile[1:3] profile.append(ballot1) profile.extend([ballot1, ballot2]) # Iterate over ballots for ballot in profile: print(ballot) ``` -------------------------------- ### Get Ballot Multiplicity Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns the number of times a specific ballot appears in the profile. This indicates the ballot's weight or count. ```python def multiplicity(self, ballot: FrozenTrichotomousBallot) -> int: """ Returns the multiplicity of a given ballot in the profile. Parameters ---------- ballot : FrozenTrichotomousBallot The ballot whose multiplicity is requested. Returns ------- int The number of times the ballot appears in the profile. """ return self[ballot] ``` -------------------------------- ### NetSupportThieleScore ILP Builder Initialization Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/thiele.html Initializes variables for the NetSupportThieleScore ILP. It creates 'sat_vars' for each ballot and sets up constraints based on approved and disapproved alternatives. ```python def init_vars(self) -> None: super().init_vars() self.vars["sat_vars"] = {} for i, ballot in enumerate(self.profile): sat_vars = { k: LpVariable(f"s_{i}_{k}", lowBound=-1, upBound=1, cat=LpInteger) for k in range(1, len(self.profile.alternatives) + 1) } self.vars["sat_vars"][i] = sat_vars # Constraints self.model += lpSum(sat_vars.values()) == ( lpSum(self.vars["selection"][alt] for alt in ballot.approved) - lpSum(self.vars["selection"][alt] for alt in ballot.disapproved) ) ``` -------------------------------- ### frac() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/reference/fractions.html Instantiates a fraction using the module defined by the FRACTION constant. It accepts one or two numeric arguments. If more than two arguments are provided, an error will occur. ```APIDOC ## frac() ### Description Returns a fraction instantiated from the module defined by the FRACTION constant. If more than two numbers are provided, an error is raised. ### Parameters #### Path Parameters - **arg** (int | float | mpq) - Required - One or two numbers. ### Returns - **Numeric** - The fraction. ### Return Type Numeric ``` -------------------------------- ### Get Disapproved Alternatives from Frozen Ballot Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_ballot.html Provides read-only access to the tuple of disapproved alternatives in a FrozenTrichotomousBallot. This property ensures immutability. ```python @property def disapproved(self) -> tuple[Alternative, ...]: """Tuple of disapproved alternatives.""" return self._disapproved ``` -------------------------------- ### Get Approved Alternatives from Frozen Ballot Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_ballot.html Provides read-only access to the tuple of approved alternatives in a FrozenTrichotomousBallot. This property ensures immutability. ```python @property def approved(self) -> tuple[Alternative, ...]: """Tuple of approved alternatives.""" return self._approved ``` -------------------------------- ### tax_pb_instance Source: https://github.com/comsoc-community/trivoting/blob/main/docs/reference/rules/index.html Constructs a Participatory Budgeting (PB) instance and PB profile from a trichotomous profile. It translates the trichotomous voting profile into a PB instance, setting project costs inversely proportional to net support. ```APIDOC ## tax_pb_instance ### Description Constructs a Participatory Budgeting (PB) instance and PB profile from a trichotomous profile. This function translates the trichotomous voting profile into a PB instance, setting project costs inversely proportional to net support. ### Method N/A (Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **profile** (_AbstractTrichotomousProfile_) – The trichotomous profile. * **max_size_selection** (_int_) – The budget limit or maximum number of alternatives to be selected. * **initial_selection** (_Selection or None, optional_) – An initial selection fixing some alternatives as selected or rejected. * **tax_function** (_type[TaxFunction], optional_) – A tax function defined as a subclass of the `TaxFunction` class. Defaults to `TaxKraiczy2025`. ### Returns * _pb_election.Instance_ – The generated PB instance containing projects. * _pb_election.ApprovalMultiProfile_ – The PB profile created from approval ballots derived from the trichotomous profile. * _dict_ – A mapping from PB projects back to the original alternatives. ``` -------------------------------- ### Get Total Number of Ballots Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Computes the total number of ballots in the profile, considering their multiplicities. This method is re-implemented for compatibility with Python versions older than 3.10. ```python def total(self): """ Computes the total number of ballots in the profile, counting multiplicities. Returns ------- int Total number of ballots. """ # Re-implemented as it is not available in Python <3.10 return sum(self.values()) ``` -------------------------------- ### Generate All Feasible Selections Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Illustrates how to generate all feasible selections for a given profile, specifying the maximum size of the selection. This is useful for multiwinner election scenarios. ```python for selection in profile.all_feasible_selections(2): print(selection) ``` -------------------------------- ### Define Fractions using trivoting.fractions Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Create fractions using the `frac()` and `str_as_frac()` functions for precise handling. It is recommended to use these utilities to avoid potential issues. ```python from trivoting.fractions import frac, str_as_frac # Define a fraction fraction = frac(1, 4) # Define a fraction from an integer fraction_from_int = frac(2) # Define a fraction from a float fraction_from_int = frac(2.6) # Define a fraction from a string fraction_from_str = str_as_frac("2.3") ``` -------------------------------- ### Get Alternative by Name Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Retrieves an alternative object from the profile's set of alternatives using its name. Returns None if no alternative matches the given name. ```python def get_alternative_by_name(self, alt_name: str) -> Alternative | None: """ Retrieves an alternative by its name. Parameters ---------- alt_name : str The name of the alternative. Returns ------- Alternative | None The alternative with the given name. None if there is no such alternative. """ for alt in self.alternatives: if alt.name == alt_name: return alt ``` -------------------------------- ### init_vars() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html Initializes general variables within the ILPBuilder. ```APIDOC ## init_vars() ### Description Initializes the general variables for the Integer Linear Programming (ILP) model. ### Method Belongs to the `ILPBuilder` class. ``` -------------------------------- ### index(_value_[, _start_[, _stop_]]) Source: https://github.com/comsoc-community/trivoting/blob/main/docs/reference/election/index.html Returns the index of the first occurrence of a value in the TrichotomousProfile. Supports optional start and stop arguments for searching within a slice. ```APIDOC ## index(_value_[, _start_[, _stop_]]) ### Description Returns the first index of value. Raises ValueError if the value is not present. Supporting start and stop arguments is optional, but recommended. ### Parameters - **_value_**: The value to find the index of. - **_start_** (optional): The starting index for the search. - **_stop_** (optional): The stopping index for the search. ### Returns The index of the first occurrence of the value. ``` -------------------------------- ### Get Ballot Multiplicity Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Returns the multiplicity of a given ballot. Note: This implementation always returns 1 for computational efficiency, regardless of the ballot's actual presence. ```python def multiplicity(self, ballot: TrichotomousBallot) -> int: """ Returns the multiplicity of a ballot in the profile. Note: This implementation returns 1 for any ballot regardless of its presence in the profile, to save computation time. Parameters ---------- ballot : TrichotomousBallot The ballot whose multiplicity is inquired. Returns ------- int The multiplicity of the ballot, always 1. """ return 1 ``` -------------------------------- ### tax_pb_instance Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/tax_rules.html Constructs a Participatory Budgeting (PB) instance and profile from a trichotomous voting profile. It sets project costs inversely proportional to net support, using a specified tax function. ```APIDOC ## tax_pb_instance ### Description Translates a trichotomous voting profile into a Participatory Budgeting (PB) instance. Project costs are determined by a tax function, which is inversely proportional to the net support for each alternative. ### Parameters - **profile** (AbstractTrichotomousProfile) - The input trichotomous profile. - **max_size_selection** (int) - The budget limit or maximum number of alternatives that can be selected. - **initial_selection** (Selection or None, optional) - An optional initial selection that fixes certain alternatives as selected or rejected. - **tax_function** (type[TaxFunction], optional) - A tax function class (subclass of `TaxFunction`). Defaults to `TaxKraiczy2025`. ### Returns - **pb_election.Instance** - The generated PB instance containing projects with calculated costs. - **pb_election.ApprovalMultiProfile** - The PB profile created from approval ballots derived from the trichotomous profile. - **dict** - A mapping from PB projects back to the original alternatives. ``` -------------------------------- ### Calculate Support for an Alternative Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Calculates the net support for a specific alternative by summing approvals and subtracting disapprovals across all ballots. Use this to get a single score for an alternative. ```python def support(self, alternative: Alternative) -> int: score = 0 for ballot in self: if alternative in ballot.approved: score += 1 elif alternative in ballot.disapproved: score -= 1 return score ``` -------------------------------- ### support_dict Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Calculates the support for all alternatives and returns them as a dictionary. ```APIDOC ## support_dict ### Description Calculates the support for all alternatives and returns them as a dictionary where keys are alternatives and values are their support scores. ### Method `support_dict() -> defaultdict[Alternative, int]` ### Returns - **defaultdict[Alternative, int]** - A dictionary mapping each alternative to its support score. ``` -------------------------------- ### Get Multiplicity of a Ballot in MultiProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Retrieves the multiplicity (number of occurrences) of a specific frozen ballot within a TrichotomousMultiProfile. This helps understand how many voters submitted the same ballot. ```python multiplicity = multi_profile.multiplicity(frozen_ballot1) ``` -------------------------------- ### trivoting.rules.tax_rules.tax_pb_instance() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html Creates an instance for tax calculation using the PB method. This function is in the trivoting.rules.tax_rules module. ```APIDOC ## tax_pb_instance() ### Description Creates an instance for tax calculations using the PB method. ### Method (Function call) ### Endpoint N/A (Python function) ### Parameters None explicitly documented in the provided text. ### Request Example N/A ### Response (Details not provided in the source text) ``` -------------------------------- ### Get Length of Trichotomous Ballot Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_ballot.html Returns the total count of alternatives across both approved and disapproved sets. Use to determine the total number of alternatives considered in the ballot. ```python def __len__(self): """ Return the total number of alternatives in the ballot (both approved and disapproved). Returns ------- int """ return len(self.approved) + len(self.disapproved) ``` -------------------------------- ### tax_pb_instance Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/reference/rules/index.md Constructs a Participatory Budgeting (PB) instance and profile from a trichotomous profile. It translates the trichotomous voting profile into a PB instance, setting project costs inversely proportional to net support. ```APIDOC ## tax_pb_instance(profile: AbstractTrichotomousProfile, max_size_selection: int, initial_selection: Selection | None = None, tax_function: type[TaxFunction] = None) -> tuple[Instance, ApprovalMultiProfile, dict[Project, Alternative]] ### Description Constructs a Participatory Budgeting (PB) instance and profile from a trichotomous profile. This function translates the trichotomous voting profile into a PB instance, setting project costs inversely proportional to net support. ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Parameters * **profile** (AbstractTrichotomousProfile) - The trichotomous profile. * **max_size_selection** (int) - The budget limit or maximum number of alternatives to be selected. * **initial_selection** (Selection | None) - Optional. An initial selection fixing some alternatives as selected or rejected. * **tax_function** (type[TaxFunction] | None) - Optional. A tax function defined as a subclass of the `TaxFunction` class. Defaults to `TaxKraiczy2025`. ### Returns * pb_election.Instance - The generated PB instance containing projects. * pb_election.ApprovalMultiProfile - The PB profile created from approval ballots derived from the trichotomous profile. * dict - A mapping from PB projects back to the original alternatives. ``` -------------------------------- ### Instantiate Fraction using `frac` function Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/fractions.html Creates a fraction based on the `FRACTION` constant. Accepts one or two numeric arguments. Raises ValueError for invalid `FRACTION` values or incorrect argument counts. ```python def frac(*arg: Numeric) -> Numeric: """ Returns a fraction instantiated from the module defined by the `FRACTION` constant. If more than two numbers are provided, an error is raised. Parameters ---------- Numeric One or two numbers. Returns ------- Numeric The fraction. """ if len(arg) == 1: if FRACTION == GMPY_FRAC: return mpq(arg[0]) elif FRACTION == FLOAT_FRAC: return arg[0] else: raise ValueError( f"The current value of pabutools.fractions.FRACTION '{FRACTION}' is invalid, it needs to be in " "[gmpy2, float]." ) elif len(arg) == 2: if FRACTION == GMPY_FRAC: return mpq(arg[0], arg[1]) elif FRACTION == FLOAT_FRAC: return arg[0] / arg[1] else: raise ValueError( f"The current value of pabutools.fractions.FRACTION '{FRACTION}' is invalid, it needs to be in " "[gmpy2, float]." ) raise ValueError("frac can only take 1 or 2 arguments") ``` -------------------------------- ### TrichotomousMultiProfile.support() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html Calculates the support for a given alternative within a multi-profile context. This is a method of the TrichotomousMultiProfile class. ```APIDOC ## support() ### Description Calculates the support for an alternative within a multi-profile. ### Method (Implicitly a method call on a TrichotomousMultiProfile instance) ### Endpoint N/A (Python method) ### Parameters None explicitly documented in the provided text. ### Request Example N/A ### Response (Details not provided in the source text) ``` -------------------------------- ### ILPBuilder class Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html A class for building Integer Linear Programming models. ```APIDOC ## ILPBuilder ### Description Class responsible for constructing Integer Linear Programming (ILP) models. ### Location `trivoting.rules.ilp_schemes` ``` -------------------------------- ### AbstractTrichotomousProfile Initialization Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Initializes the AbstractTrichotomousProfile with a set of alternatives and an optional maximum selection size. Handles cases where alternatives are not provided. ```python from __future__ import annotations from abc import ABC, abstractmethod from collections import Counter, defaultdict from collections.abc import ( Iterable, MutableSequence, MutableMapping, Iterator, Collection, ) from itertools import product from trivoting.election.alternative import Alternative from trivoting.election.selection import Selection from trivoting.election.trichotomous_ballot import ( TrichotomousBallot, AbstractTrichotomousBallot, FrozenTrichotomousBallot, ) from trivoting.fractions import Numeric from trivoting.utils import generate_subsets, generate_two_list_partitions class AbstractTrichotomousProfile(ABC, Iterable[AbstractTrichotomousBallot]): """ Abstract class representing a profile, i.e., a collection of ballots. This class is only meant to be inherited and provides a common interface for trichotomous profiles. Attributes ---------- alternatives : set[Alternative] The set of all alternatives in the profile. max_size_selection : int or None The maximum number of alternatives that can be selected in a feasible selection (optional). """ def __init__( self, alternatives: Iterable[Alternative] = None, max_size_selection: int = None ): if alternatives is None: self.alternatives = set() else: self.alternatives = set(alternatives) self.max_size_selection = max_size_selection ``` -------------------------------- ### Create and Use TrichotomousMultiProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Demonstrates how to create a TrichotomousMultiProfile by freezing ballots and adding them with multiplicities. It also shows how to access ballot multiplicities and modify the profile. ```python from trivoting.election.trichotomous_ballot import FrozenTrichotomousBallot from trivoting.election.trichotomous_profile import TrichotomousMultiProfile # Freeze ballots to make them hashable and usable in multiprofiles frozen_ballot1 = ballot1.freeze() frozen_ballot2 = ballot2.freeze() # Initialize multiprofile with multiple copies of ballots multi_profile = TrichotomousMultiProfile([frozen_ballot1, frozen_ballot1, frozen_ballot2], alternatives=[a, b, c]) # Multiplicity of a specific ballot multiplicity = multi_profile.multiplicity(frozen_ballot1) # Acces the ballots (behaves like a dict) profile[ballot1] = 3 profile[ballot2] += 1 # Iterate over ballots for ballot in multi_profile: print(ballot) ``` -------------------------------- ### Initialize and Use TrichotomousMultiProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs/usage.html Shows how to create a TrichotomousMultiProfile using frozen ballots and manage ballot multiplicities. This is efficient for profiles with many identical ballots. ```python from trivoting.election.trichotomous_ballot import FrozenTrichotomousBallot from trivoting.election.trichotomous_profile import TrichotomousMultiProfile # Assuming 'ballot1' and 'ballot2' are already defined TrichotomousBallot instances # and 'a', 'b', 'c' are Alternative instances from the previous example. # Freeze ballots to make them hashable and usable in multiprofiles frozen_ballot1 = ballot1.freeze() frozen_ballot2 = ballot2.freeze() # Initialize multiprofile with multiple copies of ballots multi_profile = TrichotomousMultiProfile([frozen_ballot1, frozen_ballot1, frozen_ballot2], alternatives=[a, b, c]) # Multiplicity of a specific ballot multiplicity = multi_profile.multiplicity(frozen_ballot1) # Acces the ballots (behaves like a dict) # Note: The following lines modify the 'profile' object from the previous example, not 'multi_profile'. # To modify multi_profile, you would use its specific methods or re-initialization. # profile[ballot1] = 3 # profile[ballot2] += 1 # Iterate over ballots for ballot in multi_profile: print(ballot) ``` -------------------------------- ### cat_instance_to_trichotomous_profile Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/reference/election/index.md Converts a PrefLib CategoricalInstance into a trichotomous profile. The PrefLib instance should have 1, 2 or 3 categories. ```APIDOC ## cat_instance_to_trichotomous_profile(cat_instance: CategoricalInstance) ### Description Converts a PrefLib CategoricalInstance into a trichotomous profile. The PrefLib instance should have 1, 2 or 3 categories. If there is a single categories, it is assumed to represent the approved alternatives. If there are 2 categories, it is assumed that they represent the approved and neutral alternatives. In case of 3 categories, the categories are assumed to represent approved, neutral and disapproved alternatives, in that order. Each ballot in the categorical instance is converted using cat_preferences_to_trichotomous_ballot. ### Parameters #### Path Parameters * **cat_instance** (CategoricalInstance) - Required - A parsed categorical instance from PrefLib. ### Returns A multi-profile composed of trichotomous ballots. ### Return type [TrichotomousMultiProfile](#trivoting.election.trichotomous_profile.TrichotomousMultiProfile) ``` -------------------------------- ### Run Unit Tests Source: https://github.com/comsoc-community/trivoting/blob/main/README.md Execute the unit tests for the trivoting package. This command is used to verify the correctness of the code and identify any regressions. ```shell python -m unittest ``` -------------------------------- ### init_selection_vars() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html Initializes selection variables within the ILPBuilder. ```APIDOC ## init_selection_vars() ### Description Initializes the variables related to selections in the Integer Linear Programming (ILP) model. ### Method Belongs to the `ILPBuilder` class. ``` -------------------------------- ### ILPSolver Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/ilp_schemes.html Enumerates the different solvers available for ILP. ```APIDOC ## ILPSolver ### Description Enumerates the different solvers available. ### Enum Members * **HIGHS**: HiGHS: open-source software to solve linear programming * **CBC**: Cbc (Coin-or branch and cut) is an open-source mixed integer linear programming solver ``` -------------------------------- ### Initialize TrichotomousMultiProfile Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/trichotomous_profile.html Initializes a TrichotomousMultiProfile with an optional iterable of ballots, alternatives, and max selection size. It can also inherit these from an existing profile. ```python def __init__( self, init: Iterable[FrozenTrichotomousBallot] = (), *, alternatives: Iterable[Alternative] = None, max_size_selection: int = None, ) -> None: self._ballots_counter = Counter(init) if alternatives is None and isinstance(init, AbstractTrichotomousProfile): alternatives = init.alternatives if max_size_selection is None and isinstance(init, AbstractTrichotomousProfile): max_size_selection = init.max_size_selection AbstractTrichotomousProfile.__init__(self, alternatives, max_size_selection) ``` -------------------------------- ### Constructing Participatory Budgeting Instance Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/tax_rules.html This function translates a trichotomous voting profile into a Participatory Budgeting (PB) instance. Project costs are set inversely proportional to net support, using a specified tax function. ```python def tax_pb_instance( profile: AbstractTrichotomousProfile, max_size_selection: int, initial_selection: Selection | None = None, tax_function: type[TaxFunction] = None, ) -> tuple[ pb_election.Instance, pb_election.ApprovalMultiProfile, dict[pb_election.Project, Alternative], ]: """ Construct a Participatory Budgeting (PB) instance and PB profile from a trichotomous profile. This function translates the trichotomous voting profile into a PB instance, setting project costs inversely proportional to net support. Parameters ---------- profile : AbstractTrichotomousProfile The trichotomous profile. max_size_selection : int The budget limit or maximum number of alternatives to be selected. initial_selection : Selection or None, optional An initial selection fixing some alternatives as selected or rejected. tax_function: type[TaxFunction], optional A tax function defined as a subclass of the :py:class:`TaxFunction` class. Defaults to :py:class:`TaxKraiczy2025`. Returns ------- pb_election.Instance The generated PB instance containing projects. pb_election.ApprovalMultiProfile The PB profile created from approval ballots derived from the trichotomous profile. dict A mapping from PB projects back to the original alternatives. """ if initial_selection is None: initial_selection = Selection() if tax_function is None: tax_function = TaxKraiczy2025 tax_function = tax_function(profile, max_size_selection) alt_to_project = dict() project_to_alt = dict() running_alternatives = set() pb_instance = pb_election.Instance( budget_limit=max_size_selection - len(initial_selection) ) for alt in profile.alternatives: if alt not in initial_selection: cost = tax_function.tax_alternative(alt) if cost is not None: project = pb_election.Project( alt.name, cost=tax_function.tax_alternative(alt) ) pb_instance.add(project) running_alternatives.add(alt) alt_to_project[alt] = project project_to_alt[project] = alt pb_profile = pb_election.ApprovalMultiProfile(instance=pb_instance) for ballot in profile: pb_profile.append( pb_election.FrozenApprovalBallot( alt_to_project[alt] for alt in ballot.approved if alt in running_alternatives ) ) return pb_instance, pb_profile, project_to_alt ``` -------------------------------- ### Head Pre Assets Macro Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_static/webpack-macros.html Macro for preloading head assets. It's currently a placeholder. ```html {% macro head_pre_assets() %} {% endmacro %} ``` -------------------------------- ### Apply Tax Method of Equal Shares Wrapper Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Use a specialized wrapper for the tax-based participatory budgeting rule, specifically the method of equal shares. This simplifies the application of tax-based rules. ```python from trivoting.rules import tax_method_of_equal_shares from trivoting.tiebreaking import lexico_tie_breaking ``` -------------------------------- ### Max Net Support Rule Implementation Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/max_net_support.html This snippet shows the core logic for the Max Net Support rule when resoluteness is True. It calculates alternative scores and iteratively selects alternatives with positive net support up to a specified maximum size. ```python def max_net_support( profile: AbstractTrichotomousProfile, max_size_selection: int, initial_selection: Selection = None, resoluteness: bool = True, ) -> Selection | list[Selection]: """ Compute the selections maximising the total net support of the voters by sequentially selecting up to `max_size_selection` alternatives with positive highest net support. The net support of an alternative is the number of voters approving of it minus the number of voters disapproving of it. Parameters ---------- profile : AbstractTrichotomousProfile The trichotomous profile. max_size_selection : int Maximum number of alternatives to select. initial_selection : Selection, optional An initial selection that fixes some alternatives as selected or rejected. If `implicit_reject` is True, no alternatives are fixed to be rejected. resoluteness : bool, optional If True, returns a single selection (resolute). If False, returns all tied optimal selections (irresolute). Defaults to True. Returns ------- Selection | list[Selection] The selection if resolute (:code:`resoluteness == True`), or a list of selections if irresolute (:code:`resoluteness == False`). """ if not resoluteness: raise NotImplementedError( "Max Net Support does not yet support resoluteness=False." ) alt_scores = profile.support_dict() if initial_selection is None: selection = Selection(implicit_reject=True) else: selection = initial_selection for alt, score in sorted(alt_scores.items(), key=lambda x: x[1], reverse=True): if len(selection) >= max_size_selection: break if score > 0: selection.add_selected(alt) return selection ``` -------------------------------- ### Configure Fraction Handling Backend Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Change the `FRACTION` constant to select the backend for fraction arithmetic. The default is 'gmpy2', but it can be switched to 'float'. ```python import trivoting.fractions # The default value pabutools.fractions.FRACTION = "gmpy2" # Change to Python float pabutools.fractions.FRACTION = "float" ``` -------------------------------- ### Parse PrefLib File to Trichotomous Profile Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/election/preflib.html Parses a PrefLib file into a TrichotomousMultiProfile. It uses `preflibtools.get_parsed_instance` and supports only categorical instances with 1-3 categories. Raises a ValueError for unsupported instance types. ```python def parse_preflib(file_path: str) -> TrichotomousMultiProfile: """ Parses a PrefLib file and returns the corresponding trichotomous profile. The file is parsed using `preflibtools.get_parsed_instance`, and only categorical instances with 1–3 categories are supported. Parameters ---------- file_path : str The file path to a PrefLib categorical instance. Returns ------- TrichotomousMultiProfile A trichotomous multi-profile built from the given file. """ instance = get_parsed_instance(file_path, autocorrect=True) if isinstance(instance, CategoricalInstance): return cat_instance_to_trichotomous_profile(instance) raise ValueError( f"PrefLib instances of type {type(instance)} cannot be converted to trichotomous profiles." ) ``` -------------------------------- ### Apply Max Net Support Rule (ILP Version) Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Use the Integer Linear Programming (ILP) version of the Max Net Support rule, primarily for debugging and comparison. This outcome can also be computed as a Thiele rule. ```python from trivoting.rules.max_net_support import max_net_support_ilp from trivoting.rules.thiele import NetSupportThieleScore from trivoting.rules import thiele selection = max_net_support_ilp(profile, max_size_selection=3) selection_same = thiele(profile, max_size_selection=3, thiele_score_class=NetSupportThieleScore) ``` -------------------------------- ### Parse PaBuLib Participatory Budgeting Profiles Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Demonstrates parsing participatory budgeting profiles from PaBuLib format into Trivoting's profile objects. The budget limit is stored in the 'max_size_selection' attribute. ```python from trivoting.election import parse_pabulib profile = parse_pabulib("path/to/preflib_file.pb") print(profile.max_size_selection) # The budget limit is saved as 'max_size_selection' ``` -------------------------------- ### PAVScoreKraiczy2025 ILP Builder Initialization Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_modules/trivoting/rules/thiele.html Initializes variables for the ILP solver for PAVScoreKraiczy2025, including satisfaction variables for each ballot and alternative. ```python def init_vars(self) -> None: super().init_vars() self.vars["sat_vars"] = dict() for i, ballot in enumerate(self.profile): sat_vars = dict() for k in range(1, len(self.profile.alternatives) + 1): sat_vars[k] = LpVariable(f"s_{i}_{k}", cat=LpBinary) self.vars["sat_vars"][i] = sat_vars # Constraint them to ensure proper counting for i, ballot in enumerate(self.profile): self.model += lpSum(self.vars["sat_vars"][i].values()) == lpSum( self.vars["selection"][alt] for alt in ballot.approved ) + lpSum(1 - self.vars["selection"][alt] for alt in ballot.disapproved) ``` -------------------------------- ### frac Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/reference/fractions.md Instantiates a fraction from the module defined by the FRACTION constant. It accepts one or two numeric arguments. ```APIDOC ## frac(*arg: int | float | mpq) -> int | float | mpq ### Description Returns a fraction instantiated from the module defined by the FRACTION constant. If more than two numbers are provided, an error is raised. ### Parameters * **Numeric** – One or two numbers. ### Returns The fraction. ### Return type [*Numeric*](#trivoting.fractions.Numeric) ``` -------------------------------- ### Set Document Mode and Theme Source: https://github.com/comsoc-community/trivoting/blob/main/docs/search.html Sets the document's mode and theme based on local storage, defaulting to 'light' if not found. This is typically run on page load. ```javascript document.documentElement.dataset.mode = localStorage.getItem("mode") || "light"; document.documentElement.dataset.theme = localStorage.getItem("theme") || "light"; ``` -------------------------------- ### TrichotomousMultiProfile.support_dict() Source: https://github.com/comsoc-community/trivoting/blob/main/docs/genindex.html Returns a dictionary of supports for alternatives within a multi-profile. This method belongs to the TrichotomousMultiProfile class. ```APIDOC ## support_dict() ### Description Returns a dictionary mapping alternatives to their support values within a multi-profile. ### Method (Implicitly a method call on a TrichotomousMultiProfile instance) ### Endpoint N/A (Python method) ### Parameters None explicitly documented in the provided text. ### Request Example N/A ### Response (Details not provided in the source text) ``` -------------------------------- ### Use Specialized Tax-Based Rules Source: https://github.com/comsoc-community/trivoting/blob/main/docs-source/source/usage.md Convenience wrappers for adapting specific PB rules with tax functions. Use tax_method_of_equal_shares for the method of equal shares and tax_sequential_phragmen for sequential Phragmen. ```python from trivoting.rules import tax_method_of_equal_shares from trivoting.tiebreaking import lexico_tie_breaking selection = tax_method_of_equal_shares( profile, max_size_selection=5, resoluteness=False, tie_breaking=lexico_tie_breaking ) ``` -------------------------------- ### Generate All Subprofiles Source: https://github.com/comsoc-community/trivoting/blob/main/docs/_sources/usage.rst Demonstrates how to generate all possible subprofiles from both normal and multi-profiles. This is useful for analyzing subsets of voter preferences. ```python for subprofile in profile.all_sub_profiles(): print(subprofile) for sub_multi_profile in multi_profile.all_sub_profiles(): print(sub_multi_profile) ```