Manipulation#
[1]:
import svvamp
Create a population of 9 voters with preferences over 5 candidates, using the Spheroid model (which extends Impartial Culture to utilities):
[2]:
random_profile = svvamp.GeneratorProfileSpheroid(n_v=9, n_c=5)
profile = random_profile()
Define a voting rule (Instant Runoff Voting) and load the profile:
[3]:
rule = svvamp.RuleIRV()
Ask whether the voting rule meets the Condorcet criterion:
[4]:
rule.meets_condorcet_c_rk
[4]:
False
Load the profile:
[5]:
rule(profile)
[5]:
<svvamp.rules.rule_irv.RuleIRV at 0x1a02a98d7c0>
Coalitional Manipulation#
For a definition of this notion, cf the Reference section (Rule.is_cm_
).
Decide coalitional manipulation (CM):
[6]:
rule.is_cm_
[6]:
False
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 nan
meaning that the algorithm was not able to decide.
log_CM_
is a string representing the options used to compute CM:
[7]:
rule.log_cm_
[7]:
'cm_option = fast, fast_algo = c_minus_max, icm_option = exact, tm_option = exact'
Check the possible options:
[8]:
rule.options_parameters
[8]:
{'iia_subset_maximum_size': {'allowed': <function svvamp.utils.type_checker.is_number(value)>,
'default': 2},
'im_option': {'allowed': ['lazy', 'exact'], 'default': 'lazy'},
'tm_option': {'allowed': ['exact'], 'default': 'exact'},
'um_option': {'allowed': ['fast', 'exact'], 'default': 'fast'},
'icm_option': {'allowed': ['exact'], 'default': 'exact'},
'cm_option': {'allowed': ['fast', 'slow', 'exact'], 'default': 'fast'},
'fast_algo': {'allowed': ['c_minus_max', 'minus_max', 'hardest_first'],
'default': 'c_minus_max'}}
The main option is cm_option
. Change it and compute CM again:
[9]:
rule.cm_option = 'exact'
rule.is_cm_
[9]:
False
Now, the return value is necessarily a Boolean.
You could have set the option as soon as you defined the rule with the following syntax:
[10]:
rule = svvamp.RuleIRV(cm_option='exact')
rule(profile)
[10]:
<svvamp.rules.rule_irv.RuleIRV at 0x1a02bb26f30>
Or, as a one-liner:
[11]:
rule = svvamp.RuleIRV(cm_option='exact')(profile)
Get more details about CM:
[12]:
rule.candidates_cm_
[12]:
array([0., 0., 0., 0., 0.])
Now, SVVAMP returns an array of boolean indicating which candidates can benefit from CM.
SVVAMP is clever enough:
Not to do obviously useless computation,
Not to do the same computation twice.
Other Notions of Coalitional Manipulation#
Ignorant-Coalition Manipulation (cf Reference section, Rule.is_icm_
):
[13]:
rule.is_icm_
[13]:
False
[14]:
rule.candidates_icm_
[14]:
array([0., 0., 0., 0., 0.])
Trivial Manipulation (cf Reference section, Rule.is_tm_
):
[15]:
rule.is_tm_
[15]:
False
[16]:
rule.candidates_tm_
[16]:
array([0., 0., 0., 0., 0.])
Unison Manipulation (cf Reference section, Rule.is_um_
):
[17]:
rule.is_um_
[17]:
False
[18]:
rule.candidates_um_
[18]:
array([0., 0., 0., 0., 0.])
Individual Manipulation#
For a definition of this notion, cf the Reference section (Rule.is_im_
).
Decide Individual Manipulation (IM):
[19]:
rule.im_option = 'exact'
rule.is_im_
[19]:
False
More details about IM:
[20]:
rule.v_im_for_c_
[20]:
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
For each voter v and candidate c, v_im_for_c_[v, c]
indicates whether voter v can manipulate in favor of c.
Independence of Irrelevant Alternatives#
For a definition of this notion, cf the Reference section (Rule.is_iia_
).
Modify the option in order to compute IIA with an exact (non-polynomial) algorithm:
[21]:
import numpy as np
rule.iia_subset_maximum_size = np.inf
Decide IIA:
[22]:
rule.is_iia_
[22]:
True
More details about IIA:
[23]:
rule.example_subset_iia_
[23]:
nan
[24]:
rule.example_winner_iia_
[24]:
nan