| author | wenzelm | 
| Sun, 16 Feb 2014 17:17:26 +0100 | |
| changeset 55515 | 0e161deca64d | 
| parent 51489 | f738e6dbd844 | 
| child 57512 | cc97b347b301 | 
| permissions | -rw-r--r-- | 
| 41959 | 1 | (* Title: HOL/Library/Nat_Bijection.thy | 
| 35700 | 2 | Author: Brian Huffman | 
| 3 | Author: Florian Haftmann | |
| 4 | Author: Stefan Richter | |
| 5 | Author: Tobias Nipkow | |
| 6 | Author: Alexander Krauss | |
| 7 | *) | |
| 8 | ||
| 9 | header {* Bijections between natural numbers and other types *}
 | |
| 10 | ||
| 11 | theory Nat_Bijection | |
| 12 | imports Main Parity | |
| 13 | begin | |
| 14 | ||
| 15 | subsection {* Type @{typ "nat \<times> nat"} *}
 | |
| 16 | ||
| 17 | text "Triangle numbers: 0, 1, 3, 6, 10, 15, ..." | |
| 18 | ||
| 19 | definition | |
| 20 | triangle :: "nat \<Rightarrow> nat" | |
| 21 | where | |
| 22 | "triangle n = n * Suc n div 2" | |
| 23 | ||
| 24 | lemma triangle_0 [simp]: "triangle 0 = 0" | |
| 25 | unfolding triangle_def by simp | |
| 26 | ||
| 27 | lemma triangle_Suc [simp]: "triangle (Suc n) = triangle n + Suc n" | |
| 28 | unfolding triangle_def by simp | |
| 29 | ||
| 30 | definition | |
| 31 | prod_encode :: "nat \<times> nat \<Rightarrow> nat" | |
| 32 | where | |
| 33 | "prod_encode = (\<lambda>(m, n). triangle (m + n) + m)" | |
| 34 | ||
| 35 | text {* In this auxiliary function, @{term "triangle k + m"} is an invariant. *}
 | |
| 36 | ||
| 37 | fun | |
| 38 | prod_decode_aux :: "nat \<Rightarrow> nat \<Rightarrow> nat \<times> nat" | |
| 39 | where | |
| 40 | "prod_decode_aux k m = | |
| 41 | (if m \<le> k then (m, k - m) else prod_decode_aux (Suc k) (m - Suc k))" | |
| 42 | ||
| 43 | declare prod_decode_aux.simps [simp del] | |
| 44 | ||
| 45 | definition | |
| 46 | prod_decode :: "nat \<Rightarrow> nat \<times> nat" | |
| 47 | where | |
| 48 | "prod_decode = prod_decode_aux 0" | |
| 49 | ||
| 50 | lemma prod_encode_prod_decode_aux: | |
| 51 | "prod_encode (prod_decode_aux k m) = triangle k + m" | |
| 52 | apply (induct k m rule: prod_decode_aux.induct) | |
| 53 | apply (subst prod_decode_aux.simps) | |
| 54 | apply (simp add: prod_encode_def) | |
| 55 | done | |
| 56 | ||
| 57 | lemma prod_decode_inverse [simp]: "prod_encode (prod_decode n) = n" | |
| 58 | unfolding prod_decode_def by (simp add: prod_encode_prod_decode_aux) | |
| 59 | ||
| 60 | lemma prod_decode_triangle_add: | |
| 61 | "prod_decode (triangle k + m) = prod_decode_aux k m" | |
| 62 | apply (induct k arbitrary: m) | |
| 63 | apply (simp add: prod_decode_def) | |
| 64 | apply (simp only: triangle_Suc add_assoc) | |
| 65 | apply (subst prod_decode_aux.simps, simp) | |
| 66 | done | |
| 67 | ||
| 68 | lemma prod_encode_inverse [simp]: "prod_decode (prod_encode x) = x" | |
| 69 | unfolding prod_encode_def | |
| 70 | apply (induct x) | |
| 71 | apply (simp add: prod_decode_triangle_add) | |
| 72 | apply (subst prod_decode_aux.simps, simp) | |
| 73 | done | |
| 74 | ||
| 75 | lemma inj_prod_encode: "inj_on prod_encode A" | |
| 76 | by (rule inj_on_inverseI, rule prod_encode_inverse) | |
| 77 | ||
| 78 | lemma inj_prod_decode: "inj_on prod_decode A" | |
| 79 | by (rule inj_on_inverseI, rule prod_decode_inverse) | |
| 80 | ||
| 81 | lemma surj_prod_encode: "surj prod_encode" | |
| 82 | by (rule surjI, rule prod_decode_inverse) | |
| 83 | ||
| 84 | lemma surj_prod_decode: "surj prod_decode" | |
| 85 | by (rule surjI, rule prod_encode_inverse) | |
| 86 | ||
| 87 | lemma bij_prod_encode: "bij prod_encode" | |
| 88 | by (rule bijI [OF inj_prod_encode surj_prod_encode]) | |
| 89 | ||
| 90 | lemma bij_prod_decode: "bij prod_decode" | |
| 91 | by (rule bijI [OF inj_prod_decode surj_prod_decode]) | |
| 92 | ||
| 93 | lemma prod_encode_eq: "prod_encode x = prod_encode y \<longleftrightarrow> x = y" | |
| 94 | by (rule inj_prod_encode [THEN inj_eq]) | |
| 95 | ||
| 96 | lemma prod_decode_eq: "prod_decode x = prod_decode y \<longleftrightarrow> x = y" | |
| 97 | by (rule inj_prod_decode [THEN inj_eq]) | |
| 98 | ||
| 99 | text {* Ordering properties *}
 | |
