| author | haftmann | 
| Wed, 18 Jul 2018 20:51:23 +0200 | |
| changeset 68660 | 4ce18f389f53 | 
| parent 68084 | 152cc388cd1e | 
| child 69745 | aec42cee2521 | 
| permissions | -rw-r--r-- | 
| 63375 | 1 | (* Author: Florian Haftmann, TU Muenchen *) | 
| 2 | ||
| 3 | section \<open>Fragments on permuations\<close> | |
| 4 | ||
| 5 | theory Perm_Fragments | |
| 66453 
cc19f7ca2ed6
session-qualified theory imports: isabelle imports -U -i -d '~~/src/Benchmarks' -a;
 wenzelm parents: 
63882diff
changeset | 6 | imports "HOL-Library.Perm" "HOL-Library.Dlist" | 
| 63375 | 7 | begin | 
| 8 | ||
| 9 | unbundle permutation_syntax | |
| 10 | ||
| 11 | ||
| 12 | text \<open>On cycles\<close> | |
| 13 | ||
| 63882 
018998c00003
renamed listsum -> sum_list, listprod ~> prod_list
 nipkow parents: 
63375diff
changeset | 14 | lemma cycle_prod_list: | 
| 
018998c00003
renamed listsum -> sum_list, listprod ~> prod_list
 nipkow parents: 
63375diff
changeset | 15 | "\<langle>a # as\<rangle> = prod_list (map (\<lambda>b. \<langle>a\<leftrightarrow>b\<rangle>) (rev as))" | 
| 63375 | 16 | by (induct as) simp_all | 
| 17 | ||
| 18 | lemma cycle_append [simp]: | |
| 19 | "\<langle>a # as @ bs\<rangle> = \<langle>a # bs\<rangle> * \<langle>a # as\<rangle>" | |
| 20 | proof (induct as rule: cycle.induct) | |
| 21 | case (3 b c as) | |
| 22 | then have "\<langle>a # (b # as) @ bs\<rangle> = \<langle>a # bs\<rangle> * \<langle>a # b # as\<rangle>" | |
| 23 | by simp | |
| 24 | then have "\<langle>a # as @ bs\<rangle> * \<langle>a\<leftrightarrow>b\<rangle> = | |
| 25 | \<langle>a # bs\<rangle> * \<langle>a # as\<rangle> * \<langle>a\<leftrightarrow>b\<rangle>" | |
| 26 | by (simp add: ac_simps) | |
| 27 | then have "\<langle>a # as @ bs\<rangle> * \<langle>a\<leftrightarrow>b\<rangle> * \<langle>a\<leftrightarrow>b\<rangle> = | |
| 28 | \<langle>a # bs\<rangle> * \<langle>a # as\<rangle> * \<langle>a\<leftrightarrow>b\<rangle> * \<langle>a\<leftrightarrow>b\<rangle>" | |
| 29 | by simp | |
| 30 | then have "\<langle>a # as @ bs\<rangle> = \<langle>a # bs\<rangle> * \<langle>a # as\<rangle>" | |
| 31 | by (simp add: ac_simps) | |
| 32 | then show "\<langle>a # (b # c # as) @ bs\<rangle> = | |
| 33 | \<langle>a # bs\<rangle> * \<langle>a # b # c # as\<rangle>" | |
| 34 | by (simp add: ac_simps) | |
| 35 | qed simp_all | |
| 36 | ||
| 37 | lemma affected_cycle: | |
| 38 | "affected \<langle>as\<rangle> \<subseteq> set as" | |
| 39 | proof (induct as rule: cycle.induct) | |
| 40 | case (3 a b as) | |
| 41 | from affected_times | |
| 42 | have "affected (\<langle>a # as\<rangle> * \<langle>a\<leftrightarrow>b\<rangle>) | |
| 43 | \<subseteq> affected \<langle>a # as\<rangle> \<union> affected \<langle>a\<leftrightarrow>b\<rangle>" . | |
| 44 | moreover from 3 | |
| 45 | have "affected (\<langle>a # as\<rangle>) \<subseteq> insert a (set as)" | |
| 46 | by simp | |
| 47 | moreover | |
| 48 |   have "affected \<langle>a\<leftrightarrow>b\<rangle> \<subseteq> {a, b}"
 | |
