ProfileHistogram
- class poisson_approval.ProfileHistogram(d_ranking_share, d_ranking_histogram=None, d_weak_order_share=None, normalization_warning=True, ratio_sincere=0, ratio_fanatic=0, voting_rule='Approval', symbolic=False)[source]
A profile of preference with histogram distributions of utility.
- Parameters
d_ranking_share (dict) – E.g.
{'abc': 0.4, 'cab': 0.6}
.d_ranking_share['abc']
is the probability that a voter prefers candidatea
, then candidateb
, then candidatec
.d_ranking_histogram (dict) –
Each key is a ranking, e.g.
'abc'
. Each value is a list that represents a piecewise constant probability density function (PDF) of having a utility u for the middle candidate, e.g.b
. By convention, the list sums to 1 (contrary to the usual convention where the integral of the function would sum to 1).For example, if the list is
[0.4, 0.3, 0.2, 0.1]
, it means that a fraction 0.4 of voters'abc'
have a utility forb
that is in the first quarter, i.e. between 0 and 0.25. These voters are uniformly distributed in this segment.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 candidatesa
andb
equally and prefer them to candidatec
.normalization_warning (bool) – Whether a warning should be issued if the input distribution is not normalized.
ratio_sincere (Number) – The ratio of sincere voters, in the interval [0, 1]. This is used for
tau()
.ratio_fanatic (Number) – The ratio of fanatic voters, in the interval [0, 1]. This is used for
tau()
. The sum of ratio_sincere and ratio_fanatic must not exceed 1.voting_rule (str) – The voting rule. Possible values are
APPROVAL
,PLURALITY
andANTI_PLURALITY
.symbolic (bool) – Whether the computations are symbolic or numeric.
Notes
If the input distribution is not normalized, the profile will be normalized anyway and a warning will be issued (unless normalization_warning is False).
Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> profile ProfileHistogram({'abc': Fraction(1, 10), 'bac': Fraction(3, 5), 'cab': Fraction(3, 10)}, {'abc': array([1]), 'bac': array([1, 0]), 'cab': array([Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)], dtype=object)}) >>> print(profile) <abc: 1/10 [1], bac: 3/5 [1 0], cab: 3/10 [Fraction(2, 3) 0 0 0 0 0 0 0 0 Fraction(1, 3)]> (Condorcet winner: b) >>> profile.abc Fraction(1, 10) >>> profile.d_ranking_share['abc'] # Alternate syntax for profile.abc Fraction(1, 10) >>> profile.d_candidate_welfare {'a': Fraction(71, 200), 'b': Fraction(13, 20), 'c': Fraction(3, 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 >>> strategy = StrategyThreshold({'abc': 0, 'bac': 1, 'cab': Fraction(1, 2)}, profile=profile) >>> print(profile.tau_sincere) <a: 1/20, ab: 1/20, ac: 1/10, b: 3/5, c: 1/5> ==> b >>> print(profile.tau_fanatic) <a: 1/10, b: 3/5, c: 3/10> ==> b >>> print(profile.tau_strategic(strategy)) <ab: 1/10, ac: 1/10, b: 3/5, c: 1/5> ==> b >>> print(profile.tau(strategy)) <ab: 1/10, ac: 1/10, b: 3/5, c: 1/5> ==> b >>> profile.is_equilibrium(strategy) EquilibriumStatus.EQUILIBRIUM >>> profile.analyzed_strategies_group Equilibria: <abc: ab, bac: b, cab: utility-dependent (1/2)> ==> b (FF) <abc: a, bac: ab, cab: c> ==> a (D) <abc: a, bac: b, cab: ac> ==> b (FF) Non-equilibria: <abc: ab, bac: ab, cab: ac> ==> a (D) <abc: ab, bac: ab, cab: utility-dependent (1/2)> ==> a (D) <abc: ab, bac: ab, cab: c> ==> a, b (FF) <abc: ab, bac: b, cab: ac> ==> b (FF) <abc: ab, bac: b, cab: c> ==> b (FF) <abc: a, bac: ab, cab: ac> ==> a (D) <abc: a, bac: ab, cab: utility-dependent (1/2)> ==> a (D) <abc: a, bac: b, cab: utility-dependent (1/2)> ==> b (FF) <abc: a, bac: b, cab: c> ==> b (FF) >>> strategy_ini = StrategyThreshold({'abc': .5, 'bac': .5, 'cab': .5}) >>> cycle = profile.iterated_voting(strategy_ini, 100)['cycle_strategies'] >>> len(cycle) 1 >>> print(cycle[0]) <abc: ab, bac: utility-dependent (0.7199316142046179), cab: utility-dependent (0.28006838579538196)> ==> b >>> limit_strategy = profile.fictitious_play(strategy_ini, 100, perception_update_ratio=1)['strategy'] >>> print(limit_strategy) <abc: ab, bac: utility-dependent (0.7199316142046179), cab: utility-dependent (0.28006838579538196)> ==> b
The profile can include weak orders:
>>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10)}, ... {'abc': [1], 'bac': [1, 0]}, ... d_weak_order_share={'c~a>b': Fraction(3, 10)}) >>> profile ProfileHistogram({'abc': Fraction(1, 10), 'bac': Fraction(3, 5)}, {'abc': array([1]), 'bac': array([1, 0])}, d_weak_order_share={'a~c>b': Fraction(3, 10)}) >>> print(profile) <abc: 1/10 [1], bac: 3/5 [1 0], a~c>b: 3/10> (Condorcet winner: b)
An alternate syntax to define a profile:
>>> profile = ProfileHistogram({ ... ('abc', (1, )): Fraction(1, 10), ('bac', (1, 0)): Fraction(6, 10), ... ('cab', (Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3))): Fraction(2, 10), ... 'a~b>c': Fraction(1, 10) ... }) >>> print(profile) <abc: 1/10 [1], bac: 3/5 [1 0], cab: 1/5 [Fraction(2, 3) 0 0 0 0 0 0 0 0 Fraction(1, 3)], a~b>c: 1/10> (Condorcet winner: b)
- property abc
Share of voters with this ranking.
- Type
Number
- property 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
Examples
- property analyzed_strategies_group
Analyzed group strategies.
Cf.
analyzed_strategies()
andstrategies_group
. This is implemented only for profiles where we consider that there is a natural notion of group, such asProfileNoisyDiscrete
.- Type
- property analyzed_strategies_ordinal
Analyzed ordinal strategies.
Cf.
analyzed_strategies()
andstrategies_ordinal
.- Type
- property analyzed_strategies_pure
Analyzed pure strategies.
Cf.
analyzed_strategies()
andstrategies_pure
. This is implemented only for discrete profiles such asProfileTwelve
orProfileDiscrete
.- Type
- property bac
Share of voters with this ranking.
- Type
Number
- property bca
Share of voters with this ranking.
- Type
Number
- best_responses_to_strategy(tau, ratio_optimistic=None)
Convert best responses to a
StrategyThreshold
.- Parameters
tau (TauVector) – Tau-vector.
ratio_optimistic – The value of ratio_optimistic to use. Default: None (since it is a ProfileCardinalContinuous, we do not care about this value).
- Returns
The conversion of the best responses into a strategy. Only the rankings present in this profile are mentioned in the strategy.
- Return type
- property cab
Share of voters with this ranking.
- Type
Number
- property cba
Share of voters with this ranking.
- Type
Number
- property contains_rankings
Whether the profile contains some rankings.
- Type
bool
- property contains_weak_orders
Whether the profile contains some weak orders.
- Type
bool
Ballot shares due to the weak orders if they vote fanatically.
Voters of type
'a>b~c'
(lovers):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 type
'a~b>c'
(haters):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
Ballot shares due to the weak orders if they vote sincerely.
Voters of type
'a>b~c'
(lovers):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 type
'a~b>c'
(haters):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
dict : Ballot shares due to the weak orders if they vote strategically.
For voters with a weak order, strategic voting is the same as sincere voting, except in two cases:
For voters of type
'a~b>c'
(haters)`in Plurality, who have two dominant strategies: vote for a or b.For voters of type
'a>b~c'
(lovers) in Anti-Plurality, who have two dominant strategies: vote against b or c (i.e. respectively for ac or ab).
- property d_candidate_anti_plurality_welfare
Anti-plurality welfare of each candidate, i.e. share of voters with utility > 0.
- Type
- property d_candidate_plurality_welfare
Plurality welfare of each candidate, i.e. share of voters with utility 1.
- Type
- property d_candidate_relative_anti_plurality_welfare
Relative anti-plurality welfare of each candidate. This is similar to
d_candidate_anti_plurality_welfare
, but renormalized so that the candidate with best welfare has 1 and the one with worst welfare has 0. In math: relative_welfare = (welfare - min_welfare) / (max_welfare - min_welfare). In the case where all candidates have the same welfare, by convention, the relative welfare is 1 for all of them.- Type
- property d_candidate_relative_plurality_welfare
Relative plurality welfare of each candidate. This is similar to
d_candidate_plurality_welfare
, but renormalized so that the candidate with best welfare has 1 and the one with worst welfare has 0. In math: relative_welfare = (welfare - min_welfare) / (max_welfare - min_welfare). In the case where all candidates have the same welfare, by convention, the relative welfare is 1 for all of them.- Type
- property d_candidate_relative_welfare
Relative welfare of each candidate. This is similar to
d_candidate_welfare
, but renormalized so that the candidate with best welfare has 1 and the one with worst welfare has 0. In math: relative_welfare = (welfare - min_welfare) / (max_welfare - min_welfare). In the case where all candidates have the same welfare, by convention, the relative welfare is 1 for all of them.- Type
- property d_candidate_welfare
Welfare of each candidate. E.g.
'a': 0.7
means that candidate'a'
has a welfare (average utility) equal to 0.7 for the voters. Since utilities are in [0, 1], so is the welfare.- Type
Shares of rankings. E.g.
'abc': 0.3
means that a ratio 0.3 of the voters have ranking'abc'
.- Type
dict
Shares of weak orders. E.g.
'a~b>c': 0.3
means that a ratio 0.3 of the voters have weak order'a~b>c'
.- Type
dict
- fictitious_play(init, n_max_episodes, perception_update_ratio=<function one_over_t>, ballot_update_ratio=1, winning_frequency_update_ratio=<function one_over_t>, other_statistics_update_ratio=<function one_over_t>, other_statistics_tau=None, other_statistics_strategy=None, verbose=False)
Seek for convergence by fictitious play.
- Parameters
init (Strategy or TauVector or str) –
The initialization.
If it is a strategy, it must be an argument accepted by
tau()
, i.e. bytau_strategic()
.If it is a tau-vector, it is used directly.
If it is a string:
'sincere'
or'fanatic'
:tau_sincere
ortau_fanatic
is respectively used.'random_tau'
: useRandTauVectorUniform
to draw a tau-vector uniformly at random that is consistent with the voting rule.'random_tau_undominated'
: userandom_tau_undominated()
to draw a tau-vector where all voters cast an undominated ballot at random.
n_max_episodes (int) – Maximal number of iterations.
perception_update_ratio (callable or Number) – The coefficient when updating the perceived tau: tau_perceived = (1 - perception_update_ratio(t)) * tau_perceived + perception_update_ratio(t) * tau_actual. For any t from 2 to n_max_episodes included, the update ratio must be in [0, 1]. The default function is
one_over_t()
, which leads to an arithmetic average. However, the recommended function isone_over_log_t_plus_one()
, which accelerates the convergence. If perception_update_ratio is a Number, it is considered as a constant function.ballot_update_ratio (callable or Number) – The ratio of voters who update their ballot: tau_actual = (1 - ballot_update_ratio(t)) * tau_actual + ballot_update_ratio(t) * tau_response. For any t from 2 to n_max_episodes included, the update ratio must be in [0, 1]. The default function is the constant 1, which corresponds to a full update. If ballot_update_ratio is a Number, it is considered as a constant function.
winning_frequency_update_ratio (callable or Number) – The coefficient when updating the winning frequency of each candidate: d_candidate_winning_frequency[c] = (1 - winning_frequency_update_ratio(t)) * d_candidate_winning_frequency[c] + winning_frequency_update_ratio(t) * winning_probability[c]. The default function is
one_over_t()
, which leads to an arithmetic average. Note that this parameters has an influence only in case of non-convergence.other_statistics_update_ratio (callable or Number) – The coefficient when updating the other statistics (cf. below).
other_statistics_tau (dict) – Key: name of the statistic (different from
converges
,tau
,strategy
,tau_init
,n_episodes
, andd_candidate_winning_frequency
). Value: a function whose input is a tau-vector, and whose output is a number or a numpy array.other_statistics_strategy (dict) – Key: name of the statistic (different from
converges
,tau
,strategy
,tau_init
,n_episodes
,d_candidate_winning_frequency
and the names inother_statistics_tau
). Value: a function whose input is a strategy, and whose output is a number or a numpy array.verbose (bool) – If True, print all intermediate steps.
- Returns
Key
converges
: bool. True if the process converges.Key
tau
:TauVector
or None. The limit tau-vector. If None, it means that the process did not converge.Key
strategy
:StrategyThreshold
or None. The limit strategy. If None, it means that the process did not converge.Key
tau_init
: the tau-vector at initialization.Key
n_episodes
: the number of episodes until convergence. If the process did not converge, by convention, this value is n_max_episodes.Key
d_candidate_winning_frequency
: dict. Key: candidate. Value: winning frequency. If the process reached a limit, the winning frequencies are computed in the limit only. If the process did not converge, the frequency is computed on the whole history.Others keys are those of
other_statistics_tau
andother_statistics_strategy
. Similarly tod_candidate_winning_frequency
, they give the long-run average of the corresponding statistics.
- Return type
dict
Notes
Comparison between
iterated_voting()
andfictitious_play()
:iterated_voting()
can detect cycles (whereasfictitious_play()
only looks for a limit).fictitious_play()
accepts update ratios that are functions of the time (whereasiterated_voting()
only accepts constants).fictitious_play()
is faster and uses less memory, because it only looks for a limit and not for a cycle.
In general, you should use
iterated_voting()
only if you care about cycles, with the constraint that it implies having constant update ratios.
- property has_majority_favorite
Whether there is a majority favorite (a candidate ranked first by strictly more than half of the voters).
- Type
bool
- property has_majority_ranking
Whether there is a majority ranking (a ranking shared by strictly more than half of the voters).
- Type
bool
- have_ranking_with_utility_above_u(ranking, u)[source]
Share of voters who have a given ranking and a utility for their middle candidate that is strictly above a given value.
Cf.
ProfileCardinal.have_ranking_with_utility_above_u()
.Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> profile.have_ranking_with_utility_above_u(ranking='cab', u=0) Fraction(3, 10) >>> profile.have_ranking_with_utility_above_u(ranking='cab', u=Fraction(1, 100)) Fraction(7, 25) >>> profile.have_ranking_with_utility_above_u(ranking='cab', u=Fraction(99, 100)) Fraction(1, 100) >>> profile.have_ranking_with_utility_above_u(ranking='cab', u=1) 0
- have_ranking_with_utility_below_u(ranking, u)[source]
Share of voters who have a given ranking and a utility for their middle candidate that is strictly below a given value.
Cf.
ProfileCardinal.have_ranking_with_utility_below_u()
.Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> profile.have_ranking_with_utility_below_u(ranking='cab', u=0) 0 >>> profile.have_ranking_with_utility_below_u(ranking='cab', u=Fraction(1, 100)) Fraction(1, 50) >>> profile.have_ranking_with_utility_below_u(ranking='cab', u=Fraction(99, 100)) Fraction(29, 100) >>> profile.have_ranking_with_utility_below_u(ranking='cab', u=1) Fraction(3, 10)
- have_ranking_with_utility_u(ranking, u)
Share of voters who have a given ranking and a utility for their middle candidate that is equal to a given value.
Since it is a continuous profile, this method always returns 0.
- is_equilibrium(strategy)
Whether a strategy is an equilibrium.
- Parameters
strategy (StrategyThreshold) – A strategy that specifies at least all the rankings that are present in the profile. If some voters have a utility for their second candidate that is equal to the utility threshold of the strategy, then the ratio of optimistic voters must be specified.
- Returns
Whether strategy is an equilibrium in this profile. This is based on the assumption that:
A proportion ratio_sincere of voters cast their ballot sincerely (in the sense of
tau_sincere
),A proportion ratio_fanatic of voters vote for their top candidate only,
And the rest of the voters use strategy.
- Return type
- is_equilibrium_stable(strategy)[source]
Whether a forward-focused equilibrium strategy is stable in this profile.
Limitations of the current implementation:
The profile has only one bin per ranking, i.e. the utility distribution is uniform on [0, 1].
All voters are strategic (no sincere or fanatic).
The voting rule is Approval voting.
- Parameters
strategy (StrategyThreshold) – A strategy that is assumed to be a forward-focused equilibrium for this profile (this method does not check if it is indeed the case).
- Returns
True iff the equilibrium is stable, which is a sufficient condition to be an equilibrium in the sense of Myerson.
- Return type
bool
- property is_generic_in_rankings
Whether the profile is generic in rankings (contains all rankings).
- Type
bool
- property is_profile_condorcet
Whether the profile is Condorcet. By convention,
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
- property is_single_peaked
Whether the profile is single-peaked.
- Type
bool
- property is_standardized
Whether the profile is standardized. Cf.
standardized_version()
.- Type
bool
- iterated_voting(init, n_max_episodes, perception_update_ratio=1, ballot_update_ratio=1, winning_frequency_update_ratio=<function one_over_t>, other_statistics_update_ratio=<function one_over_t>, other_statistics_tau=None, other_statistics_strategy=None, verbose=False)
Seek for convergence by iterated voting.
- Parameters
init (Strategy or TauVector or str) –
The initialization.
If it is a strategy, it must be an argument accepted by
tau()
, i.e. bytau_strategic()
.If it is a tau-vector, it is used directly.
If it is a string:
'sincere'
or'fanatic'
:tau_sincere
ortau_fanatic
is respectively used.'random_tau'
: useRandTauVectorUniform
to draw a tau-vector uniformly at random that is consistent with the voting rule.'random_tau_undominated'
: userandom_tau_undominated()
to draw a tau-vector where all voters cast an undominated ballot at random.
n_max_episodes (int) – Maximal number of iterations.
perception_update_ratio (Number) – Number in [0, 1]. The coefficient when updating the perceived tau: tau_perceived = (1 - perception_update_ratio) * tau_perceived + perception_update_ratio * tau_actual.
ballot_update_ratio (Number) – Number in [0, 1]. The ratio of voters who update their ballot: tau_actual = (1 - ballot_update_ratio) * tau_actual + ballot_update_ratio * tau_response.
winning_frequency_update_ratio (callable or Number) – The coefficient when updating the winning frequency of each candidate: d_candidate_winning_frequency[c] = (1 - winning_frequency_update_ratio(t)) * d_candidate_winning_frequency[c] + winning_frequency_update_ratio(t) * winning_probability[c]. The default function is
one_over_t()
, which leads to an arithmetic average. Note that this parameters has an influence only in case of non-convergence.other_statistics_update_ratio (callable or Number) – The coefficient when updating the other statistics (cf. below).
other_statistics_tau (dict) – Key: name of the statistic (different from
converges
,tau
,strategy
,tau_init
,n_episodes
, andd_candidate_winning_frequency
). Value: a function whose input is a tau-vector, and whose output is a number or a numpy array.other_statistics_strategy (dict) – Key: name of the statistic (different from
converges
,tau
,strategy
,tau_init
,n_episodes
,d_candidate_winning_frequency
and the names inother_statistics_tau
). Value: a function whose input is a strategy, and whose output is a number or a numpy array.verbose (bool) – If True, print all intermediate steps.
- Returns
Key
converges
: bool. True if the process converges (i.e. cycle of length 1).Key
cycle_taus_perceived
: list ofTauVector
. The limit cycle of perceived tau-vectors. cycle_taus_perceived[t] is a barycenter of cycle_taus_perceived[t - 1] with cycle_taus_actual[t - 1], parametrized by perception_update_ratio.Key
cycle_strategies
: list ofStrategyThreshold
. The limit cycle of strategies. cycle_strategies[t] is the best response to cycle_taus_perceived[t].Key
cycle_taus_actual
: list ofTauVector
. The limit cycle of actual tau-vectors. cycle_taus_actual[t] is a barycenter of cycle_taus_actual[t - 1] and the tau-vector resulting from strategies[t], parametrized by ballot_update_ratio.Key
tau_init
: the tau-vector at initialization.Key
n_episodes
: the number of episodes until convergence. If the process did not converge, by convention, this value is n_max_episodes.Key
d_candidate_winning_frequency
: dict. Key: candidate. Value: winning frequency. If the process reached a limit or a periodical orbit, the winning frequencies are computed in the limit only. If the process did not converge, the frequency is computed on the whole history.Others keys are those of
other_statistics_tau
andother_statistics_strategy
. Similarly tod_candidate_winning_frequency
, they give the long-run average of the corresponding statistics.
The return values cycle_taus_perceived, cycle_strategies and cycle_taus_actual are lists of the same length. If the length is 1, the process converges to this limit. If it is greater than 1, the process reaches a periodical orbit. If it is 0, by convention, it means that the process does not converge and does not reach a periodical orbit.
- Return type
dict
Notes
Comparison between
iterated_voting()
andfictitious_play()
:iterated_voting()
can detect cycles (whereasfictitious_play()
only looks for a limit).fictitious_play()
accepts update ratios that are functions of the time (whereasiterated_voting()
only accepts constants).fictitious_play()
is faster and uses less memory, because it only looks for a limit and not for a cycle.
In general, you should use
iterated_voting()
only if you care about cycles, with the constraint that it implies having constant update ratios.
- classmethod order_and_label(t)[source]
Order and label of a discrete type.
Cf.
Profile.order_and_label()
.Examples
>>> ProfileHistogram.order_and_label(('abc', (0.1, 0.5, 0.4))) ('abc', '$r(abc)$') >>> ProfileHistogram.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)$')
- plot_cdf(ranking, x_label=None, y_label=None, **kwargs)[source]
Plot the cumulative distribution function (CDF) for a given ranking.
- Parameters
ranking (str) – A ranking.
x_label (str, optional) – The label for x-axis. If not specified, an appropriate label is provided.
y_label – The label for y-axis. If not specified, an appropriate label is provided.
kwargs – The additional keyword arguments are passed to the function
plot
of matplotlib.
Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> profile.plot_cdf('cab')
- plot_histogram(ranking, x_label=None, y_label=None, **kwargs)[source]
Plot the histogram for a given ranking.
Up to a renormalization, it is the probability density function (PDF).
- Parameters
ranking (str) – A ranking.
x_label (str, optional) – The label for x-axis. If not specified, an appropriate label is provided.
y_label – The label for y-axis. If not specified, an appropriate label is provided.
kwargs – The additional keyword arguments are passed to the function
plot
of matplotlib.
Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> profile.plot_histogram('cab')
- random_tau_undominated()
Random tau based on undominated ballots.
This is used, for example, in
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
Share of voters that happen to cast a sincere ballot.
- Parameters
strategy – An argument accepted by
share_sincere_among_strategic_voters()
.- Returns
The ratio of voters that happen to cast a sincere ballot. This includes all kinds of voters (sincere, fanatic or strategic).
- Return type
Number
Share of fanatic voters that happen to cast a sincere ballot.
In Plurality or Anti-Plurality, this number is always 1 because fanatic voters are sincere by our definition.
In Approval, this is the proportion of fanatic voters whose ballot happen to be sincere, i.e. whose utility for their second candidate is lower or equal to 0.5.
Note that this share is relative to the share of fanatic voters: therefore, it is independent of ratio_fanatic and can be defined conventionally even if ratio_fanatic is 0, with the same computation.
- Type
Number
Share of strategic voters that happen to cast a sincere ballot.
- Parameters
strategy (StrategyThreshold) – A strategy that specifies at least all the rankings that are present in the profile. If some voters have a utility for their second candidate that is equal to the utility threshold of the strategy, then the ratio of optimistic voters must be specified.
- Returns
The ratio of sincere voters among strategic voters. In particular, if all strategic voters happen to be sincere with the given strategy, then the ratio is 1, even if there are non-strategic voters (for example, in Approval, fanatic voters who have a utility > 0.5 for their second candidate and are therefore not “sincere”, according to our definition).
- Return type
Number
- property standardized_version
Standardized version of the profile (makes it unique, up to permutations of the candidates).
Examples
>>> from fractions import Fraction >>> profile = ProfileHistogram( ... {'abc': Fraction(1, 10), 'bac': Fraction(6, 10), 'cab': Fraction(3, 10)}, ... {'abc': [1], 'bac': [1, 0], 'cab': [Fraction(2, 3), 0, 0, 0, 0, 0, 0, 0, 0, Fraction(1, 3)]}) >>> print(profile.standardized_version) <abc: 3/5 [1 0], bac: 1/10 [1], cba: 3/10 [Fraction(2, 3) 0 0 0 0 0 0 0 0 Fraction(1, 3)]> (Condorcet winner: a) >>> profile.is_standardized False
- Type
- property strategies_group
group strategies of the profile.
- Yields
StrategyThreshold
– All possible group strategies of the profile. Each bin of each histogram is considered as a “group” of voters. In other words, the considered strategies are all the threshold strategies where for each ranking, the corresponding threshold is at a limit between two bins of the histogram.- Type
Iterator
- property strategies_ordinal
Ordinal strategies of the profile.
- Yields
StrategyOrdinal
– All possible ordinal strategies for this profile.
Examples
Cf.
ProfileOrdinal
.- Type
Iterator
- property strategies_pure
Pure strategies of the profile.
- Yields
Strategy
– All possible pure strategies of the profile. This is implemented only for discrete profiles such asProfileTwelve
orProfileDiscrete
.
Examples
Cf.
ProfileDiscrete
.- Type
Iterator
- property support_in_rankings
Support of the profile (in terms of rankings).
- Type
SetPrintingInOrder
of str
- property support_in_weak_orders
Support of the profile (in terms of weak orders).
- Type
SetPrintingInOrder
of str
- tau(strategy)
Tau-vector associated to a strategy, with partial sincere and fanatic voting.
- Parameters
strategy – An argument accepted by
tau_strategic()
.- Returns
A share ratio_sincere of the voters vote sincerely (in the sense of
tau_sincere
), a share ratio_fanatic vote only for their top candidate (cf.tau_fanatic
), and the rest of the voters vote strategically (in the sense oftau_strategic()
). In other words, this tau-vector is the barycenter of tau_sincere, tau_fanatic and tau_strategic(strategy), with respective weights ratio_sincere, ratio_fanatic and 1 - ratio_sincere - ratio_fanatic.- Return type
- property tau_fanatic
Tau-vector associated to fanatic voting.
- Returns
In Approval or Plurality, all voters approve of their top candidate only,
In Anti-plurality, all voters vote against their bottom candidate (i.e. for the other two).
- Return type
Notes
In Plurality and Anti-plurality, sincere and fanatic voting are the same. They differ only in Approval.
- property tau_sincere
Tau-vector associated to sincere voting.
- Returns
In Approval, all voters approve of their top candidate, and voters approve of their middle candidate if and only if their utility for her is strictly greater than 0.5.
In Plurality, all voters vote for their top candidate.
In Anti-plurality, all voters vote against their bottom candidate (i.e. for the other two).
- Return type
Notes
In Plurality and Anti-plurality, sincere and fanatic voting are the same. They differ only in Approval.
- tau_strategic(strategy)
Tau-vector associated to a strategy (fully strategic voting).
- Parameters
strategy (StrategyThreshold) – A strategy that specifies at least all the rankings that are present in the profile. If some voters have a utility for their second candidate that is equal to the utility threshold of the strategy, then the ratio of optimistic voters must be specified.
- Returns
Tau-vector associated to this profile and strategy strategy.
- Return type
- property weighted_maj_graph
Weighted majority graph.
- Type
numpy.ndarray