6 |
6 |
7 theory Permutations |
7 theory Permutations |
8 imports Multiset Disjoint_Sets |
8 imports Multiset Disjoint_Sets |
9 begin |
9 begin |
10 |
10 |
|
11 subsection \<open>Auxiliary\<close> |
|
12 |
|
13 abbreviation (input) fixpoints :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set\<close> |
|
14 where \<open>fixpoints f \<equiv> {x. f x = x}\<close> |
|
15 |
|
16 lemma inj_on_fixpoints: |
|
17 \<open>inj_on f (fixpoints f)\<close> |
|
18 by (rule inj_onI) simp |
|
19 |
|
20 lemma bij_betw_fixpoints: |
|
21 \<open>bij_betw f (fixpoints f) (fixpoints f)\<close> |
|
22 using inj_on_fixpoints by (auto simp add: bij_betw_def) |
|
23 |
|
24 |
11 subsection \<open>Basic definition and consequences\<close> |
25 subsection \<open>Basic definition and consequences\<close> |
12 |
26 |
13 definition permutes (infixr "permutes" 41) |
27 definition permutes :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set \<Rightarrow> bool\<close> (infixr \<open>permutes\<close> 41) |
14 where "(p permutes S) \<longleftrightarrow> (\<forall>x. x \<notin> S \<longrightarrow> p x = x) \<and> (\<forall>y. \<exists>!x. p x = y)" |
28 where \<open>p permutes S \<longleftrightarrow> (\<forall>x. x \<notin> S \<longrightarrow> p x = x) \<and> (\<forall>y. \<exists>!x. p x = y)\<close> |
15 |
29 |
16 lemma permutes_in_image: "p permutes S \<Longrightarrow> p x \<in> S \<longleftrightarrow> x \<in> S" |
30 lemma bij_imp_permutes: |
17 unfolding permutes_def by metis |
31 \<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> |
18 |
32 proof - |
19 lemma permutes_not_in: "f permutes S \<Longrightarrow> x \<notin> S \<Longrightarrow> f x = x" |
33 note \<open>bij_betw p S S\<close> |
20 by (auto simp: permutes_def) |
34 moreover have \<open>bij_betw p (- S) (- S)\<close> |
21 |
35 by (auto simp add: stable intro!: bij_betw_imageI inj_onI) |
22 lemma permutes_image: "p permutes S \<Longrightarrow> p ` S = S" |
36 ultimately have \<open>bij_betw p (S \<union> - S) (S \<union> - S)\<close> |
23 unfolding permutes_def |
37 by (rule bij_betw_combine) simp |
24 apply (rule set_eqI) |
38 then have \<open>\<exists>!x. p x = y\<close> for y |
25 apply (simp add: image_iff) |
39 by (simp add: bij_iff) |
26 apply metis |
40 with stable show ?thesis |
27 done |
41 by (simp add: permutes_def) |
28 |
42 qed |
29 lemma permutes_inj: "p permutes S \<Longrightarrow> inj p" |
43 |
30 unfolding permutes_def inj_def by blast |
44 context |
31 |
45 fixes p :: \<open>'a \<Rightarrow> 'a\<close> and S :: \<open>'a set\<close> |
32 lemma permutes_inj_on: "f permutes S \<Longrightarrow> inj_on f A" |
46 assumes perm: \<open>p permutes S\<close> |
33 by (auto simp: permutes_def inj_on_def) |
47 begin |
34 |
48 |
35 lemma permutes_surj: "p permutes s \<Longrightarrow> surj p" |
49 lemma permutes_inj: |
36 unfolding permutes_def surj_def by metis |
50 \<open>inj p\<close> |
37 |
51 using perm by (auto simp: permutes_def inj_on_def) |
38 lemma permutes_bij: "p permutes s \<Longrightarrow> bij p" |
52 |
39 unfolding bij_def by (metis permutes_inj permutes_surj) |
53 lemma permutes_image: |
40 |
54 \<open>p ` S = S\<close> |
41 lemma permutes_imp_bij: "p permutes S \<Longrightarrow> bij_betw p S S" |
55 proof (rule set_eqI) |
42 by (metis UNIV_I bij_betw_subset permutes_bij permutes_image subsetI) |
56 fix x |
43 |
57 show \<open>x \<in> p ` S \<longleftrightarrow> x \<in> S\<close> |
44 lemma bij_imp_permutes: "bij_betw p S S \<Longrightarrow> (\<And>x. x \<notin> S \<Longrightarrow> p x = x) \<Longrightarrow> p permutes S" |
58 proof |
45 unfolding permutes_def bij_betw_def inj_on_def |
59 assume \<open>x \<in> p ` S\<close> |
46 by auto (metis image_iff)+ |
60 then obtain y where \<open>y \<in> S\<close> \<open>p y = x\<close> |
|
61 by blast |
|
62 with perm show \<open>x \<in> S\<close> |
|
63 by (cases \<open>y = x\<close>) (auto simp add: permutes_def) |
|
64 next |
|
65 assume \<open>x \<in> S\<close> |
|
66 with perm obtain y where \<open>y \<in> S\<close> \<open>p y = x\<close> |
|
67 by (metis permutes_def) |
|
68 then show \<open>x \<in> p ` S\<close> |
|
69 by blast |
|
70 qed |
|
71 qed |
|
72 |
|
73 lemma permutes_not_in: |
|
74 \<open>x \<notin> S \<Longrightarrow> p x = x\<close> |
|
75 using perm by (auto simp: permutes_def) |
|
76 |
|
77 lemma permutes_image_complement: |
|
78 \<open>p ` (- S) = - S\<close> |
|
79 by (auto simp add: permutes_not_in) |
|
80 |
|
81 lemma permutes_in_image: |
|
82 \<open>p x \<in> S \<longleftrightarrow> x \<in> S\<close> |
|
83 using permutes_image permutes_inj by (auto dest: inj_image_mem_iff) |
|
84 |
|
85 lemma permutes_surj: |
|
86 \<open>surj p\<close> |
|
87 proof - |
|
88 have \<open>p ` (S \<union> - S) = p ` S \<union> p ` (- S)\<close> |
|
89 by (rule image_Un) |
|
90 then show ?thesis |
|
91 by (simp add: permutes_image permutes_image_complement) |
|
92 qed |
47 |
93 |
48 lemma permutes_inv_o: |
94 lemma permutes_inv_o: |
49 assumes permutes: "p permutes S" |
|
50 shows "p \<circ> inv p = id" |
95 shows "p \<circ> inv p = id" |
51 and "inv p \<circ> p = id" |
96 and "inv p \<circ> p = id" |
52 using permutes_inj[OF permutes] permutes_surj[OF permutes] |
97 using permutes_inj permutes_surj |
53 unfolding inj_iff[symmetric] surj_iff[symmetric] by blast+ |
98 unfolding inj_iff [symmetric] surj_iff [symmetric] by auto |
54 |
99 |
55 lemma permutes_inverses: |
100 lemma permutes_inverses: |
56 fixes p :: "'a \<Rightarrow> 'a" |
|
57 assumes permutes: "p permutes S" |
|
58 shows "p (inv p x) = x" |
101 shows "p (inv p x) = x" |
59 and "inv p (p x) = x" |
102 and "inv p (p x) = x" |
60 using permutes_inv_o[OF permutes, unfolded fun_eq_iff o_def] by auto |
103 using permutes_inv_o [unfolded fun_eq_iff o_def] by auto |
61 |
104 |
62 lemma permutes_subset: "p permutes S \<Longrightarrow> S \<subseteq> T \<Longrightarrow> p permutes T" |
105 lemma permutes_inv_eq: |
63 unfolding permutes_def by blast |
106 \<open>inv p y = x \<longleftrightarrow> p x = y\<close> |
|
107 by (auto simp add: permutes_inverses) |
|
108 |
|
109 lemma permutes_inj_on: |
|
110 \<open>inj_on p A\<close> |
|
111 by (rule inj_on_subset [of _ UNIV]) (auto intro: permutes_inj) |
|
112 |
|
113 lemma permutes_bij: |
|
114 \<open>bij p\<close> |
|
115 unfolding bij_def by (metis permutes_inj permutes_surj) |
|
116 |
|
117 lemma permutes_imp_bij: |
|
118 \<open>bij_betw p S S\<close> |
|
119 by (simp add: bij_betw_def permutes_image permutes_inj_on) |
|
120 |
|
121 lemma permutes_subset: |
|
122 \<open>p permutes T\<close> if \<open>S \<subseteq> T\<close> |
|
123 proof (rule bij_imp_permutes) |
|
124 define R where \<open>R = T - S\<close> |
|
125 with that have \<open>T = R \<union> S\<close> \<open>R \<inter> S = {}\<close> |
|
126 by auto |
|
127 then have \<open>p x = x\<close> if \<open>x \<in> R\<close> for x |
|
128 using that by (auto intro: permutes_not_in) |
|
129 then have \<open>p ` R = R\<close> |
|
130 by simp |
|
131 with \<open>T = R \<union> S\<close> show \<open>bij_betw p T T\<close> |
|
132 by (simp add: bij_betw_def permutes_inj_on image_Un permutes_image) |
|
133 fix x |
|
134 assume \<open>x \<notin> T\<close> |
|
135 with \<open>T = R \<union> S\<close> show \<open>p x = x\<close> |
|
136 by (simp add: permutes_not_in) |
|
137 qed |
64 |
138 |
65 lemma permutes_imp_permutes_insert: |
139 lemma permutes_imp_permutes_insert: |
66 \<open>p permutes insert x S\<close> if \<open>p permutes S\<close> |
140 \<open>p permutes insert x S\<close> |
67 using that by (rule permutes_subset) auto |
141 by (rule permutes_subset) auto |
68 |
142 |
69 lemma permutes_empty[simp]: "p permutes {} \<longleftrightarrow> p = id" |
143 end |
70 by (auto simp add: fun_eq_iff permutes_def) |
144 |
71 |
145 lemma permutes_id [simp]: |
72 lemma permutes_sing[simp]: "p permutes {a} \<longleftrightarrow> p = id" |
146 \<open>id permutes S\<close> |
73 by (simp add: fun_eq_iff permutes_def) metis (*somewhat slow*) |
147 by (auto intro: bij_imp_permutes) |
|
148 |
|
149 lemma permutes_empty [simp]: |
|
150 \<open>p permutes {} \<longleftrightarrow> p = id\<close> |
|
151 proof |
|
152 assume \<open>p permutes {}\<close> |
|
153 then show \<open>p = id\<close> |
|
154 by (auto simp add: fun_eq_iff permutes_not_in) |
|
155 next |
|
156 assume \<open>p = id\<close> |
|
157 then show \<open>p permutes {}\<close> |
|
158 by simp |
|
159 qed |
|
160 |
|
161 lemma permutes_sing [simp]: |
|
162 \<open>p permutes {a} \<longleftrightarrow> p = id\<close> |
|
163 proof |
|
164 assume perm: \<open>p permutes {a}\<close> |
|
165 show \<open>p = id\<close> |
|
166 proof |
|
167 fix x |
|
168 from perm have \<open>p ` {a} = {a}\<close> |
|
169 by (rule permutes_image) |
|
170 with perm show \<open>p x = id x\<close> |
|
171 by (cases \<open>x = a\<close>) (auto simp add: permutes_not_in) |
|
172 qed |
|
173 next |
|
174 assume \<open>p = id\<close> |
|
175 then show \<open>p permutes {a}\<close> |
|
176 by simp |
|
177 qed |
74 |
178 |
75 lemma permutes_univ: "p permutes UNIV \<longleftrightarrow> (\<forall>y. \<exists>!x. p x = y)" |
179 lemma permutes_univ: "p permutes UNIV \<longleftrightarrow> (\<forall>y. \<exists>!x. p x = y)" |
76 by (simp add: permutes_def) |
180 by (simp add: permutes_def) |
77 |
181 |
78 lemma permutes_inv_eq: "p permutes S \<Longrightarrow> inv p y = x \<longleftrightarrow> p x = y" |
|
79 unfolding permutes_def inv_def |
|
80 apply auto |
|
81 apply (erule allE[where x=y]) |
|
82 apply (erule allE[where x=y]) |
|
83 apply (rule someI_ex) |
|
84 apply blast |
|
85 apply (rule some1_equality) |
|
86 apply blast |
|
87 apply blast |
|
88 done |
|
89 |
|
90 lemma permutes_swap_id: "a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> Fun.swap a b id permutes S" |
182 lemma permutes_swap_id: "a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> Fun.swap a b id permutes S" |
91 unfolding permutes_def Fun.swap_def fun_upd_def by auto metis |
183 by (rule bij_imp_permutes) (auto simp add: swap_id_eq) |
92 |
184 |
93 lemma permutes_superset: "p permutes S \<Longrightarrow> (\<forall>x \<in> S - T. p x = x) \<Longrightarrow> p permutes T" |
185 lemma permutes_superset: |
94 by (simp add: Ball_def permutes_def) metis |
186 \<open>p permutes T\<close> if \<open>p permutes S\<close> \<open>\<And>x. x \<in> S - T \<Longrightarrow> p x = x\<close> |
|
187 proof - |
|
188 define R U where \<open>R = T \<inter> S\<close> and \<open>U = S - T\<close> |
|
189 then have \<open>T = R \<union> (T - S)\<close> \<open>S = R \<union> U\<close> \<open>R \<inter> U = {}\<close> |
|
190 by auto |
|
191 from that \<open>U = S - T\<close> have \<open>p ` U = U\<close> |
|
192 by simp |
|
193 from \<open>p permutes S\<close> have \<open>bij_betw p (R \<union> U) (R \<union> U)\<close> |
|
194 by (simp add: permutes_imp_bij \<open>S = R \<union> U\<close>) |
|
195 moreover have \<open>bij_betw p U U\<close> |
|
196 using that \<open>U = S - T\<close> by (simp add: bij_betw_def permutes_inj_on) |
|
197 ultimately have \<open>bij_betw p R R\<close> |
|
198 using \<open>R \<inter> U = {}\<close> \<open>R \<inter> U = {}\<close> by (rule bij_betw_partition) |
|
199 then have \<open>p permutes R\<close> |
|
200 proof (rule bij_imp_permutes) |
|
201 fix x |
|
202 assume \<open>x \<notin> R\<close> |
|
203 with \<open>R = T \<inter> S\<close> \<open>p permutes S\<close> show \<open>p x = x\<close> |
|
204 by (cases \<open>x \<in> S\<close>) (auto simp add: permutes_not_in that(2)) |
|
205 qed |
|
206 then have \<open>p permutes R \<union> (T - S)\<close> |
|
207 by (rule permutes_subset) simp |
|
208 with \<open>T = R \<union> (T - S)\<close> show ?thesis |
|
209 by simp |
|
210 qed |
95 |
211 |
96 lemma permutes_bij_inv_into: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close> |
212 lemma permutes_bij_inv_into: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close> |
97 fixes A :: "'a set" |
213 fixes A :: "'a set" |
98 and B :: "'b set" |
214 and B :: "'b set" |
99 assumes "p permutes A" |
215 assumes "p permutes A" |
384 |
497 |
385 lemma finite_permutations: |
498 lemma finite_permutations: |
386 assumes "finite S" |
499 assumes "finite S" |
387 shows "finite {p. p permutes S}" |
500 shows "finite {p. p permutes S}" |
388 using card_permutations[OF refl assms] by (auto intro: card_ge_0_finite) |
501 using card_permutations[OF refl assms] by (auto intro: card_ge_0_finite) |
|
502 |
|
503 |
|
504 subsection \<open>Hence a sort of induction principle composing by swaps\<close> |
|
505 |
|
506 lemma permutes_induct [consumes 2, case_names id swap]: |
|
507 \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close> |
|
508 and id: \<open>P id\<close> |
|
509 and swap: \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> p permutes S \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b id \<circ> p)\<close> |
|
510 using \<open>finite S\<close> \<open>p permutes S\<close> swap proof (induction S arbitrary: p) |
|
511 case empty |
|
512 with id show ?case |
|
513 by (simp only: permutes_empty) |
|
514 next |
|
515 case (insert x S p) |
|
516 define q where \<open>q = Fun.swap x (p x) id \<circ> p\<close> |
|
517 then have swap_q: \<open>Fun.swap x (p x) id \<circ> q = p\<close> |
|
518 by (simp add: o_assoc) |
|
519 from \<open>p permutes insert x S\<close> have \<open>q permutes S\<close> |
|
520 by (simp add: q_def permutes_insert_lemma) |
|
521 then have \<open>q permutes insert x S\<close> |
|
522 by (simp add: permutes_imp_permutes_insert) |
|
523 from \<open>q permutes S\<close> have \<open>P q\<close> |
|
524 by (auto intro: insert.IH insert.prems(2) permutes_imp_permutes_insert) |
|
525 have \<open>x \<in> insert x S\<close> |
|
526 by simp |
|
527 moreover from \<open>p permutes insert x S\<close> have \<open>p x \<in> insert x S\<close> |
|
528 using permutes_in_image [of p \<open>insert x S\<close> x] by simp |
|
529 ultimately have \<open>P (Fun.swap x (p x) id \<circ> q)\<close> |
|
530 using \<open>q permutes insert x S\<close> \<open>P q\<close> |
|
531 by (rule insert.prems(2)) |
|
532 then show ?case |
|
533 by (simp add: swap_q) |
|
534 qed |
|
535 |
|
536 lemma permutes_rev_induct [consumes 2, case_names id swap]: |
|
537 \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close> |
|
538 and id': \<open>P id\<close> |
|
539 and swap': \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> p permutes S \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b p)\<close> |
|
540 using \<open>p permutes S\<close> \<open>finite S\<close> proof (induction rule: permutes_induct) |
|
541 case id |
|
542 from id' show ?case . |
|
543 next |
|
544 case (swap a b p) |
|
545 have \<open>P (Fun.swap (inv p a) (inv p b) p)\<close> |
|
546 by (rule swap') (auto simp add: swap permutes_in_image permutes_inv) |
|
547 also have \<open>Fun.swap (inv p a) (inv p b) p = Fun.swap a b id \<circ> p\<close> |
|
548 by (rule bij_swap_comp [symmetric]) (rule permutes_bij, rule swap) |
|
549 finally show ?case . |
|
550 qed |
389 |
551 |
390 |
552 |
391 subsection \<open>Permutations of index set for iterated operations\<close> |
553 subsection \<open>Permutations of index set for iterated operations\<close> |
392 |
554 |
393 lemma (in comm_monoid_set) permute: |
555 lemma (in comm_monoid_set) permute: |
832 qed |
994 qed |
833 |
995 |
834 |
996 |
835 subsection \<open>Relation to \<open>permutes\<close>\<close> |
997 subsection \<open>Relation to \<open>permutes\<close>\<close> |
836 |
998 |
|
999 lemma permutes_imp_permutation: |
|
1000 \<open>permutation p\<close> if \<open>finite S\<close> \<open>p permutes S\<close> |
|
1001 proof - |
|
1002 from \<open>p permutes S\<close> have \<open>{x. p x \<noteq> x} \<subseteq> S\<close> |
|
1003 by (auto dest: permutes_not_in) |
|
1004 then have \<open>finite {x. p x \<noteq> x}\<close> |
|
1005 using \<open>finite S\<close> by (rule finite_subset) |
|
1006 moreover from \<open>p permutes S\<close> have \<open>bij p\<close> |
|
1007 by (auto dest: permutes_bij) |
|
1008 ultimately show ?thesis |
|
1009 by (simp add: permutation) |
|
1010 qed |
|
1011 |
|
1012 lemma permutation_permutesE: |
|
1013 assumes \<open>permutation p\<close> |
|
1014 obtains S where \<open>finite S\<close> \<open>p permutes S\<close> |
|
1015 proof - |
|
1016 from assms have fin: \<open>finite {x. p x \<noteq> x}\<close> |
|
1017 by (simp add: permutation) |
|
1018 from assms have \<open>bij p\<close> |
|
1019 by (simp add: permutation) |
|
1020 also have \<open>UNIV = {x. p x \<noteq> x} \<union> {x. p x = x}\<close> |
|
1021 by auto |
|
1022 finally have \<open>bij_betw p {x. p x \<noteq> x} {x. p x \<noteq> x}\<close> |
|
1023 by (rule bij_betw_partition) (auto simp add: bij_betw_fixpoints) |
|
1024 then have \<open>p permutes {x. p x \<noteq> x}\<close> |
|
1025 by (auto intro: bij_imp_permutes) |
|
1026 with fin show thesis .. |
|
1027 qed |
|
1028 |
837 lemma permutation_permutes: "permutation p \<longleftrightarrow> (\<exists>S. finite S \<and> p permutes S)" |
1029 lemma permutation_permutes: "permutation p \<longleftrightarrow> (\<exists>S. finite S \<and> p permutes S)" |
838 unfolding permutation permutes_def bij_iff[symmetric] |
1030 by (auto elim: permutation_permutesE intro: permutes_imp_permutation) |
839 apply (rule iffI, clarify) |
|
840 apply (rule exI[where x="{x. p x \<noteq> x}"]) |
|
841 apply simp |
|
842 apply clarsimp |
|
843 apply (rule_tac B="S" in finite_subset) |
|
844 apply auto |
|
845 done |
|
846 |
|
847 |
|
848 subsection \<open>Hence a sort of induction principle composing by swaps\<close> |
|
849 |
|
850 lemma permutes_induct [consumes 2, case_names id swap]: |
|
851 \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close> |
|
852 and id: \<open>P id\<close> |
|
853 and swap: \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> permutation p \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b id \<circ> p)\<close> |
|
854 using \<open>finite S\<close> \<open>p permutes S\<close> id swap proof (induction S arbitrary: p) |
|
855 case empty |
|
856 then show ?case by auto |
|
857 next |
|
858 case (insert x F p) |
|
859 let ?r = "Fun.swap x (p x) id \<circ> p" |
|
860 let ?q = "Fun.swap x (p x) id \<circ> ?r" |
|
861 have qp: "?q = p" |
|
862 by (simp add: o_assoc) |
|
863 from permutes_insert_lemma[OF \<open>p permutes insert x F\<close>] insert have Pr: "P ?r" |
|
864 by blast |
|
865 from permutes_in_image[OF \<open>p permutes insert x F\<close>, of x] |
|
866 have pxF: "p x \<in> insert x F" |
|
867 by simp |
|
868 have xF: "x \<in> insert x F" |
|
869 by simp |
|
870 have rp: "permutation ?r" |
|
871 unfolding permutation_permutes |
|
872 using insert.hyps(1) permutes_insert_lemma[OF \<open>p permutes insert x F\<close>] |
|
873 by blast |
|
874 from insert.prems(3)[OF xF pxF rp Pr] qp show ?case |
|
875 by (simp only:) |
|
876 qed |
|
877 |
1031 |
878 |
1032 |
879 subsection \<open>Sign of a permutation as a real number\<close> |
1033 subsection \<open>Sign of a permutation as a real number\<close> |
880 |
1034 |
881 definition sign :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> int\<close> \<comment> \<open>TODO: prefer less generic name\<close> |
1035 definition sign :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> int\<close> \<comment> \<open>TODO: prefer less generic name\<close> |