ProfileOrdinal

class poisson_approval.ProfileOrdinal(d_ranking_share, d_weak_order_share=None, normalization_warning=True, well_informed_voters=True, ratio_fanatic=0, voting_rule='Approval', symbolic=False)[source]

An ordinal profile of preference.

Parameters:
  • d_ranking_share (dict) – E.g. {'abc': 0.4, 'cab': 0.3}. d_ranking_share['abc'] is the probability that a voter prefers candidate a, then candidate b, then candidate c.
  • d_weak_order_share (dict) – E.g. {'a~b>c': 0.2, 'a>b~c': 0.1}. d_weak_order_share['a~b>c'] is the probability that a voter likes candidates a and b equally and prefer them to candidate c.
  • normalization_warning (bool) – Whether a warning should be issued if the input distribution is not normalized.
  • well_informed_voters (bool.) – If True (default), it is the usual model. If False, voters “see” only the candidates’ expected scores and believe that the scores follow independent Poisson distributions. This option has an effect only for Approval (neither for Plurality nor Anti-plurality).
  • ratio_fanatic (Number) – The ratio of fanatic voters, in the interval [0, 1]. This is used for tau().
  • voting_rule (str) – The voting rule. Possible values are APPROVAL, PLURALITY and ANTI_PLURALITY.
  • symbolic (bool) – Whether the computations are symbolic or numeric.

Notes

If the input distribution d_ranking_share is not normalized, the profile will be normalized anyway and a warning is issued (unless normalization_warning is False).

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> profile
ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(3, 5), 'cab': Fraction(3, 10)})
>>> print(profile)
<abc: 1/10, bac: 3/5, cab: 3/10> (Condorcet winner: b)
>>> profile.abc
Fraction(1, 10)
>>> profile.d_ranking_share['abc']  # Alternate syntax for profile.abc
Fraction(1, 10)
>>> profile.weighted_maj_graph
array([[0, Fraction(-1, 5), Fraction(2, 5)],
       [Fraction(1, 5), 0, Fraction(2, 5)],
       [Fraction(-2, 5), Fraction(-2, 5), 0]], dtype=object)
>>> profile.condorcet_winners
Winners({'b'})
>>> profile.is_profile_condorcet
1.0
>>> profile.has_majority_favorite  # Is one candidate 'top' in a majority of ballots?
True
>>> profile.has_majority_ranking  # Does one ranking represent a majority of ballots?
True
>>> profile.is_single_peaked  # Is the profile single-peaked?
True
>>> profile.support_in_rankings
{'abc', 'bac', 'cab'}
>>> profile.is_generic_in_rankings  # Are all rankings there?
False
>>> profile.analyzed_strategies_ordinal
Equilibria:
<abc: a, bac: b, cab: ac> ==> b (FF)
<abc: a, bac: ab, cab: c> ==> a (D)
<BLANKLINE>
Utility-dependent equilibrium:
<abc: ab, bac: b, cab: c> ==> b (FF)
<BLANKLINE>
Non-equilibria:
<abc: a, bac: b, cab: c> ==> b (FF)
<abc: a, bac: ab, cab: ac> ==> a (D)
<abc: ab, bac: b, cab: ac> ==> b (FF)
<abc: ab, bac: ab, cab: c> ==> a, b (FF)
<abc: ab, bac: ab, cab: ac> ==> a (D)
>>> print(profile.analyzed_strategies_ordinal.equilibria[0])
<abc: a, bac: b, cab: ac> ==> b
>>> print(profile.analyzed_strategies_ordinal.winners_at_equilibrium)
a, b

The profile can include weak orders:

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10)},
...                          d_weak_order_share={'c>a~b': Fraction(3, 10)})
>>> profile
ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(3, 5)}, d_weak_order_share={'c>a~b': Fraction(3, 10)})
>>> print(profile)
<abc: 1/10, bac: 3/5, c>a~b: 3/10> (Condorcet winner: b)
abc

Share of voters with this ranking.

Type:Number
acb

Share of voters with this ranking.

Type:Number
analyzed_strategies(strategies)

Analyze a list of strategies for the profile.

Parameters:strategies (iterable) – An iterator of strategies, such as a list of strategies.
Returns:The analyzed strategies of the profile.
Return type:AnalyzedStrategies

Examples

Cf. ProfileOrdinal.analyzed_strategies_ordinal().

analyzed_strategies_group

Analyzed group strategies.

Cf. analyzed_strategies() and strategies_group. This is implemented only for profiles where we consider that there is a natural notion of group, such as ProfileNoisyDiscrete.

Type:AnalyzedStrategies
analyzed_strategies_ordinal

