| author | nipkow | 
| Mon, 27 Apr 1998 17:52:03 +0200 | |
| changeset 4834 | dd89afb55272 | 
| parent 4812 | d65372e425e5 | 
| child 4884 | 1ec740e30811 | 
| permissions | -rw-r--r-- | 
| 1804 | 1 | (* Title: HOL/ex/Primes.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Christophe Tabacznyj and Lawrence C Paulson | |
| 4 | Copyright 1996 University of Cambridge | |
| 5 | ||
| 6 | The "divides" relation, the greatest common divisor and Euclid's algorithm | |
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 7 | |
| 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 8 | See H. Davenport, "The Higher Arithmetic". 6th edition. (CUP, 1992) | 
| 1804 | 9 | *) | 
| 10 | ||
| 11 | eta_contract:=false; | |
| 12 | ||
| 13 | open Primes; | |
| 14 | ||
| 15 | (************************************************) | |
| 16 | (** Greatest Common Divisor **) | |
| 17 | (************************************************) | |
| 18 | ||
| 3495 
04739732b13e
New comments on how to deal with unproved termination conditions
 paulson parents: 
3457diff
changeset | 19 | (*** Euclid's Algorithm ***) | 
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 20 | |
| 1804 | 21 | |
| 3495 
04739732b13e
New comments on how to deal with unproved termination conditions
 paulson parents: 
3457diff
changeset | 22 | (** Prove the termination condition and remove it from the recursion equations | 
| 
04739732b13e
New comments on how to deal with unproved termination conditions
 paulson parents: 
3457diff
changeset | 23 | and induction rule **) | 
| 
04739732b13e
New comments on how to deal with unproved termination conditions
 paulson parents: 
3457diff
changeset | 24 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 25 | Tfl.tgoalw thy [] gcd.rules; | 
| 4356 | 26 | by (simp_tac (simpset() addsimps [mod_less_divisor]) 1); | 
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 27 | val tc = result(); | 
| 1804 | 28 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 29 | val gcd_eq = tc RS hd gcd.rules; | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 30 | |
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 31 | val prems = goal thy | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 32 | "[| !!m. P m 0; \ | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 33 | \ !!m n. [| 0<n; P n (m mod n) |] ==> P m n \ | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 34 | \ |] ==> P m n"; | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 35 | by (res_inst_tac [("u","m"),("v","n")] (tc RS gcd.induct) 1);
 | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 36 | by (case_tac "n=0" 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 37 | by (asm_simp_tac (simpset() addsimps prems) 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 38 | by Safe_tac; | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 39 | by (asm_simp_tac (simpset() addsimps prems) 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 40 | qed "gcd_induct"; | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 41 | |
| 1804 | 42 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 43 | goal thy "gcd(m,0) = m"; | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 44 | by (rtac (gcd_eq RS trans) 1); | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 45 | by (Simp_tac 1); | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 46 | qed "gcd_0"; | 
| 4809 | 47 | Addsimps [gcd_0]; | 
| 1804 | 48 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 49 | goal thy "!!m. 0<n ==> gcd(m,n) = gcd (n, m mod n)"; | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 50 | by (rtac (gcd_eq RS trans) 1); | 
| 4686 | 51 | by (Asm_simp_tac 1); | 
| 4356 | 52 | by (Blast_tac 1); | 
| 4809 | 53 | qed "gcd_non_0"; | 
| 1804 | 54 | |
| 4809 | 55 | goal thy "gcd(m,1) = 1"; | 
| 56 | by (simp_tac (simpset() addsimps [gcd_non_0]) 1); | |
| 57 | qed "gcd_1"; | |
| 58 | Addsimps [gcd_1]; | |
| 1804 | 59 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 60 | (*gcd(m,n) divides m and n. The conjunctions don't seem provable separately*) | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 61 | goal thy "(gcd(m,n) dvd m) & (gcd(m,n) dvd n)"; | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 62 | by (res_inst_tac [("m","m"),("n","n")] gcd_induct 1);
 | 
| 4809 | 63 | by (ALLGOALS | 
| 64 | (asm_full_simp_tac (simpset() addsimps [gcd_non_0, mod_less_divisor]))); | |
| 4089 | 65 | by (blast_tac (claset() addDs [dvd_mod_imp_dvd]) 1); | 
| 4809 | 66 | qed "gcd_dvd_both"; | 
| 67 | ||
| 68 | bind_thm ("gcd_dvd1", gcd_dvd_both RS conjunct1);
 | |
| 69 | bind_thm ("gcd_dvd2", gcd_dvd_both RS conjunct2);
 | |
| 70 | ||
| 1804 | 71 | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 72 | (*Maximality: for all m,n,f naturals, | 
| 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 73 | if f divides m and f divides n then f divides gcd(m,n)*) | 
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 74 | goal thy "!!k. (f dvd m) --> (f dvd n) --> f dvd gcd(m,n)"; | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 75 | by (res_inst_tac [("m","m"),("n","n")] gcd_induct 1);
 | 
| 4809 | 76 | by (ALLGOALS | 
| 77 | (asm_full_simp_tac (simpset() addsimps[gcd_non_0, dvd_mod, | |
| 78 | mod_less_divisor]))); | |
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 79 | qed_spec_mp "gcd_greatest"; | 
| 1804 | 80 | |
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 81 | (*Function gcd yields the Greatest Common Divisor*) | 
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 82 | goalw thy [is_gcd_def] "is_gcd (gcd(m,n)) m n"; | 
| 4809 | 83 | by (asm_simp_tac (simpset() addsimps [gcd_greatest, gcd_dvd_both]) 1); | 
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 84 | qed "is_gcd"; | 
| 1804 | 85 | |
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 86 | (*uniqueness of GCDs*) | 
| 4809 | 87 | goalw thy [is_gcd_def] "!!m n. [| is_gcd m a b; is_gcd n a b |] ==> m=n"; | 
| 4089 | 88 | by (blast_tac (claset() addIs [dvd_anti_sym]) 1); | 
| 3242 
406ae5ced4e9
Renamed egcd and gcd; defined the gcd function using TFL
 paulson parents: 
2102diff
changeset | 89 | qed "is_gcd_unique"; | 
| 1804 | 90 | |
| 4809 | 91 | (*USED??*) | 
| 92 | goalw thy [is_gcd_def] | |
| 93 | "!!m n. [| is_gcd m a b; k dvd a; k dvd b |] ==> k dvd m"; | |
| 94 | by (Blast_tac 1); | |
| 95 | qed "is_gcd_dvd"; | |
| 96 | ||
| 97 | (** Commutativity **) | |
| 98 | ||
| 99 | goalw thy [is_gcd_def] "is_gcd k m n = is_gcd k n m"; | |
| 100 | by (Blast_tac 1); | |
| 101 | qed "is_gcd_commute"; | |
| 102 | ||
| 103 | goal thy "gcd(m,n) = gcd(n,m)"; | |
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 104 | by (rtac is_gcd_unique 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 105 | by (rtac is_gcd 2); | 
| 4809 | 106 | by (asm_simp_tac (simpset() addsimps [is_gcd, is_gcd_commute]) 1); | 
| 107 | qed "gcd_commute"; | |
| 108 | ||
| 109 | goal thy "gcd(gcd(k,m),n) = gcd(k,gcd(m,n))"; | |
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 110 | by (rtac is_gcd_unique 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 111 | by (rtac is_gcd 2); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 112 | by (rewtac is_gcd_def); | 
| 4809 | 113 | by (blast_tac (claset() addSIs [gcd_dvd1, gcd_dvd2] | 
| 114 | addIs [gcd_greatest, dvd_trans]) 1); | |
| 115 | qed "gcd_assoc"; | |
| 116 | ||
| 117 | goal thy "gcd(0,m) = m"; | |
| 118 | by (stac gcd_commute 1); | |
| 119 | by (rtac gcd_0 1); | |
| 120 | qed "gcd_0_left"; | |
| 121 | ||
| 122 | goal thy "gcd(1,m) = 1"; | |
| 123 | by (stac gcd_commute 1); | |
| 124 | by (rtac gcd_1 1); | |
| 125 | qed "gcd_1_left"; | |
| 126 | Addsimps [gcd_0_left, gcd_1_left]; | |
| 127 | ||
| 128 | ||
| 129 | (** Multiplication laws **) | |
| 130 | ||
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 131 | (*Davenport, page 27*) | 
| 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 132 | goal thy "k * gcd(m,n) = gcd(k*m, k*n)"; | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 133 | by (res_inst_tac [("m","m"),("n","n")] gcd_induct 1);
 | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 134 | by (Asm_full_simp_tac 1); | 
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 135 | by (case_tac "k=0" 1); | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 136 | by (Asm_full_simp_tac 1); | 
| 4809 | 137 | by (asm_full_simp_tac | 
| 138 | (simpset() addsimps [mod_geq, gcd_non_0, mod_mult_distrib2]) 1); | |
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 139 | qed "gcd_mult_distrib2"; | 
| 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 140 | |
| 4809 | 141 | goal thy "gcd(m,m) = m"; | 
| 142 | by (cut_inst_tac [("k","m"),("m","1"),("n","1")] gcd_mult_distrib2 1);
 | |
| 143 | by (Asm_full_simp_tac 1); | |
| 144 | qed "gcd_self"; | |
| 145 | Addsimps [gcd_self]; | |
| 146 | ||
| 147 | goal thy "gcd(k, k*n) = k"; | |
| 148 | by (cut_inst_tac [("k","k"),("m","1"),("n","n")] gcd_mult_distrib2 1);
 | |
| 149 | by (Asm_full_simp_tac 1); | |
| 150 | qed "gcd_mult"; | |
| 151 | Addsimps [gcd_mult]; | |
| 152 | ||
| 153 | goal thy "!!k. [| gcd(k,n)=1; k dvd (m*n) |] ==> k dvd m"; | |
| 154 | by (subgoal_tac "m = gcd(m*k, m*n)" 1); | |
| 155 | by (etac ssubst 1 THEN rtac gcd_greatest 1); | |
| 156 | by (ALLGOALS (asm_simp_tac (simpset() addsimps [gcd_mult_distrib2 RS sym]))); | |
| 157 | qed "relprime_dvd_mult"; | |
| 158 | ||
| 159 | goalw thy [prime_def] "!!p. [| p: prime; ~ p dvd n |] ==> gcd (p, n) = 1"; | |
| 160 | by (cut_inst_tac [("m","p"),("n","n")] gcd_dvd_both 1);
 | |
| 161 | by (fast_tac (claset() addSss (simpset())) 1); | |
| 162 | qed "prime_imp_relprime"; | |
| 163 | ||
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 164 | (*This theorem leads immediately to a proof of the uniqueness of factorization. | 
| 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 165 | If p divides a product of primes then it is one of those primes.*) | 
| 4809 | 166 | goal thy "!!p. [| p: prime; p dvd (m*n) |] ==> p dvd m | p dvd n"; | 
| 167 | by (blast_tac (claset() addIs [relprime_dvd_mult, prime_imp_relprime]) 1); | |
| 3377 
afa1fedef73f
New results including the basis for unique factorization
 paulson parents: 
3359diff
changeset | 168 | qed "prime_dvd_mult"; | 
| 4809 | 169 | |
| 170 | ||
| 171 | (** Addition laws **) | |
| 172 | ||
| 173 | goal thy "gcd(m, m+n) = gcd(m,n)"; | |
| 174 | by (res_inst_tac [("n1", "m+n")] (gcd_commute RS ssubst) 1);
 | |
| 175 | by (rtac (gcd_eq RS trans) 1); | |
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 176 | by Auto_tac; | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 177 | by (asm_simp_tac (simpset() addsimps [mod_add_self1]) 1); | 
| 4809 | 178 | by (stac gcd_commute 1); | 
| 179 | by (stac gcd_non_0 1); | |
| 180 | by Safe_tac; | |
| 181 | qed "gcd_add"; | |
| 182 | ||
| 183 | goal thy "gcd(m, n+m) = gcd(m,n)"; | |
| 184 | by (asm_simp_tac (simpset() addsimps [add_commute, gcd_add]) 1); | |
| 185 | qed "gcd_add2"; | |
| 186 | ||
| 187 | ||
| 188 | (** More multiplication laws **) | |
| 189 | ||
| 190 | goal thy "gcd(m,n) dvd gcd(k*m, n)"; | |
| 191 | by (blast_tac (claset() addIs [gcd_greatest, dvd_trans, | |
| 192 | gcd_dvd1, gcd_dvd2]) 1); | |
| 193 | qed "gcd_dvd_gcd_mult"; | |
| 194 | ||
| 195 | goal thy "!!n. gcd(k,n) = 1 ==> gcd(k*m, n) = gcd(m,n)"; | |
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 196 | by (rtac dvd_anti_sym 1); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 197 | by (rtac gcd_dvd_gcd_mult 2); | 
| 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 198 | by (rtac ([relprime_dvd_mult, gcd_dvd2] MRS gcd_greatest) 1); | 
| 4809 | 199 | by (stac mult_commute 2); | 
| 4812 
d65372e425e5
expandshort;  new gcd_induct with inbuilt case analysis
 paulson parents: 
4809diff
changeset | 200 | by (rtac gcd_dvd1 2); | 
| 4809 | 201 | by (stac gcd_commute 1); | 
| 202 | by (asm_simp_tac (simpset() addsimps [gcd_assoc RS sym]) 1); | |
| 203 | qed "gcd_mult_cancel"; |