| 49 | by (cases "a = b") (simp_all add: affected_swap) | |
| 50 | ultimately have "affected (\<langle>a # as\<rangle> * \<langle>a\<leftrightarrow>b\<rangle>) | |
| 51 | \<subseteq> insert a (insert b (set as))" | |
| 52 | by blast | |
| 53 | then show ?case by auto | |
| 54 | qed simp_all | |
| 55 | ||
| 56 | lemma orbit_cycle_non_elem: | |
| 57 | assumes "a \<notin> set as" | |
| 58 |   shows "orbit \<langle>as\<rangle> a = {a}"
 | |
| 59 | unfolding not_in_affected_iff_orbit_eq_singleton [symmetric] | |
| 60 | using assms affected_cycle [of as] by blast | |
| 61 | ||
| 62 | lemma inverse_cycle: | |
| 63 | assumes "distinct as" | |
| 64 | shows "inverse \<langle>as\<rangle> = \<langle>rev as\<rangle>" | |
| 65 | using assms proof (induct as rule: cycle.induct) | |
| 66 | case (3 a b as) | |
| 67 | then have *: "inverse \<langle>a # as\<rangle> = \<langle>rev (a # as)\<rangle>" | |
| 68 | and distinct: "distinct (a # b # as)" | |
| 69 | by simp_all | |
| 70 | show " inverse \<langle>a # b # as\<rangle> = \<langle>rev (a # b # as)\<rangle>" | |
| 71 | proof (cases as rule: rev_cases) | |
| 72 | case Nil with * show ?thesis | |
| 73 | by (simp add: swap_sym) | |
| 74 | next | |
| 75 | case (snoc cs c) | |
| 76 | with distinct have "distinct (a # b # cs @ [c])" | |
| 77 | by simp | |
| 78 | then have **: "\<langle>a\<leftrightarrow>b\<rangle> * \<langle>c\<leftrightarrow>a\<rangle> = \<langle>c\<leftrightarrow>a\<rangle> * \<langle>c\<leftrightarrow>b\<rangle>" | |
| 79 | by transfer (auto simp add: comp_def Fun.swap_def) | |
| 80 | with snoc * show ?thesis | |
| 81 | by (simp add: mult.assoc [symmetric]) | |
| 82 | qed | |
| 83 | qed simp_all | |
| 84 | ||
| 85 | lemma order_cycle_non_elem: | |
| 86 | assumes "a \<notin> set as" | |
| 87 | shows "order \<langle>as\<rangle> a = 1" | |
| 88 | proof - | |
| 89 |   from assms have "orbit \<langle>as\<rangle> a = {a}" 
 | |
| 90 | by (rule orbit_cycle_non_elem) | |
| 91 |   then have "card (orbit \<langle>as\<rangle> a) = card {a}"
 | |