Analyzed ordinal strategies.

Cf. analyzed_strategies() and strategies_ordinal.

Type:AnalyzedStrategies
analyzed_strategies_pure

Analyzed pure strategies.

Cf. analyzed_strategies() and strategies_pure. This is implemented only for discrete profiles such as ProfileTwelve or ProfileDiscrete.

Type:AnalyzedStrategies
bac

Share of voters with this ranking.

Type:Number
bca

Share of voters with this ranking.

Type:Number
best_responses_to_strategy(d_ranking_best_response)

Convert best responses to a StrategyThreshold.

Parameters:d_ranking_best_response (dict) – Key: ranking. Value: BestResponse.
Returns:The conversion of the best responses into a strategy. Only the rankings present in this profile are mentioned in the strategy.
Return type:StrategyThreshold
cab

Share of voters with this ranking.

Type:Number
cba

Share of voters with this ranking.

Type:Number
condorcet_winners

Condorcet winner(s).

Type:Winners
contains_rankings

Whether the profile contains some rankings.

Type:bool
contains_weak_orders

Whether the profile contains some weak orders.

Type:bool
d_ballot_share_weak_voters_fanatic

Ballot shares due to the weak orders if they vote fanatically

Voters of the type 'a>b~c':

  • In Approval or Plurality, they vote for a.
  • In Anti-plurality, half of them vote for ab (i.e. against c) and half of them vote for ac (i.e. against b).

Voters of the type 'a~b>c':

  • In Approval or Plurality, half of them vote for a and half of them vote for b.
  • In Anti-plurality, they vote for ab (i.e. against c).
Type:dict
d_ballot_share_weak_voters_sincere

Ballot shares due to the weak orders if they vote sincerely

Voters of the type 'a>b~c':

  • In Approval or Plurality, they vote for a.
  • In Anti-plurality, half of them vote for ab (i.e. against c) and half of them vote for ac (i.e. against b).

Voters of the type 'a~b>c':

  • In Approval or Anti-plurality, they vote for ab (i.e. against c).
  • In Plurality, half of them vote for a and half of them vote for b.
Type:dict
distribution_equilibria(test=None)[source]

Distribution of numbers of equilibria (depending on the utilities).

Parameters:test (callable) – A function StrategyOrdinal -> bool that gives a condition on the strategy. Default: always True.
Returns:A list that represents an histogram. The distribution of number of equilibria (meeting the test condition).
Return type:list

Notes

The result is exact (not based on a Monte-Carlo estimation).

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> profile.distribution_equilibria()
array([0.        , 0.        , 0.86290531, 0.13709469])
distribution_winners(test=None)[source]

Distribution of the number of equilibrium winners (depending on the utilities).

Parameters:test (callable) – A function StrategyOrdinal -> bool that gives a condition on the strategy. Default: always True.
Returns:A list that represents an histogram. The distribution of number of possible equilibrium winner (with strategies that meet the test condition).
Return type:list

Notes

The result is exact (not based on a Monte-Carlo estimation).

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> profile.distribution_winners()
array([0, 0, 1, 0])
has_majority_favorite

Whether there is a majority favorite (a candidate ranked first by strictly more than half of the voters).

Type:bool
has_majority_ranking

Whether there is a majority ranking (a ranking shared by strictly more than half of the voters).

Type:bool
is_equilibrium(strategy)[source]

Whether a strategy is an equilibrium.

Parameters:strategy (StrategyOrdinal) – A strategy that specifies at least all the rankings that are present in the profile.
Returns:Whether strategy is an equilibrium in this profile.
Return type:EquilibriumStatus

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> strategy = StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'})
>>> profile.is_equilibrium(strategy)
EquilibriumStatus.EQUILIBRIUM
is_generic_in_rankings

Whether the profile is generic in rankings (contains all rankings).

Type:bool
is_profile_condorcet

Whether the profile is Condorcet. 1. means there is a strict Condorcet winner, 0.5 means there are one or more weak Condorcet winner(s), 0. means there is no Condorcet winner.

Type:float
is_single_peaked

Whether the profile is single-peaked.

Type:bool
is_standardized

Whether the profile is standardized. Cf. standardized_version().

Type:bool
classmethod order_and_label(t)[source]

Order and label of a discrete type.

Cf. Profile.order_and_label().

Examples

>>> ProfileOrdinal.order_and_label('abc')
('abc', '$r(abc)$')
>>> ProfileOrdinal.order_and_label('a~b>c')
('a~b>c', '$r(a\\sim b>c)$')
classmethod order_and_label_weak(t)

Auxiliary function for order_and_label(), specialized for weak orders.