| 100 | ||
| 101 | lemma le_prod_encode_1: "a \<le> prod_encode (a, b)" | |
| 102 | unfolding prod_encode_def by simp | |
| 103 | ||
| 104 | lemma le_prod_encode_2: "b \<le> prod_encode (a, b)" | |
| 105 | unfolding prod_encode_def by (induct b, simp_all) | |
| 106 | ||
| 107 | ||
| 108 | subsection {* Type @{typ "nat + nat"} *}
 | |
| 109 | ||
| 110 | definition | |
| 111 | sum_encode :: "nat + nat \<Rightarrow> nat" | |
| 112 | where | |
| 113 | "sum_encode x = (case x of Inl a \<Rightarrow> 2 * a | Inr b \<Rightarrow> Suc (2 * b))" | |
| 114 | ||
| 115 | definition | |
| 116 | sum_decode :: "nat \<Rightarrow> nat + nat" | |
| 117 | where | |
| 118 | "sum_decode n = (if even n then Inl (n div 2) else Inr (n div 2))" | |
| 119 | ||
| 120 | lemma sum_encode_inverse [simp]: "sum_decode (sum_encode x) = x" | |
| 121 | unfolding sum_decode_def sum_encode_def | |
| 122 | by (induct x) simp_all | |
| 123 | ||
| 124 | lemma sum_decode_inverse [simp]: "sum_encode (sum_decode n) = n" | |
| 125 | unfolding sum_decode_def sum_encode_def numeral_2_eq_2 | |
| 126 | by (simp add: even_nat_div_two_times_two odd_nat_div_two_times_two_plus_one | |
| 127 | del: mult_Suc) | |
| 128 | ||
| 129 | lemma inj_sum_encode: "inj_on sum_encode A" | |
| 130 | by (rule inj_on_inverseI, rule sum_encode_inverse) | |
| 131 | ||
| 132 | lemma inj_sum_decode: "inj_on sum_decode A" | |
| 133 | by (rule inj_on_inverseI, rule sum_decode_inverse) | |
| 134 | ||
| 135 | lemma surj_sum_encode: "surj sum_encode" | |
| 136 | by (rule surjI, rule sum_decode_inverse) | |
| 137 | ||
| 138 | lemma surj_sum_decode: "surj sum_decode" | |
| 139 | by (rule surjI, rule sum_encode_inverse) | |
| 140 | ||
| 141 | lemma bij_sum_encode: "bij sum_encode" | |
| 142 | by (rule bijI [OF inj_sum_encode surj_sum_encode]) | |
| 143 | ||
| 144 | lemma bij_sum_decode: "bij sum_decode" | |
| 145 | by (rule bijI [OF inj_sum_decode surj_sum_decode]) | |
| 146 | ||
| 147 | lemma sum_encode_eq: "sum_encode x = sum_encode y \<longleftrightarrow> x = y" | |
| 148 | by (rule inj_sum_encode [THEN inj_eq]) | |
| 149 | ||
| 150 | lemma sum_decode_eq: "sum_decode x = sum_decode y \<longleftrightarrow> x = y" | |
| 151 | by (rule inj_sum_decode [THEN inj_eq]) | |
| 152 | ||
| 153 | ||
| 154 | subsection {* Type @{typ "int"} *}
 | |