| 92 | by simp | |
| 93 | then show ?thesis | |
| 94 | by simp | |
| 95 | qed | |
| 96 | ||
| 97 | lemma orbit_cycle_elem: | |
| 98 | assumes "distinct as" and "a \<in> set as" | |
| 99 | shows "orbit \<langle>as\<rangle> a = set as" | |
| 67226 | 100 | oops \<comment> \<open>(we need rotation here\<close> | 
| 63375 | 101 | |
| 102 | lemma order_cycle_elem: | |
| 103 | assumes "distinct as" and "a \<in> set as" | |
| 104 | shows "order \<langle>as\<rangle> a = length as" | |
| 105 | oops | |
| 106 | ||
| 107 | ||
| 108 | text \<open>Adding fixpoints\<close> | |
| 109 | ||
| 110 | definition fixate :: "'a \<Rightarrow> 'a perm \<Rightarrow> 'a perm" | |
| 111 | where | |
| 112 | "fixate a f = (if a \<in> affected f then f * \<langle>apply (inverse f) a\<leftrightarrow>a\<rangle> else f)" | |
| 113 | ||
| 114 | lemma affected_fixate_trivial: | |
| 115 | assumes "a \<notin> affected f" | |
| 116 | shows "affected (fixate a f) = affected f" | |
| 117 | using assms by (simp add: fixate_def) | |
| 118 | ||
| 119 | lemma affected_fixate_binary_circle: | |
| 120 | assumes "order f a = 2" | |
| 121 |   shows "affected (fixate a f) = affected f - {a, apply f a}" (is "?A = ?B")
 | |
| 122 | proof (rule set_eqI) | |
| 123 | interpret bijection "apply f" | |
| 124 | by standard simp | |
| 125 | fix b | |
| 126 | from assms order_greater_eq_two_iff [of f a] have "a \<in> affected f" | |
| 127 | by simp | |
| 128 | moreover have "apply (f ^ 2) a = a" | |
| 129 | by (simp add: assms [symmetric]) | |
| 130 | ultimately show "b \<in> ?A \<longleftrightarrow> b \<in> ?B" | |
| 131 |     by (cases "b \<in> {a, apply (inverse f) a}")
 | |
| 132 | (auto simp add: in_affected power2_eq_square apply_inverse apply_times fixate_def) | |
| 133 | qed | |
| 134 | ||
| 135 | lemma affected_fixate_no_binary_circle: | |
| 136 | assumes "order f a > 2" | |
| 137 |   shows "affected (fixate a f) = affected f - {a}" (is "?A = ?B")
 | |
| 138 | proof (rule set_eqI) | |
| 139 | interpret bijection "apply f" | |
| 140 | by standard simp | |
| 141 | fix b | |
| 142 | from assms order_greater_eq_two_iff [of f a] | |
| 143 | have "a \<in> affected f" | |
| 144 | by simp | |
| 145 | moreover from assms | |
| 146 | have "apply f (apply f a) \<noteq> a" | |
| 147 | using apply_power_eq_iff [of f 2 a 0] | |
| 148 | by (simp add: power2_eq_square apply_times) | |
| 149 | ultimately show "b \<in> ?A \<longleftrightarrow> b \<in> ?B" | |
| 150 |     by (cases "b \<in> {a, apply (inverse f) a}")
 | |
| 151 | (auto simp add: in_affected apply_inverse apply_times fixate_def) | |
| 152 | qed | |
| 153 | ||
| 154 | lemma affected_fixate: | |
| 155 |   "affected (fixate a f) \<subseteq> affected f - {a}"
 | |
| 156 | proof - | |
| 157 | have "a \<notin> affected f \<or> order f a = 2 \<or> order f a > 2" | |
| 158 | by (auto simp add: not_less dest: affected_order_greater_eq_two) | |
| 159 | then consider "a \<notin> affected f" | "order f a = 2" | "order f a > 2" | |
| 160 | by blast | |
| 161 | then show ?thesis apply cases | |
| 162 | using affected_fixate_trivial [of a f] | |
| 163 | affected_fixate_binary_circle [of f a] | |
| 164 | affected_fixate_no_binary_circle [of f a] | |
| 165 | by auto | |
| 166 | qed | |
| 167 | ||
| 168 | lemma orbit_fixate_self [simp]: | |
| 169 |   "orbit (fixate a f) a = {a}"
 | |
| 170 | proof - | |
| 171 | have "apply (f * inverse f) a = a" | |
| 172 | by simp | |
| 173 | then have "apply f (apply (inverse f) a) = a" | |
| 174 | by (simp only: apply_times comp_apply) | |
| 175 | then show ?thesis | |
| 176 | by (simp add: fixate_def not_in_affected_iff_orbit_eq_singleton [symmetric] in_affected apply_times) | |
| 177 | qed | |
| 178 | ||
| 179 | lemma order_fixate_self [simp]: | |
| 180 | "order (fixate a f) a = 1" | |
| 181 | proof - | |
| 182 |   have "card (orbit (fixate a f) a) = card {a}"
 | |
| 183 | by simp | |
| 184 | then show ?thesis | |
| 185 | by (simp only: card_orbit_eq) simp | |
| 186 | qed | |
| 187 | ||
| 188 | lemma | |
| 189 | assumes "b \<notin> orbit f a" | |
| 190 | shows "orbit (fixate b f) a = orbit f a" | |
| 191 | oops | |
| 192 | ||
| 193 | lemma | |
| 194 | assumes "b \<in> orbit f a" and "b \<noteq> a" | |
| 195 |   shows "orbit (fixate b f) a = orbit f a - {b}"
 | |
| 196 | oops | |
| 197 | ||
| 198 | ||
| 199 | text \<open>Distilling cycles from permutations\<close> | |
| 200 | ||
| 201 | inductive_set orbits :: "'a perm \<Rightarrow> 'a set set" for f | |
| 202 | where | |
| 203 | in_orbitsI: "a \<in> affected f \<Longrightarrow> orbit f a \<in> orbits f" | |
| 204 | ||
| 205 | lemma orbits_unfold: | |
| 206 | "orbits f = orbit f ` affected f" | |
| 207 | by (auto intro: in_orbitsI elim: orbits.cases) | |
| 208 | ||
| 209 | lemma in_orbit_affected: | |
| 210 | assumes "b \<in> orbit f a" | |
| 211 | assumes "a \<in> affected f" | |
| 212 | shows "b \<in> affected f" | |
| 213 | proof (cases "a = b") | |
| 214 | case True with assms show ?thesis by simp | |
| 215 | next | |
| 216 |   case False with assms have "{a, b} \<subseteq> orbit f a"
 | |
| 217 | by auto | |
| 218 | also from assms have "orbit f a \<subseteq> affected f" | |
| 219 | by (blast intro!: orbit_subset_eq_affected) | |
| 220 | finally show ?thesis by simp | |
| 221 | qed | |
| 222 | ||
| 223 | lemma Union_orbits [simp]: | |
| 224 | "\<Union>orbits f = affected f" | |
| 225 | by (auto simp add: orbits.simps intro: in_orbitsI in_orbit_affected) | |
| 226 | ||
| 227 | lemma finite_orbits [simp]: | |
| 228 | "finite (orbits f)" | |
| 229 | by (simp add: orbits_unfold) | |
| 230 | ||
| 231 | lemma card_in_orbits: | |
| 232 | assumes "A \<in> orbits f" | |
| 233 | shows "card A \<ge> 2" | |
| 234 | using assms by cases | |
| 235 | (auto dest: affected_order_greater_eq_two) | |
| 236 | ||
| 237 | lemma disjoint_orbits: | |
| 238 | assumes "A \<in> orbits f" and "B \<in> orbits f" and "A \<noteq> B" | |
| 239 |   shows "A \<inter> B = {}"
 | |
| 240 | using \<open>A \<in> orbits f\<close> apply cases | |
| 241 | using \<open>B \<in> orbits f\<close> apply cases | |
| 242 | using \<open>A \<noteq> B\<close> apply (simp_all add: orbit_disjoint) | |
| 243 | done | |
| 244 | ||
| 245 | definition trace :: "'a \<Rightarrow> 'a perm \<Rightarrow> 'a list" | |
| 246 | where | |
| 247 | "trace a f = map (\<lambda>n. apply (f ^ n) a) [0..<order f a]" | |
| 248 | ||
| 249 | lemma set_trace_eq [simp]: | |
| 250 | "set (trace a f) = orbit f a" | |
| 251 | by (auto simp add: trace_def orbit_unfold_image) | |
| 252 | ||
| 253 | definition seeds :: "'a perm \<Rightarrow> 'a::linorder list" | |
| 254 | where | |
| 255 | "seeds f = sorted_list_of_set (Min ` orbits f)" | |
| 256 | ||
| 257 | definition cycles :: "'a perm \<Rightarrow> 'a::linorder list list" | |
| 258 | where | |
| 259 | "cycles f = map (\<lambda>a. trace a f) (seeds f)" | |
| 260 | ||
| 261 | lemma (in comm_monoid_list_set) sorted_list_of_set: | |
| 262 | assumes "finite A" | |
| 263 | shows "list.F (map h (sorted_list_of_set A)) = set.F h A" | |
| 264 | proof - | |
| 265 | from distinct_sorted_list_of_set | |
| 266 | have "set.F h (set (sorted_list_of_set A)) = list.F (map h (sorted_list_of_set A))" | |
| 267 | by (rule distinct_set_conv_list) | |
| 268 | with \<open>finite A\<close> show ?thesis | |
| 68084 | 269 | by (simp) | 
| 63375 | 270 | qed | 
| 271 | ||
| 272 | ||
| 273 | text \<open>Misc\<close> | |
| 274 | ||
| 275 | primrec subtract :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" | |
| 276 | where | |
| 277 | "subtract [] ys = ys" | |
| 278 | | "subtract (x # xs) ys = subtract xs (removeAll x ys)" | |
| 279 | ||
| 280 | lemma length_subtract_less_eq [simp]: | |
| 281 | "length (subtract xs ys) \<le> length ys" | |
| 282 | proof (induct xs arbitrary: ys) | |
| 283 | case Nil then show ?case by simp | |
| 284 | next | |
| 285 | case (Cons x xs) | |
| 286 | then have "length (subtract xs (removeAll x ys)) \<le> length (removeAll x ys)" . | |
| 287 | also have "length (removeAll x ys) \<le> length ys" | |
| 288 | by simp | |
| 289 | finally show ?case | |
| 290 | by simp | |
| 291 | qed | |
| 292 | ||
| 293 | end |