Tutorial 3: Manipulation¶
Create a population of 9 voters with preferences over 5 candidates, using the Spheroid model (extending Impartial Culture to utilities):
import svvamp
pop = svvamp.PopulationSpheroid(V=9, C=5)
Create an election, using Instant-Runoff Voting:
election = svvamp.IRV(pop)
Ask SVVAMP whether the voting system meets the Condorcet criterion (in general, not for this particular population):
print(election.meets_Condorcet_c_rk)
Coalitional Manipulation¶
Cf. CM_full()
for a definition of this notion.
Check Coalitional Manipulation (CM):
print(election.CM())
SVVAMP returns a pair (is_CM
, log_CM
).
For each voting system, SVVAMP uses by default its most precise algorithm
running in polynomial time. For IRV, the decision problem is
NP-complete, so this polynomial algorithm is not exact. For that reason,
is_CM
can be a boolean (whether the election is manipulable or not), or
the conventional value numpy.nan
meaning that the algorithm was not able
to decide.
log_CM
is a string representing the options used to compute CM. Check the
possible options:
print(election.options_parameters)
The main option is CM_option
. Change it and compute CM again:
election.CM_option = 'exact'
print(election.CM())
Now, the return value is_CM
is necessarily a boolean.
You could have set the option as soon as you created the election with the following syntax:
election = svvamp.IRV(pop, CM_option='exact')
Print more details about CM:
print(election.CM_with_candidates())
Now, SVVAMP also return candidates_CM
, an array of boolean indicating
which candidates can benefit from CM.
SVVAMP is clever enough: 1. not to do obviously useless computation and 2. not to do the same computation twice.
- In this example, when calling
CM()
, SVVAMP may decide that CM is impossible for candidates 0 and 1, but possible for candidate 2. SVVAMP stops computation and decidesis_CM = True
.- In that case, when calling
CM_full()
, SVVAMP does not perform the computation again for candidates 0, 1 and 2.
Other notions of coalitional manipulation¶
Check Ignorant-Coalition Manipulation (cf. ICM_full()
):
print(election.ICM())
print(election.ICM_with_candidates())
Check Trivial Manipulation (cf. TM_full()
):
print(election.TM())
print(election.TM_with_candidates())
Check Unison Manipulation (cf. UM_full()
):
election.UM_option = 'exact'
print(election.UM())
print(election.UM_with_candidates())
Individual Manipulation¶
Cf. IM_full()
for a definition of this notion.
Check Individual Manipulation (IM):
election.IM_option = 'exact'
print(election.IM())
SVVAMP returns a boolean is_IM
(whether the election is manipulable by a
single manipulator or not) and a string log_IM
(the option used to compute
IM).
Print more details about IM:
print(election.IM_full())
Now, SVVAMP returns (is_IM
, log_IM
, candidates_IM
, voters_IM
and v_IM_for_c
). candidates_IM
indicates which candidates can benefit
from IM. voters_IM
indicates which voters can and want to perform IM.
v_IM_for_c
indicates, for each voter v
and each candidate c
,
whether v
can and want to manipulate for c
.
Independence of Irrelevant Alternatives¶
Cf. not_IIA_full()
for a definition of this notion.
Modify the option in order to compute IIA with an exact (non-polynomial) algorithm:
import numpy
election.IIA_subset_maximum_size = numpy.inf
Check Independence of Irrelevant Alternatives (IIA):
print(election.not_IIA())
SVVAMP returns a boolean (whether the election violates IIA) and a string (the options used to do the computation).
You can ask more information about IIA:
print(election.not_IIA_full())
If the election violates IIA, then SVVAMP provides an example of subset of candidates violating IIA and the corresponding winner.