1 (* Title: ZF/ex/Primes.thy |
1 (* Title: ZF/ex/Primes.thy |
2 Author: Christophe Tabacznyj and Lawrence C Paulson |
2 Author: Christophe Tabacznyj and Lawrence C Paulson |
3 Copyright 1996 University of Cambridge |
3 Copyright 1996 University of Cambridge |
4 *) |
4 *) |
5 |
5 |
6 section{*The Divides Relation and Euclid's algorithm for the GCD*} |
6 section\<open>The Divides Relation and Euclid's algorithm for the GCD\<close> |
7 |
7 |
8 theory Primes imports Main begin |
8 theory Primes imports Main begin |
9 |
9 |
10 definition |
10 definition |
11 divides :: "[i,i]=>o" (infixl "dvd" 50) where |
11 divides :: "[i,i]=>o" (infixl "dvd" 50) where |
12 "m dvd n == m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" |
12 "m dvd n == m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" |
13 |
13 |
14 definition |
14 definition |
15 is_gcd :: "[i,i,i]=>o" --{*definition of great common divisor*} where |
15 is_gcd :: "[i,i,i]=>o" --\<open>definition of great common divisor\<close> where |
16 "is_gcd(p,m,n) == ((p dvd m) & (p dvd n)) & |
16 "is_gcd(p,m,n) == ((p dvd m) & (p dvd n)) & |
17 (\<forall>d\<in>nat. (d dvd m) & (d dvd n) \<longrightarrow> d dvd p)" |
17 (\<forall>d\<in>nat. (d dvd m) & (d dvd n) \<longrightarrow> d dvd p)" |
18 |
18 |
19 definition |
19 definition |
20 gcd :: "[i,i]=>i" --{*Euclid's algorithm for the gcd*} where |
20 gcd :: "[i,i]=>i" --\<open>Euclid's algorithm for the gcd\<close> where |
21 "gcd(m,n) == transrec(natify(n), |
21 "gcd(m,n) == transrec(natify(n), |
22 %n f. \<lambda>m \<in> nat. |
22 %n f. \<lambda>m \<in> nat. |
23 if n=0 then m else f`(m mod n)`n) ` natify(m)" |
23 if n=0 then m else f`(m mod n)`n) ` natify(m)" |
24 |
24 |
25 definition |
25 definition |
26 coprime :: "[i,i]=>o" --{*the coprime relation*} where |
26 coprime :: "[i,i]=>o" --\<open>the coprime relation\<close> where |
27 "coprime(m,n) == gcd(m,n) = 1" |
27 "coprime(m,n) == gcd(m,n) = 1" |
28 |
28 |
29 definition |
29 definition |
30 prime :: i --{*the set of prime numbers*} where |
30 prime :: i --\<open>the set of prime numbers\<close> where |
31 "prime == {p \<in> nat. 1<p & (\<forall>m \<in> nat. m dvd p \<longrightarrow> m=1 | m=p)}" |
31 "prime == {p \<in> nat. 1<p & (\<forall>m \<in> nat. m dvd p \<longrightarrow> m=1 | m=p)}" |
32 |
32 |
33 |
33 |
34 subsection{*The Divides Relation*} |
34 subsection\<open>The Divides Relation\<close> |
35 |
35 |
36 lemma dvdD: "m dvd n ==> m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" |
36 lemma dvdD: "m dvd n ==> m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" |
37 by (unfold divides_def, assumption) |
37 by (unfold divides_def, assumption) |
38 |
38 |
39 lemma dvdE: |
39 lemma dvdE: |
75 apply (simp add: mult_ac) |
75 apply (simp add: mult_ac) |
76 apply (rule mult_type) |
76 apply (rule mult_type) |
77 done |
77 done |
78 |
78 |
79 |
79 |
80 subsection{*Euclid's Algorithm for the GCD*} |
80 subsection\<open>Euclid's Algorithm for the GCD\<close> |
81 |
81 |
82 lemma gcd_0 [simp]: "gcd(m,0) = natify(m)" |
82 lemma gcd_0 [simp]: "gcd(m,0) = natify(m)" |
83 apply (simp add: gcd_def) |
83 apply (simp add: gcd_def) |
84 apply (subst transrec, simp) |
84 apply (subst transrec, simp) |
85 done |
85 done |
159 !!m n. [|m \<in> nat; n \<in> nat; 0<n; P(n, m mod n)|] ==> P(m,n) |] |
159 !!m n. [|m \<in> nat; n \<in> nat; 0<n; P(n, m mod n)|] ==> P(m,n) |] |
160 ==> P (m,n)" |
160 ==> P (m,n)" |
161 by (blast intro: gcd_induct_lemma) |
161 by (blast intro: gcd_induct_lemma) |
162 |
162 |
163 |
163 |
164 subsection{*Basic Properties of @{term gcd}*} |
164 subsection\<open>Basic Properties of @{term gcd}\<close> |
165 |
165 |
166 text{*type of gcd*} |
166 text\<open>type of gcd\<close> |
167 lemma gcd_type [simp,TC]: "gcd(m, n) \<in> nat" |
167 lemma gcd_type [simp,TC]: "gcd(m, n) \<in> nat" |
168 apply (subgoal_tac "gcd (natify (m), natify (n)) \<in> nat") |
168 apply (subgoal_tac "gcd (natify (m), natify (n)) \<in> nat") |
169 apply simp |
169 apply simp |
170 apply (rule_tac m = "natify (m)" and n = "natify (n)" in gcd_induct) |
170 apply (rule_tac m = "natify (m)" and n = "natify (n)" in gcd_induct) |
171 apply auto |
171 apply auto |
172 apply (simp add: gcd_non_0) |
172 apply (simp add: gcd_non_0) |
173 done |
173 done |
174 |
174 |
175 |
175 |
176 text{* Property 1: gcd(a,b) divides a and b *} |
176 text\<open>Property 1: gcd(a,b) divides a and b\<close> |
177 |
177 |
178 lemma gcd_dvd_both: |
178 lemma gcd_dvd_both: |
179 "[| m \<in> nat; n \<in> nat |] ==> gcd (m, n) dvd m & gcd (m, n) dvd n" |
179 "[| m \<in> nat; n \<in> nat |] ==> gcd (m, n) dvd m & gcd (m, n) dvd n" |
180 apply (rule_tac m = m and n = n in gcd_induct) |
180 apply (rule_tac m = m and n = n in gcd_induct) |
181 apply (simp_all add: gcd_non_0) |
181 apply (simp_all add: gcd_non_0) |
190 lemma gcd_dvd2 [simp]: "n \<in> nat ==> gcd(m,n) dvd n" |
190 lemma gcd_dvd2 [simp]: "n \<in> nat ==> gcd(m,n) dvd n" |
191 apply (cut_tac m = "natify (m)" and n = "natify (n)" in gcd_dvd_both) |
191 apply (cut_tac m = "natify (m)" and n = "natify (n)" in gcd_dvd_both) |
192 apply auto |
192 apply auto |
193 done |
193 done |
194 |
194 |
195 text{* if f divides a and b then f divides gcd(a,b) *} |
195 text\<open>if f divides a and b then f divides gcd(a,b)\<close> |
196 |
196 |
197 lemma dvd_mod: "[| f dvd a; f dvd b |] ==> f dvd (a mod b)" |
197 lemma dvd_mod: "[| f dvd a; f dvd b |] ==> f dvd (a mod b)" |
198 apply (simp add: divides_def) |
198 apply (simp add: divides_def) |
199 apply (case_tac "b=0") |
199 apply (case_tac "b=0") |
200 apply (simp add: DIVISION_BY_ZERO_MOD, auto) |
200 apply (simp add: DIVISION_BY_ZERO_MOD, auto) |
201 apply (blast intro: mod_mult_distrib2 [symmetric]) |
201 apply (blast intro: mod_mult_distrib2 [symmetric]) |
202 done |
202 done |
203 |
203 |
204 text{* Property 2: for all a,b,f naturals, |
204 text\<open>Property 2: for all a,b,f naturals, |
205 if f divides a and f divides b then f divides gcd(a,b)*} |
205 if f divides a and f divides b then f divides gcd(a,b)\<close> |
206 |
206 |
207 lemma gcd_greatest_raw [rule_format]: |
207 lemma gcd_greatest_raw [rule_format]: |
208 "[| m \<in> nat; n \<in> nat; f \<in> nat |] |
208 "[| m \<in> nat; n \<in> nat; f \<in> nat |] |
209 ==> (f dvd m) \<longrightarrow> (f dvd n) \<longrightarrow> f dvd gcd(m,n)" |
209 ==> (f dvd m) \<longrightarrow> (f dvd n) \<longrightarrow> f dvd gcd(m,n)" |
210 apply (rule_tac m = m and n = n in gcd_induct) |
210 apply (rule_tac m = m and n = n in gcd_induct) |
219 lemma gcd_greatest_iff [simp]: "[| k \<in> nat; m \<in> nat; n \<in> nat |] |
219 lemma gcd_greatest_iff [simp]: "[| k \<in> nat; m \<in> nat; n \<in> nat |] |
220 ==> (k dvd gcd (m, n)) \<longleftrightarrow> (k dvd m & k dvd n)" |
220 ==> (k dvd gcd (m, n)) \<longleftrightarrow> (k dvd m & k dvd n)" |
221 by (blast intro!: gcd_greatest gcd_dvd1 gcd_dvd2 intro: dvd_trans) |
221 by (blast intro!: gcd_greatest gcd_dvd1 gcd_dvd2 intro: dvd_trans) |
222 |
222 |
223 |
223 |
224 subsection{*The Greatest Common Divisor*} |
224 subsection\<open>The Greatest Common Divisor\<close> |
225 |
225 |
226 text{*The GCD exists and function gcd computes it.*} |
226 text\<open>The GCD exists and function gcd computes it.\<close> |
227 |
227 |
228 lemma is_gcd: "[| m \<in> nat; n \<in> nat |] ==> is_gcd(gcd(m,n), m, n)" |
228 lemma is_gcd: "[| m \<in> nat; n \<in> nat |] ==> is_gcd(gcd(m,n), m, n)" |
229 by (simp add: is_gcd_def) |
229 by (simp add: is_gcd_def) |
230 |
230 |
231 text{*The GCD is unique*} |
231 text\<open>The GCD is unique\<close> |
232 |
232 |
233 lemma is_gcd_unique: "[|is_gcd(m,a,b); is_gcd(n,a,b); m\<in>nat; n\<in>nat|] ==> m=n" |
233 lemma is_gcd_unique: "[|is_gcd(m,a,b); is_gcd(n,a,b); m\<in>nat; n\<in>nat|] ==> m=n" |
234 apply (simp add: is_gcd_def) |
234 apply (simp add: is_gcd_def) |
235 apply (blast intro: dvd_anti_sym) |
235 apply (blast intro: dvd_anti_sym) |
236 done |
236 done |
269 |
269 |
270 lemma gcd_1_left [simp]: "gcd (1, m) = 1" |
270 lemma gcd_1_left [simp]: "gcd (1, m) = 1" |
271 by (simp add: gcd_commute [of 1]) |
271 by (simp add: gcd_commute [of 1]) |
272 |
272 |
273 |
273 |
274 subsection{*Addition laws*} |
274 subsection\<open>Addition laws\<close> |
275 |
275 |
276 lemma gcd_add1 [simp]: "gcd (m #+ n, n) = gcd (m, n)" |
276 lemma gcd_add1 [simp]: "gcd (m #+ n, n) = gcd (m, n)" |
277 apply (subgoal_tac "gcd (m #+ natify (n), natify (n)) = gcd (m, natify (n))") |
277 apply (subgoal_tac "gcd (m #+ natify (n), natify (n)) = gcd (m, natify (n))") |
278 apply simp |
278 apply simp |
279 apply (case_tac "natify (n) = 0") |
279 apply (case_tac "natify (n) = 0") |
298 apply (cut_tac k = "natify (k)" in gcd_add_mult_raw) |
298 apply (cut_tac k = "natify (k)" in gcd_add_mult_raw) |
299 apply auto |
299 apply auto |
300 done |
300 done |
301 |
301 |
302 |
302 |
303 subsection{* Multiplication Laws*} |
303 subsection\<open>Multiplication Laws\<close> |
304 |
304 |
305 lemma gcd_mult_distrib2_raw: |
305 lemma gcd_mult_distrib2_raw: |
306 "[| k \<in> nat; m \<in> nat; n \<in> nat |] |
306 "[| k \<in> nat; m \<in> nat; n \<in> nat |] |
307 ==> k #* gcd (m, n) = gcd (k #* m, k #* n)" |
307 ==> k #* gcd (m, n) = gcd (k #* m, k #* n)" |
308 apply (erule_tac m = m and n = n in gcd_induct, assumption) |
308 apply (erule_tac m = m and n = n in gcd_induct, assumption) |
347 |
347 |
348 lemma prime_nonzero: "p \<in> prime \<Longrightarrow> p\<noteq>0" |
348 lemma prime_nonzero: "p \<in> prime \<Longrightarrow> p\<noteq>0" |
349 by (auto simp add: prime_def) |
349 by (auto simp add: prime_def) |
350 |
350 |
351 |
351 |
352 text{*This theorem leads immediately to a proof of the uniqueness of |
352 text\<open>This theorem leads immediately to a proof of the uniqueness of |
353 factorization. If @{term p} divides a product of primes then it is |
353 factorization. If @{term p} divides a product of primes then it is |
354 one of those primes.*} |
354 one of those primes.\<close> |
355 |
355 |
356 lemma prime_dvd_mult: |
356 lemma prime_dvd_mult: |
357 "[|p dvd m #* n; p \<in> prime; m \<in> nat; n \<in> nat |] ==> p dvd m \<or> p dvd n" |
357 "[|p dvd m #* n; p \<in> prime; m \<in> nat; n \<in> nat |] ==> p dvd m \<or> p dvd n" |
358 by (blast intro: relprime_dvd_mult prime_imp_relprime prime_into_nat) |
358 by (blast intro: relprime_dvd_mult prime_imp_relprime prime_into_nat) |
359 |
359 |
373 apply (cut_tac m = "natify (m)" and n = "natify (n)" in gcd_mult_cancel_raw) |
373 apply (cut_tac m = "natify (m)" and n = "natify (n)" in gcd_mult_cancel_raw) |
374 apply auto |
374 apply auto |
375 done |
375 done |
376 |
376 |
377 |
377 |
378 subsection{*The Square Root of a Prime is Irrational: Key Lemma*} |
378 subsection\<open>The Square Root of a Prime is Irrational: Key Lemma\<close> |
379 |
379 |
380 lemma prime_dvd_other_side: |
380 lemma prime_dvd_other_side: |
381 "\<lbrakk>n#*n = p#*(k#*k); p \<in> prime; n \<in> nat\<rbrakk> \<Longrightarrow> p dvd n" |
381 "\<lbrakk>n#*n = p#*(k#*k); p \<in> prime; n \<in> nat\<rbrakk> \<Longrightarrow> p dvd n" |
382 apply (subgoal_tac "p dvd n#*n") |
382 apply (subgoal_tac "p dvd n#*n") |
383 apply (blast dest: prime_dvd_mult) |
383 apply (blast dest: prime_dvd_mult) |