Theory Anonymous_PAPP_Lowering
section ‹Lowering P-APP Rules to Smaller Settings›
theory Anonymous_PAPP_Lowering
imports Anonymous_PAPP
begin
text ‹
In this section, we prove a number of lemmas (corresponding to Lemma~1 in the paper) that allow
us to take an anonymous P-APP rule with some additional properties (typically
Cardinality-Strategyproofness and Weak Representation or Weak Proportional Representation) and
construct from it an anonymous P-APP rule for a different setting, i.e.\ different number of
voters, parties, and/or result committee size.
In the reverse direction, this also allows us to lift impossibility results from one setting
to another.
›
subsection ‹Preliminary Lemmas›
context card_stratproof_anon_papp
begin
text ‹
The following lemma is obtained by applying Strategyproofness repeatedly. It shows that
if we have ‹l› voters with identical approval lists, then this entire group of voters has no
incentive to submit wrong preferences. That is, the outcome they obtain by submitting their
genuine approval lists is weakly preferred by them over all outcomes obtained where these ‹l›
voters submit any other preferences (and the remaining $n - l$ voters submit the same preferences
as before).
This is stronger than regular Strategyproofness, where we only demand that no voter has an
incentive to submit wrong preferences ∗‹unilaterally› (and everyone else keeps the same
preferences). Here we know that the entire group of ‹l› voters has no incentive to submit
wrong preferences in coordination with one another.
›
lemma proposition2:
assumes "size B = l" "size A + l = n_voters"
assumes "X ≠ {}" "X ⊆ parties" "{} ∉# A+B" "∀X'∈#A+B. X' ⊆ parties"
shows "r (replicate_mset l X + A) ≽[Comm(X)] r (B + A)"
using assms
proof (induction l arbitrary: A B)
case 0
thus ?case
by simp
next
case (Suc l A B)
from Suc.prems have "set_mset B ≠ {}"
by auto
then obtain Y where Y: "Y ∈# B"
by blast
define B' where "B' = B - {#Y#}"
define A' where "A' = A + {#Y#}"
have [simp]: "size B' = l"
using Suc.prems Y by (simp add: B'_def size_Diff_singleton)
have [simp]: "size A' = n_voters - l"
using Suc.prems Y by (simp add: A'_def)
have "r (B' + A') ≼[Comm(X)] r (replicate_mset l X + A')"
by (rule Suc.IH) (use Suc.prems Y in ‹auto simp: A'_def B'_def size_Diff_singleton›)
also have "B' + A' = B + A"
using Y by (simp add: B'_def A'_def)
also have "r (replicate_mset l X + A') ≼[Comm(X)] r (replicate_mset (Suc l) X + A)"
proof (rule not_manipulable'')
show "replicate_mset (Suc l) X + A + {#Y#} = replicate_mset l X + A' + {#X#}"
by (simp add: A'_def)
next
show "is_pref_profile (replicate_mset (Suc l) X + A)"
using Suc.prems by unfold_locales (auto split: if_splits)
next
show "is_pref_profile (replicate_mset l X + A')"
using Suc.prems Y by unfold_locales (auto split: if_splits simp: A'_def)
qed
finally show ?case .
qed
end
context card_stratproof_weak_rep_anon_papp
begin
text ‹
In a setting with Weak Representation and Cardinality-Strategyproofness, Proposition 2 allows
us to strengthen Weak Representation in the following way: Suppose we at least
$l \lfloor n/k\rfloor$ voters with the same approval list ‹X›, and ‹X› consists of at least ‹l›
parties. Then at least ‹l› of the members of the result committee are in ‹X›.
›
lemma proposition3:
assumes "is_pref_profile A" "X ⊆ parties" "card X ≥ l"
assumes "committee_size > 0"
assumes "count A X ≥ l * ⌈n_voters / committee_size⌉"
shows "size {# x∈# r A. x ∈ X #} ≥ l"
using assms
proof (induction l arbitrary: A X rule: less_induct)
case (less l A X)
interpret A: anon_papp_profile n_voters parties committee_size A
by fact
consider "l = 0" | "l = 1" | "l > 1"
by force
thus ?case
proof cases
assume "l = 0"
thus ?thesis by simp
next
assume [simp]: "l = 1"
define n where "n = count A X"
with less.prems have "X ≠ {}"
by auto
then obtain x where x: "x ∈ X"
by blast
have "n ≤ size A"
unfolding n_def by (rule count_le_size)
hence "n ≤ n_voters"
by (simp add: A.size_A)
have "count A X > 0"
by (rule Nat.gr0I) (use n_voters_pos less.prems in ‹auto simp: field_simps›)
hence "X ∈# A"
by force
have [simp]: "replicate_mset n X ⊆# A"
by (simp add: n_def flip: count_le_replicate_mset_subset_eq)
define A'' where "A'' = A - replicate_mset n X"
define A' where "A' = A'' + replicate_mset n {x}"
interpret A': anon_papp_profile n_voters parties committee_size A'
using A.A_nonempty A.A_subset A.size_A x ‹X ∈# A›
by unfold_locales
(fastforce simp: A'_def A''_def size_Diff_submset subset_mset.add_increasing2
split: if_splits dest!: in_diffD)+
have "x ∈# r A'"
proof (rule weak_representation)
show "is_pref_profile A'"
by (fact A'.anon_papp_profile_axioms)
next
have "n_voters ≤ committee_size * n"
using less.prems by (simp add: n_def ceiling_le_iff field_simps flip: of_nat_mult)
also have "n ≤ count A' {x}"
by (simp add: A'_def)
finally show "n_voters ≤ committee_size * count A' {x}"
by simp
qed
hence "1 ≤ count (r A') x"
by simp
also have "… = size {# y ∈# r A'. y = x #}"
by simp
also have "… ≤ size {# y ∈# r A'. y ∈ X #}"
by (intro size_mset_mono multiset_filter_mono') (use x in auto)
also have "r A' ≼[Comm(X)] r A"
proof -
have "r (replicate_mset n {x} + A'') ≼[Comm(X)] r (replicate_mset n X + A'')"
proof (rule proposition2)
show "{} ∉# A'' + replicate_mset n {x}"
using A'.A_nonempty by (auto simp: A'_def)
show "∀X'∈#A'' + replicate_mset n {x}. X' ⊆ parties"
using A'.A_subset x by (auto simp: A'_def dest: in_diffD)
show "size A'' + n = n_voters"
using ‹n ≤ n_voters› by (auto simp: A''_def size_Diff_submset A.size_A)
qed (use less.prems in auto)
also have "replicate_mset n X + A'' = A"
by (simp add: A''_def n_def flip: count_le_replicate_mset_subset_eq)
finally show ?thesis
by (simp add: A'_def add_ac)
qed
hence "size {# y ∈# r A'. y ∈ X #} ≤ size {# y ∈# r A. y ∈ X #}"
by (simp add: committee_preference_def)
finally show ?thesis
by simp
next
assume l: "l > 1"
define n where "n = count A X"
have "n ≤ size A"
unfolding n_def by (rule count_le_size)
hence "n ≤ n_voters"
by (simp add: A.size_A)
define m where "m = nat (ceiling (n_voters / committee_size))"
have "n_voters / committee_size ≤ m"
unfolding m_def by linarith
hence m: "n_voters ≤ committee_size * m"
using ‹committee_size > 0› by (simp add: field_simps flip: of_nat_mult)
have "real n_voters / real committee_size > 0"
using n_voters_pos less.prems by auto
hence m': "⌈real n_voters / real committee_size⌉ = int m"
by (simp add: m_def)
have "1 * m ≤ l * m"
using l by (intro mult_right_mono) auto
also have "l * m ≤ n"
using less.prems by (simp add: m' n_def flip: of_nat_mult)
finally have "m ≤ n"
by simp
with less.prems l have "X ≠ {}"
by auto
then obtain x where x: "x ∈ X"
by blast
have "card (X - {x}) > 0"
using less.prems x l by simp
hence "X - {x} ≠ {}"
by force
have "count A X > 0"
by (rule Nat.gr0I) (use n_voters_pos less.prems l in ‹auto simp: field_simps mult_le_0_iff›)
hence "X ∈# A"
by force
have [simp]: "replicate_mset n X ⊆# A"
by (simp add: n_def flip: count_le_replicate_mset_subset_eq)
define A'' where "A'' = A - replicate_mset n X"
define A' where "A' = A'' + replicate_mset m {x} + replicate_mset (n - m) (X - {x})"
interpret A': anon_papp_profile n_voters parties committee_size A'
proof
show "Y ⊆ parties" if "Y ∈# A'" for Y
using that A.A_subset x ‹X ∈# A›
by (fastforce simp: A'_def A''_def dest!: in_diffD split: if_splits)
next
show "{} ∉# A'"
using A.A_nonempty x ‹X ∈# A› ‹X - {x} ≠ {}›
by (auto simp: A'_def A''_def dest!: in_diffD split: if_splits)
next
show "size A' = n_voters"
using ‹m ≤ n›
by (auto simp: A'_def A''_def A.size_A subset_mset.add_increasing2 size_Diff_submset)
qed
have "x ∈# r A'"
proof (rule weak_representation)
show "is_pref_profile A'"
by (fact A'.anon_papp_profile_axioms)
next
have "n_voters ≤ committee_size * m"
by (fact m)
also have "m ≤ count A' {x}"
by (simp add: A'_def)
finally show "n_voters ≤ committee_size * count A' {x}"
by simp
qed
hence "1 ≤ count (r A') x"
by simp
also have "… = size {# y ∈# r A'. y = x #}"
by simp
finally have 1: "size {#y ∈# r A'. y = x#} ≥ 1" .
have 2: "size {# y ∈# r A'. y ∈ X - {x} #} ≥ l - 1"
proof (rule less.IH)
have "int (l - 1) * ⌈real n_voters / real committee_size⌉ = int ((l - 1) * m)"
by (auto simp add: m' not_less)
also have "(l - 1) * m = l * m - m"
by (simp add: algebra_simps)
also have "l * m ≤ n"
using less.prems by (simp add: m' n_def flip: of_nat_mult)
hence "l * m - m ≤ n - m"
by (meson diff_le_mono)
also have "n - m ≤ count A' (X - {x})"
by (simp add: A'_def A''_def)
finally show "int (l - 1) * ⌈real n_voters / real committee_size⌉ ≤ int (count A' (X - {x}))"
by simp
qed (use l A'.anon_papp_profile_axioms x less.prems in ‹auto›)
have "1 + (l - 1) ≤ size {#y ∈# r A'. y = x#} + size {#y ∈# r A'. y ∈ X - {x}#}"
by (intro add_mono 1 2)
also have "… = size ({#y ∈# r A'. y = x#} + {#y ∈# r A'. y ∈ X - {x}#})"
by simp
also have "{#y ∈# r A'. y = x#} + {#y ∈# r A'. y ∈ X - {x}#} =
{#y ∈# r A'. y = x ∨ y ∈ X - {x}#}"
by (rule filter_mset_disjunction [symmetric]) auto
also have "(λy. y = x ∨ y ∈ X - {x}) = (λy. y ∈ X)"
using x by auto
also have "1 + (l - 1) = l"
using l by simp
also have "r A' ≼[Comm(X)] r A"
proof -
have "r (replicate_mset m {x} + replicate_mset (n - m) (X - {x}) + A'') ≼[Comm(X)]
r (replicate_mset n X + A'')"
proof (rule proposition2)
show " {} ∉# A'' + (replicate_mset m {x} + replicate_mset (n - m) (X - {x}))"
using A'.A_nonempty by (auto simp: A'_def)
show "∀X'∈# A'' + (replicate_mset m {x} + replicate_mset (n - m) (X - {x})). X' ⊆ parties"
using A'.A_subset x by (auto simp: A'_def dest: in_diffD)
show "size A'' + n = n_voters"
using ‹n ≤ n_voters› by (auto simp: A''_def size_Diff_submset A.size_A)
qed (use less.prems l ‹m ≤ n› in auto)
also have "replicate_mset n X + A'' = A"
by (simp add: A''_def n_def flip: count_le_replicate_mset_subset_eq)
finally show ?thesis
by (simp add: A'_def add_ac)
qed
hence "size {# y ∈# r A'. y ∈ X #} ≤ size {# y ∈# r A. y ∈ X #}"
by (simp add: committee_preference_def)
finally show ?thesis
by simp
qed
qed
end
subsection ‹Dividing the number of voters›
text ‹
If we have a PAPP rule that satisfies weak representation and cardinality strategyproofness,
for $ln$ voters, we can turn it into one for ‹n› voters.
This is done by simply cloning each voter ‹l› times.
Consequently, if we have an impossibility result for $n$ voters, it also holds for any
integer multiple of ‹n›.
›
locale divide_voters_card_stratproof_weak_rep_anon_papp =
card_stratproof_weak_rep_anon_papp "l * n_voters" parties committee_size r
for l n_voters parties committee_size r
begin
definition lift_profile :: "'a set multiset ⇒ 'a set multiset" where
"lift_profile A = (∑X∈#A. replicate_mset l X)"
sublocale lowered: anon_papp_election n_voters parties
by standard (use n_voters_pos in auto)
lemma l_pos: "l > 0"
using n_voters_pos by auto
lemma empty_in_lift_profile_iff [simp]: "{} ∈# lift_profile A ⟷ {} ∈# A"
using l_pos by (auto simp: lift_profile_def)
lemma set_mset_lift_profile [simp]: "set_mset (lift_profile A) = set_mset A"
using l_pos by (auto simp: lift_profile_def)
lemma size_lift_profile: "size (lift_profile A) = l * size A"
by (simp add: size_mset_sum_mset lift_profile_def image_mset.compositionality o_def)
lemma count_lift_profile [simp]: "count (lift_profile A) x = l * count A x"
unfolding lift_profile_def by (induction A) auto
lemma is_pref_profile_lift_profile [intro]:
assumes "lowered.is_pref_profile A"
shows "is_pref_profile (lift_profile A)"
proof -
interpret anon_papp_profile n_voters parties committee_size A
by fact
show ?thesis
using A_nonempty A_subset size_A
by unfold_locales
(auto simp: lift_profile_def size_mset_sum_mset image_mset.compositionality o_def)
qed
sublocale lowered: anon_papp n_voters parties committee_size "r ∘ lift_profile"
proof
fix A assume "lowered.is_pref_profile A"
hence "is_pref_profile (lift_profile A)"
by blast
hence "is_committee (r (lift_profile A))"
using rule_wf by blast
thus "lowered.is_committee ((r ∘ lift_profile) A)"
by simp
qed
sublocale lowered: weak_rep_anon_papp n_voters parties committee_size "r ∘ lift_profile"
proof
fix A x
assume A: "lowered.is_pref_profile A" and x: "n_voters ≤ committee_size * count A {x}"
from A have A': "is_pref_profile (lift_profile A)"
by blast
from x have "l * n_voters ≤ l * (committee_size * count A {x})"
by (rule mult_left_mono) auto
also have "… = committee_size * count (lift_profile A) {x}"
by simp
finally have "x ∈# r (lift_profile A)"
by (intro weak_representation A')
thus "x ∈# (r ∘ lift_profile) A"
by simp
qed
sublocale lowered: card_stratproof_anon_papp n_voters parties committee_size "r ∘ lift_profile"
proof
fix A X Y
show "¬lowered.card_manipulable A X Y"
unfolding lowered.card_manipulable_def
proof (rule notI, elim conjE)
assume A: "lowered.is_pref_profile A" and XY: "X ∈# A" "Y ≠ {}" "Y ⊆ parties"
assume *: "(r ∘ lift_profile) A ≺[lowered.committee_preference X]
(r ∘ lift_profile) (A - {#X#} + {#Y#})"
interpret anon_papp_profile n_voters parties committee_size A
by fact
have X: "X ≠ {}" "X ⊆ parties"
using XY A_nonempty A_subset by auto
define A' where "A' = A - {#X#}"
have A': "A = A' + {#X#}"
using XY by (simp add: A'_def)
have "r (lift_profile A) ≺[committee_preference X]
r (lift_profile (A - {#X#} + {#Y#}))"
using * by simp
also have "r (lift_profile (A - {#X#} + {#Y#})) ≼[committee_preference X]
r (lift_profile A - {#X#} + {#Y#})"
proof -
have "r (replicate_mset (l - 1) Y + (lift_profile A' + {#Y#})) ≼[committee_preference X]
r (replicate_mset (l - 1) X + (lift_profile A' + {#Y#}))"
proof (rule proposition2)
show "size (lift_profile A' + {#Y#}) + (l - 1) = l * n_voters"
using XY l_pos n_voters_pos
by (simp add: A'_def size_lift_profile size_Diff_singleton
algebra_simps Suc_diff_le size_A)
next
show "{} ∉# lift_profile A' + {#Y#} + replicate_mset (l - 1) Y"
using XY A_nonempty by (auto simp: A'_def dest: in_diffD)
next
show "∀X'∈#lift_profile A' + {#Y#} + replicate_mset (l - 1) Y. X' ⊆ parties"
using XY A_subset by (auto simp: A'_def dest: in_diffD)
qed (use X in auto)
thus ?thesis
by (simp add: A' replicate_mset_rec l_pos lift_profile_def)
qed
finally have "card_manipulable (lift_profile A) X Y"
unfolding card_manipulable_def using XY A by auto
with not_manipulable show False
by blast
qed
qed
sublocale lowered: card_stratproof_weak_rep_anon_papp n_voters parties committee_size "r ∘ lift_profile"
..
end
locale divide_voters_card_stratproof_weak_prop_rep_anon_papp =
card_stratproof_weak_prop_rep_anon_papp "l * n_voters" parties committee_size r
for l n_voters parties committee_size r
begin
sublocale divide_voters_card_stratproof_weak_rep_anon_papp ..
sublocale lowered: card_stratproof_weak_prop_rep_anon_papp
n_voters parties committee_size "r ∘ lift_profile"
proof
fix A x l'
assume A: "lowered.is_pref_profile A" and x: "l' * n_voters ≤ committee_size * count A {x}"
from A have A': "is_pref_profile (lift_profile A)"
by blast
from x have "l * (l' * n_voters) ≤ l * (committee_size * count A {x})"
by (rule mult_left_mono) auto
also have "… = committee_size * count (lift_profile A) {x}"
by simp
also have "l * (l' * n_voters) = l' * (l * n_voters)"
by (simp add: algebra_simps)
finally have "count (r (lift_profile A)) x ≥ l'"
by (intro weak_proportional_representation A')
thus "count ((r ∘ lift_profile) A) x ≥ l'"
by simp
qed
end
subsection ‹Decreasing the number of parties›
text ‹
If we have a PAPP rule that satisfies weak representation and cardinality strategyproofness,
for $m$ parties, we can turn it into one for $m-1$ parties. This is done by simply
duplicating one particular party (say ‹x›) in the preference profile, i.e.\ whenever
‹x› is part of an approval list, we add a clone of ‹x› (say ‹y›) as well. Should ‹y› then end up
in the committee, we simply replace it with ‹x›.
Consequently, if we have an impossibility result for $k$ parties, it also holds for
$\geq m$ parties.
›
locale remove_alt_card_stratproof_weak_rep_anon_papp =
card_stratproof_weak_rep_anon_papp n_voters parties committee_size r
for n_voters and parties :: "'a set" and committee_size r +
fixes x y :: 'a
assumes xy: "x ∈ parties" "y ∈ parties" "x ≠ y"
begin
definition lift_applist :: "'a set ⇒ 'a set" where
"lift_applist X = (if x ∈ X then insert y X else X)"
definition lift_profile :: "'a set multiset ⇒ 'a set multiset" where
"lift_profile A = image_mset lift_applist A"
definition lower_result where "lower_result C = image_mset (λz. if z = y then x else z) C"
definition lowered where "lowered = lower_result ∘ r ∘ lift_profile"
lemma lift_profile_empty [simp]: "lift_profile {#} = {#}"
by (simp add: lift_profile_def)
lemma lift_profile_add_mset [simp]:
"lift_profile (add_mset X A) = add_mset (lift_applist X) (lift_profile A)"
by (simp add: lift_profile_def)
lemma empty_in_lift_profile_iff [simp]: "{} ∈# lift_profile A ⟷ {} ∈# A"
by (auto simp: lift_applist_def lift_profile_def)
lemma size_lift_profile [simp]: "size (lift_profile A) = size A"
by (simp add: lift_profile_def)
lemma lift_applist_eq_self_iff [simp]: "lift_applist X = X ⟷ x ∉ X ∨ y ∈ X"
by (auto simp: lift_applist_def)
lemma lift_applist_eq_self_iff' [simp]: "lift_applist (X - {y}) = X ⟷ (x ∈ X ⟷ y ∈ X)"
by (cases "y ∈ X") (auto simp: lift_applist_def xy)
lemma in_lift_applist_iff: "z ∈ lift_applist X ⟷ z ∈ X ∨ (z = y ∧ x ∈ X)"
by (auto simp: lift_applist_def)
lemma count_lift_profile:
assumes "∀Y∈#A. y ∉ Y"
shows "count (lift_profile A) X = (if x ∈ X ⟷ y ∈ X then count A (X - {y}) else 0)"
using assms xy by (induction A) (auto simp: lift_applist_def)
lemma y_notin_lower_result [simp]: "y ∉# lower_result C"
using xy by (auto simp: lower_result_def)
lemma lower_result_subset: "set_mset (lower_result C) ⊆ insert x (set_mset C - {y})"
using xy by (auto simp: lower_result_def)
lemma lower_result_subset': "set_mset C ⊆ parties ⟹ set_mset (lower_result C) ⊆ parties"
using xy by (auto simp: lower_result_def)
lemma size_lower_result [simp]: "size (lower_result C) = size C"
by (simp add: lower_result_def)
lemma count_lower_result:
"count (lower_result C) z =
(if z = y then 0
else if z = x then count C x + count C y
else count C z)"
using xy by (induction C) (auto simp: lower_result_def)
lemma in_lower_result_iff:
"z ∈# lower_result C ⟷ z ≠ y ∧ (z ∈# C ∨ (z = x ∧ y ∈# C))"
unfolding lower_result_def using xy by (induction C) auto
sublocale lowered: anon_papp_election n_voters "parties - {y}"
by standard (use n_voters_pos xy in auto)
lemma is_pref_profile_lift_profile [intro]:
assumes "lowered.is_pref_profile A"
shows "is_pref_profile (lift_profile A)"
proof -
interpret anon_papp_profile n_voters "parties - {y}" committee_size A
by fact
show ?thesis
using A_nonempty A_subset size_A
by unfold_locales
(auto simp: lift_profile_def lift_applist_def xy
size_mset_sum_mset image_mset.compositionality o_def)
qed
sublocale lowered: anon_papp n_voters "parties - {y}" committee_size lowered
proof
fix A assume "lowered.is_pref_profile A"
hence "is_pref_profile (lift_profile A)"
by blast
hence "is_committee (r (lift_profile A))"
using rule_wf by blast
thus "lowered.is_committee (lowered A)"
unfolding lowered.is_committee_def is_committee_def lowered_def
using lower_result_subset'[of "r (lift_profile A)"] by auto
qed
sublocale lowered: weak_rep_anon_papp n_voters "parties - {y}" committee_size lowered
proof
fix A z
assume A: "lowered.is_pref_profile A" and z: "n_voters ≤ committee_size * count A {z}"
interpret A: anon_papp_profile n_voters "parties - {y}" committee_size A
by fact
have "committee_size > 0"
using z n_voters_pos by (intro Nat.gr0I) auto
from A have A': "is_pref_profile (lift_profile A)"
by blast
have "count A {z} > 0"
using z n_voters_pos by (intro Nat.gr0I) auto
hence "{z} ∈# A"
by simp
hence z': "z ∈ parties - {y}"
using A.A_subset z by auto
define C where "C = r (lift_profile A)"
show "z ∈# lowered A"
proof (cases "z = x")
case False
have "n_voters ≤ committee_size * count A {z}"
by fact
also have "count A {z} ≤ count (lift_profile A) {z}"
using A.A_subset z' False by (subst count_lift_profile) auto
hence "committee_size * count A {z} ≤ committee_size * count (lift_profile A) {z}"
by (intro mult_left_mono) auto
finally have "z ∈# r (lift_profile A)"
by (intro weak_representation A')
thus "z ∈# lowered A"
using False z' by (simp add: lowered_def in_lower_result_iff)
next
case [simp]: True
have "1 ≤ size {#z ∈# C. z ∈ {x, y}#}"
unfolding C_def
proof (rule proposition3)
have [simp]: "{x, y} - {y} = {x}"
using xy by auto
hence "n_voters ≤ committee_size * count (lift_profile A) {x, y}"
using xy A.A_subset z by (subst count_lift_profile) auto
thus "int 1 * ⌈real n_voters / real committee_size⌉ ≤ int (count (lift_profile A) {x, y})"
using ‹committee_size > 0›
by (auto simp: ceiling_le_iff field_simps simp flip: of_nat_mult)
qed (use A' xy ‹committee_size > 0› in auto)
also have "… = count C x + count C y"
using xy by (induction C) auto
also have "… = count (lowered A) x"
using xy by (simp add: lowered_def count_lower_result C_def)
finally show "z ∈# lowered A"
by simp
qed
qed
lemma filter_lower_result_eq:
"y ∉ X ⟹ {#x ∈# lower_result C. x ∈ X#} = lower_result {#x ∈# C. x ∈ lift_applist X#}"
by (induction C) (auto simp: lower_result_def lift_applist_def)
sublocale lowered: card_stratproof_anon_papp n_voters "parties - {y}" committee_size lowered
proof
fix A X Y
show "¬lowered.card_manipulable A X Y"
unfolding lowered.card_manipulable_def
proof (rule notI, elim conjE)
assume A: "lowered.is_pref_profile A" and XY: "X ∈# A" "Y ≠ {}" "Y ⊆ parties - {y}"
assume *: "lowered A ≺[lowered.committee_preference X] lowered (A - {#X#} + {#Y#})"
interpret anon_papp_profile n_voters "parties - {y}" committee_size A
by fact
have X: "X ≠ {}" "X ⊆ parties - {y}"
using XY A_nonempty A_subset by auto
define A' where "A' = A - {#X#}"
have A': "A = A' + {#X#}"
using XY by (simp add: A'_def)
from * have "size {#x ∈# lower_result (r (lift_profile A' + {#lift_applist X#})). x ∈ X#} <
size {#x ∈# lower_result (r (lift_profile A' + {#lift_applist Y#})). x ∈ X#}"
by (simp add: lowered_def A' lowered.strong_committee_preference_iff)
also have "{#x ∈# lower_result (r (lift_profile A' + {#lift_applist X#})). x ∈ X#} =
lower_result {#x ∈# r (lift_profile A' + {#lift_applist X#}). x ∈ lift_applist X#}"
using X by (subst filter_lower_result_eq) auto
also have "{#x ∈# lower_result (r (lift_profile A' + {#lift_applist Y#})). x ∈ X#} =
lower_result {#x ∈# r (lift_profile A' + {#lift_applist Y#}). x ∈ lift_applist X#}"
using X by (subst filter_lower_result_eq) auto
finally have "size {#x ∈# r (lift_profile A' + {#lift_applist X#}). x ∈ lift_applist X#} <
size {#x ∈# r (lift_profile A' + {#lift_applist Y#}). x ∈ lift_applist X#}"
by simp
hence "r (lift_profile A' + {#lift_applist X#}) ≺[committee_preference (lift_applist X)]
r (lift_profile A' + {#lift_applist Y#})"
by (simp add: strong_committee_preference_iff)
moreover have "¬r (lift_profile A' + {#lift_applist X#}) ≺[committee_preference (lift_applist X)]
r (lift_profile A' + {#lift_applist Y#})"
proof (rule not_manipulable' [where Y = "lift_applist Y"])
have "is_pref_profile (lift_profile A)"
using A by blast
thus "is_pref_profile (lift_profile A' + {#lift_applist X#})"
using A by (simp add: A')
next
have "is_pref_profile (lift_profile (A - {#X#} + {#Y#}))"
using A XY lowered.is_pref_profile_replace by blast
thus "is_pref_profile (lift_profile A' + {#lift_applist Y#})"
by (simp add: A')
qed auto
ultimately show False
by contradiction
qed
qed
sublocale lowered: card_stratproof_weak_rep_anon_papp n_voters "parties - {y}" committee_size lowered
..
end
text ‹
The following lemma is now simply an iterated application of the above. This allows us to
restrict a P-APP rule to any non-empty subset of parties.
›
lemma card_stratproof_weak_rep_anon_papp_restrict_parties:
assumes "card_stratproof_weak_rep_anon_papp n parties k r" "parties' ⊆ parties" "parties' ≠ {}"
shows "∃r. card_stratproof_weak_rep_anon_papp n parties' k r"
proof -
have "finite parties"
proof -
interpret card_stratproof_weak_rep_anon_papp n parties k r
by fact
show ?thesis
by (rule finite_parties)
qed
thus ?thesis
using assms
proof (induction parties arbitrary: r rule: finite_psubset_induct)
case (psubset parties r)
show ?thesis
proof (cases "parties = parties'")
case True
thus ?thesis
using psubset.prems by auto
next
case False
obtain x where x: "x ∈ parties'"
using psubset.prems by blast
from False and psubset.prems have "parties - parties' ≠ {}"
by auto
then obtain y where y: "y ∈ parties - parties'"
by blast
interpret card_stratproof_weak_rep_anon_papp n parties k r
by fact
interpret remove_alt_card_stratproof_weak_rep_anon_papp n parties k r x y
by standard (use x y psubset.prems in auto)
show ?thesis
proof (rule psubset.IH)
show "parties - {y} ⊂ parties" and "parties' ⊆ parties - {y}" "parties' ≠ {}"
using x y psubset.prems by auto
next
show "card_stratproof_weak_rep_anon_papp n (parties - {y}) k lowered"
using lowered.card_stratproof_weak_rep_anon_papp_axioms .
qed
qed
qed
qed
subsection ‹Decreasing the committee size›
text ‹
If we have a PAPP rule that satisfies weak representation and cardinality strategyproofness,
for $l(k+1)$ voters, $m+1$ parties, and a committee size of $k+1$, we can turn it into
one for $lk$ voters, $m$ parties, and a committee size of $k$.
This is done by again cloning a party ‹x› into a new party ‹y› and additionally
adding ‹l› new voters whose preferences are ‹{x, y}›. We again replace any ‹y› occuring in the
output committee with ‹x›. Weak representation then ensures that ‹x› occurs in the output
at least once, and we then simply remove one ‹x› from the committee to obtain an output
committee of size ‹k - 1›.
Consequently, if we have an impossibility result for a committee size of $m$, we can
extend it to a larger committee size, but at the cost of introducing a new party
and new voters, and with a restriction on the number of voters.
›
locale decrease_committee_card_stratproof_weak_rep_anon_papp =
card_stratproof_weak_rep_anon_papp "l * (k + 1)" "insert y parties" "k + 1" r
for l k y and parties :: "'a set" and r +
fixes x :: 'a
assumes xy: "x ∈ parties" "y ∉ parties"
assumes k: "k > 0"
begin
definition lift_applist :: "'a set ⇒ 'a set" where
"lift_applist X = (if x ∈ X then insert y X else X)"
definition lift_profile :: "'a set multiset ⇒ 'a set multiset" where
"lift_profile A = image_mset lift_applist A + replicate_mset l {x, y}"
definition lower_result
where "lower_result C = image_mset (λz. if z = y then x else z) C - {#x#}"
definition lowered where "lowered = lower_result ∘ r ∘ lift_profile"
lemma l: "l > 0"
using n_voters_pos by auto
lemma x_neq_y [simp]: "x ≠ y" "y ≠ x"
using xy by auto
lemma lift_profile_empty [simp]: "lift_profile {#} = replicate_mset l {x, y}"
by (simp add: lift_profile_def)
lemma lift_profile_add_mset [simp]:
"lift_profile (add_mset X A) = add_mset (lift_applist X) (lift_profile A)"
by (simp add: lift_profile_def)
lemma empty_in_lift_profile_iff [simp]: "{} ∈# lift_profile A ⟷ {} ∈# A"
by (auto simp: lift_applist_def lift_profile_def)
lemma size_lift_profile [simp]: "size (lift_profile A) = size A + l"
by (simp add: lift_profile_def)
lemma lift_applist_eq_self_iff [simp]: "lift_applist X = X ⟷ x ∉ X ∨ y ∈ X"
by (auto simp: lift_applist_def)
lemma lift_applist_eq_self_iff' [simp]: "lift_applist (X - {y}) = X ⟷ (x ∈ X ⟷ y ∈ X)"
by (cases "y ∈ X") (auto simp: lift_applist_def xy)
lemma in_lift_applist_iff: "z ∈ lift_applist X ⟷ z ∈ X ∨ (z = y ∧ x ∈ X)"
by (auto simp: lift_applist_def)
lemma count_lift_profile:
assumes "∀Y∈#A. y ∉ Y"
shows "count (lift_profile A) X =
(if x ∈ X ⟷ y ∈ X then count A (X - {y}) else 0) +
(if X = {x, y} then l else 0)"
using assms xy by (induction A) (auto simp: lift_applist_def)
lemma y_notin_lower_result [simp]: "y ∉# lower_result C"
using xy by (auto simp: lower_result_def dest: in_diffD)
lemma lower_result_subset: "set_mset (lower_result C) ⊆ insert x (set_mset C - {y})"
using xy by (auto simp: lower_result_def dest: in_diffD)
lemma lower_result_subset': "set_mset C ⊆ insert y parties ⟹ set_mset (lower_result C) ⊆ parties"
by (rule order.trans[OF lower_result_subset]) (use xy in auto)
lemma size_lower_result [simp]:
assumes "x ∈# C ∨ y ∈# C"
shows "size (lower_result C) = size C - 1"
using assms by (auto simp: lower_result_def size_Diff_singleton)
lemma size_lower_result': "size (lower_result C) = size C - (if x ∈# C ∨ y ∈# C then 1 else 0)"
proof -
define f where "f = (λC. image_mset (λz. if z = y then x else z) C)"
have "size (lower_result C) = size (f C - {#x#})"
by (simp add: lower_result_def f_def)
also have "… = size (f C) - (if x ∈# f C then 1 else 0)"
by (simp add: diff_single_trivial size_Diff_singleton)
finally show ?thesis
by (auto simp: f_def)
qed
lemma count_lower_result:
"count (lower_result C) z =
(if z = y then 0
else if z = x then count C x + count C y - 1
else count C z)" (is "_ = ?rhs")
proof -
define f where "f = (λC. image_mset (λz. if z = y then x else z) C)"
have "count (lower_result C) z = count (f C - {#x#}) z"
by (simp add: lower_result_def f_def)
also have "… = count (f C) z - (if z = x then 1 else 0)"
by auto
also have "count (f C) z = (if z = y then 0 else if z = x then count C x + count C y else count C z)"
using xy by (induction C) (auto simp: f_def)
also have "… - (if z = x then 1 else 0) = ?rhs"
by auto
finally show ?thesis .
qed
lemma in_lower_resultD:
"z ∈# lower_result C ⟹ z = x ∨ z ∈# C"
using xy by (auto simp: lower_result_def dest!: in_diffD)
lemma in_lower_result_iff:
"z ∈# lower_result C ⟷ z ≠ y ∧ (if z = x then count C x + count C y > 1 else z ∈# C)"
(is "_ = ?rhs")
proof -
have "z ∈# lower_result C ⟷ count (lower_result C) z > 0"
by auto
also have "… ⟷ ?rhs"
by (subst count_lower_result) auto
finally show ?thesis .
qed
lemma filter_lower_result_eq:
assumes "y ∉ X"
shows "{#z ∈# lower_result C. z ∈ X#} = lower_result {#z ∈# C. z ∈ lift_applist X#}"
proof -
define f where "f = (λC. {#if z = y then x else z. z ∈# C#})"
have "lower_result {#z ∈# C. z ∈ lift_applist X#} = f {#z ∈# C. z ∈ lift_applist X#} - {#x#}"
by (simp add: f_def lower_result_def)
also have "f {#z ∈# C. z ∈ lift_applist X#} = {#z ∈# f C. z ∈ X#}"
using assms by (induction C) (auto simp: f_def lift_applist_def)
also have "… - {#x#} = {#z ∈# f C - {#x#}. z ∈ X#}"
by (subst filter_diff_mset') auto
also have "f C - {#x#} = lower_result C"
by (simp add: f_def lower_result_def)
finally show ?thesis ..
qed
sublocale lowered: anon_papp_election "l * k" parties k
by standard (use n_voters_pos xy finite_parties k in auto)
lemma is_pref_profile_lift_profile [intro]:
assumes "lowered.is_pref_profile A"
shows "is_pref_profile (lift_profile A)"
proof -
interpret A: anon_papp_profile "l * k" parties k A
by fact
show ?thesis
using A.A_nonempty A.A_subset A.size_A l
by unfold_locales
(auto simp: lift_profile_def lift_applist_def xy
size_mset_sum_mset image_mset.compositionality o_def)
qed
lemma is_committee_lower_result:
assumes "is_committee C" "x ∈# C ∨ y ∈# C"
shows "lowered.is_committee (lower_result C)"
using assms unfolding is_committee_def lowered.is_committee_def
using lower_result_subset'[of C] by auto
lemma x_or_y_in_r_lift_profile:
assumes "lowered.is_pref_profile A"
shows "x ∈# r (lift_profile A) ∨ y ∈# r (lift_profile A)"
proof -
interpret A: anon_papp_profile "l * k" parties k A
by fact
have "size {#z ∈# r (lift_profile A). z ∈ {x, y}#} ≥ 1"
proof (rule proposition3)
have "real (l * (k + 1)) / real (k + 1) = real l"
by (simp add: field_simps)
also have "int 1 * ⌈…⌉ = int l"
by simp
also have "l ≤ count (lift_profile A) {x, y}"
using xy A.A_subset by (subst count_lift_profile) auto
finally show "int 1 * ⌈real (l * (k + 1)) / real (k + 1)⌉ ≤ int (count (lift_profile A) {x, y})"
by simp
next
show "is_pref_profile (lift_profile A)"
by (intro is_pref_profile_lift_profile) fact
qed (use xy in auto)
hence "{#z ∈# r (lift_profile A). z ∈ {x, y}#} ≠ {#}"
by force
thus ?thesis
by auto
qed
sublocale lowered: anon_papp "l * k" parties k lowered
proof
fix A assume A: "lowered.is_pref_profile A"
hence "is_pref_profile (lift_profile A)"
by blast
hence "is_committee (r (lift_profile A))"
using rule_wf by blast
thus "lowered.is_committee (lowered A)"
unfolding lowered_def o_def using x_or_y_in_r_lift_profile[of A] A
by (intro is_committee_lower_result) auto
qed
sublocale lowered: weak_rep_anon_papp "l * k" parties k lowered
proof
fix A z
assume A: "lowered.is_pref_profile A" and z: "l * k ≤ k * count A {z}"
interpret A: anon_papp_profile "l * k" "parties" k A
by fact
from A have A': "is_pref_profile (lift_profile A)"
by blast
have "count A {z} > 0"
using z k n_voters_pos by (intro Nat.gr0I) auto
hence "{z} ∈# A"
by simp
hence z': "z ∈ parties"
using A.A_subset z by auto
hence [simp]: "y ≠ z" "z ≠ y"
using xy by auto
define C where "C = r (lift_profile A)"
show "z ∈# lowered A"
proof (cases "z = x")
case False
have "l ≤ count A {z}"
using z k by (simp add: algebra_simps)
hence "l * (k + 1) ≤ (k + 1) * count A {z}"
by (subst mult.commute, intro mult_right_mono) auto
also have "count A {z} = count (lift_profile A) {z}"
using False A.A_subset xy by (subst count_lift_profile) auto
finally have "z ∈# r (lift_profile A)"
by (intro weak_representation A')
thus "z ∈# lowered A"
using False by (auto simp: lowered_def in_lower_result_iff)
next
case [simp]: True
from xy have [simp]: "{x, y} - {y} = {x}"
by auto
have "size {#z ∈# C. z ∈ {x, y}#} ≥ 2"
unfolding C_def
proof (rule proposition3)
have "real (l * (k + 1)) / real (k + 1) = l"
unfolding of_nat_mult using k by (simp add: divide_simps)
also have "int 2 * ⌈…⌉ = int (2 * l)"
by simp
also have "… ≤ count (lift_profile A) {x, y}"
using z k xy A.A_subset by (subst count_lift_profile) auto
finally show "int 2 * ⌈real (l * (k + 1)) / real (k + 1)⌉ ≤ …" .
qed (use A' xy in auto)
also have "size {#z ∈# C. z ∈ {x, y}#} = count C x + count C y"
by (induction C) auto
finally have "x ∈# lower_result C"
by (subst in_lower_result_iff) auto
thus "z ∈# lowered A"
by (simp add: lowered_def C_def)
qed
qed
sublocale lowered: card_stratproof_anon_papp "l * k" parties k lowered
proof
fix A X Y
show "¬lowered.card_manipulable A X Y"
unfolding lowered.card_manipulable_def
proof (rule notI, elim conjE)
assume A: "lowered.is_pref_profile A" and XY: "X ∈# A" "Y ≠ {}" "Y ⊆ parties"
assume *: "lowered A ≺[lowered.committee_preference X] lowered (A - {#X#} + {#Y#})"
interpret anon_papp_profile "l * k" "parties" k A
by fact
have X: "X ≠ {}" "X ⊆ parties"
using XY A_nonempty A_subset by auto
define A' where "A' = A - {#X#}"
have A': "A = A' + {#X#}"
using XY by (simp add: A'_def)
from xy X XY have [simp]: "y ∉ X" "y ∉ Y"
by auto
define Al1 where "Al1 = lift_profile A"
define Al2 where "Al2 = lift_profile (A' + {#Y#})"
have A'_plus_Y: "lowered.is_pref_profile (A' + {#Y#})"
unfolding A'_def using A XY lowered.is_pref_profile_replace by blast
have Al1: "is_pref_profile Al1"
unfolding Al1_def using A by blast
have Al2: "is_pref_profile Al2"
unfolding Al2_def unfolding A'_def using A XY lowered.is_pref_profile_replace by blast
have size_aux: "size (lower_result {#x ∈# r (lift_profile A). x ∈ lift_applist X#}) =
size {#x ∈# r (lift_profile A). x ∈ lift_applist X#} - (if x ∈ X then 1 else 0)"
if A: "lowered.is_pref_profile A" for A
using x_or_y_in_r_lift_profile[OF A]
by (subst size_lower_result') (auto simp: lift_applist_def)
from * have "size {#x ∈# lower_result (r Al1). x ∈ X#} <
size {#x ∈# lower_result (r Al2). x ∈ X#}"
by (simp add: Al1_def Al2_def lowered_def A' lowered.strong_committee_preference_iff)
also have "{#x ∈# lower_result (r Al1). x ∈ X#} = lower_result {#x ∈# r Al1. x ∈ lift_applist X#}"
using X xy by (subst filter_lower_result_eq) auto
also have "{#x ∈# lower_result (r Al2). x ∈ X#} = lower_result {#x ∈# r Al2. x ∈ lift_applist X#}"
using X xy by (subst filter_lower_result_eq) auto
also have "size (lower_result {#x ∈# r Al1. x ∈ lift_applist X#}) =
size {#x ∈# r Al1. x ∈ lift_applist X#} - (if x ∈ X then 1 else 0)"
unfolding Al1_def by (rule size_aux) fact
also have "size (lower_result {#x ∈# r Al2. x ∈ lift_applist X#}) =
size {#x ∈# r Al2. x ∈ lift_applist X#} - (if x ∈ X then 1 else 0)"
unfolding Al2_def by (rule size_aux) fact
finally have "size {#x ∈# r Al1. x ∈ lift_applist X#} < size {#x ∈# r Al2. x ∈ lift_applist X#}"
by auto
hence "r Al1 ≺[committee_preference (lift_applist X)] r Al2"
by (simp add: strong_committee_preference_iff)
moreover have "¬r Al1 ≺[committee_preference (lift_applist X)] r Al2"
by (rule not_manipulable' [where Y = "lift_applist Y"])
(use Al1 Al2 in ‹auto simp: Al1_def Al2_def A'›)
ultimately show False
by contradiction
qed
qed
sublocale lowered: card_stratproof_weak_rep_anon_papp "l * k" parties k lowered
..
end
text ‹
For Weak ∗‹Proportional› Representation, the lowering argument to decrease the committee size
is somewhat easier since it does not involve adding a new party; instead, we simply
add ‹l› new voters whose preferences are ‹{x}›.
›
locale decrease_committee_card_stratproof_weak_prop_rep_anon_papp =
card_stratproof_weak_prop_rep_anon_papp "l * (k + 1)" parties "k + 1" r
for l k and parties :: "'a set" and r +
fixes x :: 'a
assumes x: "x ∈ parties"
assumes k: "k > 0"
begin
definition lift_profile :: "'a set multiset ⇒ 'a set multiset" where
"lift_profile A = A + replicate_mset l {x}"
definition lower_result
where "lower_result C = C - {#x#}"
definition lowered where "lowered = lower_result ∘ r ∘ lift_profile"
lemma l: "l > 0"
using n_voters_pos by auto
lemma lift_profile_empty [simp]: "lift_profile {#} = replicate_mset l {x}"
by (simp add: lift_profile_def)
lemma lift_profile_add_mset [simp]:
"lift_profile (add_mset X A) = add_mset X (lift_profile A)"
by (simp add: lift_profile_def)
lemma empty_in_lift_profile_iff [simp]: "{} ∈# lift_profile A ⟷ {} ∈# A"
by (auto simp: lift_profile_def)
lemma size_lift_profile [simp]: "size (lift_profile A) = size A + l"
by (simp add: lift_profile_def)
lemma count_lift_profile:
"count (lift_profile A) X = count A X + (if X = {x} then l else 0)"
by (auto simp: lift_profile_def)
lemma size_lower_result [simp]:
assumes "x ∈# C"
shows "size (lower_result C) = size C - 1"
using assms by (auto simp: lower_result_def size_Diff_singleton)
lemma size_lower_result': "size (lower_result C) = size C - (if x ∈# C then 1 else 0)"
by (induction C) (auto simp: lower_result_def size_Diff_singleton)
lemma count_lower_result:
"count (lower_result C) z = count C z - (if z = x then 1 else 0)"
by (auto simp: lower_result_def)
lemma in_lower_resultD:
"z ∈# lower_result C ⟹ z ∈# C"
by (auto simp: lower_result_def dest!: in_diffD)
lemma in_lower_result_iff:
"z ∈# lower_result C ⟷ (if z = x then count C x > 1 else z ∈# C)"
(is "_ = ?rhs")
proof -
have "z ∈# lower_result C ⟷ count (lower_result C) z > 0"
by auto
also have "… ⟷ ?rhs"
by (subst count_lower_result) auto
finally show ?thesis .
qed
sublocale lowered: anon_papp_election "l * k" parties k
by standard (use n_voters_pos finite_parties k in auto)
lemma is_pref_profile_lift_profile [intro]:
assumes "lowered.is_pref_profile A"
shows "is_pref_profile (lift_profile A)"
proof -
interpret A: anon_papp_profile "l * k" parties k A
by fact
show ?thesis
using A.A_nonempty A.A_subset A.size_A l
by unfold_locales
(auto simp: lift_profile_def x size_mset_sum_mset image_mset.compositionality o_def)
qed
lemma is_committee_lower_result:
assumes "is_committee C" "x ∈# C"
shows "lowered.is_committee (lower_result C)"
using assms unfolding is_committee_def lowered.is_committee_def
by (auto simp: lower_result_def size_Diff_singleton dest: in_diffD)
lemma x_in_r_lift_profile:
assumes "lowered.is_pref_profile A"
shows "x ∈# r (lift_profile A)"
proof (rule weak_representation)
show "is_pref_profile (lift_profile A)"
using assms by blast
next
have "(k + 1) * l ≤ (k + 1) * count (lift_profile A) {x}"
by (intro mult_left_mono) (auto simp: count_lift_profile)
thus "l * (k + 1) ≤ (k + 1) * count (lift_profile A) {x}"
by (simp add: algebra_simps)
qed
sublocale lowered: anon_papp "l * k" parties k lowered
proof
fix A assume A: "lowered.is_pref_profile A"
hence "is_pref_profile (lift_profile A)"
by blast
hence "is_committee (r (lift_profile A))"
using rule_wf by blast
thus "lowered.is_committee (lowered A)"
unfolding lowered_def o_def using x_in_r_lift_profile[of A] A
by (intro is_committee_lower_result) auto
qed
sublocale lowered: weak_prop_rep_anon_papp "l * k" parties k lowered
proof
fix A z l'
assume A: "lowered.is_pref_profile A" and z: "l' * (l * k) ≤ k * count A {z}"
interpret A: anon_papp_profile "l * k" "parties" k A
by fact
show "count (lowered A) z ≥ l'"
proof (cases "l' > 0")
case False
thus ?thesis by auto
next
case l: True
from A have A': "is_pref_profile (lift_profile A)"
by blast
have "count A {z} > 0"
using z k n_voters_pos l by (intro Nat.gr0I) auto
hence "{z} ∈# A"
by simp
hence z': "z ∈ parties"
using A.A_subset z by auto
define C where "C = r (lift_profile A)"
show "count (lowered A) z ≥ l'"
proof (cases "z = x")
case False
have "l' * l ≤ count A {z}"
using z k by (simp add: algebra_simps)
hence "l' * l * (k + 1) ≤ (k + 1) * count A {z}"
by (subst mult.commute, intro mult_right_mono) auto
also have "count A {z} = count (lift_profile A) {z}"
using False A.A_subset by (subst count_lift_profile) auto
finally have "count (r (lift_profile A)) z ≥ l'"
by (intro weak_proportional_representation A') (auto simp: algebra_simps)
thus "l' ≤ count (lowered A) z"
using False by (simp add: lowered_def lower_result_def)
next
case [simp]: True
have "l' * l ≤ count A {x}"
using z k by (simp add: algebra_simps)
hence "l' * l * (k + 1) ≤ (k + 1) * count A {x}"
by (subst mult.commute, intro mult_right_mono) auto
also have "… + (k + 1) * l = (k + 1) * count (lift_profile A) {x}"
by (simp add: count_lift_profile algebra_simps)
finally have "(l' + 1) * (l * (k + 1)) ≤ (k + 1) * count (lift_profile A) {x}"
by (simp add: algebra_simps)
hence "count (r (lift_profile A)) x ≥ l' + 1"
by (intro weak_proportional_representation A')
thus "l' ≤ count (lowered A) z"
by (simp add: lowered_def lower_result_def)
qed
qed
qed
sublocale lowered: card_stratproof_anon_papp "l * k" parties k lowered
proof
fix A X Y
show "¬lowered.card_manipulable A X Y"
unfolding lowered.card_manipulable_def
proof (rule notI, elim conjE)
assume A: "lowered.is_pref_profile A" and XY: "X ∈# A" "Y ≠ {}" "Y ⊆ parties"
assume *: "lowered A ≺[lowered.committee_preference X] lowered (A - {#X#} + {#Y#})"
interpret anon_papp_profile "l * k" "parties" k A
by fact
have X: "X ≠ {}" "X ⊆ parties"
using XY A_nonempty A_subset by auto
define A' where "A' = A - {#X#}"
have A': "A = A' + {#X#}"
using XY by (simp add: A'_def)
define Al1 where "Al1 = lift_profile A"
define Al2 where "Al2 = lift_profile (A' + {#Y#})"
have A'_plus_Y: "lowered.is_pref_profile (A' + {#Y#})"
unfolding A'_def using A XY lowered.is_pref_profile_replace by blast
have Al1: "is_pref_profile Al1"
unfolding Al1_def using A by blast
have Al2: "is_pref_profile Al2"
unfolding Al2_def unfolding A'_def using A XY lowered.is_pref_profile_replace by blast
have size_aux: "size (lower_result {#x ∈# r (lift_profile A). x ∈ X#}) =
size {#x ∈# r (lift_profile A). x ∈ X#} - (if x ∈ X then 1 else 0)"
if A: "lowered.is_pref_profile A" for A
using x_in_r_lift_profile[OF A] by (subst size_lower_result') auto
from * have "size {#x ∈# lower_result (r Al1). x ∈ X#} <
size {#x ∈# lower_result (r Al2). x ∈ X#}"
by (simp add: Al1_def Al2_def lowered_def A' lowered.strong_committee_preference_iff)
also have "{#x ∈# lower_result (r Al1). x ∈ X#} = lower_result {#x ∈# r Al1. x ∈ X#}"
using X x unfolding lower_result_def by (subst filter_diff_mset') auto
also have "{#x ∈# lower_result (r Al2). x ∈ X#} = lower_result {#x ∈# r Al2. x ∈ X#}"
using X x unfolding lower_result_def by (subst filter_diff_mset') auto
also have "size (lower_result {#x ∈# r Al1. x ∈ X#}) =
size {#x ∈# r Al1. x ∈ X#} - (if x ∈ X then 1 else 0)"
unfolding Al1_def by (rule size_aux) fact
also have "size (lower_result {#x ∈# r Al2. x ∈ X#}) =
size {#x ∈# r Al2. x ∈ X#} - (if x ∈ X then 1 else 0)"
unfolding Al2_def by (rule size_aux) fact
finally have "size {#x ∈# r Al1. x ∈ X#} < size {#x ∈# r Al2. x ∈ X#}"
by auto
hence "r Al1 ≺[committee_preference X] r Al2"
by (simp add: strong_committee_preference_iff)
moreover have "¬r Al1 ≺[committee_preference X] r Al2"
by (rule not_manipulable' [where Y = "Y"])
(use Al1 Al2 in ‹auto simp: Al1_def Al2_def A'›)
ultimately show False
by contradiction
qed
qed
sublocale lowered: card_stratproof_weak_prop_rep_anon_papp "l * k" parties k lowered
..
end
end