| author | wenzelm | 
| Tue, 12 Mar 2024 11:18:38 +0100 | |
| changeset 79868 | ede8b298cfe8 | 
| parent 74965 | 9469d9223689 | 
| 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  | 
||
| 60500 | 9  | 
section \<open>Bijections between natural numbers and other types\<close>  | 
| 35700 | 10  | 
|
11  | 
theory Nat_Bijection  | 
|
| 63625 | 12  | 
imports Main  | 
| 35700 | 13  | 
begin  | 
14  | 
||
| 69593 | 15  | 
subsection \<open>Type \<^typ>\<open>nat \<times> nat\<close>\<close>  | 
| 35700 | 16  | 
|
| 63625 | 17  | 
text \<open>Triangle numbers: 0, 1, 3, 6, 10, 15, ...\<close>  | 
| 35700 | 18  | 
|
| 62046 | 19  | 
definition triangle :: "nat \<Rightarrow> nat"  | 
20  | 
where "triangle n = (n * Suc n) div 2"  | 
|
| 35700 | 21  | 
|
22  | 
lemma triangle_0 [simp]: "triangle 0 = 0"  | 
|
| 63625 | 23  | 
by (simp add: triangle_def)  | 
| 35700 | 24  | 
|
25  | 
lemma triangle_Suc [simp]: "triangle (Suc n) = triangle n + Suc n"  | 
|
| 63625 | 26  | 
by (simp add: triangle_def)  | 
| 35700 | 27  | 
|
| 62046 | 28  | 
definition prod_encode :: "nat \<times> nat \<Rightarrow> nat"  | 
29  | 
where "prod_encode = (\<lambda>(m, n). triangle (m + n) + m)"  | 
|
| 35700 | 30  | 
|
| 69593 | 31  | 
text \<open>In this auxiliary function, \<^term>\<open>triangle k + m\<close> is an invariant.\<close>  | 
| 35700 | 32  | 
|
| 62046 | 33  | 
fun prod_decode_aux :: "nat \<Rightarrow> nat \<Rightarrow> nat \<times> nat"  | 
| 63625 | 34  | 
where "prod_decode_aux k m =  | 
| 35700 | 35  | 
(if m \<le> k then (m, k - m) else prod_decode_aux (Suc k) (m - Suc k))"  | 
36  | 
||
37  | 
declare prod_decode_aux.simps [simp del]  | 
|
38  | 
||
| 62046 | 39  | 
definition prod_decode :: "nat \<Rightarrow> nat \<times> nat"  | 
40  | 
where "prod_decode = prod_decode_aux 0"  | 
|
| 35700 | 41  | 
|
| 63625 | 42  | 
lemma prod_encode_prod_decode_aux: "prod_encode (prod_decode_aux k m) = triangle k + m"  | 
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
43  | 
proof (induction k m rule: prod_decode_aux.induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
44  | 
case (1 k m)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
45  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
46  | 
by (simp add: prod_encode_def prod_decode_aux.simps)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
47  | 
qed  | 
| 35700 | 48  | 
|
49  | 
lemma prod_decode_inverse [simp]: "prod_encode (prod_decode n) = n"  | 
|
| 63625 | 50  | 
by (simp add: prod_decode_def prod_encode_prod_decode_aux)  | 
| 35700 | 51  | 
|
| 62046 | 52  | 
lemma prod_decode_triangle_add: "prod_decode (triangle k + m) = prod_decode_aux k m"  | 
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
53  | 
proof (induct k arbitrary: m)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
54  | 
case 0  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
55  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
56  | 
by (simp add: prod_decode_def)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
57  | 
next  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
58  | 
case (Suc k)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
59  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
60  | 
by (metis ab_semigroup_add_class.add_ac(1) add_diff_cancel_left' le_add1 not_less_eq_eq prod_decode_aux.simps triangle_Suc)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
61  | 
qed  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
62  | 
|
| 35700 | 63  | 
|
64  | 
lemma prod_encode_inverse [simp]: "prod_decode (prod_encode x) = x"  | 
|
| 63625 | 65  | 
unfolding prod_encode_def  | 
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
66  | 
proof (induct x)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
67  | 
case (Pair a b)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
68  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
69  | 
by (simp add: prod_decode_triangle_add prod_decode_aux.simps)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
70  | 
qed  | 
| 35700 | 71  | 
|
72  | 
lemma inj_prod_encode: "inj_on prod_encode A"  | 
|
| 63625 | 73  | 
by (rule inj_on_inverseI) (rule prod_encode_inverse)  | 
| 35700 | 74  | 
|
75  | 
lemma inj_prod_decode: "inj_on prod_decode A"  | 
|
| 63625 | 76  | 
by (rule inj_on_inverseI) (rule prod_decode_inverse)  | 
| 35700 | 77  | 
|
78  | 
lemma surj_prod_encode: "surj prod_encode"  | 
|
| 63625 | 79  | 
by (rule surjI) (rule prod_decode_inverse)  | 
| 35700 | 80  | 
|
81  | 
lemma surj_prod_decode: "surj prod_decode"  | 
|
| 63625 | 82  | 
by (rule surjI) (rule prod_encode_inverse)  | 
| 35700 | 83  | 
|
84  | 
lemma bij_prod_encode: "bij prod_encode"  | 
|
| 63625 | 85  | 
by (rule bijI [OF inj_prod_encode surj_prod_encode])  | 
| 35700 | 86  | 
|
87  | 
lemma bij_prod_decode: "bij prod_decode"  | 
|
| 63625 | 88  | 
by (rule bijI [OF inj_prod_decode surj_prod_decode])  | 
| 35700 | 89  | 
|
| 
74965
 
9469d9223689
Tiny additions inspired by Roth development
 
paulson <lp15@cam.ac.uk> 
parents: 
71848 
diff
changeset
 | 
90  | 
lemma prod_encode_eq [simp]: "prod_encode x = prod_encode y \<longleftrightarrow> x = y"  | 
| 63625 | 91  | 
by (rule inj_prod_encode [THEN inj_eq])  | 
| 35700 | 92  | 
|
| 
74965
 
9469d9223689
Tiny additions inspired by Roth development
 
paulson <lp15@cam.ac.uk> 
parents: 
71848 
diff
changeset
 | 
93  | 
lemma prod_decode_eq [simp]: "prod_decode x = prod_decode y \<longleftrightarrow> x = y"  | 
| 63625 | 94  | 
by (rule inj_prod_decode [THEN inj_eq])  | 
| 35700 | 95  | 
|
| 62046 | 96  | 
|
| 60500 | 97  | 
text \<open>Ordering properties\<close>  | 
| 35700 | 98  | 
|
99  | 
lemma le_prod_encode_1: "a \<le> prod_encode (a, b)"  | 
|
| 63625 | 100  | 
by (simp add: prod_encode_def)  | 
| 35700 | 101  | 
|
102  | 
lemma le_prod_encode_2: "b \<le> prod_encode (a, b)"  | 
|
| 63625 | 103  | 
by (induct b) (simp_all add: prod_encode_def)  | 
| 35700 | 104  | 
|
105  | 
||
| 69593 | 106  | 
subsection \<open>Type \<^typ>\<open>nat + nat\<close>\<close>  | 
| 35700 | 107  | 
|
| 62046 | 108  | 
definition sum_encode :: "nat + nat \<Rightarrow> nat"  | 
| 63625 | 109  | 
where "sum_encode x = (case x of Inl a \<Rightarrow> 2 * a | Inr b \<Rightarrow> Suc (2 * b))"  | 
| 35700 | 110  | 
|
| 62046 | 111  | 
definition sum_decode :: "nat \<Rightarrow> nat + nat"  | 
| 63625 | 112  | 
where "sum_decode n = (if even n then Inl (n div 2) else Inr (n div 2))"  | 
| 35700 | 113  | 
|
114  | 
lemma sum_encode_inverse [simp]: "sum_decode (sum_encode x) = x"  | 
|
| 63625 | 115  | 
by (induct x) (simp_all add: sum_decode_def sum_encode_def)  | 
| 35700 | 116  | 
|
117  | 
lemma sum_decode_inverse [simp]: "sum_encode (sum_decode n) = n"  | 
|
| 58834 | 118  | 
by (simp add: even_two_times_div_two sum_decode_def sum_encode_def)  | 
| 35700 | 119  | 
|
120  | 
lemma inj_sum_encode: "inj_on sum_encode A"  | 
|
| 63625 | 121  | 
by (rule inj_on_inverseI) (rule sum_encode_inverse)  | 
| 35700 | 122  | 
|
123  | 
lemma inj_sum_decode: "inj_on sum_decode A"  | 
|
| 63625 | 124  | 
by (rule inj_on_inverseI) (rule sum_decode_inverse)  | 
| 35700 | 125  | 
|
126  | 
lemma surj_sum_encode: "surj sum_encode"  | 
|
| 63625 | 127  | 
by (rule surjI) (rule sum_decode_inverse)  | 
| 35700 | 128  | 
|
129  | 
lemma surj_sum_decode: "surj sum_decode"  | 
|
| 63625 | 130  | 
by (rule surjI) (rule sum_encode_inverse)  | 
| 35700 | 131  | 
|
132  | 
lemma bij_sum_encode: "bij sum_encode"  | 
|
| 63625 | 133  | 
by (rule bijI [OF inj_sum_encode surj_sum_encode])  | 
| 35700 | 134  | 
|
135  | 
lemma bij_sum_decode: "bij sum_decode"  | 
|
| 63625 | 136  | 
by (rule bijI [OF inj_sum_decode surj_sum_decode])  | 
| 35700 | 137  | 
|
138  | 
lemma sum_encode_eq: "sum_encode x = sum_encode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 139  | 
by (rule inj_sum_encode [THEN inj_eq])  | 
| 35700 | 140  | 
|
141  | 
lemma sum_decode_eq: "sum_decode x = sum_decode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 142  | 
by (rule inj_sum_decode [THEN inj_eq])  | 
| 35700 | 143  | 
|
144  | 
||
| 69593 | 145  | 
subsection \<open>Type \<^typ>\<open>int\<close>\<close>  | 
| 35700 | 146  | 
|
| 62046 | 147  | 
definition int_encode :: "int \<Rightarrow> nat"  | 
| 63625 | 148  | 
where "int_encode i = sum_encode (if 0 \<le> i then Inl (nat i) else Inr (nat (- i - 1)))"  | 
| 35700 | 149  | 
|
| 62046 | 150  | 
definition int_decode :: "nat \<Rightarrow> int"  | 
| 63625 | 151  | 
where "int_decode n = (case sum_decode n of Inl a \<Rightarrow> int a | Inr b \<Rightarrow> - int b - 1)"  | 
| 35700 | 152  | 
|
153  | 
lemma int_encode_inverse [simp]: "int_decode (int_encode x) = x"  | 
|
| 63625 | 154  | 
by (simp add: int_decode_def int_encode_def)  | 
| 35700 | 155  | 
|
156  | 
lemma int_decode_inverse [simp]: "int_encode (int_decode n) = n"  | 
|
| 63625 | 157  | 
unfolding int_decode_def int_encode_def  | 
158  | 
using sum_decode_inverse [of n] by (cases "sum_decode n") simp_all  | 
|
| 35700 | 159  | 
|
160  | 
lemma inj_int_encode: "inj_on int_encode A"  | 
|
| 63625 | 161  | 
by (rule inj_on_inverseI) (rule int_encode_inverse)  | 
| 35700 | 162  | 
|
163  | 
lemma inj_int_decode: "inj_on int_decode A"  | 
|
| 63625 | 164  | 
by (rule inj_on_inverseI) (rule int_decode_inverse)  | 
| 35700 | 165  | 
|
166  | 
lemma surj_int_encode: "surj int_encode"  | 
|
| 63625 | 167  | 
by (rule surjI) (rule int_decode_inverse)  | 
| 35700 | 168  | 
|
169  | 
lemma surj_int_decode: "surj int_decode"  | 
|
| 63625 | 170  | 
by (rule surjI) (rule int_encode_inverse)  | 
| 35700 | 171  | 
|
172  | 
lemma bij_int_encode: "bij int_encode"  | 
|
| 63625 | 173  | 
by (rule bijI [OF inj_int_encode surj_int_encode])  | 
| 35700 | 174  | 
|
175  | 
lemma bij_int_decode: "bij int_decode"  | 
|
| 63625 | 176  | 
by (rule bijI [OF inj_int_decode surj_int_decode])  | 
| 35700 | 177  | 
|
178  | 
lemma int_encode_eq: "int_encode x = int_encode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 179  | 
by (rule inj_int_encode [THEN inj_eq])  | 
| 35700 | 180  | 
|
181  | 
lemma int_decode_eq: "int_decode x = int_decode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 182  | 
by (rule inj_int_decode [THEN inj_eq])  | 
| 35700 | 183  | 
|
184  | 
||
| 69593 | 185  | 
subsection \<open>Type \<^typ>\<open>nat list\<close>\<close>  | 
| 35700 | 186  | 
|
| 62046 | 187  | 
fun list_encode :: "nat list \<Rightarrow> nat"  | 
| 63625 | 188  | 
where  | 
189  | 
"list_encode [] = 0"  | 
|
190  | 
| "list_encode (x # xs) = Suc (prod_encode (x, list_encode xs))"  | 
|
| 35700 | 191  | 
|
| 62046 | 192  | 
function list_decode :: "nat \<Rightarrow> nat list"  | 
| 63625 | 193  | 
where  | 
194  | 
"list_decode 0 = []"  | 
|
195  | 
| "list_decode (Suc n) = (case prod_decode n of (x, y) \<Rightarrow> x # list_decode y)"  | 
|
196  | 
by pat_completeness auto  | 
|
| 35700 | 197  | 
|
198  | 
termination list_decode  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
199  | 
proof -  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
200  | 
have "\<And>n x y. (x, y) = prod_decode n \<Longrightarrow> y < Suc n"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
201  | 
by (metis le_imp_less_Suc le_prod_encode_2 prod_decode_inverse)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
202  | 
then show ?thesis  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
203  | 
using "termination" by blast  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
204  | 
qed  | 
| 35700 | 205  | 
|
206  | 
lemma list_encode_inverse [simp]: "list_decode (list_encode x) = x"  | 
|
| 63625 | 207  | 
by (induct x rule: list_encode.induct) simp_all  | 
| 35700 | 208  | 
|
209  | 
lemma list_decode_inverse [simp]: "list_encode (list_decode n) = n"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
210  | 
proof (induct n rule: list_decode.induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
211  | 
case (2 n)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
212  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
213  | 
by (metis list_encode.simps(2) list_encode_inverse prod_decode_inverse surj_pair)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
214  | 
qed auto  | 
| 35700 | 215  | 
|
216  | 
lemma inj_list_encode: "inj_on list_encode A"  | 
|
| 63625 | 217  | 
by (rule inj_on_inverseI) (rule list_encode_inverse)  | 
| 35700 | 218  | 
|
219  | 
lemma inj_list_decode: "inj_on list_decode A"  | 
|
| 63625 | 220  | 
by (rule inj_on_inverseI) (rule list_decode_inverse)  | 
| 35700 | 221  | 
|
222  | 
lemma surj_list_encode: "surj list_encode"  | 
|
| 63625 | 223  | 
by (rule surjI) (rule list_decode_inverse)  | 
| 35700 | 224  | 
|
225  | 
lemma surj_list_decode: "surj list_decode"  | 
|
| 63625 | 226  | 
by (rule surjI) (rule list_encode_inverse)  | 
| 35700 | 227  | 
|
228  | 
lemma bij_list_encode: "bij list_encode"  | 
|
| 63625 | 229  | 
by (rule bijI [OF inj_list_encode surj_list_encode])  | 
| 35700 | 230  | 
|
231  | 
lemma bij_list_decode: "bij list_decode"  | 
|
| 63625 | 232  | 
by (rule bijI [OF inj_list_decode surj_list_decode])  | 
| 35700 | 233  | 
|
234  | 
lemma list_encode_eq: "list_encode x = list_encode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 235  | 
by (rule inj_list_encode [THEN inj_eq])  | 
| 35700 | 236  | 
|
237  | 
lemma list_decode_eq: "list_decode x = list_decode y \<longleftrightarrow> x = y"  | 
|
| 63625 | 238  | 
by (rule inj_list_decode [THEN inj_eq])  | 
| 35700 | 239  | 
|
240  | 
||
| 60500 | 241  | 
subsection \<open>Finite sets of naturals\<close>  | 
| 35700 | 242  | 
|
| 60500 | 243  | 
subsubsection \<open>Preliminaries\<close>  | 
| 35700 | 244  | 
|
245  | 
lemma finite_vimage_Suc_iff: "finite (Suc -` F) \<longleftrightarrow> finite F"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
246  | 
proof  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
247  | 
have "F \<subseteq> insert 0 (Suc ` Suc -` F)"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
248  | 
using nat.nchotomy by force  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
249  | 
moreover  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
250  | 
assume "finite (Suc -` F)"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
251  | 
then have "finite (insert 0 (Suc ` Suc -` F))"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
252  | 
by blast  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
253  | 
ultimately show "finite F"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
254  | 
using finite_subset by blast  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
255  | 
qed (force intro: finite_vimageI inj_Suc)  | 
| 35700 | 256  | 
|
257  | 
lemma vimage_Suc_insert_0: "Suc -` insert 0 A = Suc -` A"  | 
|
| 63625 | 258  | 
by auto  | 
| 35700 | 259  | 
|
| 63625 | 260  | 
lemma vimage_Suc_insert_Suc: "Suc -` insert (Suc n) A = insert n (Suc -` A)"  | 
261  | 
by auto  | 
|
| 35700 | 262  | 
|
263  | 
lemma div2_even_ext_nat:  | 
|
| 58834 | 264  | 
fixes x y :: nat  | 
265  | 
assumes "x div 2 = y div 2"  | 
|
| 63625 | 266  | 
and "even x \<longleftrightarrow> even y"  | 
| 58834 | 267  | 
shows "x = y"  | 
268  | 
proof -  | 
|
| 60500 | 269  | 
from \<open>even x \<longleftrightarrow> even y\<close> have "x mod 2 = y mod 2"  | 
| 58834 | 270  | 
by (simp only: even_iff_mod_2_eq_zero) auto  | 
271  | 
with assms have "x div 2 * 2 + x mod 2 = y div 2 * 2 + y mod 2"  | 
|
272  | 
by simp  | 
|
273  | 
then show ?thesis  | 
|
274  | 
by simp  | 
|
275  | 
qed  | 
|
| 35700 | 276  | 
|
| 
58710
 
7216a10d69ba
augmented and tuned facts on even/odd and division
 
haftmann 
parents: 
57512 
diff
changeset
 | 
277  | 
|
| 60500 | 278  | 
subsubsection \<open>From sets to naturals\<close>  | 
| 35700 | 279  | 
|
| 62046 | 280  | 
definition set_encode :: "nat set \<Rightarrow> nat"  | 
| 67399 | 281  | 
where "set_encode = sum ((^) 2)"  | 
| 35700 | 282  | 
|
283  | 
lemma set_encode_empty [simp]: "set_encode {} = 0"
 | 
|
| 
59506
 
4af607652318
Not a simprule, as it complicates proofs
 
paulson <lp15@cam.ac.uk> 
parents: 
58881 
diff
changeset
 | 
284  | 
by (simp add: set_encode_def)  | 
| 
 
4af607652318
Not a simprule, as it complicates proofs
 
paulson <lp15@cam.ac.uk> 
parents: 
58881 
diff
changeset
 | 
285  | 
|
| 63625 | 286  | 
lemma set_encode_inf: "\<not> finite A \<Longrightarrow> set_encode A = 0"  | 
287  | 
by (simp add: set_encode_def)  | 
|
288  | 
||
289  | 
lemma set_encode_insert [simp]: "finite A \<Longrightarrow> n \<notin> A \<Longrightarrow> set_encode (insert n A) = 2^n + set_encode A"  | 
|
290  | 
by (simp add: set_encode_def)  | 
|
| 35700 | 291  | 
|
292  | 
lemma even_set_encode_iff: "finite A \<Longrightarrow> even (set_encode A) \<longleftrightarrow> 0 \<notin> A"  | 
|
| 63625 | 293  | 
by (induct set: finite) (auto simp: set_encode_def)  | 
| 35700 | 294  | 
|
295  | 
lemma set_encode_vimage_Suc: "set_encode (Suc -` A) = set_encode A div 2"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
296  | 
proof (induction A rule: infinite_finite_induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
297  | 
case (infinite A)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
298  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
299  | 
by (simp add: finite_vimage_Suc_iff set_encode_inf)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
300  | 
next  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
301  | 
case (insert x A)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
302  | 
show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
303  | 
proof (cases x)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
304  | 
case 0  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
305  | 
with insert show ?thesis  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
306  | 
by (simp add: even_set_encode_iff vimage_Suc_insert_0)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
307  | 
next  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
308  | 
case (Suc y)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
309  | 
with insert show ?thesis  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
310  | 
by (simp add: finite_vimageI add.commute vimage_Suc_insert_Suc)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
311  | 
qed  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
312  | 
qed auto  | 
| 35700 | 313  | 
|
314  | 
lemmas set_encode_div_2 = set_encode_vimage_Suc [symmetric]  | 
|
315  | 
||
| 62046 | 316  | 
|
| 60500 | 317  | 
subsubsection \<open>From naturals to sets\<close>  | 
| 35700 | 318  | 
|
| 62046 | 319  | 
definition set_decode :: "nat \<Rightarrow> nat set"  | 
320  | 
  where "set_decode x = {n. odd (x div 2 ^ n)}"
 | 
|
| 35700 | 321  | 
|
322  | 
lemma set_decode_0 [simp]: "0 \<in> set_decode x \<longleftrightarrow> odd x"  | 
|
| 63625 | 323  | 
by (simp add: set_decode_def)  | 
| 35700 | 324  | 
|
| 63625 | 325  | 
lemma set_decode_Suc [simp]: "Suc n \<in> set_decode x \<longleftrightarrow> n \<in> set_decode (x div 2)"  | 
326  | 
by (simp add: set_decode_def div_mult2_eq)  | 
|
| 35700 | 327  | 
|
328  | 
lemma set_decode_zero [simp]: "set_decode 0 = {}"
 | 
|
| 63625 | 329  | 
by (simp add: set_decode_def)  | 
| 35700 | 330  | 
|
331  | 
lemma set_decode_div_2: "set_decode (x div 2) = Suc -` set_decode x"  | 
|
| 63625 | 332  | 
by auto  | 
| 35700 | 333  | 
|
334  | 
lemma set_decode_plus_power_2:  | 
|
335  | 
"n \<notin> set_decode z \<Longrightarrow> set_decode (2 ^ n + z) = insert n (set_decode z)"  | 
|
| 
60352
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
336  | 
proof (induct n arbitrary: z)  | 
| 63625 | 337  | 
case 0  | 
338  | 
show ?case  | 
|
| 
60352
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
339  | 
proof (rule set_eqI)  | 
| 63625 | 340  | 
show "q \<in> set_decode (2 ^ 0 + z) \<longleftrightarrow> q \<in> insert 0 (set_decode z)" for q  | 
341  | 
by (induct q) (use 0 in simp_all)  | 
|
| 
60352
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
342  | 
qed  | 
| 
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
343  | 
next  | 
| 63625 | 344  | 
case (Suc n)  | 
345  | 
show ?case  | 
|
| 
60352
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
346  | 
proof (rule set_eqI)  | 
| 63625 | 347  | 
show "q \<in> set_decode (2 ^ Suc n + z) \<longleftrightarrow> q \<in> insert (Suc n) (set_decode z)" for q  | 
348  | 
by (induct q) (use Suc in simp_all)  | 
|
| 
60352
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
349  | 
qed  | 
| 
 
d46de31a50c4
separate class for division operator, with particular syntax added in more specific classes
 
haftmann 
parents: 
59506 
diff
changeset
 | 
350  | 
qed  | 
| 35700 | 351  | 
|
352  | 
lemma finite_set_decode [simp]: "finite (set_decode n)"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
353  | 
proof (induction n rule: less_induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
354  | 
case (less n)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
355  | 
show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
356  | 
proof (cases "n = 0")  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
357  | 
case False  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
358  | 
then show ?thesis  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
359  | 
using less.IH [of "n div 2"] finite_vimage_Suc_iff set_decode_div_2 by auto  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
360  | 
qed auto  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
361  | 
qed  | 
| 35700 | 362  | 
|
| 62046 | 363  | 
|
| 60500 | 364  | 
subsubsection \<open>Proof of isomorphism\<close>  | 
| 35700 | 365  | 
|
366  | 
lemma set_decode_inverse [simp]: "set_encode (set_decode n) = n"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
367  | 
proof (induction n rule: less_induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
368  | 
case (less n)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
369  | 
show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
370  | 
proof (cases "n = 0")  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
371  | 
case False  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
372  | 
then have "set_encode (set_decode (n div 2)) = n div 2"  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
373  | 
using less.IH by auto  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
374  | 
then show ?thesis  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
375  | 
by (metis div2_even_ext_nat even_set_encode_iff finite_set_decode set_decode_0 set_decode_div_2 set_encode_div_2)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
376  | 
qed auto  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
377  | 
qed  | 
| 35700 | 378  | 
|
379  | 
lemma set_encode_inverse [simp]: "finite A \<Longrightarrow> set_decode (set_encode A) = A"  | 
|
| 
71848
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
380  | 
proof (induction rule: finite_induct)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
381  | 
case (insert x A)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
382  | 
then show ?case  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
383  | 
by (simp add: set_decode_plus_power_2)  | 
| 
 
3c7852327787
A few new theorems, plus some tidying up
 
paulson <lp15@cam.ac.uk> 
parents: 
69593 
diff
changeset
 | 
384  | 
qed auto  | 
| 35700 | 385  | 
|
386  | 
lemma inj_on_set_encode: "inj_on set_encode (Collect finite)"  | 
|
| 63625 | 387  | 
by (rule inj_on_inverseI [where g = "set_decode"]) simp  | 
| 35700 | 388  | 
|
| 63625 | 389  | 
lemma set_encode_eq: "finite A \<Longrightarrow> finite B \<Longrightarrow> set_encode A = set_encode B \<longleftrightarrow> A = B"  | 
390  | 
by (rule iffI) (simp_all add: inj_onD [OF inj_on_set_encode])  | 
|
| 35700 | 391  | 
|
| 62046 | 392  | 
lemma subset_decode_imp_le:  | 
393  | 
assumes "set_decode m \<subseteq> set_decode n"  | 
|
394  | 
shows "m \<le> n"  | 
|
| 51414 | 395  | 
proof -  | 
396  | 
have "n = m + set_encode (set_decode n - set_decode m)"  | 
|
397  | 
proof -  | 
|
| 63625 | 398  | 
obtain A B where  | 
399  | 
"m = set_encode A" "finite A"  | 
|
400  | 
"n = set_encode B" "finite B"  | 
|
| 51414 | 401  | 
by (metis finite_set_decode set_decode_inverse)  | 
| 63625 | 402  | 
with assms show ?thesis  | 
| 64267 | 403  | 
by auto (simp add: set_encode_def add.commute sum.subset_diff)  | 
| 51414 | 404  | 
qed  | 
| 63625 | 405  | 
then show ?thesis  | 
| 51414 | 406  | 
by (metis le_add1)  | 
407  | 
qed  | 
|
408  | 
||
| 35700 | 409  | 
end  |