TauVector

[1]:
from fractions import Fraction
import poisson_approval as pa

A Tau-Vector and its Basic Properties

The most usual way to define a tau-vector (ballot shares) is to deduce it from applying a given strategy in a given profile, like in the tutorial on ProfileNoisyDiscrete. That being said, a tau-vector can also be defined directly:

[2]:
tau = pa.TauVector({'a': Fraction(1, 10), 'ab': Fraction(3, 5), 'c': Fraction(3, 10)})

Share of the ballot \(ab\):

[3]:
tau.ab
[3]:
Fraction(3, 5)

Share of single / double votes:

[4]:
tau.share_single_votes
[4]:
Fraction(2, 5)
[5]:
tau.share_double_votes
[5]:
Fraction(3, 5)

Scores:

[6]:
tau.scores
[6]:
{a: 7/10, b: 3/5, c: 3/10}

Winners:

[7]:
tau.winners
[7]:
{'a'}

Events: Duos, Pivots and Trios

An Event provides the asymptotic development of the probability when the expected number of voters \(n\) tend to infinity, as well as the offsets for each type of ballot.

Duo between \(a\) and \(b\):

(\(a\) and \(b\) have the same score, but not necessarily higher than \(c\).)

[8]:
tau.duo_ab
[8]:
<asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>

Access the asymptotic development and the offsets:

[9]:
tau.duo_ab.asymptotic
[9]:
exp(- 0.1 n + o(1))
[10]:
tau.duo_ab.phi_a
[10]:
0.0

Pivots between \(a\) and \(b\):

(For the definition of each variant, cf. the Reference section.)

[11]:
tau.pivot_weak_ab
[11]:
<asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
[12]:
tau.pivot_strict_ab
[12]:
<asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
[13]:
tau.pivot_tij_abc
[13]:
<asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
[14]:
tau.pivot_tjk_abc
[14]:
<asymptotic = exp(- inf)>

Trios:

(For the definition of each variant, cf. the Reference section.)

