(* Title: ZF/ex/Primes.thy Author: Christophe Tabacznyj and Lawrence C Paulson Copyright 1996 University of Cambridge
*)
section\<open>The Divides Relation and Euclid's algorithm for the GCD\<close>
theory Primes imports ZF begin
definition
divides :: "[i,i]\o" (infixl \dvd\ 50) where "m dvd n \ m \ nat \ n \ nat \ (\k \ nat. n = m#*k)"
definition
is_gcd :: "[i,i,i]\o" \ \definition of great common divisor\ where "is_gcd(p,m,n) \ ((p dvd m) \ (p dvd n)) \
(\<forall>d\<in>nat. (d dvd m) \<and> (d dvd n) \<longrightarrow> d dvd p)"
definition
gcd :: "[i,i]\i" \ \Euclid's algorithm for the gcd\ where "gcd(m,n) \ transrec(natify(n), \<lambda>n f. \<lambda>m \<in> nat. if n=0 then m else f`(m mod n)`n) ` natify(m)"
lemma gcd_non_0_raw: "\0 nat\ \ gcd(m,n) = gcd(n, m mod n)" apply (simp add: gcd_def) apply (rule_tac P = "\z. left (z) = right" for left right in transrec [THEN ssubst]) apply (simp add: ltD [THEN mem_imp_not_eq, THEN not_sym]
mod_less_divisor [THEN ltD]) done
lemma gcd_non_0: "0 < natify(n) \ gcd(m,n) = gcd(n, m mod n)" apply (cut_tac m = m and n = "natify (n) "in gcd_non_0_raw) apply auto done
lemma dvd_add: "\k dvd a; k dvd b\ \ k dvd (a #+ b)" apply (simp add: divides_def) apply (fast intro: add_mult_distrib_left [symmetric] add_type) done
lemma dvd_mult: "k dvd n \ k dvd (m #* n)" apply (simp add: divides_def) apply (fast intro: mult_left_commute mult_type) done
lemma dvd_mult2: "k dvd m \ k dvd (m #* n)" apply (subst mult_commute) apply (blast intro: dvd_mult) done
(* k dvd (m*k) *) lemmas dvdI1 [simp] = dvd_refl [THEN dvd_mult] lemmas dvdI2 [simp] = dvd_refl [THEN dvd_mult2]
lemma dvd_mod_imp_dvd_raw: "\a \ nat; b \ nat; k dvd b; k dvd (a mod b)\ \ k dvd a" apply (case_tac "b=0") apply (simp add: DIVISION_BY_ZERO_MOD) apply (blast intro: mod_div_equality [THEN subst]
elim: dvdE
intro!: dvd_add dvd_mult mult_type mod_type div_type) done
lemma dvd_mod_imp_dvd: "\k dvd (a mod b); k dvd b; a \ nat\ \ k dvd a" apply (cut_tac b = "natify (b)"in dvd_mod_imp_dvd_raw) apply auto apply (simp add: divides_def) done
(*Imitating TFL*) lemma gcd_induct_lemma [rule_format (no_asm)]: "\n \ nat; \<forall>m \<in> nat. P(m,0); \<forall>m \<in> nat. \<forall>n \<in> nat. 0<n \<longrightarrow> P(n, m mod n) \<longrightarrow> P(m,n)\<rbrakk> \<Longrightarrow> \<forall>m \<in> nat. P (m,n)" apply (erule_tac i = n in complete_induct) apply (case_tac "x=0") apply (simp (no_asm_simp)) apply clarify apply (drule_tac x1 = m and x = x in bspec [THEN bspec]) apply (simp_all add: Ord_0_lt_iff) apply (blast intro: mod_less_divisor [THEN ltD]) done
lemma gcd_induct: "\P. \m \ nat; n \ nat; \<And>m. m \<in> nat \<Longrightarrow> P(m,0); \<And>m n. \<lbrakk>m \<in> nat; n \<in> nat; 0<n; P(n, m mod n)\<rbrakk> \<Longrightarrow> P(m,n)\<rbrakk> \<Longrightarrow> P (m,n)" by (blast intro: gcd_induct_lemma)
subsection\<open>Basic Properties of \<^term>\<open>gcd\<close>\<close>
text\<open>type of gcd\<close> lemma gcd_type [simp,TC]: "gcd(m, n) \ nat" apply (subgoal_tac "gcd (natify (m), natify (n)) \ nat") apply simp apply (rule_tac m = "natify (m)"and n = "natify (n)"in gcd_induct) apply auto apply (simp add: gcd_non_0) done
text\<open>Property 1: gcd(a,b) divides a and b\<close>
lemma gcd_dvd_both: "\m \ nat; n \ nat\ \ gcd (m, n) dvd m \ gcd (m, n) dvd n" apply (rule_tac m = m and n = n in gcd_induct) apply (simp_all add: gcd_non_0) apply (blast intro: dvd_mod_imp_dvd_raw nat_into_Ord [THEN Ord_0_lt]) done
lemma gcd_dvd1 [simp]: "m \ nat \ gcd(m,n) dvd m" apply (cut_tac m = "natify (m)"and n = "natify (n)"in gcd_dvd_both) apply auto done
lemma gcd_dvd2 [simp]: "n \ nat \ gcd(m,n) dvd n" apply (cut_tac m = "natify (m)"and n = "natify (n)"in gcd_dvd_both) apply auto done
text\<open>if f divides a and b then f divides gcd(a,b)\<close>
lemma dvd_mod: "\f dvd a; f dvd b\ \ f dvd (a mod b)" apply (simp add: divides_def) apply (case_tac "b=0") apply (simp add: DIVISION_BY_ZERO_MOD, auto) apply (blast intro: mod_mult_distrib2 [symmetric]) done
text\<open>Property 2: for all a,b,f naturals, if f divides a and f divides b then f divides gcd(a,b)\<close>
lemma gcd_greatest_raw [rule_format]: "\m \ nat; n \ nat; f \ nat\ \<Longrightarrow> (f dvd m) \<longrightarrow> (f dvd n) \<longrightarrow> f dvd gcd(m,n)" apply (rule_tac m = m and n = n in gcd_induct) apply (simp_all add: gcd_non_0 dvd_mod) done
lemma gcd_greatest: "\f dvd m; f dvd n; f \ nat\ \ f dvd gcd(m,n)" apply (rule gcd_greatest_raw) apply (auto simp add: divides_def) done
lemma gcd_greatest_iff [simp]: "\k \ nat; m \ nat; n \ nat\ \<Longrightarrow> (k dvd gcd (m, n)) \<longleftrightarrow> (k dvd m \<and> k dvd n)" by (blast intro!: gcd_greatest gcd_dvd1 gcd_dvd2 intro: dvd_trans)
subsection\<open>The Greatest Common Divisor\<close>
text\<open>The GCD exists and function gcd computes it.\<close>
lemma is_gcd: "\m \ nat; n \ nat\ \ is_gcd(gcd(m,n), m, n)" by (simp add: is_gcd_def)
lemma gcd_add_mult: "gcd (m, k #* m #+ n) = gcd (m, n)" apply (cut_tac k = "natify (k)"in gcd_add_mult_raw) apply auto done
subsection\<open>Multiplication Laws\<close>
lemma gcd_mult_distrib2_raw: "\k \ nat; m \ nat; n \ nat\ \<Longrightarrow> k #* gcd (m, n) = gcd (k #* m, k #* n)" apply (erule_tac m = m and n = n in gcd_induct, assumption) apply simp apply (case_tac "k = 0", simp) apply (simp add: mod_geq gcd_non_0 mod_mult_distrib2 Ord_0_lt_iff) done
lemma gcd_mult_distrib2: "k #* gcd (m, n) = gcd (k #* m, k #* n)" apply (cut_tac k = "natify (k)"and m = "natify (m)"and n = "natify (n) " in gcd_mult_distrib2_raw) apply auto done
lemma gcd_mult [simp]: "gcd (k, k #* n) = natify(k)" by (cut_tac k = k and m = 1 and n = n in gcd_mult_distrib2, auto)
lemma gcd_self [simp]: "gcd (k, k) = natify(k)" by (cut_tac k = k and n = 1 in gcd_mult, auto)
lemma relprime_dvd_mult: "\gcd (k,n) = 1; k dvd (m #* n); m \ nat\ \ k dvd m" apply (cut_tac k = m and m = k and n = n in gcd_mult_distrib2, auto) apply (erule_tac b = m in ssubst) apply (simp add: dvd_imp_nat1) done
lemma relprime_dvd_mult_iff: "\gcd (k,n) = 1; m \ nat\ \ k dvd (m #* n) \ k dvd m" by (blast intro: dvdI2 relprime_dvd_mult dvd_trans)
lemma prime_imp_relprime: "\p \ prime; \ (p dvd n); n \ nat\ \ gcd (p, n) = 1" apply (simp add: prime_def, clarify) apply (drule_tac x = "gcd (p,n)"in bspec) apply auto apply (cut_tac m = p and n = n in gcd_dvd2, auto) done
lemma prime_into_nat: "p \ prime \ p \ nat" by (simp add: prime_def)
lemma prime_nonzero: "p \ prime \ p\0" by (auto simp add: prime_def)
text\<open>This theorem leads immediately to a proof of the uniqueness of
factorization. If\<^term>\<open>p\<close> divides a product of primes then it is
one of those primes.\<close>
lemma prime_dvd_mult: "\p dvd m #* n; p \ prime; m \ nat; n \ nat\ \ p dvd m \ p dvd n" by (blast intro: relprime_dvd_mult prime_imp_relprime prime_into_nat)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.