| author | paulson | 
| Wed, 26 Jun 2002 10:26:46 +0200 | |
| changeset 13248 | ae66c22ed52e | 
| parent 12867 | 5c900a821a7c | 
| child 13259 | 01fa0c8dbc92 | 
| permissions | -rw-r--r-- | 
| 1792 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 1 | (* Title: ZF/ex/Primes.thy | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 2 | ID: $Id$ | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 3 | Author: Christophe Tabacznyj and Lawrence C Paulson | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 4 | Copyright 1996 University of Cambridge | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 5 | |
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 6 | The "divides" relation, the greatest common divisor and Euclid's algorithm | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 7 | *) | 
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 8 | |
| 12867 | 9 | theory Primes = Main: | 
| 10 | constdefs | |
| 11 | divides :: "[i,i]=>o" (infixl "dvd" 50) | |
| 12 | "m dvd n == m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" | |
| 1792 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 13 | |
| 12867 | 14 | is_gcd :: "[i,i,i]=>o" (* great common divisor *) | 
| 15 | "is_gcd(p,m,n) == ((p dvd m) & (p dvd n)) & | |
| 16 | (\<forall>d\<in>nat. (d dvd m) & (d dvd n) --> d dvd p)" | |
| 1792 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 17 | |
| 12867 | 18 | gcd :: "[i,i]=>i" (* gcd by Euclid's algorithm *) | 
| 19 | "gcd(m,n) == transrec(natify(n), | |
| 20 | %n f. \<lambda>m \<in> nat. | |
| 11382 
a816fead971a
now more like the HOL versions, and with the Square Root example added
 paulson parents: 
11316diff
changeset | 21 | if n=0 then m else f`(m mod n)`n) ` natify(m)" | 
| 1792 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 22 | |
| 12867 | 23 | coprime :: "[i,i]=>o" (* coprime relation *) | 
| 11382 
a816fead971a
now more like the HOL versions, and with the Square Root example added
 paulson parents: 
11316diff
changeset | 24 | "coprime(m,n) == gcd(m,n) = 1" | 
| 
a816fead971a
now more like the HOL versions, and with the Square Root example added
 paulson parents: 
11316diff
changeset | 25 | |
| 
a816fead971a
now more like the HOL versions, and with the Square Root example added
 paulson parents: 
11316diff
changeset | 26 | prime :: i (* set of prime numbers *) | 
| 12867 | 27 |    "prime == {p \<in> nat. 1<p & (\<forall>m \<in> nat. m dvd p --> m=1 | m=p)}"
 | 
| 28 | ||
| 29 | (************************************************) | |
| 30 | (** Divides Relation **) | |
| 31 | (************************************************) | |
| 32 | ||
| 33 | lemma dvdD: "m dvd n ==> m \<in> nat & n \<in> nat & (\<exists>k \<in> nat. n = m#*k)" | |
| 34 | apply (unfold divides_def) | |
| 35 | apply assumption | |
| 36 | done | |
| 37 | ||
| 38 | lemma dvdE: | |
| 39 | "[|m dvd n; !!k. [|m \<in> nat; n \<in> nat; k \<in> nat; n = m#*k|] ==> P|] ==> P" | |
| 40 | by (blast dest!: dvdD) | |
| 41 | ||
| 42 | lemmas dvd_imp_nat1 = dvdD [THEN conjunct1, standard] | |
| 43 | lemmas dvd_imp_nat2 = dvdD [THEN conjunct2, THEN conjunct1, standard] | |
| 44 | ||
| 45 | ||
| 46 | lemma dvd_0_right [simp]: "m \<in> nat ==> m dvd 0" | |
| 47 | apply (unfold divides_def) | |
| 48 | apply (fast intro: nat_0I mult_0_right [symmetric]) | |
| 49 | done | |
| 50 | ||
| 51 | lemma dvd_0_left: "0 dvd m ==> m = 0" | |
| 52 | by (unfold divides_def, force) | |
| 53 | ||
| 54 | lemma dvd_refl [simp]: "m \<in> nat ==> m dvd m" | |
| 55 | apply (unfold divides_def) | |
| 56 | apply (fast intro: nat_1I mult_1_right [symmetric]) | |
| 57 | done | |
| 58 | ||
| 59 | lemma dvd_trans: "[| m dvd n; n dvd p |] ==> m dvd p" | |
| 60 | apply (unfold divides_def) | |
| 61 | apply (fast intro: mult_assoc mult_type) | |
| 62 | done | |
| 63 | ||
| 64 | lemma dvd_anti_sym: "[| m dvd n; n dvd m |] ==> m=n" | |
| 65 | apply (unfold divides_def) | |
| 66 | apply (force dest: mult_eq_self_implies_10 | |
| 67 | simp add: mult_assoc mult_eq_1_iff) | |
| 68 | done | |
| 69 | ||
| 70 | lemma dvd_mult_left: "[|(i#*j) dvd k; i \<in> nat|] ==> i dvd k" | |
| 71 | apply (unfold divides_def) | |
| 72 | apply (simp add: mult_assoc) | |
| 73 | apply blast | |
| 74 | done | |
| 75 | ||
| 76 | lemma dvd_mult_right: "[|(i#*j) dvd k; j \<in> nat|] ==> j dvd k" | |
| 77 | apply (unfold divides_def) | |
| 78 | apply clarify | |
| 79 | apply (rule_tac x = "i#*k" in bexI) | |
| 80 | apply (simp add: mult_ac) | |
| 81 | apply (rule mult_type) | |
| 82 | done | |
| 83 | ||
| 84 | ||
| 85 | (************************************************) | |
| 86 | (** Greatest Common Divisor **) | |
| 87 | (************************************************) | |
| 88 | ||
| 89 | (* GCD by Euclid's Algorithm *) | |
| 90 | ||
| 91 | lemma gcd_0 [simp]: "gcd(m,0) = natify(m)" | |
| 92 | apply (unfold gcd_def) | |
| 93 | apply (subst transrec) | |
| 94 | apply simp | |
| 95 | done | |
| 96 | ||
| 97 | lemma gcd_natify1 [simp]: "gcd(natify(m),n) = gcd(m,n)" | |
| 98 | by (simp add: gcd_def) | |
| 99 | ||
| 100 | lemma gcd_natify2 [simp]: "gcd(m, natify(n)) = gcd(m,n)" | |
| 101 | by (simp add: gcd_def) | |
| 102 | ||
| 103 | lemma gcd_non_0_raw: | |
| 104 | "[| 0<n; n \<in> nat |] ==> gcd(m,n) = gcd(n, m mod n)" | |
| 105 | apply (unfold gcd_def) | |
| 106 | apply (rule_tac P = "%z. ?left (z) = ?right" in transrec [THEN ssubst]) | |
| 107 | apply (simp add: ltD [THEN mem_imp_not_eq, THEN not_sym] | |
| 108 | mod_less_divisor [THEN ltD]) | |
| 109 | done | |
| 110 | ||
| 111 | lemma gcd_non_0: "0 < natify(n) ==> gcd(m,n) = gcd(n, m mod n)" | |
| 112 | apply (cut_tac m = "m" and n = "natify (n) " in gcd_non_0_raw) | |
| 113 | apply auto | |
| 114 | done | |
| 115 | ||
| 116 | lemma gcd_1 [simp]: "gcd(m,1) = 1" | |
| 117 | by (simp (no_asm_simp) add: gcd_non_0) | |
| 118 | ||
| 119 | lemma dvd_add: "[| k dvd a; k dvd b |] ==> k dvd (a #+ b)" | |
| 120 | apply (unfold divides_def) | |
| 121 | apply (fast intro: add_mult_distrib_left [symmetric] add_type) | |
| 122 | done | |
| 123 | ||
| 124 | lemma dvd_mult: "k dvd n ==> k dvd (m #* n)" | |
| 125 | apply (unfold divides_def) | |
| 126 | apply (fast intro: mult_left_commute mult_type) | |
| 127 | done | |
| 128 | ||
| 129 | lemma dvd_mult2: "k dvd m ==> k dvd (m #* n)" | |
| 130 | apply (subst mult_commute) | |
| 131 | apply (blast intro: dvd_mult) | |
| 132 | done | |
| 133 | ||
| 134 | (* k dvd (m*k) *) | |
| 135 | lemmas dvdI1 [simp] = dvd_refl [THEN dvd_mult, standard] | |
| 136 | lemmas dvdI2 [simp] = dvd_refl [THEN dvd_mult2, standard] | |
| 137 | ||
| 138 | lemma dvd_mod_imp_dvd_raw: | |
| 139 | "[| a \<in> nat; b \<in> nat; k dvd b; k dvd (a mod b) |] ==> k dvd a" | |
| 140 | apply (tactic "div_undefined_case_tac \"b=0\" 1") | |
| 141 | apply (blast intro: mod_div_equality [THEN subst] | |
| 142 | elim: dvdE | |
| 143 | intro!: dvd_add dvd_mult mult_type mod_type div_type) | |
| 144 | done | |
| 145 | ||
| 146 | lemma dvd_mod_imp_dvd: "[| k dvd (a mod b); k dvd b; a \<in> nat |] ==> k dvd a" | |
| 147 | apply (cut_tac b = "natify (b) " in dvd_mod_imp_dvd_raw) | |
| 148 | apply auto | |
| 149 | apply (simp add: divides_def) | |
| 150 | done | |
| 151 | ||
| 152 | (*Imitating TFL*) | |
| 153 | lemma gcd_induct_lemma [rule_format (no_asm)]: "[| n \<in> nat; | |
| 154 | \<forall>m \<in> nat. P(m,0); | |
| 155 | \<forall>m \<in> nat. \<forall>n \<in> nat. 0<n --> P(n, m mod n) --> P(m,n) |] | |
| 156 | ==> \<forall>m \<in> nat. P (m,n)" | |
| 157 | apply (erule_tac i = "n" in complete_induct) | |
| 158 | apply (case_tac "x=0") | |
| 159 | apply (simp (no_asm_simp)) | |
| 160 | apply clarify | |
| 161 | apply (drule_tac x1 = "m" and x = "x" in bspec [THEN bspec]) | |
| 162 | apply (simp_all add: Ord_0_lt_iff) | |
| 163 | apply (blast intro: mod_less_divisor [THEN ltD]) | |
| 164 | done | |
| 165 | ||
| 166 | lemma gcd_induct: "!!P. [| m \<in> nat; n \<in> nat; | |
| 167 | !!m. m \<in> nat ==> P(m,0); | |
| 168 | !!m n. [|m \<in> nat; n \<in> nat; 0<n; P(n, m mod n)|] ==> P(m,n) |] | |
| 169 | ==> P (m,n)" | |
| 170 | by (blast intro: gcd_induct_lemma) | |
| 171 | ||
| 172 | ||
| 173 | ||
| 174 | (* gcd type *) | |
| 175 | ||
| 176 | lemma gcd_type [simp,TC]: "gcd(m, n) \<in> nat" | |
| 177 | apply (subgoal_tac "gcd (natify (m) , natify (n)) \<in> nat") | |
| 178 | apply simp | |
| 179 | apply (rule_tac m = "natify (m) " and n = "natify (n) " in gcd_induct) | |
| 180 | apply auto | |
| 181 | apply (simp add: gcd_non_0) | |
| 182 | done | |
| 183 | ||
| 184 | ||
| 185 | (* Property 1: gcd(a,b) divides a and b *) | |
| 186 | ||
| 187 | lemma gcd_dvd_both: | |
| 188 | "[| m \<in> nat; n \<in> nat |] ==> gcd (m, n) dvd m & gcd (m, n) dvd n" | |
| 189 | apply (rule_tac m = "m" and n = "n" in gcd_induct) | |
| 190 | apply (simp_all add: gcd_non_0) | |
| 191 | apply (blast intro: dvd_mod_imp_dvd_raw nat_into_Ord [THEN Ord_0_lt]) | |
| 192 | done | |
| 193 | ||
| 194 | lemma gcd_dvd1 [simp]: "m \<in> nat ==> gcd(m,n) dvd m" | |
| 195 | apply (cut_tac m = "natify (m) " and n = "natify (n) " in gcd_dvd_both) | |
| 196 | apply auto | |
| 197 | done | |
| 198 | ||
| 199 | lemma gcd_dvd2 [simp]: "n \<in> nat ==> gcd(m,n) dvd n" | |
| 200 | apply (cut_tac m = "natify (m) " and n = "natify (n) " in gcd_dvd_both) | |
| 201 | apply auto | |
| 202 | done | |
| 203 | ||
| 204 | (* if f divides a and b then f divides gcd(a,b) *) | |
| 205 | ||
| 206 | lemma dvd_mod: "[| f dvd a; f dvd b |] ==> f dvd (a mod b)" | |
| 207 | apply (unfold divides_def) | |
| 208 | apply (tactic "div_undefined_case_tac \"b=0\" 1") | |
| 209 | apply auto | |
| 210 | apply (blast intro: mod_mult_distrib2 [symmetric]) | |
| 211 | done | |
| 212 | ||
| 213 | (* Property 2: for all a,b,f naturals, | |
| 214 | if f divides a and f divides b then f divides gcd(a,b)*) | |
| 215 | ||
| 216 | lemma gcd_greatest_raw [rule_format]: | |
| 217 | "[| m \<in> nat; n \<in> nat; f \<in> nat |] | |
| 218 | ==> (f dvd m) --> (f dvd n) --> f dvd gcd(m,n)" | |
| 219 | apply (rule_tac m = "m" and n = "n" in gcd_induct) | |
| 220 | apply (simp_all add: gcd_non_0 dvd_mod) | |
| 221 | done | |
| 222 | ||
| 223 | lemma gcd_greatest: "[| f dvd m; f dvd n; f \<in> nat |] ==> f dvd gcd(m,n)" | |
| 224 | apply (rule gcd_greatest_raw) | |
| 225 | apply (auto simp add: divides_def) | |
| 226 | done | |
| 227 | ||
| 228 | lemma gcd_greatest_iff [simp]: "[| k \<in> nat; m \<in> nat; n \<in> nat |] | |
| 229 | ==> (k dvd gcd (m, n)) <-> (k dvd m & k dvd n)" | |
| 230 | by (blast intro!: gcd_greatest gcd_dvd1 gcd_dvd2 intro: dvd_trans) | |
| 231 | ||
| 232 | ||
| 233 | (* GCD PROOF: GCD exists and gcd fits the definition *) | |
| 234 | ||
| 235 | lemma is_gcd: "[| m \<in> nat; n \<in> nat |] ==> is_gcd(gcd(m,n), m, n)" | |
| 236 | by (simp add: is_gcd_def) | |
| 237 | ||
| 238 | (* GCD is unique *) | |
| 239 | ||
| 240 | lemma is_gcd_unique: "[|is_gcd(m,a,b); is_gcd(n,a,b); m\<in>nat; n\<in>nat|] ==> m=n" | |
| 241 | apply (unfold is_gcd_def) | |
| 242 | apply (blast intro: dvd_anti_sym) | |
| 243 | done | |
| 244 | ||
| 245 | lemma is_gcd_commute: "is_gcd(k,m,n) <-> is_gcd(k,n,m)" | |
| 246 | by (unfold is_gcd_def, blast) | |
| 247 | ||
| 248 | lemma gcd_commute_raw: "[| m \<in> nat; n \<in> nat |] ==> gcd(m,n) = gcd(n,m)" | |
| 249 | apply (rule is_gcd_unique) | |
| 250 | apply (rule is_gcd) | |
| 251 | apply (rule_tac [3] is_gcd_commute [THEN iffD1]) | |
| 252 | apply (rule_tac [3] is_gcd) | |
| 253 | apply auto | |
| 254 | done | |
| 255 | ||
| 256 | lemma gcd_commute: "gcd(m,n) = gcd(n,m)" | |
| 257 | apply (cut_tac m = "natify (m) " and n = "natify (n) " in gcd_commute_raw) | |
| 258 | apply auto | |
| 259 | done | |
| 260 | ||
| 261 | lemma gcd_assoc_raw: "[| k \<in> nat; m \<in> nat; n \<in> nat |] | |
| 262 | ==> gcd (gcd (k, m), n) = gcd (k, gcd (m, n))" | |
| 263 | apply (rule is_gcd_unique) | |
| 264 | apply (rule is_gcd) | |
| 265 | apply (simp_all add: is_gcd_def) | |
| 266 | apply (blast intro: gcd_dvd1 gcd_dvd2 gcd_type intro: dvd_trans) | |
| 267 | done | |
| 268 | ||
| 269 | lemma gcd_assoc: "gcd (gcd (k, m), n) = gcd (k, gcd (m, n))" | |
| 270 | apply (cut_tac k = "natify (k) " and m = "natify (m) " and n = "natify (n) " | |
| 271 | in gcd_assoc_raw) | |
| 272 | apply auto | |
| 273 | done | |
| 274 | ||
| 275 | lemma gcd_0_left [simp]: "gcd (0, m) = natify(m)" | |
| 276 | by (simp add: gcd_commute [of 0]) | |
| 277 | ||
| 278 | lemma gcd_1_left [simp]: "gcd (1, m) = 1" | |
| 279 | by (simp add: gcd_commute [of 1]) | |
| 280 | ||
| 281 | ||
| 282 | (* Multiplication laws *) | |
| 283 | ||
| 284 | lemma gcd_mult_distrib2_raw: | |
| 285 | "[| k \<in> nat; m \<in> nat; n \<in> nat |] | |
| 286 | ==> k #* gcd (m, n) = gcd (k #* m, k #* n)" | |
| 287 | apply (erule_tac m = "m" and n = "n" in gcd_induct) | |
| 288 | apply assumption | |
| 289 | apply (simp) | |
| 290 | apply (case_tac "k = 0") | |
| 291 | apply simp | |
| 292 | apply (simp add: mod_geq gcd_non_0 mod_mult_distrib2 Ord_0_lt_iff) | |
| 293 | done | |
| 294 | ||
| 295 | lemma gcd_mult_distrib2: "k #* gcd (m, n) = gcd (k #* m, k #* n)" | |
| 296 | apply (cut_tac k = "natify (k) " and m = "natify (m) " and n = "natify (n) " | |
| 297 | in gcd_mult_distrib2_raw) | |
| 298 | apply auto | |
| 299 | done | |
| 300 | ||
| 301 | lemma gcd_mult [simp]: "gcd (k, k #* n) = natify(k)" | |
| 302 | apply (cut_tac k = "k" and m = "1" and n = "n" in gcd_mult_distrib2) | |
| 303 | apply auto | |
| 304 | done | |
| 305 | ||
| 306 | lemma gcd_self [simp]: "gcd (k, k) = natify(k)" | |
| 307 | apply (cut_tac k = "k" and n = "1" in gcd_mult) | |
| 308 | apply auto | |
| 309 | done | |
| 310 | ||
| 311 | lemma relprime_dvd_mult: | |
| 312 | "[| gcd (k,n) = 1; k dvd (m #* n); m \<in> nat |] ==> k dvd m" | |
| 313 | apply (cut_tac k = "m" and m = "k" and n = "n" in gcd_mult_distrib2) | |
| 314 | apply auto | |
| 315 | apply (erule_tac b = "m" in ssubst) | |
| 316 | apply (simp add: dvd_imp_nat1) | |
| 317 | done | |
| 318 | ||
| 319 | lemma relprime_dvd_mult_iff: | |
| 320 | "[| gcd (k,n) = 1; m \<in> nat |] ==> k dvd (m #* n) <-> k dvd m" | |
| 321 | by (blast intro: dvdI2 relprime_dvd_mult dvd_trans) | |
| 322 | ||
| 323 | lemma prime_imp_relprime: | |
| 324 | "[| p \<in> prime; ~ (p dvd n); n \<in> nat |] ==> gcd (p, n) = 1" | |
| 325 | apply (unfold prime_def) | |
| 326 | apply clarify | |
| 327 | apply (drule_tac x = "gcd (p,n) " in bspec) | |
| 328 | apply auto | |
| 329 | apply (cut_tac m = "p" and n = "n" in gcd_dvd2) | |
| 330 | apply auto | |
| 331 | done | |
| 332 | ||
| 333 | lemma prime_into_nat: "p \<in> prime ==> p \<in> nat" | |
| 334 | by (unfold prime_def, auto) | |
| 335 | ||
| 336 | lemma prime_nonzero: "p \<in> prime \<Longrightarrow> p\<noteq>0" | |
| 337 | by (unfold prime_def, auto) | |
| 338 | ||
| 339 | ||
| 340 | (*This theorem leads immediately to a proof of the uniqueness of | |
| 341 | factorization. If p divides a product of primes then it is | |
| 342 | one of those primes.*) | |
| 343 | ||
| 344 | lemma prime_dvd_mult: | |
| 345 | "[|p dvd m #* n; p \<in> prime; m \<in> nat; n \<in> nat |] ==> p dvd m \<or> p dvd n" | |
| 346 | by (blast intro: relprime_dvd_mult prime_imp_relprime prime_into_nat) | |
| 347 | ||
| 348 | ||
| 349 | (** Addition laws **) | |
| 350 | ||
| 351 | lemma gcd_add1 [simp]: "gcd (m #+ n, n) = gcd (m, n)" | |
| 352 | apply (subgoal_tac "gcd (m #+ natify (n) , natify (n)) = gcd (m, natify (n))") | |
| 353 | apply simp | |
| 354 | apply (case_tac "natify (n) = 0") | |
| 355 | apply (auto simp add: Ord_0_lt_iff gcd_non_0) | |
| 356 | done | |
| 357 | ||
| 358 | lemma gcd_add2 [simp]: "gcd (m, m #+ n) = gcd (m, n)" | |
| 359 | apply (rule gcd_commute [THEN trans]) | |
| 360 | apply (subst add_commute) | |
| 361 | apply simp | |
| 362 | apply (rule gcd_commute) | |
| 363 | done | |
| 364 | ||
| 365 | lemma gcd_add2' [simp]: "gcd (m, n #+ m) = gcd (m, n)" | |
| 366 | by (subst add_commute, rule gcd_add2) | |
| 367 | ||
| 368 | lemma gcd_add_mult_raw: "k \<in> nat ==> gcd (m, k #* m #+ n) = gcd (m, n)" | |
| 369 | apply (erule nat_induct) | |
| 370 | apply (auto simp add: gcd_add2 add_assoc) | |
| 371 | done | |
| 372 | ||
| 373 | lemma gcd_add_mult: "gcd (m, k #* m #+ n) = gcd (m, n)" | |
| 374 | apply (cut_tac k = "natify (k) " in gcd_add_mult_raw) | |
| 375 | apply auto | |
| 376 | done | |
| 377 | ||
| 378 | ||
| 379 | (* More multiplication laws *) | |
| 380 | ||
| 381 | lemma gcd_mult_cancel_raw: | |
| 382 | "[|gcd (k,n) = 1; m \<in> nat; n \<in> nat|] ==> gcd (k #* m, n) = gcd (m, n)" | |
| 383 | apply (rule dvd_anti_sym) | |
| 384 | apply (rule gcd_greatest) | |
| 385 | apply (rule relprime_dvd_mult [of _ k]) | |
| 386 | apply (simp add: gcd_assoc) | |
| 387 | apply (simp add: gcd_commute) | |
| 388 | apply (simp_all add: mult_commute) | |
| 389 | apply (blast intro: dvdI1 gcd_dvd1 dvd_trans) | |
| 390 | done | |
| 391 | ||
| 392 | lemma gcd_mult_cancel: "gcd (k,n) = 1 ==> gcd (k #* m, n) = gcd (m, n)" | |
| 393 | apply (cut_tac m = "natify (m) " and n = "natify (n) " in gcd_mult_cancel_raw) | |
| 394 | apply auto | |
| 395 | done | |
| 396 | ||
| 397 | ||
| 398 | (*** The square root of a prime is irrational: key lemma ***) | |
| 399 | ||
| 400 | lemma prime_dvd_other_side: | |
| 401 | "\<lbrakk>n#*n = p#*(k#*k); p \<in> prime; n \<in> nat\<rbrakk> \<Longrightarrow> p dvd n" | |
| 402 | apply (subgoal_tac "p dvd n#*n") | |
| 403 | apply (blast dest: prime_dvd_mult) | |
| 404 | apply (rule_tac j = "k#*k" in dvd_mult_left) | |
| 405 | apply (auto simp add: prime_def) | |
| 406 | done | |
| 407 | ||
| 408 | lemma reduction: | |
| 409 | "\<lbrakk>k#*k = p#*(j#*j); p \<in> prime; 0 < k; j \<in> nat; k \<in> nat\<rbrakk> | |
| 410 | \<Longrightarrow> k < p#*j & 0 < j" | |
| 411 | apply (rule ccontr) | |
| 412 | apply (simp add: not_lt_iff_le prime_into_nat) | |
| 413 | apply (erule disjE) | |
| 414 | apply (frule mult_le_mono, assumption+) | |
| 415 | apply (simp add: mult_ac) | |
| 416 | apply (auto dest!: natify_eqE | |
| 417 | simp add: not_lt_iff_le prime_into_nat mult_le_cancel_le1) | |
| 418 | apply (simp add: prime_def) | |
| 419 | apply (blast dest: lt_trans1) | |
| 420 | done | |
| 421 | ||
| 422 | lemma rearrange: "j #* (p#*j) = k#*k \<Longrightarrow> k#*k = p#*(j#*j)" | |
| 423 | by (simp add: mult_ac) | |
| 424 | ||
| 425 | lemma prime_not_square: | |
| 426 | "\<lbrakk>m \<in> nat; p \<in> prime\<rbrakk> \<Longrightarrow> \<forall>k \<in> nat. 0<k \<longrightarrow> m#*m \<noteq> p#*(k#*k)" | |
| 427 | apply (erule complete_induct) | |
| 428 | apply clarify | |
| 429 | apply (frule prime_dvd_other_side) | |
| 430 | apply assumption | |
| 431 | apply assumption | |
| 432 | apply (erule dvdE) | |
| 433 | apply (simp add: mult_assoc mult_cancel1 prime_nonzero prime_into_nat) | |
| 434 | apply (blast dest: rearrange reduction ltD) | |
| 435 | done | |
| 1792 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 436 | |
| 
75c54074cd8c
The "divides" relation, the greatest common divisor and Euclid's algorithm
 paulson parents: diff
changeset | 437 | end |