[15]:
tau.trio
[15]:
<asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
[16]:
tau.trio_1t_a
[16]:
<asymptotic = exp(- inf)>
[17]:
tau.trio_2t_ab
[17]:
<asymptotic = exp(- 0.151472 n - 0.5 log n - 1.18339 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>

Print the order of the magnitudes of the pivots:

[18]:
tau.print_magnitudes_order()
mu_ac > mu_ab > mu_bc

Print all the weak pivots:

[19]:
tau.print_weak_pivots()
pivot_weak_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_weak_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_weak_bc:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>

Print all the pivots:

[20]:
tau.print_all_pivots()
pivot_weak_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_weak_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_weak_bc:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
pivot_strict_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_strict_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_strict_bc:  <asymptotic = exp(- inf)>
pivot_tij_abc:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_tij_acb:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.371758 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_tij_bac:  <asymptotic = exp(- 0.1 n + log n - 2.30259 + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_tij_bca:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.302013 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
pivot_tij_cab:  <asymptotic = exp(- 0.0834849 n - 0.5 log n + 0.0518905 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_tij_cba:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
pivot_tjk_abc:  <asymptotic = exp(- inf)>
pivot_tjk_acb:  <asymptotic = exp(- inf)>
pivot_tjk_bac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.371758 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_tjk_bca:  <asymptotic = exp(- 0.0834849 n - 0.5 log n + 0.0518905 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_tjk_cab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_tjk_cba:  <asymptotic = exp(- 0.1 n + log n - 2.30259 + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
trio:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio_1t_a:  <asymptotic = exp(- inf)>
trio_1t_b:  <asymptotic = exp(- 0.151472 n + 0.5 log n - 3.48597 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio_1t_c:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.490239 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio_2t_ab:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 1.18339 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio_2t_ac:  <asymptotic = exp(- inf)>
trio_2t_bc:  <asymptotic = exp(- 0.151472 n + 0.5 log n - 3.1394 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
duo_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
duo_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
duo_bc:  <asymptotic = exp(- 0.0514719 n - 0.5 log n - 0.836813 + o(1)), phi_a = 1, phi_c = 1.41421, phi_ab = 0.707107>

Best Responses

The focus of a tau-vector is defined as:

  • Direct: the three weak pivots have distinct magnitudes.

  • Forward-Focused: the two lowest magnitudes are equal, the highest one is different.

  • Backward-Focused: the two highest magnitudes are equal, the lowest one is different.

  • Unfocused: the three magnitudes are equal.

[21]:
tau.focus
[21]:
Focus.DIRECT

Best response for each ranking:

[22]:
tau.d_ranking_best_response
[22]:
{abc: <ballot = a, utility_threshold = 1, justification = Asymptotic method>, acb: <ballot = a, utility_threshold = 1, justification = Asymptotic method>, bac: <ballot = ab, utility_threshold = 0, justification = Asymptotic method>, bca: <ballot = bc, utility_threshold = 0, justification = Asymptotic method>, cab: <ballot = c, utility_threshold = 1, justification = Asymptotic method>, cba: <ballot = bc, utility_threshold = 0, justification = Asymptotic method>}

Characteristics of the best response for voters with ranking \(abc\):

[23]:
tau.d_ranking_best_response['abc']
[23]:
<ballot = a, utility_threshold = 1, justification = Asymptotic method>
[24]:
tau.d_ranking_best_response['abc'].ballot
[24]:
'a'
[25]:
tau.d_ranking_best_response['abc'].utility_threshold
[25]:
1.0
[26]:
tau.d_ranking_best_response['abc'].justification
[26]:
'Asymptotic method'
[27]:
tau.d_ranking_best_response['abc'].pivot_tij
[27]:
<asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>

Strategy with Attached Profile and Implicit Tau

As mentioned in the tutorial on ProfileNoisyDiscrete, you can define a strategy with an attached profile:

[28]:
profile = pa.ProfileNoisyDiscrete({
    ('abc', 0.4, 0.01): Fraction(1, 10),
    ('bac', 0.2, 0.01): Fraction(6, 10),
    ('cab', 0.7, 0.01): Fraction(3, 10)
})
strategy = pa.StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'}, profile=profile)

This defines a tau vector:

[29]:
strategy.tau
[29]:
<a: 1/10, ab: 3/5, c: 3/10> ==> a

In that case, the strategy has shortcuts for all the properties of the tau vector. Thus for example, instead of writing:

[30]:
strategy.tau.scores
[30]:
{a: 7/10, b: 3/5, c: 3/10}

You can simply write:

[31]:
strategy.scores
[31]:
{a: 7/10, b: 3/5, c: 3/10}

Similarly, instead of writing:

[32]:
strategy.tau.print_weak_pivots()
pivot_weak_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_weak_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_weak_bc:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>

You can write:

[33]:
strategy.print_weak_pivots()
pivot_weak_ab:  <asymptotic = exp(- 0.1 n + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_weak_ac:  <asymptotic = exp(- 0.0834849 n - 0.5 log n - 0.87535 + o(1)), phi_a = 0.654654, phi_c = 1.52753, phi_ab = 0.654654>
pivot_weak_bc:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>
trio:  <asymptotic = exp(- 0.151472 n - 0.5 log n - 0.836813 + o(1)), phi_a = 0, phi_c = 1.41421, phi_ab = 0.707107>

Symbolic Computation

Up to now, all the computations we made were numeric. When defining a profile or a tau-vector, you can use the option symbolic=True. In that case, all computations will be symbolic if possible. Note, however, that this option is much slower than numeric computation.

[34]:
profile = pa.ProfileNoisyDiscrete({
    ('abc', 0.4, 0.01): Fraction(1, 10),
    ('bac', 0.2, 0.01): Fraction(6, 10),
    ('cab', 0.7, 0.01): Fraction(3, 10)
}, symbolic=True)
strategy = pa.StrategyOrdinal({'abc': 'a', 'bac': 'ab', 'cab': 'c'}, profile=profile)
[35]:
strategy.print_weak_pivots()
pivot_weak_ab:  <asymptotic = exp(- n/10 + o(1)), phi_a = 0, phi_c = 1, phi_ab = 1>
pivot_weak_ac:  <asymptotic = exp(n*(-1 + sqrt(21)/5) - log(n)/2 - log(2*sqrt(21)*pi/5)/2 + o(1)), phi_a = sqrt(21)/7, phi_c = sqrt(21)/3, phi_ab = sqrt(21)/7>
pivot_weak_bc:  <asymptotic = exp(n*(-1 + 3*sqrt(2)/5) - log(n)/2 - log(6*sqrt(2)*pi/5)/2 + o(1)), phi_a = 0, phi_c = sqrt(2), phi_ab = sqrt(2)/2>
trio:  <asymptotic = exp(n*(-1 + 3*sqrt(2)/5) - log(n)/2 - log(6*sqrt(2)*pi/5)/2 + o(1)), phi_a = 0, phi_c = sqrt(2), phi_ab = sqrt(2)/2>