| author | huffman | 
| Wed, 23 Nov 2011 07:00:01 +0100 | |
| changeset 45615 | c05e8209a3aa | 
| parent 41959 | b460124855b8 | 
| child 51414 | 587f493447d9 | 
| 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: 
37591 
diff
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: 
37591 
diff
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  | 
||
371  | 
end  |