Theory Rankings.Rankings
section ‹Rankings›
theory Rankings
imports
"HOL-Combinatorics.Multiset_Permutations"
"List-Index.List_Index"
"Randomised_Social_Choice.Order_Predicates"
begin
subsection ‹Preliminaries›
lemma find_index_map: "find_index P (map f xs) = find_index (λx. P (f x)) xs"
by (induction xs) auto
lemma map_index_self:
assumes "distinct xs"
shows "map (index xs) xs = [0..<length xs]"
proof -
have "xs = map (λi. xs ! i) [0..<length xs]"
by (simp add: map_nth)
also have "map (index xs) … = map id [0..<length xs]"
unfolding map_map by (intro map_cong) (use assms in ‹simp_all add: index_nth_id›)
finally show ?thesis
by simp
qed
lemma bij_betw_map_prod:
assumes "bij_betw f A B" "bij_betw g C D"
shows "bij_betw (map_prod f g) (A × C) (B × D)"
using assms unfolding bij_betw_def by (auto simp: inj_on_def)
definition comap_relation :: "('a ⇒ 'b) ⇒ 'a relation ⇒ 'b relation" where
"comap_relation f R = (λx y. ∃x' y'. x = f x' ∧ y = f y' ∧ R x' y')"
lemma is_weak_ranking_map_singleton_iff [simp]:
"is_weak_ranking (map (λx. {x}) xs) ⟷ distinct xs"
by (induction xs) (auto simp: is_weak_ranking_Cons)
lemma is_finite_weak_ranking_map_singleton_iff [simp]:
"is_finite_weak_ranking (map (λx. {x}) xs) ⟷ distinct xs"
by (induction xs) (auto simp: is_finite_weak_ranking_Cons)
lemma of_weak_ranking_altdef':
assumes "is_weak_ranking xs"
shows "of_weak_ranking xs x y ⟷ x ∈ ⋃(set xs) ∧ y ∈ ⋃(set xs) ∧
find_index ((∈) x) xs ≥ find_index ((∈) y) xs"
proof (cases "x ∈ ⋃(set xs) ∧ y ∈ ⋃(set xs)")
case True
thus ?thesis
using True of_weak_ranking_altdef[OF assms, of x y] by auto
next
case False
interpret total_preorder_on "⋃(set xs)" "of_weak_ranking xs"
by (rule total_preorder_of_weak_ranking) (use assms in auto)
have "¬of_weak_ranking xs x y"
using not_outside False by blast
thus ?thesis using False
by blast
qed
subsection ‹Definition›
text ‹
A ∗‹ranking› is a representation of a linear order on a finite set as a list in descending
order, starting with the biggest element. Clearly, this gives a bijection between the linear
orders on a finite set and the permutations of that set.
›
inductive of_ranking :: "'alt list ⇒ 'alt relation" where
"i ≤ j ⟹ i < length xs ⟹ j < length xs ⟹ xs ! i ≽[of_ranking xs] xs ! j"
lemma of_ranking_conv_of_weak_ranking:
"x ≽[of_ranking xs] y ⟷ x ≽[of_weak_ranking (map (λx. {x}) xs)] y"
unfolding of_ranking.simps of_weak_ranking.simps by fastforce
lemma of_ranking_imp_in_set:
assumes "of_ranking xs a b"
shows "a ∈ set xs" "b ∈ set xs"
using assms by (fastforce elim!: of_ranking.cases)+
lemma of_ranking_Nil [simp]: "of_ranking [] = (λ_ _. False)"
by (auto simp: of_ranking.simps fun_eq_iff)
lemma of_ranking_Nil' [code]: "of_ranking [] x y = False"
by simp
lemma of_ranking_Cons [code]:
"x ≽[of_ranking (z#zs)] y ⟷ x = z ∧ y ∈ set (z#zs) ∨ x ≽[of_ranking zs] y"
by (auto simp: of_ranking_conv_of_weak_ranking of_weak_ranking_Cons)
lemma of_ranking_Cons':
assumes "distinct (x#xs)" "a ∈ set (x#xs)" "b ∈ set (x#xs)"
shows "of_ranking (x#xs) a b ⟷ b = x ∨ (a ≠ x ∧ of_ranking xs a b)"
using assms of_ranking_imp_in_set[of xs a b] by (auto simp: of_ranking_Cons)
lemma of_ranking_append:
"x ≽[of_ranking (xs @ ys)] y ⟷ x ∈ set xs ∧ y ∈ set ys ∨ x ≽[of_ranking xs] y ∨ x ≽[of_ranking ys] y"
by (induction xs) (auto simp: of_ranking_Cons)
lemma of_ranking_strongly_preferred_Cons_iff:
assumes "distinct (x # xs)"
shows "a ≻[of_ranking (x # xs)] b ⟷ x = a ∧ b ∈ set xs ∨ a ≻[of_ranking xs] b"
using assms of_ranking_imp_in_set[of xs]
by (auto simp: strongly_preferred_def of_ranking_Cons)
lemma of_ranking_strongly_preferred_append_iff:
assumes "distinct (xs @ ys)"
shows "a ≻[of_ranking (xs @ ys)] b ⟷
a ∈ set xs ∧ b ∈ set ys ∨ a ≻[of_ranking xs] b ∨ a ≻[of_ranking ys] b"
using assms of_ranking_imp_in_set[of xs a b] of_ranking_imp_in_set[of ys a b]
of_ranking_imp_in_set[of xs b a] of_ranking_imp_in_set[of ys b a]
unfolding strongly_preferred_def of_ranking_append distinct_append set_eq_iff Int_iff empty_iff
by metis
lemma not_strongly_preferred_of_ranking_iff:
assumes "a ∈ set xs" "b ∈ set xs"
shows "¬a ≺[of_ranking xs] b ⟷ a ≽[of_ranking xs] b"
using assms unfolding strongly_preferred_def
by (metis index_less_size_conv linorder_le_cases nth_index of_ranking.intros)
lemma of_ranking_refl:
assumes "x ∈ set xs"
shows "x ≼[of_ranking xs] x"
using assms by (induction xs) (auto simp: of_ranking_Cons)
lemma of_ranking_altdef:
assumes "distinct xs" "x ∈ set xs" "y ∈ set xs"
shows "of_ranking xs x y ⟷ index xs x ≥ index xs y"
unfolding of_ranking_conv_of_weak_ranking
by (subst of_weak_ranking_altdef)
(use assms in ‹auto simp: index_def find_index_map eq_commute[of _ y] eq_commute[of _ x]›)
lemma of_ranking_altdef':
assumes "distinct xs"
shows "of_ranking xs x y ⟷ x ∈ set xs ∧ y ∈ set xs ∧ index xs x ≥ index xs y"
unfolding of_ranking_conv_of_weak_ranking
by (subst of_weak_ranking_altdef')
(use assms in ‹auto simp: index_def find_index_map eq_commute[of _ y] eq_commute[of _ x]›)
lemma of_ranking_nth_iff:
assumes "distinct xs" "i < length xs" "j < length xs"
shows "of_ranking xs (xs ! i) (xs ! j) ⟷ i ≥ j"
using assms by (simp add: index_nth_id of_ranking_altdef)
lemma strongly_preferred_of_ranking_nth_iff:
assumes "distinct xs" "i < length xs" "j < length xs"
shows "xs ! i ≻[of_ranking xs] xs ! j ⟷ i < j"
using assms by (auto simp: strongly_preferred_def of_ranking_nth_iff)
lemma of_ranking_total: "x ∈ set xs ⟹ y ∈ set xs ⟹ of_ranking xs x y ∨ of_ranking xs y x"
by (induction xs) (auto simp: of_ranking_Cons)
lemma of_ranking_antisym:
"x ∈ set xs ⟹ y ∈ set xs ⟹ of_ranking xs x y ⟹ of_ranking xs y x ⟹ distinct xs ⟹ x = y"
by (simp add: of_ranking_altdef')
lemma finite_linorder_of_ranking:
assumes "set xs = A" "distinct xs"
shows "finite_linorder_on A (of_ranking xs)"
proof -
interpret total_preorder_on A "of_ranking xs"
unfolding of_ranking_conv_of_weak_ranking
by (rule total_preorder_of_weak_ranking) (use assms in auto)
show ?thesis
proof
fix x y assume "of_ranking xs x y" "of_ranking xs y x"
thus "x = y"
by (metis assms(1,2) index_eq_index_conv nle_le not_outside(2) of_ranking_altdef)
qed (use assms(1) in auto)
qed
lemma linorder_of_ranking:
assumes "set xs = A" "distinct xs"
shows "linorder_on A (of_ranking xs)"
proof -
interpret finite_linorder_on A "of_ranking xs"
by (rule finite_linorder_of_ranking) fact+
show ?thesis ..
qed
lemma total_preorder_of_ranking:
assumes "set xs = A" "distinct xs"
shows "total_preorder_on A (of_ranking xs)"
unfolding of_ranking_conv_of_weak_ranking
by (rule total_preorder_of_weak_ranking) (use assms in auto)
subsection ‹Transformations›
lemma map_relation_of_ranking:
"map_relation f (of_ranking xs) = of_weak_ranking (map (λx. f -` {x}) xs)"
unfolding of_ranking_conv_of_weak_ranking of_weak_ranking_map map_map o_def ..
lemma of_ranking_map: "of_ranking (map f xs) = comap_relation f (of_ranking xs)"
by (induction xs) (auto simp: comap_relation_def of_ranking_Cons fun_eq_iff)
lemma of_ranking_permute':
assumes "f permutes set xs"
shows "map_relation f (of_ranking xs) = of_ranking (map (inv f) xs)"
unfolding of_ranking_conv_of_weak_ranking
by (subst of_weak_ranking_permute') (use assms in ‹auto simp: map_map o_def›)
lemma of_ranking_permute:
assumes "f permutes set xs"
shows "of_ranking (map f xs) = map_relation (inv f) (of_ranking xs)"
using of_ranking_permute'[OF permutes_inv[OF assms]] assms
by (simp add: inv_inv_eq permutes_bij)
lemma of_ranking_rev [simp]:
"of_ranking (rev xs) x y ⟷ of_ranking xs y x"
unfolding of_ranking_conv_of_weak_ranking by (simp flip: rev_map)
lemma of_ranking_filter:
"of_ranking (filter P xs) = restrict_relation {x. P x} (of_ranking xs)"
by (induction xs) (auto simp: of_ranking_Cons restrict_relation_def fun_eq_iff)
lemma strongly_preferred_of_ranking_conv_index:
assumes "distinct xs"
shows "x ≺[of_ranking xs] y ⟷ x ∈ set xs ∧ y ∈ set xs ∧ index xs x > index xs y"
unfolding strongly_preferred_def using of_ranking_altdef'[OF assms] by auto
lemma restrict_relation_of_weak_ranking_Cons:
assumes "distinct (x # xs)"
shows "restrict_relation (set xs) (of_ranking (x # xs)) = of_ranking xs"
proof -
from assms interpret R: total_preorder_on "set xs" "of_ranking xs"
by (intro total_preorder_of_ranking) auto
from assms show ?thesis using R.not_outside
by (intro ext) (auto simp: restrict_relation_def of_ranking_Cons)
qed
lemma of_ranking_zero_upt_nat:
"of_ranking [0::nat..<n] = (λx y. x ≥ y ∧ x < n)"
by (induction n) (auto simp: of_ranking_append of_ranking_Cons fun_eq_iff)
lemma of_ranking_rev_zero_upt_nat:
"of_ranking (rev [0::nat..<n]) = (λx y. x ≤ y ∧ y < n)"
by (induction n) (auto simp: of_ranking_Cons fun_eq_iff)
lemma sorted_wrt_ranking: "distinct xs ⟹ sorted_wrt (of_ranking xs) (rev xs)"
unfolding sorted_wrt_iff_nth_less by (force simp: of_ranking.simps rev_nth)
subsection ‹Inverse operation and isomorphism›
lemma (in finite_linorder_on) of_ranking_ranking: "of_ranking (ranking le) = le"
proof -
have "of_ranking (ranking le) =
of_weak_ranking (map (λx. {the_elem x}) (weak_ranking le))"
unfolding of_ranking_conv_of_weak_ranking ranking_def by (simp add: map_map o_def)
also have "map (λx. {the_elem x}) (weak_ranking le) = map (λx. x) (weak_ranking le)"
by (intro map_cong HOL.refl)
(metis is_singleton_the_elem singleton_weak_ranking)+
also have "of_weak_ranking (map (λx. x) (weak_ranking le)) = le"
using of_weak_ranking_weak_ranking[OF finite_total_preorder_on_axioms] by simp
finally show ?thesis .
qed
lemma (in finite_linorder_on) distinct_ranking: "distinct (ranking le)"
using weak_ranking_ranking weak_ranking_total_preorder(1) by simp
lemma ranking_of_ranking:
assumes "distinct xs"
shows "ranking (of_ranking xs) = xs"
proof -
have "ranking (of_ranking xs) = map the_elem (weak_ranking (of_weak_ranking (map (λx. {x}) xs)))"
unfolding ranking_def of_ranking_conv_of_weak_ranking ..
also have "… = xs"
by (subst weak_ranking_of_weak_ranking) (use assms in ‹auto simp: o_def›)
finally show ?thesis .
qed
lemma (in finite_linorder_on) set_ranking: "set (ranking le) = carrier"
using weak_ranking_Union weak_ranking_ranking by auto
lemma bij_betw_permutations_of_set_finite_linorders_on:
"bij_betw of_ranking (permutations_of_set A) {R. finite_linorder_on A R}"
by (rule bij_betwI[of _ _ _ ranking])
(auto simp: finite_linorder_on.of_ranking_ranking ranking_of_ranking
permutations_of_set_def finite_linorder_on.distinct_ranking
finite_linorder_on.set_ranking intro: finite_linorder_of_ranking)
lemma bij_betw_permutations_of_set_finite_linorders_on':
"bij_betw ranking {R. finite_linorder_on A R} (permutations_of_set A)"
by (rule bij_betwI[of _ _ _ of_ranking])
(auto simp: finite_linorder_on.of_ranking_ranking ranking_of_ranking
permutations_of_set_def finite_linorder_on.distinct_ranking
finite_linorder_on.set_ranking intro: finite_linorder_of_ranking)
lemma card_linorders_on:
assumes "finite A"
shows "card {R. linorder_on A R} = fact (card A)"
proof -
have "{R. linorder_on A R} = {R. finite_linorder_on A R}"
using assms by (simp add: finite_linorder_on_def finite_linorder_on_axioms_def)
also have "card … = card (permutations_of_set A)"
using bij_betw_same_card[OF bij_betw_permutations_of_set_finite_linorders_on[of A]] by simp
also have "… = fact (card A)"
using assms by simp
finally show ?thesis .
qed
lemma finite_linorders_on [intro]:
assumes "finite A"
shows "finite {R. linorder_on A R}"
proof -
from assms have "finite (permutations_of_set A)"
by simp
also have "finite (permutations_of_set A) ⟷ finite {R. finite_linorder_on A R}"
by (rule bij_betw_finite[OF bij_betw_permutations_of_set_finite_linorders_on])
also have "{R. finite_linorder_on A R} = {R. linorder_on A R}"
using assms by (simp add: finite_linorder_on_axioms.intro finite_linorder_on_def)
finally show ?thesis .
qed
end