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 0x2899517e520>

Coalitional Manipulation

For a definition of this notion, cf the Reference section (Rule.is_cm_).

Decide coalitional manipulation (CM):

[6]:
rule.is_cm_
[6]:
nan

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 0x289b815e310>

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:

  1. Not to do obviously useless computation,

  2. 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