Parameters:t (object) – A weak order of the form 'a>b~c' or 'a~b>c'.
Returns:
  • order (str) – The weak order itself.
  • label (str) – The label to be used for the corner of the triangle.

Examples

>>> Profile.order_and_label_weak('a~b>c')
('a~b>c', '$r(a\\sim b>c)$')
proba_equilibrium(test=None)[source]

Probability that an equilibrium exists (depending on the utilities).

Parameters:test (callable) – A function StrategyOrdinal -> bool that gives a condition on the strategy. Default: always True.
Returns:The probability that an equilibrium strategy exists, that meets the test condition.
Return type:float

Notes

The result is exact (not based on a Monte-Carlo estimation).

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> profile.proba_equilibrium()
1
random_tau_undominated()

Random tau based on undominated ballots.

This is used, for example, in ProfileCardinal.iterated_voting().

Returns:A random tau-vector. Independently for each ranking, a proportion uniformly drawn in [0, 1] of voters use one undominated ballot, and the rest use the other undominated ballot. For example, in Approval voting, voters with ranking abc are randomly split between ballots a and ab.
Return type:TauVector
standardized_version

Standardized version of the profile (makes it unique, up to permutations of the candidates).

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> profile.standardized_version
ProfileOrdinal({'abc': Fraction(3, 5), 'bac': Fraction(1, 10), 'cba': Fraction(3, 10)})
>>> profile.is_standardized
False
Type:ProfileOrdinal
strategies_group

group strategies of the profile.

Yields:Strategy – All possible group strategies of the profile. This is implemented only for profiles where we consider that there is a natural notion of group, such as ProfileNoisyDiscrete.

Examples

Cf. ProfileNoisyDiscrete.

Type:Iterator
strategies_ordinal

ordinal strategies of the profile.

Yields:StrategyOrdinal – All possible ordinal strategies for this profile.

Examples

Cf. ProfileOrdinal.

Type:Iterator
strategies_pure

pure strategies of the profile.

Yields:Strategy – All possible pure strategies of the profile. This is implemented only for discrete profiles such as ProfileTwelve or ProfileDiscrete.

Examples

Cf. ProfileDiscrete.

Type:Iterator
support_in_rankings

Support of the profile (in terms of rankings).

Type:SetPrintingInOrder of str
support_in_weak_orders

Support of the profile (in terms of weak orders).

Type:SetPrintingInOrder of str
tau(strategy)[source]

Tau-vector associated to a strategy, with partial fanatic voting.

Parameters:strategy (an argument accepted by tau_strategic()) –
Returns:A share ratio_fanatic of voters vote only for their top candidate, and the rest of the voters vote strategically (in the sense of tau_strategic()). In other words, this tau-vector is the barycenter of tau_fanatic and tau_strategic(strategy), with respective weights self.ratio_fanatic and 1 - self.ratio_fanatic.
Return type:TauVector

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> strategy = StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'})
>>> tau = profile.tau(strategy)
>>> print(tau)
<a: 1/10, ab: 3/5, c: 3/10> ==> a
>>> τ = profile.τ(strategy)  # Alternate syntax
>>> print(τ)
<a: 1/10, ab: 3/5, c: 3/10> ==> a
tau_fanatic

Tau-vector associated to fanatic voting.

Returns:In Approval or Plurality, all voters approve of their top candidate only. In Anti-Plurality, they all disapprove of their bottom candidate, i.e. they approve their two first candidates.
Return type:TauVector
tau_strategic(strategy)[source]

Tau-vector associated to a strategy.

Parameters:strategy (StrategyOrdinal) – A strategy that specifies at least all the rankings that are present in the profile.
Returns:Tau-vector associated to this profile and strategy strategy.
Return type:TauVector

Examples

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)})
>>> strategy = StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'})
>>> tau_strategic = profile.tau_strategic(strategy)
>>> print(tau_strategic)
<a: 1/10, ab: 3/5, c: 3/10> ==> a

In the case of approval with badly informed voters, we do as if the tau-vector were the vector of scores (up to a renormalization):

>>> from fractions import Fraction
>>> profile = ProfileOrdinal({'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)},
...                          well_informed_voters=False)
>>> strategy = StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'})
>>> tau_strategic = profile.tau_strategic(strategy)
>>> print(tau_strategic)
<a: 7/16, b: 3/8, c: 3/16> ==> a
weighted_maj_graph

Weighted majority graph.

Type:np.ndarray
τ(strategy)

Tau-vector (alternate notation).

Parameters:strategy (Strategy) – A strategy that specifies at least all the rankings that are present in the profile.
Returns:Tau-vector associated to this profile and strategy strategy.
Return type:TauVector