| 155 | ||
| 156 | definition | |
| 157 | int_encode :: "int \<Rightarrow> nat" | |
| 158 | where | |
| 159 | "int_encode i = sum_encode (if 0 \<le> i then Inl (nat i) else Inr (nat (- i - 1)))" | |
| 160 | ||
| 161 | definition | |
| 162 | int_decode :: "nat \<Rightarrow> int" | |
| 163 | where | |
| 164 | "int_decode n = (case sum_decode n of Inl a \<Rightarrow> int a | Inr b \<Rightarrow> - int b - 1)" | |
| 165 | ||
| 166 | lemma int_encode_inverse [simp]: "int_decode (int_encode x) = x" | |
| 167 | unfolding int_decode_def int_encode_def by simp | |
| 168 | ||
| 169 | lemma int_decode_inverse [simp]: "int_encode (int_decode n) = n" | |
| 170 | unfolding int_decode_def int_encode_def using sum_decode_inverse [of n] | |
| 171 | by (cases "sum_decode n", simp_all) | |
| 172 | ||
| 173 | lemma inj_int_encode: "inj_on int_encode A" | |
| 174 | by (rule inj_on_inverseI, rule int_encode_inverse) | |
| 175 | ||
| 176 | lemma inj_int_decode: "inj_on int_decode A" | |
| 177 | by (rule inj_on_inverseI, rule int_decode_inverse) | |
| 178 | ||
| 179 | lemma surj_int_encode: "surj int_encode" | |
| 180 | by (rule surjI, rule int_decode_inverse) | |
| 181 | ||
| 182 | lemma surj_int_decode: "surj int_decode" | |
| 183 | by (rule surjI, rule int_encode_inverse) | |
| 184 | ||
| 185 | lemma bij_int_encode: "bij int_encode" | |
| 186 | by (rule bijI [OF inj_int_encode surj_int_encode]) | |
| 187 | ||
| 188 | lemma bij_int_decode: "bij int_decode" | |
| 189 | by (rule bijI [OF inj_int_decode surj_int_decode]) | |
| 190 | ||
| 191 | lemma int_encode_eq: "int_encode x = int_encode y \<longleftrightarrow> x = y" | |
| 192 | by (rule inj_int_encode [THEN inj_eq]) | |
| 193 | ||
| 194 | lemma int_decode_eq: "int_decode x = int_decode y \<longleftrightarrow> x = y" | |
| 195 | by (rule inj_int_decode [THEN inj_eq]) | |
| 196 | ||
| 197 | ||
| 198 | subsection {* Type @{typ "nat list"} *}
 | |
| 199 | ||
| 200 | fun | |
| 201 | list_encode :: "nat list \<Rightarrow> nat" | |
| 202 | where | |
| 203 | "list_encode [] = 0" | |
| 204 | | "list_encode (x # xs) = Suc (prod_encode (x, list_encode xs))" | |
| 205 | ||
| 206 | function | |
| 207 | list_decode :: "nat \<Rightarrow> nat list" | |
| 208 | where | |
| 209 | "list_decode 0 = []" | |
| 210 | | "list_decode (Suc n) = (case prod_decode n of (x, y) \<Rightarrow> x # list_decode y)" | |
| 211 | by pat_completeness auto | |
| 212 | ||
| 213 | termination list_decode | |
| 214 | apply (relation "measure id", simp_all) | |
| 215 | apply (drule arg_cong [where f="prod_encode"]) | |
| 37591 | 216 | apply (drule sym) | 
| 35700 | 217 | apply (simp add: le_imp_less_Suc le_prod_encode_2) | 
| 218 | done | |
| 219 | ||
| 220 | lemma list_encode_inverse [simp]: "list_decode (list_encode x) = x" | |
| 221 | by (induct x rule: list_encode.induct) simp_all | |
| 222 | ||
| 223 | lemma list_decode_inverse [simp]: "list_encode (list_decode n) = n" | |
| 224 | apply (induct n rule: list_decode.induct, simp) | |
| 225 | apply (simp split: prod.split) | |
| 226 | apply (simp add: prod_decode_eq [symmetric]) | |
| 227 | done | |
| 228 | ||
| 229 | lemma inj_list_encode: "inj_on list_encode A" | |
| 230 | by (rule inj_on_inverseI, rule list_encode_inverse) | |
| 231 | ||
| 232 | lemma inj_list_decode: "inj_on list_decode A" | |
| 233 | by (rule inj_on_inverseI, rule list_decode_inverse) | |
| 234 | ||
| 235 | lemma surj_list_encode: "surj list_encode" | |
| 236 | by (rule surjI, rule list_decode_inverse) | |
| 237 | ||
| 238 | lemma surj_list_decode: "surj list_decode" | |
| 239 | by (rule surjI, rule list_encode_inverse) | |
| 240 | ||
| 241 | lemma bij_list_encode: "bij list_encode" | |
| 242 | by (rule bijI [OF inj_list_encode surj_list_encode]) | |
| 243 | ||
| 244 | lemma bij_list_decode: "bij list_decode" | |
| 245 | by (rule bijI [OF inj_list_decode surj_list_decode]) | |
| 246 | ||
| 247 | lemma list_encode_eq: "list_encode x = list_encode y \<longleftrightarrow> x = y" | |
| 248 | by (rule inj_list_encode [THEN inj_eq]) | |
| 249 | ||
| 250 | lemma list_decode_eq: "list_decode x = list_decode y \<longleftrightarrow> x = y" | |
| 251 | by (rule inj_list_decode [THEN inj_eq]) | |
| 252 | ||
| 253 | ||
| 254 | subsection {* Finite sets of naturals *}
 | |
