src/ZF/ex/Primes.thy
changeset 60770 240563fbf41d
parent 59788 6f7b6adac439
child 61798 27f3c10b0b50
equal deleted inserted replaced
60769:cf7f3465eaf1 60770:240563fbf41d
     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)