(* Author: Amine Chaieb, University of Cambridge With various additions by Manuel Eberl
*)
section \<open>Permutations, both general and specifically on finite sets.\<close>
theory Permutations imports "HOL-Library.Multiset" "HOL-Library.Disjoint_Sets"
Transposition begin
subsection \<open>Auxiliary\<close>
abbreviation (input) fixpoints :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set\<close> where\<open>fixpoints f \<equiv> {x. f x = x}\<close>
lemma inj_on_fixpoints: \<open>inj_on f (fixpoints f)\<close> by (rule inj_onI) simp
lemma bij_betw_fixpoints: \<open>bij_betw f (fixpoints f) (fixpoints f)\<close> using inj_on_fixpoints by (auto simp add: bij_betw_def)
subsection \<open>Basic definition and consequences\<close>
definition permutes :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set \<Rightarrow> bool\<close> (infixr \<open>permutes\<close> 41) where\<open>p permutes S \<longleftrightarrow> (\<forall>x. x \<notin> S \<longrightarrow> p x = x) \<and> (\<forall>y. \<exists>!x. p x = y)\<close>
lemma bij_imp_permutes: \<open>p permutes S\<close> if \<open>bij_betw p S S\<close> and stable: \<open>\<And>x. x \<notin> S \<Longrightarrow> p x = x\<close> proof - note\<open>bij_betw p S S\<close> moreoverhave\<open>bij_betw p (- S) (- S)\<close> by (auto simp add: stable intro!: bij_betw_imageI inj_onI) ultimatelyhave\<open>bij_betw p (S \<union> - S) (S \<union> - S)\<close> by (rule bij_betw_combine) simp thenhave\<open>\<exists>!x. p x = y\<close> for y by (simp add: bij_iff) with stable show ?thesis by (simp add: permutes_def) qed
lemma inj_imp_permutes: assumes i: "inj_on f S"and fin: "finite S" and fS: "\x. x \ S \ f x \ S" and f: "\i. i \ S \ f i = i" shows"f permutes S" unfolding permutes_def proof (intro conjI allI impI, rule f) fix y from endo_inj_surj[OF fin _ i] fS have fs: "f ` S = S"by auto show"\!x. f x = y" proof (cases "y \ S") case False thus ?thesis by (intro ex1I[of _ y], insert fS f) force+ next case True with fs obtain x where x: "x \ S" and fx: "f x = y" by force show ?thesis proof (rule ex1I, rule fx) fix x' assume fx': "f x' = y" with True f[of x'] have "x'\<in> S" by metis from inj_onD[OF i fx[folded fx'] x this] show"x' = x"by simp qed qed qed
context fixes p :: \<open>'a \<Rightarrow> 'a\<close> and S :: \<open>'a set\<close> assumes perm: \<open>p permutes S\<close> begin
lemma permutes_inj: \<open>inj p\<close> using perm by (auto simp: permutes_def inj_on_def)
lemma permutes_image: \<open>p ` S = S\<close> proof (rule set_eqI) fix x show\<open>x \<in> p ` S \<longleftrightarrow> x \<in> S\<close> proof assume\<open>x \<in> p ` S\<close> thenobtain y where\<open>y \<in> S\<close> \<open>p y = x\<close> by blast with perm show\<open>x \<in> S\<close> by (cases \<open>y = x\<close>) (auto simp add: permutes_def) next assume\<open>x \<in> S\<close> with perm obtain y where\<open>y \<in> S\<close> \<open>p y = x\<close> by (metis permutes_def) thenshow\<open>x \<in> p ` S\<close> by blast qed qed
lemma permutes_not_in: \<open>x \<notin> S \<Longrightarrow> p x = x\<close> using perm by (auto simp: permutes_def)
lemma permutes_in_image: \<open>p x \<in> S \<longleftrightarrow> x \<in> S\<close> using permutes_image permutes_inj by (auto dest: inj_image_mem_iff)
lemma permutes_surj: \<open>surj p\<close> proof - have\<open>p ` (S \<union> - S) = p ` S \<union> p ` (- S)\<close> by (rule image_Un) thenshow ?thesis by (simp add: permutes_image permutes_image_complement) qed
lemma permutes_inv_o: shows"p \ inv p = id" and"inv p \ p = id" using permutes_inj permutes_surj unfolding inj_iff [symmetric] surj_iff [symmetric] by auto
lemma permutes_inverses: shows"p (inv p x) = x" and"inv p (p x) = x" using permutes_inv_o [unfolded fun_eq_iff o_def] by auto
lemma permutes_inv_eq: \<open>inv p y = x \<longleftrightarrow> p x = y\<close> by (auto simp add: permutes_inverses)
lemma permutes_inj_on: \<open>inj_on p A\<close> by (rule inj_on_subset [of _ UNIV]) (auto intro: permutes_inj)
lemma permutes_bij: \<open>bij p\<close> unfolding bij_def by (metis permutes_inj permutes_surj)
lemma permutes_imp_bij: \<open>bij_betw p S S\<close> by (simp add: bij_betw_def permutes_image permutes_inj_on)
lemma permutes_subset: \<open>p permutes T\<close> if \<open>S \<subseteq> T\<close> proof (rule bij_imp_permutes)
define R where\<open>R = T - S\<close> with that have\<open>T = R \<union> S\<close> \<open>R \<inter> S = {}\<close> by auto thenhave\<open>p x = x\<close> if \<open>x \<in> R\<close> for x using that by (auto intro: permutes_not_in) thenhave\<open>p ` R = R\<close> by simp with\<open>T = R \<union> S\<close> show \<open>bij_betw p T T\<close> by (simp add: bij_betw_def permutes_inj_on image_Un permutes_image) fix x assume\<open>x \<notin> T\<close> with\<open>T = R \<union> S\<close> show \<open>p x = x\<close> by (simp add: permutes_not_in) qed
lemma permutes_imp_permutes_insert: \<open>p permutes insert x S\<close> by (rule permutes_subset) auto
end
lemma permutes_id [simp]: \<open>id permutes S\<close> by (auto intro: bij_imp_permutes)
lemma permutes_empty [simp]: \<open>p permutes {} \<longleftrightarrow> p = id\<close> proof assume\<open>p permutes {}\<close> thenshow\<open>p = id\<close> by (auto simp add: fun_eq_iff permutes_not_in) next assume\<open>p = id\<close> thenshow\<open>p permutes {}\<close> by simp qed
lemma permutes_sing [simp]: \<open>p permutes {a} \<longleftrightarrow> p = id\<close> proof assume perm: \<open>p permutes {a}\<close> show\<open>p = id\<close> proof fix x from perm have\<open>p ` {a} = {a}\<close> by (rule permutes_image) with perm show\<open>p x = id x\<close> by (cases \<open>x = a\<close>) (auto simp add: permutes_not_in) qed next assume\<open>p = id\<close> thenshow\<open>p permutes {a}\<close> by simp qed
lemma permutes_univ: "p permutes UNIV \ (\y. \!x. p x = y)" by (simp add: permutes_def)
lemma permutes_swap_id: "a \ S \ b \ S \ transpose a b permutes S" by (rule bij_imp_permutes) (auto intro: transpose_apply_other)
lemma permutes_altdef: "p permutes A \ bij_betw p A A \ {x. p x \ x} \ A" using permutes_not_in[of p A] by (auto simp: permutes_imp_bij intro!: bij_imp_permutes)
lemma permutes_superset: \<open>p permutes T\<close> if \<open>p permutes S\<close> \<open>\<And>x. x \<in> S - T \<Longrightarrow> p x = x\<close> proof -
define R U where\<open>R = T \<inter> S\<close> and \<open>U = S - T\<close> thenhave\<open>T = R \<union> (T - S)\<close> \<open>S = R \<union> U\<close> \<open>R \<inter> U = {}\<close> by auto from that \<open>U = S - T\<close> have \<open>p ` U = U\<close> by simp from\<open>p permutes S\<close> have \<open>bij_betw p (R \<union> U) (R \<union> U)\<close> by (simp add: permutes_imp_bij \<open>S = R \<union> U\<close>) moreoverhave\<open>bij_betw p U U\<close> using that \<open>U = S - T\<close> by (simp add: bij_betw_def permutes_inj_on) ultimatelyhave\<open>bij_betw p R R\<close> using\<open>R \<inter> U = {}\<close> \<open>R \<inter> U = {}\<close> by (rule bij_betw_partition) thenhave\<open>p permutes R\<close> proof (rule bij_imp_permutes) fix x assume\<open>x \<notin> R\<close> with\<open>R = T \<inter> S\<close> \<open>p permutes S\<close> show \<open>p x = x\<close> by (cases \<open>x \<in> S\<close>) (auto simp add: permutes_not_in that(2)) qed thenhave\<open>p permutes R \<union> (T - S)\<close> by (rule permutes_subset) simp with\<open>T = R \<union> (T - S)\<close> show ?thesis by simp qed
lemma permutes_bij_inv_into: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close> fixes A :: "'a set" and B :: "'b set" assumes"p permutes A" and"bij_betw f A B" shows"(\x. if x \ B then f (p (inv_into A f x)) else x) permutes B" proof (rule bij_imp_permutes) from assms have"bij_betw p A A""bij_betw f A B""bij_betw (inv_into A f) B A" by (auto simp add: permutes_imp_bij bij_betw_inv_into) thenhave"bij_betw (f \ p \ inv_into A f) B B" by (simp add: bij_betw_trans) thenshow"bij_betw (\x. if x \ B then f (p (inv_into A f x)) else x) B B" by (subst bij_betw_cong[where g="f \ p \ inv_into A f"]) auto next fix x assume"x \ B" thenshow"(if x \ B then f (p (inv_into A f x)) else x) = x" by auto qed
lemma permutes_image_mset: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close> assumes"p permutes A" shows"image_mset p (mset_set A) = mset_set A" using assms by (metis image_mset_mset_set bij_betw_imp_inj_on permutes_imp_bij permutes_image)
lemma permutes_implies_image_mset_eq: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close> assumes"p permutes A""\x. x \ A \ f x = f' (p x)" shows"image_mset f' (mset_set A) = image_mset f (mset_set A)" proof - have"f x = f' (p x)"if"x \# mset_set A" for x using assms(2)[of x] that by (cases "finite A") auto with assms have"image_mset f (mset_set A) = image_mset (f' \ p) (mset_set A)" by (auto intro!: image_mset_cong) alsohave"\ = image_mset f' (image_mset p (mset_set A))" by (simp add: image_mset.compositionality) alsohave"\ = image_mset f' (mset_set A)" proof - from assms permutes_image_mset have"image_mset p (mset_set A) = mset_set A" by blast thenshow ?thesis by simp qed finallyshow ?thesis .. qed
subsection \<open>Group properties\<close>
lemma permutes_compose: "p permutes S \ q permutes S \ q \ p permutes S" unfolding permutes_def o_def by metis
lemma permutes_inv: assumes"p permutes S" shows"inv p permutes S" using assms unfolding permutes_def permutes_inv_eq[OF assms] by metis
lemma permutes_invI: assumes perm: "p permutes S" and inv: "\x. x \ S \ p' (p x) = x" and outside: "\x. x \ S \ p' x = x" shows"inv p = p'" proof show"inv p x = p' x"for x proof (cases "x \ S") case True from assms have"p' x = p' (p (inv p x))" by (simp add: permutes_inverses) alsofrom permutes_inv[OF perm] True have"\ = inv p x" by (subst inv) (simp_all add: permutes_in_image) finallyshow ?thesis .. next case False with permutes_inv[OF perm] show ?thesis by (simp_all add: outside permutes_not_in) qed qed
lemma permutes_vimage: "f permutes A \ f -` A = A" by (simp add: bij_vimage_eq_inv_image permutes_bij permutes_image[OF permutes_inv])
subsection \<open>Restricting a permutation to a subset\<close>
definition restrict_id :: "('a \ 'a) \ 'a set \ 'a \ 'a" where"restrict_id f A = (\x. if x \ A then f x else x)"
lemma restrict_id_cong [cong]: assumes"\x. x \ A \ f x = g x" "A = B" shows"restrict_id f A = restrict_id g B" using assms unfolding restrict_id_def by auto
lemma restrict_id_cong': assumes"x \ A \ f x = g x" "A = B" shows"restrict_id f A x = restrict_id g B x" using assms unfolding restrict_id_def by auto
lemma restrict_id_simps [simp]: "x \ A \ restrict_id f A x = f x" "x \ A \ restrict_id f A x = x" by (auto simp: restrict_id_def)
lemma bij_betw_restrict_id: assumes"bij_betw f A A""A \ B" shows"bij_betw (restrict_id f A) B B" proof - have"bij_betw (restrict_id f A) (A \ (B - A)) (A \ (B - A))" unfolding restrict_id_def by (rule bij_betw_disjoint_Un) (use assms in\<open>auto intro: bij_betwI\<close>) alsohave"A \ (B - A) = B" using assms(2) by blast finallyshow ?thesis . qed
lemma permutes_restrict_id: assumes"bij_betw f A A" shows"restrict_id f A permutes A" by (intro bij_imp_permutes bij_betw_restrict_id assms) auto
subsection \<open>Mapping a permutation\<close>
definition map_permutation :: "'a set \ ('a \ 'b) \ ('a \ 'a) \ 'b \ 'b" where "map_permutation A f p = restrict_id (f \ p \ inv_into A f) (f ` A)"
lemma map_permutation_cong_strong: assumes"A = B""\x. x \ A \ f x = g x" "\x. x \ A \ p x = q x" assumes"p ` A \ A" "inj_on f A" shows"map_permutation A f p = map_permutation B g q" proof - have fg: "f x = g y"if"x \ A" "x = y" for x y using assms(2) that by simp have pq: "p x = q y"if"x \ A" "x = y" for x y using assms(3) that by simp have p: "p x \ A" if "x \ A" for x using assms(4) that by blast have inv: "inv_into A f x = inv_into B g y"if"x \ f ` A" "x = y" for x y proof - from that obtain u where u: "u \ A" "x = f u" by blast have"inv_into A f (f u) = inv_into A g (f u)" using\<open>inj_on f A\<close> u(1) by (metis assms(2) inj_on_cong inv_into_f_f) thus ?thesis using u \<open>x = y\<close> \<open>A = B\<close> by simp qed
show ?thesis unfolding map_permutation_def o_def by (intro restrict_id_cong image_cong fg pq inv_into_into p inv) (auto simp: \<open>A = B\<close>) qed
lemma map_permutation_cong: assumes"inj_on f A""p permutes A" assumes"A = B""\x. x \ A \ f x = g x" "\x. x \ A \ p x = q x" shows"map_permutation A f p = map_permutation B g q" proof (intro map_permutation_cong_strong assms) show"p ` A \ A" using\<open>p permutes A\<close> by (simp add: permutes_image) qed auto
lemma inv_into_id [simp]: "x \ A \ inv_into A id x = x" by (metis f_inv_into_f id_apply image_eqI)
lemma inv_into_ident [simp]: "x \ A \ inv_into A (\x. x) x = x" by (metis f_inv_into_f image_eqI)
lemma map_permutation_id [simp]: "p permutes A \ map_permutation A id p = p" by (auto simp: fun_eq_iff map_permutation_def restrict_id_def permutes_not_in)
lemma map_permutation_ident [simp]: "p permutes A \ map_permutation A (\x. x) p = p" by (auto simp: fun_eq_iff map_permutation_def restrict_id_def permutes_not_in)
lemma map_permutation_id': "inj_on f A \ map_permutation A f id = id" unfolding map_permutation_def by (auto simp: restrict_id_def fun_eq_iff)
lemma map_permutation_ident': "inj_on f A \ map_permutation A f (\x. x) = (\x. x)" unfolding map_permutation_def by (auto simp: restrict_id_def fun_eq_iff)
lemma map_permutation_permutes: assumes"bij_betw f A B""p permutes A" shows"map_permutation A f p permutes B" proof (rule bij_imp_permutes) have f_A: "f ` A = B" using assms(1) by (auto simp: bij_betw_def) from assms(2) have"bij_betw p A A" by (simp add: permutes_imp_bij) show"bij_betw (map_permutation A f p) B B" unfolding map_permutation_def f_A by (rule bij_betw_restrict_id bij_betw_trans bij_betw_inv_into assms(1)
permutes_imp_bij[OF assms(2)] order.refl)+ show"map_permutation A f p x = x"if"x \ B" for x using that unfolding map_permutation_def f_A by simp qed
lemma map_permutation_compose: fixes f :: "'a \ 'b" and g :: "'b \ 'c" assumes"bij_betw f A B""inj_on g B" shows"map_permutation B g (map_permutation A f p) = map_permutation A (g \ f) p" proof fix c :: 'c have bij_g: "bij_betw g B (g ` B)" using\<open>inj_on g B\<close> unfolding bij_betw_def by blast have [simp]: "f x = f y \ x = y" if "x \ A" "y \ A" for x y using assms(1) that by (auto simp: bij_betw_def inj_on_def) have [simp]: "g x = g y \ x = y" if "x \ B" "y \ B" for x y using assms(2) that by (auto simp: bij_betw_def inj_on_def) show"map_permutation B g (map_permutation A f p) c = map_permutation A (g \ f) p c" proof (cases "c \ g ` B") case c: True thenobtain a where a: "a \ A" "c = g (f a)" using assms(1,2) unfolding bij_betw_def by auto have"map_permutation B g (map_permutation A f p) c = g (f (p a))" using a assms by (auto simp: map_permutation_def restrict_id_def bij_betw_def) alsohave"\ = map_permutation A (g \ f) p c" using a bij_betw_inv_into_left[OF bij_betw_trans[OF assms(1) bij_g]] by (auto simp: map_permutation_def restrict_id_def bij_betw_def) finallyshow ?thesis . next case c: False thus ?thesis using assms by (auto simp: map_permutation_def bij_betw_def restrict_id_def) qed qed
lemma map_permutation_compose_inv: assumes"bij_betw f A B""p permutes A""\x. x \ A \ g (f x) = x" shows"map_permutation B g (map_permutation A f p) = p" proof - have"inj_on g B" proof fix x y assume"x \ B" "y \ B" "g x = g y" thenobtain x' y'where *: "x' \ A" "y' : A" "x = f x'" "y = f y'" using assms(1) unfolding bij_betw_def by blast thus"x = y" using assms(3)[of x'] assms(3)[of y'] \<open>g x = g y\<close> by simp qed
have"map_permutation B g (map_permutation A f p) = map_permutation A (g \ f) p" by (rule map_permutation_compose) (use assms \<open>inj_on g B\<close> in auto) alsohave"\ = map_permutation A id p" by (intro map_permutation_cong assms comp_inj_on)
(use\<open>inj_on g B\<close> assms(1,3) in \<open>auto simp: bij_betw_def\<close>) alsohave"\ = p" by (rule map_permutation_id) fact finallyshow ?thesis . qed
lemma map_permutation_apply: assumes"inj_on f A""x \ A" shows"map_permutation A f h (f x) = f (h x)" using assms by (auto simp: map_permutation_def inj_on_def)
lemma map_permutation_compose': fixes f :: "'a \ 'b" assumes"inj_on f A""q permutes A" shows"map_permutation A f (p \ q) = map_permutation A f p \ map_permutation A f q" proof fix y :: 'b show"map_permutation A f (p \ q) y = (map_permutation A f p \ map_permutation A f q) y" proof (cases "y \ f ` A") case True thenobtain x where x: "x \ A" "y = f x" by blast have"map_permutation A f (p \ q) y = f (p (q x))" unfolding x(2) by (subst map_permutation_apply) (use assms x in auto) alsohave"\ = (map_permutation A f p \ map_permutation A f q) y" unfolding x o_apply using x(1) assms by (simp add: map_permutation_apply permutes_in_image) finallyshow ?thesis . next case False thus ?thesis using False by (simp add: map_permutation_def) qed qed
lemma map_permutation_transpose: assumes"inj_on f A""a \ A" "b \ A" shows"map_permutation A f (Transposition.transpose a b) = Transposition.transpose (f a) (f b)" proof fix y :: 'b show"map_permutation A f (Transposition.transpose a b) y = Transposition.transpose (f a) (f b) y" proof (cases "y \ f ` A") case False hence"map_permutation A f (Transposition.transpose a b) y = y" unfolding map_permutation_def by (intro restrict_id_simps) moreoverhave"Transposition.transpose (f a) (f b) y = y" using False assms by (intro transpose_apply_other) auto ultimatelyshow ?thesis by simp next case True thenobtain x where x: "x \ A" "y = f x" by blast have"map_permutation A f (Transposition.transpose a b) y =
f (Transposition.transpose a b x)" unfolding x by (subst map_permutation_apply) (use x assms in auto) alsohave"\ = Transposition.transpose (f a) (f b) y" using assms(2,3) x by (auto simp: Transposition.transpose_def inj_on_eq_iff[OF assms(1)]) finallyshow ?thesis . qed qed
lemma map_permutation_permutes_iff: assumes"bij_betw f A B""p ` A \ A" "\x. x \ A \ p x = x" shows"map_permutation A f p permutes B \ p permutes A" proof assume"p permutes A" thus"map_permutation A f p permutes B" by (intro map_permutation_permutes assms) next assume *: "map_permutation A f p permutes B" hence"map_permutation B (inv_into A f) (map_permutation A f p) permutes A" by (rule map_permutation_permutes[OF bij_betw_inv_into[OF assms(1)]]) alsohave"map_permutation B (inv_into A f) (map_permutation A f p) =
map_permutation A (inv_into A f \<circ> f) p" by (rule map_permutation_compose[OF _ inj_on_inv_into])
(use assms in\<open>auto simp: bij_betw_def\<close>) alsohave"\ = map_permutation A id p" unfolding o_def id_def by (rule sym, intro map_permutation_cong_strong inv_into_f_f[symmetric]
assms(2) bij_betw_imp_inj_on[OF assms(1)]) auto alsohave"\ = p" unfolding map_permutation_def using assms(3) by (auto simp: restrict_id_def fun_eq_iff split: if_splits) finallyshow"p permutes A" . qed
lemma bij_betw_permutations: assumes"bij_betw f A B" shows"bij_betw (\\ x. if x \ B then f (\ (inv_into A f x)) else x)
{\<pi>. \<pi> permutes A} {\<pi>. \<pi> permutes B}" (is "bij_betw ?f _ _") proof - let ?g = "(\\ x. if x \ A then inv_into A f (\ (f x)) else x)" show ?thesis proof (rule bij_betw_byWitness [of _ ?g], goal_cases) case 3 show ?caseusing permutes_bij_inv_into[OF _ assms] by auto next case 4 have bij_inv: "bij_betw (inv_into A f) B A"by (intro bij_betw_inv_into assms)
{ fix\<pi> assume "\<pi> permutes B" from permutes_bij_inv_into[OF this bij_inv] and assms have"(\x. if x \ A then inv_into A f (\ (f x)) else x) permutes A" by (simp add: inv_into_inv_into_eq cong: if_cong)
} from this show ?caseby (auto simp: permutes_inv) next case 1 thus ?caseusing assms by (auto simp: fun_eq_iff permutes_not_in permutes_in_image bij_betw_inv_into_left
dest: bij_betwE) next case 2 moreoverhave"bij_betw (inv_into A f) B A" by (intro bij_betw_inv_into assms) ultimatelyshow ?caseusing assms by (auto simp: fun_eq_iff permutes_not_in permutes_in_image bij_betw_inv_into_right
dest: bij_betwE) qed qed
lemma bij_betw_derangements: assumes"bij_betw f A B" shows"bij_betw (\\ x. if x \ B then f (\ (inv_into A f x)) else x)
{\<pi>. \<pi> permutes A \<and> (\<forall>x\<in>A. \<pi> x \<noteq> x)} {\<pi>. \<pi> permutes B \<and> (\<forall>x\<in>B. \<pi> x \<noteq> x)}"
(is"bij_betw ?f _ _") proof - let ?g = "(\\ x. if x \ A then inv_into A f (\ (f x)) else x)" show ?thesis proof (rule bij_betw_byWitness [of _ ?g], goal_cases) case 3 have"?f \ x \ x" if "\ permutes A" "\x. x \ A \ \ x \ x" "x \ B" for \ x using that and assms by (metis bij_betwE bij_betw_imp_inj_on bij_betw_imp_surj_on
inv_into_f_f inv_into_into permutes_imp_bij) with permutes_bij_inv_into[OF _ assms] show ?caseby auto next case 4 have bij_inv: "bij_betw (inv_into A f) B A"by (intro bij_betw_inv_into assms) have"?g \ permutes A" if "\ permutes B" for \ using permutes_bij_inv_into[OF that bij_inv] and assms by (simp add: inv_into_inv_into_eq cong: if_cong) moreoverhave"?g \ x \ x" if "\ permutes B" "\x. x \ B \ \ x \ x" "x \ A" for \ x using that and assms by (metis bij_betwE bij_betw_imp_surj_on f_inv_into_f permutes_imp_bij) ultimatelyshow ?caseby auto next case 1 thus ?caseusing assms by (force simp: fun_eq_iff permutes_not_in permutes_in_image bij_betw_inv_into_left
dest: bij_betwE) next case 2 moreoverhave"bij_betw (inv_into A f) B A" by (intro bij_betw_inv_into assms) ultimatelyshow ?caseusing assms by (force simp: fun_eq_iff permutes_not_in permutes_in_image bij_betw_inv_into_right
dest: bij_betwE) qed qed
subsection \<open>The number of permutations on a finite set\<close>
lemma permutes_insert_lemma: assumes"p permutes (insert a S)" shows"transpose a (p a) \ p permutes S" proof (rule permutes_superset[where S = "insert a S"]) show"Transposition.transpose a (p a) \ p permutes insert a S" by (meson assms insertI1 permutes_compose permutes_in_image permutes_swap_id) qed auto
lemma permutes_insert: "{p. p permutes (insert a S)} =
(\<lambda>(b, p). transpose a b \<circ> p) ` {(b, p). b \<in> insert a S \<and> p \<in> {p. p permutes S}}" proof - have"p permutes insert a S \
(\<exists>b q. p = transpose a b \<circ> q \<and> b \<in> insert a S \<and> q permutes S)" for p proof - have"\b q. p = transpose a b \ q \ b \ insert a S \ q permutes S" if p: "p permutes insert a S" proof - let ?b = "p a" let ?q = "transpose a (p a) \ p" have *: "p = transpose a ?b \ ?q" by (simp add: fun_eq_iff o_assoc) have **: "?b \ insert a S" unfolding permutes_in_image[OF p] by simp from permutes_insert_lemma[OF p] * ** show ?thesis by blast qed moreoverhave"p permutes insert a S" if bq: "p = transpose a b \ q" "b \ insert a S" "q permutes S" for b q proof - from permutes_subset[OF bq(3), of "insert a S"] have q: "q permutes insert a S" by auto have a: "a \ insert a S" by simp from bq(1) permutes_compose[OF q permutes_swap_id[OF a bq(2)]] show ?thesis by simp qed ultimatelyshow ?thesis by blast qed thenshow ?thesis by auto qed
lemma card_permutations: assumes"card S = n" and"finite S" shows"card {p. p permutes S} = fact n" using assms(2,1) proof (induct arbitrary: n) case empty thenshow ?caseby simp next case (insert x F)
{ fix n assume card_insert: "card (insert x F) = n" let ?xF = "{p. p permutes insert x F}" let ?pF = "{p. p permutes F}" let ?pF' = "{(b, p). b \ insert x F \ p \ ?pF}" let ?g = "(\(b, p). transpose x b \ p)" have xfgpF': "?xF = ?g ` ?pF'" by (rule permutes_insert[of x F]) from\<open>x \<notin> F\<close> \<open>finite F\<close> card_insert have Fs: "card F = n - 1" by auto from\<open>finite F\<close> insert.hyps Fs have pFs: "card ?pF = fact (n - 1)" by auto thenhave"finite ?pF" by (auto intro: card_ge_0_finite) with\<open>finite F\<close> card.insert_remove have pF'f: "finite ?pF'" by simp have ginj: "inj_on ?g ?pF'" proof -
{ fix b p c q assume bp: "(b, p) \ ?pF'" assume cq: "(c, q) \ ?pF'" assume eq: "?g (b, p) = ?g (c, q)" from bp cq have pF: "p permutes F"and qF: "q permutes F" by auto from pF \<open>x \<notin> F\<close> eq have "b = ?g (b, p) x" by (auto simp: permutes_def fun_upd_def fun_eq_iff) alsofrom qF \<open>x \<notin> F\<close> eq have "\<dots> = ?g (c, q) x" by (auto simp: fun_upd_def fun_eq_iff) alsofrom qF \<open>x \<notin> F\<close> have "\<dots> = c" by (auto simp: permutes_def fun_upd_def fun_eq_iff) finallyhave"b = c" . thenhave"transpose x b = transpose x c" by simp with eq have"transpose x b \ p = transpose x b \ q" by simp thenhave"transpose x b \ (transpose x b \ p) = transpose x b \ (transpose x b \q)" by simp thenhave"p = q" by (simp add: o_assoc) with\<open>b = c\<close> have "(b, p) = (c, q)" by simp
} thenshow ?thesis unfolding inj_on_def by blast qed from\<open>x \<notin> F\<close> \<open>finite F\<close> card_insert have "n \<noteq> 0" by auto thenhave"\m. n = Suc m" by presburger thenobtain m where n: "n = Suc m" by blast from pFs card_insert have *: "card ?xF = fact n" unfolding xfgpF' card_image[OF ginj] using\<open>finite F\<close> \<open>finite ?pF\<close> by (simp only: Collect_case_prod Collect_mem_eq card_cartesian_product) (simp add: n) from finite_imageI[OF pF'f, of ?g] have xFf: "finite ?xF" by (simp add: xfgpF' n) from * have"card ?xF = fact n" unfolding xFf by blast
} with insert show ?caseby simp qed
lemma finite_permutations: assumes"finite S" shows"finite {p. p permutes S}" using card_permutations[OF refl assms] by (auto intro: card_ge_0_finite)
lemma permutes_doubleton_iff: "f permutes {a, b} \ f = id \ f = Transposition.transpose a b" proof (cases "a = b") case False have"{id, Transposition.transpose a b} \ {f. f permutes {a, b}}" by (auto simp: permutes_id permutes_swap_id) moreoverhave"id \ Transposition.transpose a b" using False by (auto simp: fun_eq_iff Transposition.transpose_def) hence"card {id, Transposition.transpose a b} = card {f. f permutes {a, b}}" using False by (simp add: card_permutations) ultimatelyhave"{id, Transposition.transpose a b} = {f. f permutes {a, b}}" by (intro card_subset_eq finite_permutations) auto thus ?thesis by auto qed auto
subsection \<open>Permutations of index set for iterated operations\<close>
lemma (in comm_monoid_set) permute: assumes"p permutes S" shows"F g S = F (g \ p) S" proof - from\<open>p permutes S\<close> have "inj p" by (rule permutes_inj) thenhave"inj_on p S" by (auto intro: inj_on_subset) thenhave"F g (p ` S) = F (g \ p) S" by (rule reindex) moreoverfrom\<open>p permutes S\<close> have "p ` S = S" by (rule permutes_image) ultimatelyshow ?thesis by simp qed
subsection \<open>Permutations as transposition sequences\<close>
inductive swapidseq :: "nat \ ('a \ 'a) \ bool" where
id[simp]: "swapidseq 0 id"
| comp_Suc: "swapidseq n p \ a \ b \ swapidseq (Suc n) (transpose a b \ p)"
declare id[unfolded id_def, simp]
definition"permutation p \ (\n. swapidseq n p)"
subsection \<open>Some closure properties of the set of permutations, with lengths\<close>
lemma swapidseq_swap: "swapidseq (if a = b then 0 else 1) (transpose a b)" using swapidseq.simps by fastforce
lemma permutation_swap_id: "permutation (transpose a b)" by (meson permutation_def swapidseq_swap)
lemma swapidseq_comp_add: "swapidseq n p \ swapidseq m q \ swapidseq (n + m) (p \q)" proof (induct n p arbitrary: m q rule: swapidseq.induct) case (id m q) thenshow ?caseby simp next case (comp_Suc n p a b m q) thenshow ?case by (metis add_Suc comp_assoc swapidseq.comp_Suc) qed
lemma permutation_compose: "permutation p \ permutation q \ permutation (p \ q)" unfolding permutation_def using swapidseq_comp_add[of _ p _ q] by metis
lemma swapidseq_endswap: "swapidseq n p \ a \ b \ swapidseq (Suc n) (p \ transpose a b)" by (induct n p rule: swapidseq.induct)
(use swapidseq_swap[of a b] in\<open>auto simp add: comp_assoc intro: swapidseq.comp_Suc\<close>)
lemma swapidseq_inverse_exists: "swapidseq n p \ \q. swapidseq n q \ p \ q = id \q \ p = id" proof (induct n p rule: swapidseq.induct) case id thenshow ?case by (rule exI[where x=id]) simp next case (comp_Suc n p a b) from comp_Suc.hyps obtain q where q: "swapidseq n q""p \ q = id" "q \ p = id" by blast let ?q = "q \ transpose a b" note H = comp_Suc.hyps from swapidseq_swap[of a b] H(3) have *: "swapidseq 1 (transpose a b)" by simp from swapidseq_comp_add[OF q(1) *] have **: "swapidseq (Suc n) ?q" by simp have"transpose a b \ p \ ?q = transpose a b \ (p \ q) \ transpose a b" by (simp add: o_assoc) alsohave"\ = id" by (simp add: q(2)) finallyhave ***: "transpose a b \ p \ ?q = id" . have"?q \ (transpose a b \ p) = q \ (transpose a b \ transpose a b) \ p" by (simp only: o_assoc) thenhave"?q \ (transpose a b \ p) = id" by (simp add: q(3)) with ** *** show ?case by blast qed
lemma swapidseq_inverse: assumes"swapidseq n p" shows"swapidseq n (inv p)" using swapidseq_inverse_exists[OF assms] inv_unique_comp[of p] by auto
lemma permutation_inverse: "permutation p \ permutation (inv p)" using permutation_def swapidseq_inverse by blast
subsection \<open>Various combinations of transpositions with 2, 1 and 0 common elements\<close>
lemma swap_id_common:" a \ c \ b \ c \
transpose a b \<circ> transpose a c = transpose b c \<circ> transpose a b" by (simp add: fun_eq_iff transpose_def)
lemma swap_id_common': "a \ b \ a \ c \
transpose a c \<circ> transpose b c = transpose b c \<circ> transpose a b" by (simp add: fun_eq_iff transpose_def)
lemma swap_id_independent: "a \ c \ a \ d \ b \ c \ b \ d \
transpose a b \<circ> transpose c d = transpose c d \<circ> transpose a b" by (simp add: fun_eq_iff transpose_def)
subsection \<open>The identity map only has even transposition sequences\<close>
lemma symmetry_lemma: assumes"\a b c d. P a b c d \ P a b d c" and"\a b c d. a \ b \ c \ d \
a = c \<and> b = d \<or> a = c \<and> b \<noteq> d \<or> a \<noteq> c \<and> b = d \<or> a \<noteq> c \<and> a \<noteq> d \<and> b \<noteq> c \<and> b \<noteq> d \<Longrightarrow>
P a b c d" shows"\a b c d. a \ b \ c \ d \ P a b c d" using assms by metis
lemma swap_general: assumes"a \ b" "c \ d" shows"transpose a b \ transpose c d = id \
(\<exists>x y z. x \<noteq> a \<and> y \<noteq> a \<and> z \<noteq> a \<and> x \<noteq> y \<and>
transpose a b \<circ> transpose c d = transpose x y \<circ> transpose a z)" by (metis assms swap_id_common' swap_id_independent transpose_commute transpose_comp_involutory)
lemma swapidseq_id_iff[simp]: "swapidseq 0 p \ p = id" using swapidseq.cases[of 0 p "p = id"] by auto
lemma swapidseq_cases: "swapidseq n p \
n = 0 \<and> p = id \<or> (\<exists>a b q m. n = Suc m \<and> p = transpose a b \<circ> q \<and> swapidseq m q \<and> a \<noteq> b)" by (meson comp_Suc id swapidseq.cases)
lemma fixing_swapidseq_decrease: assumes"swapidseq n p" and"a \ b" and"(transpose a b \ p) a = a" shows"n \ 0 \ swapidseq (n - 1) (transpose a b \ p)" using assms proof (induct n arbitrary: p a b) case 0 thenshow ?case by (auto simp add: fun_upd_def) next case (Suc n p a b) from Suc.prems(1) swapidseq_cases[of "Suc n" p] obtain c d q m where
cdqm: "Suc n = Suc m""p = transpose c d \ q" "swapidseq m q" "c \ d" "n = m" by auto
consider "transpose a b \ transpose c d = id"
| x y z where"x \ a" "y \ a" "z \ a" "x \ y" "transpose a b \ transpose c d = transpose x y \ transpose a z" using swap_general[OF Suc.prems(2) cdqm(4)] by metis thenshow ?case proof cases case 1 thenshow ?thesis by (simp only: cdqm o_assoc) (simp add: cdqm) next case 2 thenhave az: "a \ z" by simp from 2 have *: "(transpose x y \ h) a = a \ h a = a" for h by (simp add: transpose_def) from cdqm(2) have"transpose a b \ p = transpose a b \ (transpose c d \ q)" by simp thenhave\<section>: "transpose a b \<circ> p = transpose x y \<circ> (transpose a z \<circ> q)" by (simp add: o_assoc 2) obtain **: "swapidseq (n - 1) (transpose a z \ q)" and "n\0" by (metis "*""\" Suc.hyps Suc.prems(3) az cdqm(3,5)) thenhave"Suc n - 1 = Suc (n - 1)" by auto with 2 show ?thesis using"**"\<section> swapidseq.simps by blast qed qed
lemma swapidseq_identity_even: assumes"swapidseq n (id :: 'a \ 'a)" shows"even n" using\<open>swapidseq n id\<close> proof (induct n rule: nat_less_induct) case H: (1 n)
consider "n = 0"
| a b :: 'a and q m where "n = Suc m" "id = transpose a b \ q" "swapidseq m q" "a \b" using H(2)[unfolded swapidseq_cases[of n id]] by auto thenshow ?case proof cases case 1 thenshow ?thesis by presburger next case h: 2 from fixing_swapidseq_decrease[OF h(3,4), unfolded h(2)[symmetric]] have m: "m \ 0" "swapidseq (m - 1) (id :: 'a \ 'a)" by auto from h m have mn: "m - 1 < n" by arith from H(1)[rule_format, OF mn m(2)] h(1) m(1) show ?thesis by presburger qed qed
subsection \<open>Therefore we have a welldefined notion of parity\<close>
definition"evenperm p = even (SOME n. swapidseq n p)"
lemma swapidseq_even_even: assumes m: "swapidseq m p" and n: "swapidseq n p" shows"even m \ even n" proof - from swapidseq_inverse_exists[OF n] obtain q where q: "swapidseq n q""p \ q = id" "q \p = id" by blast from swapidseq_identity_even[OF swapidseq_comp_add[OF m q(1), unfolded q]] show ?thesis by arith qed
lemma evenperm_unique: assumes"swapidseq n p"and"even n = b" shows"evenperm p = b" by (metis evenperm_def assms someI swapidseq_even_even)
subsection \<open>And it has the expected composition properties\<close>
lemma evenperm_id[simp]: "evenperm id = True" by (rule evenperm_unique[where n = 0]) simp_all
lemma evenperm_identity [simp]: \<open>evenperm (\<lambda>x. x)\<close> using evenperm_id by (simp add: id_def [abs_def])
lemma evenperm_swap: "evenperm (transpose a b) = (a = b)" by (rule evenperm_unique[where n="if a = b then 0 else 1"]) (simp_all add: swapidseq_swap)
lemma evenperm_comp: assumes"permutation p""permutation q" shows"evenperm (p \ q) \ evenperm p = evenperm q" proof - from assms obtain n m where n: "swapidseq n p"and m: "swapidseq m q" unfolding permutation_def by blast have"even (n + m) \ (even n \ even m)" by arith from evenperm_unique[OF n refl] evenperm_unique[OF m refl] and evenperm_unique[OF swapidseq_comp_add[OF n m] this] show ?thesis by blast qed
lemma evenperm_inv: assumes"permutation p" shows"evenperm (inv p) = evenperm p" proof - from assms obtain n where n: "swapidseq n p" unfolding permutation_def by blast show ?thesis by (rule evenperm_unique[OF swapidseq_inverse[OF n] evenperm_unique[OF n refl, symmetric]]) qed
subsection \<open>A more abstract characterization of permutations\<close>
lemma permutation_finite_support: assumes"permutation p" shows"finite {x. p x \ x}" proof - from assms obtain n where"swapidseq n p" unfolding permutation_def by blast thenshow ?thesis proof (induct n p rule: swapidseq.induct) case id thenshow ?caseby simp next case (comp_Suc n p a b) let ?S = "insert a (insert b {x. p x \ x})" from comp_Suc.hyps(2) have *: "finite ?S" by simp from\<open>a \<noteq> b\<close> have **: "{x. (transpose a b \<circ> p) x \<noteq> x} \<subseteq> ?S" by auto show ?case by (rule finite_subset[OF ** *]) qed qed
lemma permutation_lemma: assumes"finite S" and"bij p" and"\x. x \ S \ p x = x" shows"permutation p" using assms proof (induct S arbitrary: p rule: finite_induct) case empty thenshow ?case by simp next case (insert a F p) let ?r = "transpose a (p a) \ p" let ?q = "transpose a (p a) \ ?r" have *: "?r a = a" by simp from insert * have **: "\x. x \ F \ ?r x = x" by (metis bij_pointE comp_apply id_apply insert_iff swap_apply(3)) have"bij ?r" using insert by (simp add: bij_comp) have"permutation ?r" by (rule insert(3)[OF \<open>bij ?r\<close> **]) thenhave"permutation ?q" by (simp add: permutation_compose permutation_swap_id) thenshow ?case by (simp add: o_assoc) qed
lemma permutation: "permutation p \ bij p \ finite {x. p x \ x}" using permutation_bijective permutation_finite_support permutation_lemma by auto
lemma permutation_inverse_works: assumes"permutation p" shows"inv p \ p = id" and"p \ inv p = id" using permutation_bijective [OF assms] by (auto simp: bij_def inj_iff surj_iff)
lemma permutation_inverse_compose: assumes p: "permutation p" and q: "permutation q" shows"inv (p \ q) = inv q \ inv p" by (simp add: o_inv_distrib p permutation_bijective q)
subsection \<open>Relation to \<open>permutes\<close>\<close>
lemma permutes_imp_permutation: \<open>permutation p\<close> if \<open>finite S\<close> \<open>p permutes S\<close> proof - from\<open>p permutes S\<close> have \<open>{x. p x \<noteq> x} \<subseteq> S\<close> by (auto dest: permutes_not_in) thenhave\<open>finite {x. p x \<noteq> x}\<close> using\<open>finite S\<close> by (rule finite_subset) moreoverfrom\<open>p permutes S\<close> have \<open>bij p\<close> by (auto dest: permutes_bij) ultimatelyshow ?thesis by (simp add: permutation) qed
lemma permutation_permutesE: assumes\<open>permutation p\<close> obtains S where\<open>finite S\<close> \<open>p permutes S\<close> proof - from assms have fin: \<open>finite {x. p x \<noteq> x}\<close> by (simp add: permutation) from assms have\<open>bij p\<close> by (simp add: permutation) alsohave\<open>UNIV = {x. p x \<noteq> x} \<union> {x. p x = x}\<close> by auto finallyhave\<open>bij_betw p {x. p x \<noteq> x} {x. p x \<noteq> x}\<close> by (rule bij_betw_partition) (auto simp add: bij_betw_fixpoints) thenhave\<open>p permutes {x. p x \<noteq> x}\<close> by (auto intro: bij_imp_permutes) with fin show thesis .. qed
lemma permutation_permutes: "permutation p \ (\S. finite S \ p permutes S)" by (auto elim: permutation_permutesE intro: permutes_imp_permutation)
subsection \<open>Sign of a permutation\<close>
definition sign :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> int\<close> \<comment> \<open>TODO: prefer less generic name\<close> where\<open>sign p = (if evenperm p then 1 else - 1)\<close>
lemma sign_cases [case_names even odd]: obtains\<open>sign p = 1\<close> | \<open>sign p = - 1\<close> by (cases \<open>evenperm p\<close>) (simp_all add: sign_def)
lemma sign_nz [simp]: "sign p \ 0" by (cases p rule: sign_cases) simp_all
lemma sign_id [simp]: "sign id = 1" by (simp add: sign_def)
lemma apply_transps_append [simp]: "apply_transps (xs @ ys) = apply_transps xs \ apply_transps ys"
by (induction xs) auto
lemma permutation_apply_transps [simp, intro]: "permutation (apply_transps xs)"
proof (induction xs) case (Cons x xs)
thus ?case
unfolding apply_transps_Cons by (intro permutation_compose permutation_swap_id)
qed auto
lemma permutes_apply_transps:
assumes "\(a,b)\set xs. a \ A \ b \ A"
shows "apply_transps xs permutes A" using assms
proof (induction xs) case (Cons x xs)
from Cons.prems show ?case
unfolding apply_transps_Cons
by (intro permutes_compose permutes_swap_id Cons) auto
qed (auto simp: permutes_id)
lemma permutes_induct [consumes 2, case_names id swap]:
assumes "p permutes S""finite S"
assumes "P id"
assumes "\a b p. a \ S \ b \ S \ a \ b \ P p \ p permutes S
\<Longrightarrow> P (Transposition.transpose a b \<circ> p)"
shows "P p" using assms(2,1,4)
proof (induct S arbitrary: p rule: finite_induct) case empty
then show ?caseusing assms by (auto simp: id_def)
next case (insert x F p)
let ?r = "Transposition.transpose x (p x) \ p"
let ?q = "Transposition.transpose x (p x) \ ?r"
have qp: "?q = p"
by (simp add: o_assoc)
have "?r permutes F" using permutes_insert_lemma[OF insert.prems(1)] .
have "P ?r"
by (rule insert(3)[OF \<open>?r permutes F\<close>], rule insert(5)) (auto intro: permutes_subset)
show ?case
proof (cases "x = p x") caseFalse
have "p x \ F" using permutes_in_image[OF \<open>p permutes _\<close>, of x] False by auto
have "P ?q"
by (rule insert(5))
(use \<open>P ?r\<close> \<open>p x \<in> F\<close> \<open>?r permutes F\<close> False in \<open>auto simp: o_def intro: permutes_subset\<close>)
thus "P p"
by (simp add: qp)
qed (use \<open>P ?r\<close> in simp)
qed
lemma permutes_rev_induct[consumes 2, case_names id swap]:
assumes "finite S""p permutes S"
assumes "P id"
assumes "\a b p. a \ S \ b \ S \ a \ b \ P p \ p permutes S
\<Longrightarrow> P (p \<circ> Transposition.transpose a b)"
shows "P p"
proof -
have "inv_into UNIV p permutes S" using assms by (intro permutes_inv)
from thisand assms(1,2) show ?thesis
proof (induction "inv_into UNIV p" arbitrary: p rule: permutes_induct) case id
hence "p = id"
by (metis inv_id permutes_inv_inv)
thus ?caseusing \<open>P id\<close> by (auto simp: id_def)
next case (swap a b p p')
have "p = Transposition.transpose a b \ (Transposition.transpose a b \ p)"
by (simp add: o_assoc)
also have "\ = Transposition.transpose a b \ inv_into UNIV p'"
by (subst swap.hyps) auto
also have "Transposition.transpose a b = inv_into UNIV (Transposition.transpose a b)"
by (simp add: inv_swap_id)
also have "\ \ inv_into UNIV p' = inv_into UNIV (p' \ Transposition.transpose a b)" using swap \<open>finite S\<close>
by (intro permutation_inverse_compose [symmetric] permutation_swap_id permutation_inverse)
(auto simp: permutation_permutes)
finally have "p = inv (p' \ Transposition.transpose a b)" .
moreover have "p' \ Transposition.transpose a b permutes S"
by (intro permutes_compose permutes_swap_id swap)
ultimately have *: "P (p' \ Transposition.transpose a b)"
by (rule swap(4))
have "P (p' \ Transposition.transpose a b \ Transposition.transpose a b)"
by (rule assms; intro * swap permutes_compose permutes_swap_id)
also have "p' \ Transposition.transpose a b \ Transposition.transpose a b = p'"
by (simp flip: o_assoc)
finally show ?case .
qed
qed
lemma map_permutation_apply_transps:
assumes f: "inj_on f A"and"set ts \ A \ A"
shows "map_permutation A f (apply_transps ts) = apply_transps (map (map_prod f f) ts)" using assms(2)
proof (induction ts) case (Cons t ts)
obtain a b where [simp]: "t = (a, b)"
by (cases t)
have "map_permutation A f (apply_transps (t # ts)) =
map_permutation A f (Transposition.transpose a b \<circ> apply_transps ts)"
by simp
also have "\ = map_permutation A f (Transposition.transpose a b) \
map_permutation A f (apply_transps ts)"
by (subst map_permutation_compose')
(use f Cons.prems in \<open>auto intro!: permutes_apply_transps\<close>)
also have "map_permutation A f (Transposition.transpose a b) =
Transposition.transpose (f a) (f b)"
by (intro map_permutation_transpose f) (use Cons.prems in auto)
also have "map_permutation A f (apply_transps ts) = apply_transps (map (map_prod f f) ts)"
by (intro Cons.IH) (use Cons.prems in auto)
also have "Transposition.transpose (f a) (f b) \ apply_transps (map (map_prod f f) ts) =
apply_transps (map (map_prod f f) (t # ts))"
by simp
finally show ?case .
qed (use f in \<open>auto simp: map_permutation_id'\)
lemma permutes_from_transpositions:
assumes "p permutes A""finite A"
shows "\xs. (\(a,b)\set xs. a \ b \ a \ A \ b \ A) \ apply_transps xs = p" using assms
proof (induction rule: permutes_induct) case id
thus ?case by (intro exI[of _ "[]"]) auto
next case (swap a b p)
from swap.IH obtain xs where
xs: "(\(a,b)\set xs. a \ b \ a \ A \ b \ A)""apply_transps xs = p"
by blast
thus ?case using swap.hyps by (intro exI[of _ "(a,b) # xs"]) auto
qed
subsection \<open>More on the sign of permutations\<close>
lemma evenperm_apply_transps_iff:
assumes "\(a,b)\set xs. a \ b"
shows "evenperm (apply_transps xs) \ even (length xs)" using assms
by (induction xs)
(simp_all add: case_prod_unfold evenperm_comp permutation_swap_id evenperm_swap)
lemma evenperm_map_permutation:
assumes f: "inj_on f A"and"p permutes A""finite A"
shows "evenperm (map_permutation A f p) \ evenperm p"
proof -
note [simp] = inj_on_eq_iff[OF f]
obtain ts where ts: "\(a, b)\set ts. a \ b \ a \ A \ b \ A""apply_transps ts = p" using permutes_from_transpositions[OF assms(2,3)] by blast
have "evenperm p \ even (length ts)"
by (subst ts(2) [symmetric], subst evenperm_apply_transps_iff) (use ts(1) in auto)
also have "\ \ even (length (map (map_prod f f) ts))"
by simp
also have "\ \ evenperm (apply_transps (map (map_prod f f) ts))"
by (subst evenperm_apply_transps_iff) (use ts(1) in auto)
also have "apply_transps (map (map_prod f f) ts) = map_permutation A f p"
unfolding ts(2)[symmetric]
by (rule map_permutation_apply_transps [symmetric]) (use f ts(1) in auto)
finally show ?thesis ..
qed
lemma sign_map_permutation:
assumes "inj_on f A""p permutes A""finite A"
shows "sign (map_permutation A f p) = sign p"
unfolding sign_def by (subst evenperm_map_permutation) (use assms in auto)
text \<open>
Sometimes it can be useful to consider the sign of a function that is not a permutation in the
Isabelle/HOL sense, but its restriction to some finite subset is.
\<close>
definition sign_on :: "'a set \ ('a \ 'a) \ int"
where "sign_on A f = sign (restrict_id f A)"
lemma sign_on_cong [cong]:
assumes "A = B""\x. x \ A \ f x = g x"
shows "sign_on A f = sign_on B g"
unfolding sign_on_def using assms
by (intro arg_cong[of _ _ sign] restrict_id_cong)
lemma sign_on_permutes:
assumes "f permutes A""A \ B"
shows "sign_on B f = sign f"
proof -
have f: "f permutes B" using assms permutes_subset by blast
have "sign_on B f = sign (restrict_id f B)"
by (simp add: sign_on_def)
also have "restrict_id f B = f" using f by (auto simp: fun_eq_iff permutes_not_in restrict_id_def)
finally show ?thesis .
qed
lemma sign_on_id [simp]: "sign_on A id = 1"
by (subst sign_on_permutes[of _ A]) auto
lemma sign_on_ident [simp]: "sign_on A (\x. x) = 1" using sign_on_id[of A] unfolding id_def by simp
lemma sign_on_transpose:
assumes "a \ A""b \ A""a \ b"
shows "sign_on A (Transposition.transpose a b) = -1"
by (subst sign_on_permutes[of _ A])
(use assms in \<open>auto simp: permutes_swap_id sign_swap_id\<close>)
lemma sign_on_compose:
assumes "bij_betw f A A""bij_betw g A A""finite A"
shows "sign_on A (f \ g) = sign_on A f * sign_on A g"
proof -
define restr where "restr = (\f. restrict_id f A)"
have "sign_on A (f \ g) = sign (restr (f \ g))"
by (simp add: sign_on_def restr_def)
also have "restr (f \ g) = restr f \ restr g" using assms(2) by (auto simp: restr_def fun_eq_iff bij_betw_def restrict_id_def)
also have "sign \ = sign (restr f) * sign (restr g)" unfolding restr_def
by (rule sign_compose) (auto intro!: permutes_imp_permutation[of A] permutes_restrict_id assms)
also have "\ = sign_on A f * sign_on A g"
by (simp add: sign_on_def restr_def)
finally show ?thesis .
qed
subsection \<open>Transpositions of adjacent elements\<close>
text \<open>
We have shown above that every permutation can be written as a product of transpositions.
We will now furthermore show that any transposition of successive natural numbers
$\{m, \ldots, n\}$ can be written as a product of transpositions of \<^emph>\<open>adjacent\<close> elements,
i.e.\ transpositions of the form $i \leftrightarrow i+1$.
\<close>
function adj_transp_seq :: "nat \ nat \ nat list" where "adj_transp_seq a b =
(if a \<ge> b then [] elseif b = a + 1 then [a] else a # adj_transp_seq (a+1) b @ [a])"
by auto
termination by (relation "measure (\(a,b). b - a)") auto
lemmas [simp del] = adj_transp_seq.simps
lemma length_adj_transp_seq: "a < b \ length (adj_transp_seq a b) = 2 * (b - a) - 1"
by (induction a b rule: adj_transp_seq.induct; subst adj_transp_seq.simps) auto
definition apply_adj_transps :: "nat list \ nat \ nat"
where "apply_adj_transps xs = foldl (\) id (map (\x. Transposition.transpose x (x+1)) xs)"
lemma apply_adj_transps_aux: "f \ foldl (\) g (map (\x. Transposition.transpose x (Suc x)) xs) =
foldl (\<circ>) (f \<circ> g) (map (\<lambda>x. Transposition.transpose x (Suc x)) xs)"
by (induction xs arbitrary: f g) (auto simp: o_assoc)
lemma apply_adj_transps_Nil [simp]: "apply_adj_transps [] = id" and apply_adj_transps_Cons [simp]: "apply_adj_transps (x # xs) = Transposition.transpose x (x+1) \ apply_adj_transps xs" and apply_adj_transps_snoc [simp]: "apply_adj_transps (xs @ [x]) = apply_adj_transps xs \ Transposition.transpose x (x+1)"
by (simp_all add: apply_adj_transps_def apply_adj_transps_aux)
lemma adj_transp_seq_correct:
assumes "a < b"
shows "apply_adj_transps (adj_transp_seq a b) = Transposition.transpose a b" using assms
proof (induction a b rule: adj_transp_seq.induct) case (1 a b)
show ?case
proof (cases "b = a + 1") caseTrue
thus ?thesis
by (subst adj_transp_seq.simps) (auto simp: o_def Transposition.transpose_def apply_adj_transps_def)
next caseFalse
hence "apply_adj_transps (adj_transp_seq a b) =
Transposition.transpose a (Suc a) \<circ> Transposition.transpose (Suc a) b \<circ> Transposition.transpose a (Suc a)" using 1 by (subst adj_transp_seq.simps)
(simp add: o_assoc swap_id_common swap_id_common' id_def o_def)
also have "\ = Transposition.transpose a b" usingFalse 1 by (simp add: Transposition.transpose_def fun_eq_iff)
finally show ?thesis .
qed
qed
lemma permutation_apply_adj_transps: "permutation (apply_adj_transps xs)"
proof (induction xs) case (Cons x xs)
have "permutation (Transposition.transpose x (Suc x) \ apply_adj_transps xs)"
by (intro permutation_compose permutation_swap_id Cons)
thus ?case by (simp add: o_def)
qed auto
lemma permutes_apply_adj_transps:
assumes "\x\set xs. x \ A \ Suc x \ A"
shows "apply_adj_transps xs permutes A" using assms
by (induction xs) (auto intro!: permutes_compose permutes_swap_id permutes_id)
lemma set_adj_transp_seq: "a < b \ set (adj_transp_seq a b) = {a..
by (induction a b rule: adj_transp_seq.induct, subst adj_transp_seq.simps) auto
subsection \<open>Transferring properties of permutations along bijections\<close>
locale permutes_bij =
fixes p :: "'a \ 'a"and A :: "'a set"and B :: "'b set"
fixes f :: "'a \ 'b"and f' :: "'b \<Rightarrow> 'a"
fixes p' :: "'b \<Rightarrow> 'b"
defines "p' \ (\x. if x \ B then f (p (f' x)) else x)"
assumes permutes_p: "p permutes A"
assumes bij_f: "bij_betw f A B"
assumes f'_f: "x \ A \ f' (f x) = x"
begin
lemma bij_f': "bij_betw f' B A" using bij_f f'_f by (auto simp: bij_betw_def) (auto simp: inj_on_def image_image)
lemma f_f': "x \ B \ f (f' x) = x" using f'_f bij_f by (auto simp: bij_betw_def)
lemma f_in_B: "x \ A \ f x \ B" using bij_f by (auto simp: bij_betw_def)
lemma f'_in_A: "x \ B \ f' x \<in> A" using bij_f' by (auto simp: bij_betw_def)
lemma permutes_p': "p' permutes B"
proof -
have p': "p' x = x" if "x \<notin> B" for x using that by (simp add: p'_def)
have bij_p: "bij_betw p A A" using permutes_p by (simp add: permutes_imp_bij)
have "bij_betw (f \ p \ f') B B"
by (rule bij_betw_trans bij_f bij_f' bij_p)+
also have "?this \ bij_betw p' B B"
by (intro bij_betw_cong) (auto simp: p'_def)
finally show ?thesis using p' by (rule bij_imp_permutes)
qed
lemma f_eq_iff [simp]: "f x = f y \ x = y"if"x \ A""y \ A"for x y using that bij_f by (auto simp: bij_betw_def inj_on_def)
lemma apply_transps_map_f_aux:
assumes "\(a,b)\set xs. a \ A \ b \ A""y \ B"
shows "apply_transps (map (map_prod f f) xs) y = f (apply_transps xs (f' y))" using assms
proof (induction xs arbitrary: y) case Nil
thus ?case by (auto simp: f_f')
next case (Cons x xs y)
from Cons.prems have "apply_transps xs permutes A"
by (intro permutes_apply_transps) auto
hence [simp]: "apply_transps xs z \ A \ z \ A"for z
by (simp add: permutes_in_image)
from Cons show ?case
by (auto simp: Transposition.transpose_def f_f' f'_f case_prod_unfold f'_in_A)
qed
lemma apply_transps_map_f:
assumes "\(a,b)\set xs. a \ A \ b \ A"
shows "apply_transps (map (map_prod f f) xs) =
(\<lambda>y. if y \<in> B then f (apply_transps xs (f' y)) else y)"
proof
fix y
show "apply_transps (map (map_prod f f) xs) y =
(if y \<in> B then f (apply_transps xs (f' y)) else y)"
proof (cases "y \ B") caseTrue
thus ?thesis using apply_transps_map_f_aux[OF assms] by simp
next caseFalse
have "apply_transps (map (map_prod f f) xs) permutes B" using assms by (intro permutes_apply_transps) (auto simp: case_prod_unfold f_in_B)
with False have "apply_transps (map (map_prod f f) xs) y = y"
by (intro permutes_not_in)
with False show ?thesis
by simp
qed
qed
end
locale permutes_bij_finite = permutes_bij +
assumes finite_A: "finite A"
begin
lemma evenperm_p'_iff: "evenperm p' \<longleftrightarrow> evenperm p"
proof -
obtain xs where xs: "\(a,b)\set xs. a \ A \ b \ A \ a \ b""apply_transps xs = p" using permutes_from_transpositions[OF permutes_p finite_A] by blast
have "evenperm p \ evenperm (apply_transps xs)" using xs by simp
also have "\ \ even (length xs)" using xs by (intro evenperm_apply_transps_iff) auto
also have "\ \ even (length (map (map_prod f f) xs))"
by simp
also have "\ \ evenperm (apply_transps (map (map_prod f f) xs))"using xs
by (intro evenperm_apply_transps_iff [symmetric]) (auto simp: case_prod_unfold)
also have "apply_transps (map (map_prod f f) xs) = p'" using xs unfolding p'_def by (subst apply_transps_map_f) auto
finally show ?thesis ..
qed
lemma sign_p': "sign p' = sign p"
by (auto simp: sign_def evenperm_p'_iff)
end
subsection \<open>Permuting a list\<close>
text \<open>This function permutes a list by applying a permutation to the indices.\<close>
definition permute_list :: "(nat \ nat) \ 'a list \ 'a list"
where "permute_list f xs = map (\i. xs ! (f i)) [0..
lemma permute_list_map:
assumes "f permutes {..
shows "permute_list f (map g xs) = map g (permute_list f xs)" using permutes_in_image[OF assms] by (auto simp: permute_list_def)
lemma permute_list_nth:
assumes "f permutes {.."i < length xs"
shows "permute_list f xs ! i = xs ! f i" using permutes_in_image[OF assms(1)] assms(2)
by (simp add: permute_list_def)
lemma permute_list_Nil [simp]: "permute_list f [] = []"
by (simp add: permute_list_def)
lemma length_permute_list [simp]: "length (permute_list f xs) = length xs"
by (simp add: permute_list_def)
lemma permute_list_compose:
assumes "g permutes {..
shows "permute_list (f \ g) xs = permute_list g (permute_list f xs)" using assms[THEN permutes_in_image] by (auto simp add: permute_list_def)
lemma permute_list_id [simp]: "permute_list id xs = xs"
by (simp add: id_def)
lemma mset_permute_list [simp]:
fixes xs :: "'a list"
assumes "f permutes {..
shows "mset (permute_list f xs) = mset xs"
proof (rule multiset_eqI)
fix y :: 'a
from assms have [simp]: "f x < length xs \ x < length xs"for x using permutes_in_image[OF assms] by auto
have "count (mset (permute_list f xs)) y = card ((\i. xs ! f i) -` {y} \ {..
by (simp add: permute_list_def count_image_mset atLeast0LessThan)
also have "(\i. xs ! f i) -` {y} \ {.. y = xs ! i}"
by auto
also from assms have "card \ = card {i. i < length xs \ y = xs ! i}"
by (intro card_vimage_inj) (auto simp: permutes_inj permutes_surj)
also have "\ = count (mset xs) y"
by (simp add: count_mset count_list_eq_length_filter length_filter_conv_card)
--> --------------------
--> maximum size reached
--> --------------------
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.37Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.