| 255 | ||
| 256 | subsubsection {* Preliminaries *}
 | |
| 257 | ||
| 258 | lemma finite_vimage_Suc_iff: "finite (Suc -` F) \<longleftrightarrow> finite F" | |
| 259 | apply (safe intro!: finite_vimageI inj_Suc) | |
| 260 | apply (rule finite_subset [where B="insert 0 (Suc ` Suc -` F)"]) | |
| 261 | apply (rule subsetI, case_tac x, simp, simp) | |
| 262 | apply (rule finite_insert [THEN iffD2]) | |
| 263 | apply (erule finite_imageI) | |
| 264 | done | |
| 265 | ||
| 266 | lemma vimage_Suc_insert_0: "Suc -` insert 0 A = Suc -` A" | |
| 267 | by auto | |
| 268 | ||
| 269 | lemma vimage_Suc_insert_Suc: | |
| 270 | "Suc -` insert (Suc n) A = insert n (Suc -` A)" | |
| 271 | by auto | |
| 272 | ||
| 273 | lemma even_nat_Suc_div_2: "even x \<Longrightarrow> Suc x div 2 = x div 2" | |
| 274 | by (simp only: numeral_2_eq_2 even_nat_plus_one_div_two) | |
| 275 | ||
| 276 | lemma div2_even_ext_nat: | |
| 277 | "\<lbrakk>x div 2 = y div 2; even x = even y\<rbrakk> \<Longrightarrow> (x::nat) = y" | |
| 278 | apply (rule mod_div_equality [of x 2, THEN subst]) | |
| 279 | apply (rule mod_div_equality [of y 2, THEN subst]) | |
| 280 | apply (case_tac "even x") | |
| 281 | apply (simp add: numeral_2_eq_2 even_nat_equiv_def) | |
| 282 | apply (simp add: numeral_2_eq_2 odd_nat_equiv_def) | |
| 283 | done | |
| 284 | ||
| 285 | subsubsection {* From sets to naturals *}
 | |
| 286 | ||
| 287 | definition | |
| 288 | set_encode :: "nat set \<Rightarrow> nat" | |
| 289 | where | |
| 290 | "set_encode = setsum (op ^ 2)" | |
| 291 | ||
| 292 | lemma set_encode_empty [simp]: "set_encode {} = 0"
 | |
| 293 | by (simp add: set_encode_def) | |
| 294 | ||
| 295 | lemma set_encode_insert [simp]: | |
| 296 | "\<lbrakk>finite A; n \<notin> A\<rbrakk> \<Longrightarrow> set_encode (insert n A) = 2^n + set_encode A" | |
| 297 | by (simp add: set_encode_def) | |
| 298 | ||
| 299 | lemma even_set_encode_iff: "finite A \<Longrightarrow> even (set_encode A) \<longleftrightarrow> 0 \<notin> A" | |
| 300 | unfolding set_encode_def by (induct set: finite, auto) | |
| 301 | ||
| 302 | lemma set_encode_vimage_Suc: "set_encode (Suc -` A) = set_encode A div 2" | |
| 303 | apply (cases "finite A") | |
| 304 | apply (erule finite_induct, simp) | |
| 305 | apply (case_tac x) | |
| 306 | apply (simp add: even_nat_Suc_div_2 even_set_encode_iff vimage_Suc_insert_0) | |
| 307 | apply (simp add: finite_vimageI add_commute vimage_Suc_insert_Suc) | |
| 308 | apply (simp add: set_encode_def finite_vimage_Suc_iff) | |
| 309 | done | |
| 310 | ||
| 311 | lemmas set_encode_div_2 = set_encode_vimage_Suc [symmetric] | |
| 312 | ||
| 313 | subsubsection {* From naturals to sets *}
 | |
| 314 | ||
| 315 | definition | |
| 316 | set_decode :: "nat \<Rightarrow> nat set" | |
| 317 | where | |
| 318 |   "set_decode x = {n. odd (x div 2 ^ n)}"
 | |
| 319 | ||
| 320 | lemma set_decode_0 [simp]: "0 \<in> set_decode x \<longleftrightarrow> odd x" | |
| 321 | by (simp add: set_decode_def) | |
| 322 | ||
| 323 | lemma set_decode_Suc [simp]: | |
| 324 | "Suc n \<in> set_decode x \<longleftrightarrow> n \<in> set_decode (x div 2)" | |
| 325 | by (simp add: set_decode_def div_mult2_eq) | |
| 326 | ||
| 327 | lemma set_decode_zero [simp]: "set_decode 0 = {}"
 | |
| 328 | by (simp add: set_decode_def) | |
| 329 | ||
| 330 | lemma set_decode_div_2: "set_decode (x div 2) = Suc -` set_decode x" | |
| 331 | by auto | |
| 332 | ||
| 333 | lemma set_decode_plus_power_2: | |
| 334 | "n \<notin> set_decode z \<Longrightarrow> set_decode (2 ^ n + z) = insert n (set_decode z)" | |
| 335 | apply (induct n arbitrary: z, simp_all) | |
| 39302 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 nipkow parents: 
37591diff
changeset | 336 | apply (rule set_eqI, induct_tac x, simp, simp add: even_nat_Suc_div_2) | 
| 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 nipkow parents: 
37591diff
changeset | 337 | apply (rule set_eqI, induct_tac x, simp, simp add: add_commute) | 
| 35700 | 338 | done | 
| 339 | ||
| 340 | lemma finite_set_decode [simp]: "finite (set_decode n)" | |
| 341 | apply (induct n rule: nat_less_induct) | |
| 342 | apply (case_tac "n = 0", simp) | |
| 343 | apply (drule_tac x="n div 2" in spec, simp) | |
| 344 | apply (simp add: set_decode_div_2) | |
| 345 | apply (simp add: finite_vimage_Suc_iff) | |
| 346 | done | |
| 347 | ||
| 348 | subsubsection {* Proof of isomorphism *}
 | |
| 349 | ||
| 350 | lemma set_decode_inverse [simp]: "set_encode (set_decode n) = n" | |
| 351 | apply (induct n rule: nat_less_induct) | |
| 352 | apply (case_tac "n = 0", simp) | |
| 353 | apply (drule_tac x="n div 2" in spec, simp) | |
| 354 | apply (simp add: set_decode_div_2 set_encode_vimage_Suc) | |
| 355 | apply (erule div2_even_ext_nat) | |
| 356 | apply (simp add: even_set_encode_iff) | |
| 357 | done | |
| 358 | ||
| 359 | lemma set_encode_inverse [simp]: "finite A \<Longrightarrow> set_decode (set_encode A) = A" | |
| 360 | apply (erule finite_induct, simp_all) | |
| 361 | apply (simp add: set_decode_plus_power_2) | |
| 362 | done | |
| 363 | ||
| 364 | lemma inj_on_set_encode: "inj_on set_encode (Collect finite)" | |
| 365 | by (rule inj_on_inverseI [where g="set_decode"], simp) | |
| 366 | ||
| 367 | lemma set_encode_eq: | |
| 368 | "\<lbrakk>finite A; finite B\<rbrakk> \<Longrightarrow> set_encode A = set_encode B \<longleftrightarrow> A = B" | |
| 369 | by (rule iffI, simp add: inj_onD [OF inj_on_set_encode], simp) | |
| 370 | ||
| 51414 | 371 | lemma subset_decode_imp_le: assumes "set_decode m \<subseteq> set_decode n" shows "m \<le> n" | 
| 372 | proof - | |
| 373 | have "n = m + set_encode (set_decode n - set_decode m)" | |
| 374 | proof - | |
| 375 | obtain A B where "m = set_encode A" "finite A" | |
| 376 | "n = set_encode B" "finite B" | |
| 377 | by (metis finite_set_decode set_decode_inverse) | |
| 378 | thus ?thesis using assms | |
| 379 | apply auto | |
| 51489 | 380 | apply (simp add: set_encode_def nat_add_commute setsum.subset_diff) | 
| 51414 | 381 | done | 
| 382 | qed | |
| 383 | thus ?thesis | |
| 384 | by (metis le_add1) | |
| 385 | qed | |
| 386 | ||
| 35700 | 387 | end | 
| 51489 | 388 |