10 imports Plain "~~/src/HOL/ATP_Linkup" GCD Parity |
10 imports Plain "~~/src/HOL/ATP_Linkup" GCD Parity |
11 begin |
11 begin |
12 |
12 |
13 definition |
13 definition |
14 coprime :: "nat => nat => bool" where |
14 coprime :: "nat => nat => bool" where |
15 "coprime m n \<longleftrightarrow> (gcd (m, n) = 1)" |
15 "coprime m n \<longleftrightarrow> (gcd m n = 1)" |
16 |
16 |
17 definition |
17 definition |
18 prime :: "nat \<Rightarrow> bool" where |
18 prime :: "nat \<Rightarrow> bool" where |
19 [code func del]: "prime p \<longleftrightarrow> (1 < p \<and> (\<forall>m. m dvd p --> m = 1 \<or> m = p))" |
19 [code func del]: "prime p \<longleftrightarrow> (1 < p \<and> (\<forall>m. m dvd p --> m = 1 \<or> m = p))" |
20 |
20 |
307 ultimately have ?thesis by blast} |
307 ultimately have ?thesis by blast} |
308 ultimately show ?thesis by blast |
308 ultimately show ?thesis by blast |
309 qed |
309 qed |
310 |
310 |
311 text {* Greatest common divisor. *} |
311 text {* Greatest common divisor. *} |
312 lemma gcd_unique: "d dvd a\<and>d dvd b \<and> (\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d) \<longleftrightarrow> d = gcd(a,b)" |
312 lemma gcd_unique: "d dvd a\<and>d dvd b \<and> (\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d) \<longleftrightarrow> d = gcd a b" |
313 proof(auto) |
313 proof(auto) |
314 assume H: "d dvd a" "d dvd b" "\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d" |
314 assume H: "d dvd a" "d dvd b" "\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d" |
315 from H(3)[rule_format] gcd_dvd1[of a b] gcd_dvd2[of a b] |
315 from H(3)[rule_format] gcd_dvd1[of a b] gcd_dvd2[of a b] |
316 have th: "gcd (a,b) dvd d" by blast |
316 have th: "gcd a b dvd d" by blast |
317 from dvd_anti_sym[OF th gcd_greatest[OF H(1,2)]] show "d = gcd (a,b)" by blast |
317 from dvd_anti_sym[OF th gcd_greatest[OF H(1,2)]] show "d =gcd a b" by blast |
318 qed |
318 qed |
319 |
319 |
320 lemma gcd_eq: assumes H: "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd u \<and> d dvd v" |
320 lemma gcd_eq: assumes H: "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd u \<and> d dvd v" |
321 shows "gcd (x,y) = gcd(u,v)" |
321 shows "gcd x y = gcd u v" |
322 proof- |
322 proof- |
323 from H have "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd gcd (u,v)" by simp |
323 from H have "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd gcd u v" by simp |
324 with gcd_unique[of "gcd(u,v)" x y] show ?thesis by auto |
324 with gcd_unique[of "gcd u v" x y] show ?thesis by auto |
325 qed |
325 qed |
326 |
326 |
327 lemma bezout_gcd: "\<exists>x y. a * x - b * y = gcd(a,b) \<or> b * x - a * y = gcd(a,b)" |
327 lemma bezout_gcd: "\<exists>x y. a * x - b * y = gcd a b \<or> b * x - a * y = gcd a b" |
328 proof- |
328 proof- |
329 let ?g = "gcd (a,b)" |
329 let ?g = "gcd a b" |
330 from bezout[of a b] obtain d x y where d: "d dvd a" "d dvd b" "a * x - b * y = d \<or> b * x - a * y = d" by blast |
330 from bezout[of a b] obtain d x y where d: "d dvd a" "d dvd b" "a * x - b * y = d \<or> b * x - a * y = d" by blast |
331 from d(1,2) have "d dvd ?g" by simp |
331 from d(1,2) have "d dvd ?g" by simp |
332 then obtain k where k: "?g = d*k" unfolding dvd_def by blast |
332 then obtain k where k: "?g = d*k" unfolding dvd_def by blast |
333 from d(3) have "(a * x - b * y)*k = d*k \<or> (b * x - a * y)*k = d*k" by blast |
333 from d(3) have "(a * x - b * y)*k = d*k \<or> (b * x - a * y)*k = d*k" by blast |
334 hence "a * x * k - b * y*k = d*k \<or> b * x * k - a * y*k = d*k" |
334 hence "a * x * k - b * y*k = d*k \<or> b * x * k - a * y*k = d*k" |
337 by (simp add: k mult_assoc) |
337 by (simp add: k mult_assoc) |
338 thus ?thesis by blast |
338 thus ?thesis by blast |
339 qed |
339 qed |
340 |
340 |
341 lemma bezout_gcd_strong: assumes a: "a \<noteq> 0" |
341 lemma bezout_gcd_strong: assumes a: "a \<noteq> 0" |
342 shows "\<exists>x y. a * x = b * y + gcd(a,b)" |
342 shows "\<exists>x y. a * x = b * y + gcd a b" |
343 proof- |
343 proof- |
344 let ?g = "gcd (a,b)" |
344 let ?g = "gcd a b" |
345 from bezout_add_strong[OF a, of b] |
345 from bezout_add_strong[OF a, of b] |
346 obtain d x y where d: "d dvd a" "d dvd b" "a * x = b * y + d" by blast |
346 obtain d x y where d: "d dvd a" "d dvd b" "a * x = b * y + d" by blast |
347 from d(1,2) have "d dvd ?g" by simp |
347 from d(1,2) have "d dvd ?g" by simp |
348 then obtain k where k: "?g = d*k" unfolding dvd_def by blast |
348 then obtain k where k: "?g = d*k" unfolding dvd_def by blast |
349 from d(3) have "a * x * k = (b * y + d) *k " by auto |
349 from d(3) have "a * x * k = (b * y + d) *k " by auto |
350 hence "a * (x * k) = b * (y*k) + ?g" by (algebra add: k) |
350 hence "a * (x * k) = b * (y*k) + ?g" by (algebra add: k) |
351 thus ?thesis by blast |
351 thus ?thesis by blast |
352 qed |
352 qed |
353 |
353 |
354 lemma gcd_mult_distrib: "gcd(a * c, b * c) = c * gcd(a,b)" |
354 lemma gcd_mult_distrib: "gcd (a * c) (b * c) = c * gcd a b" |
355 by(simp add: gcd_mult_distrib2 mult_commute) |
355 by(simp add: gcd_mult_distrib2 mult_commute) |
356 |
356 |
357 lemma gcd_bezout: "(\<exists>x y. a * x - b * y = d \<or> b * x - a * y = d) \<longleftrightarrow> gcd(a,b) dvd d" |
357 lemma gcd_bezout: "(\<exists>x y. a * x - b * y = d \<or> b * x - a * y = d) \<longleftrightarrow> gcd a b dvd d" |
358 (is "?lhs \<longleftrightarrow> ?rhs") |
358 (is "?lhs \<longleftrightarrow> ?rhs") |
359 proof- |
359 proof- |
360 let ?g = "gcd (a,b)" |
360 let ?g = "gcd a b" |
361 {assume H: ?rhs then obtain k where k: "d = ?g*k" unfolding dvd_def by blast |
361 {assume H: ?rhs then obtain k where k: "d = ?g*k" unfolding dvd_def by blast |
362 from bezout_gcd[of a b] obtain x y where xy: "a * x - b * y = ?g \<or> b * x - a * y = ?g" |
362 from bezout_gcd[of a b] obtain x y where xy: "a * x - b * y = ?g \<or> b * x - a * y = ?g" |
363 by blast |
363 by blast |
364 hence "(a * x - b * y)*k = ?g*k \<or> (b * x - a * y)*k = ?g*k" by auto |
364 hence "(a * x - b * y)*k = ?g*k \<or> (b * x - a * y)*k = ?g*k" by auto |
365 hence "a * x*k - b * y*k = ?g*k \<or> b * x * k - a * y*k = ?g*k" |
365 hence "a * x*k - b * y*k = ?g*k \<or> b * x * k - a * y*k = ?g*k" |
374 from dvd_diff[OF dv(1,2)] dvd_diff[OF dv(3,4)] H |
374 from dvd_diff[OF dv(1,2)] dvd_diff[OF dv(3,4)] H |
375 have ?rhs by auto} |
375 have ?rhs by auto} |
376 ultimately show ?thesis by blast |
376 ultimately show ?thesis by blast |
377 qed |
377 qed |
378 |
378 |
379 lemma gcd_bezout_sum: assumes H:"a * x + b * y = d" shows "gcd(a,b) dvd d" |
379 lemma gcd_bezout_sum: assumes H:"a * x + b * y = d" shows "gcd a b dvd d" |
380 proof- |
380 proof- |
381 let ?g = "gcd (a,b)" |
381 let ?g = "gcd a b" |
382 have dv: "?g dvd a*x" "?g dvd b * y" |
382 have dv: "?g dvd a*x" "?g dvd b * y" |
383 using dvd_mult2[OF gcd_dvd1[of a b]] dvd_mult2[OF gcd_dvd2[of a b]] by simp_all |
383 using dvd_mult2[OF gcd_dvd1[of a b]] dvd_mult2[OF gcd_dvd2[of a b]] by simp_all |
384 from dvd_add[OF dv] H |
384 from dvd_add[OF dv] H |
385 show ?thesis by auto |
385 show ?thesis by auto |
386 qed |
386 qed |
387 |
387 |
388 lemma gcd_mult': "gcd(b,a * b) = b" |
388 lemma gcd_mult': "gcd b (a * b) = b" |
389 by (simp add: gcd_mult mult_commute[of a b]) |
389 by (simp add: gcd_mult mult_commute[of a b]) |
390 |
390 |
391 lemma gcd_add: "gcd(a + b,b) = gcd(a,b)" "gcd(b + a,b) = gcd(a,b)" "gcd(a,a + b) = gcd(a,b)" "gcd(a,b + a) = gcd(a,b)" |
391 lemma gcd_add: "gcd (a + b) b = gcd a b" "gcd (b + a) b = gcd a b" "gcd a (a + b) = gcd a b" "gcd a (b + a) = gcd a b" |
392 apply (simp_all add: gcd_add1) |
392 apply (simp_all add: gcd_add1) |
393 by (simp add: gcd_commute gcd_add1) |
393 by (simp add: gcd_commute gcd_add1) |
394 |
394 |
395 lemma gcd_sub: "b <= a ==> gcd(a - b,b) = gcd(a,b)" "a <= b ==> gcd(a,b - a) = gcd(a,b)" |
395 lemma gcd_sub: "b <= a ==> gcd (a - b) b = gcd a b" "a <= b ==> gcd a (b - a) = gcd a b" |
396 proof- |
396 proof- |
397 {fix a b assume H: "b \<le> (a::nat)" |
397 {fix a b assume H: "b \<le> (a::nat)" |
398 hence th: "a - b + b = a" by arith |
398 hence th: "a - b + b = a" by arith |
399 from gcd_add(1)[of "a - b" b] th have "gcd(a - b,b) = gcd(a,b)" by simp} |
399 from gcd_add(1)[of "a - b" b] th have "gcd (a - b) b = gcd a b" by simp} |
400 note th = this |
400 note th = this |
401 { |
401 { |
402 assume ab: "b \<le> a" |
402 assume ab: "b \<le> a" |
403 from th[OF ab] show "gcd (a - b, b) = gcd (a, b)" by blast |
403 from th[OF ab] show "gcd (a - b) b = gcd a b" by blast |
404 next |
404 next |
405 assume ab: "a \<le> b" |
405 assume ab: "a \<le> b" |
406 from th[OF ab] show "gcd (a,b - a) = gcd (a, b)" |
406 from th[OF ab] show "gcd a (b - a) = gcd a b" |
407 by (simp add: gcd_commute)} |
407 by (simp add: gcd_commute)} |
408 qed |
408 qed |
409 |
409 |
410 text {* Coprimality *} |
410 text {* Coprimality *} |
411 |
411 |
423 lemma coprime_1'[simp]: "coprime 1 a" by (simp add: coprime_def) |
423 lemma coprime_1'[simp]: "coprime 1 a" by (simp add: coprime_def) |
424 lemma coprime_Suc0[simp]: "coprime a (Suc 0)" by (simp add: coprime_def) |
424 lemma coprime_Suc0[simp]: "coprime a (Suc 0)" by (simp add: coprime_def) |
425 lemma coprime_Suc0'[simp]: "coprime (Suc 0) a" by (simp add: coprime_def) |
425 lemma coprime_Suc0'[simp]: "coprime (Suc 0) a" by (simp add: coprime_def) |
426 |
426 |
427 lemma gcd_coprime: |
427 lemma gcd_coprime: |
428 assumes z: "gcd(a,b) \<noteq> 0" and a: "a = a' * gcd(a,b)" and b: "b = b' * gcd(a,b)" |
428 assumes z: "gcd a b \<noteq> 0" and a: "a = a' * gcd a b" and b: "b = b' * gcd a b" |
429 shows "coprime a' b'" |
429 shows "coprime a' b'" |
430 proof- |
430 proof- |
431 let ?g = "gcd(a,b)" |
431 let ?g = "gcd a b" |
432 {assume bz: "a = 0" from b bz z a have ?thesis by (simp add: gcd_zero coprime_def)} |
432 {assume bz: "a = 0" from b bz z a have ?thesis by (simp add: gcd_zero coprime_def)} |
433 moreover |
433 moreover |
434 {assume az: "a\<noteq> 0" |
434 {assume az: "a\<noteq> 0" |
435 from z have z': "?g > 0" by simp |
435 from z have z': "?g > 0" by simp |
436 from bezout_gcd_strong[OF az, of b] |
436 from bezout_gcd_strong[OF az, of b] |
445 qed |
445 qed |
446 lemma coprime_0: "coprime d 0 \<longleftrightarrow> d = 1" by (simp add: coprime_def) |
446 lemma coprime_0: "coprime d 0 \<longleftrightarrow> d = 1" by (simp add: coprime_def) |
447 lemma coprime_mul: assumes da: "coprime d a" and db: "coprime d b" |
447 lemma coprime_mul: assumes da: "coprime d a" and db: "coprime d b" |
448 shows "coprime d (a * b)" |
448 shows "coprime d (a * b)" |
449 proof- |
449 proof- |
450 from da have th: "gcd(a, d) = 1" by (simp add: coprime_def gcd_commute) |
450 from da have th: "gcd a d = 1" by (simp add: coprime_def gcd_commute) |
451 from gcd_mult_cancel[of a d b, OF th] db[unfolded coprime_def] have "gcd (d, a*b) = 1" |
451 from gcd_mult_cancel[of a d b, OF th] db[unfolded coprime_def] have "gcd d (a * b) = 1" |
452 by (simp add: gcd_commute) |
452 by (simp add: gcd_commute) |
453 thus ?thesis unfolding coprime_def . |
453 thus ?thesis unfolding coprime_def . |
454 qed |
454 qed |
455 lemma coprime_lmul2: assumes dab: "coprime d (a * b)" shows "coprime d b" |
455 lemma coprime_lmul2: assumes dab: "coprime d (a * b)" shows "coprime d b" |
456 using prems unfolding coprime_bezout |
456 using prems unfolding coprime_bezout |
478 lemma coprime_mul_eq: "coprime d (a * b) \<longleftrightarrow> coprime d a \<and> coprime d b" |
478 lemma coprime_mul_eq: "coprime d (a * b) \<longleftrightarrow> coprime d a \<and> coprime d b" |
479 using coprime_rmul2[of d a b] coprime_lmul2[of d a b] coprime_mul[of d a b] |
479 using coprime_rmul2[of d a b] coprime_lmul2[of d a b] coprime_mul[of d a b] |
480 by blast |
480 by blast |
481 |
481 |
482 lemma gcd_coprime_exists: |
482 lemma gcd_coprime_exists: |
483 assumes nz: "gcd(a,b) \<noteq> 0" |
483 assumes nz: "gcd a b \<noteq> 0" |
484 shows "\<exists>a' b'. a = a' * gcd(a,b) \<and> b = b' * gcd(a,b) \<and> coprime a' b'" |
484 shows "\<exists>a' b'. a = a' * gcd a b \<and> b = b' * gcd a b \<and> coprime a' b'" |
485 proof- |
485 proof- |
486 let ?g = "gcd (a,b)" |
486 let ?g = "gcd a b" |
487 from gcd_dvd1[of a b] gcd_dvd2[of a b] |
487 from gcd_dvd1[of a b] gcd_dvd2[of a b] |
488 obtain a' b' where "a = ?g*a'" "b = ?g*b'" unfolding dvd_def by blast |
488 obtain a' b' where "a = ?g*a'" "b = ?g*b'" unfolding dvd_def by blast |
489 hence ab': "a = a'*?g" "b = b'*?g" by algebra+ |
489 hence ab': "a = a'*?g" "b = b'*?g" by algebra+ |
490 from ab' gcd_coprime[OF nz ab'] show ?thesis by blast |
490 from ab' gcd_coprime[OF nz ab'] show ?thesis by blast |
491 qed |
491 qed |
503 apply simp |
503 apply simp |
504 done |
504 done |
505 lemma coprime_minus1: "n \<noteq> 0 ==> coprime (n - 1) n" |
505 lemma coprime_minus1: "n \<noteq> 0 ==> coprime (n - 1) n" |
506 using coprime_plus1[of "n - 1"] coprime_commute[of "n - 1" n] by auto |
506 using coprime_plus1[of "n - 1"] coprime_commute[of "n - 1" n] by auto |
507 |
507 |
508 lemma bezout_gcd_pow: "\<exists>x y. a ^n * x - b ^ n * y = gcd(a,b) ^ n \<or> b ^ n * x - a ^ n * y = gcd(a,b) ^ n" |
508 lemma bezout_gcd_pow: "\<exists>x y. a ^n * x - b ^ n * y = gcd a b ^ n \<or> b ^ n * x - a ^ n * y = gcd a b ^ n" |
509 proof- |
509 proof- |
510 let ?g = "gcd (a,b)" |
510 let ?g = "gcd a b" |
511 {assume z: "?g = 0" hence ?thesis |
511 {assume z: "?g = 0" hence ?thesis |
512 apply (cases n, simp) |
512 apply (cases n, simp) |
513 apply arith |
513 apply arith |
514 apply (simp only: z power_0_Suc) |
514 apply (simp only: z power_0_Suc) |
515 apply (rule exI[where x=0]) |
515 apply (rule exI[where x=0]) |
528 using z ab'' by (simp only: power_mult_distrib[symmetric] |
528 using z ab'' by (simp only: power_mult_distrib[symmetric] |
529 diff_mult_distrib2 mult_assoc[symmetric]) |
529 diff_mult_distrib2 mult_assoc[symmetric]) |
530 hence ?thesis by blast } |
530 hence ?thesis by blast } |
531 ultimately show ?thesis by blast |
531 ultimately show ?thesis by blast |
532 qed |
532 qed |
533 lemma gcd_exp: "gcd (a^n, b^n) = gcd(a,b)^n" |
533 lemma gcd_exp: "gcd (a^n) (b^n) = gcd a b ^ n" |
534 proof- |
534 proof- |
535 let ?g = "gcd(a^n,b^n)" |
535 let ?g = "gcd (a^n) (b^n)" |
536 let ?gn = "gcd(a,b)^n" |
536 let ?gn = "gcd a b ^ n" |
537 {fix e assume H: "e dvd a^n" "e dvd b^n" |
537 {fix e assume H: "e dvd a^n" "e dvd b^n" |
538 from bezout_gcd_pow[of a n b] obtain x y |
538 from bezout_gcd_pow[of a n b] obtain x y |
539 where xy: "a ^ n * x - b ^ n * y = ?gn \<or> b ^ n * x - a ^ n * y = ?gn" by blast |
539 where xy: "a ^ n * x - b ^ n * y = ?gn \<or> b ^ n * x - a ^ n * y = ?gn" by blast |
540 from dvd_diff [OF dvd_mult2[OF H(1), of x] dvd_mult2[OF H(2), of y]] |
540 from dvd_diff [OF dvd_mult2[OF H(1), of x] dvd_mult2[OF H(2), of y]] |
541 dvd_diff [OF dvd_mult2[OF H(2), of x] dvd_mult2[OF H(1), of y]] xy |
541 dvd_diff [OF dvd_mult2[OF H(2), of x] dvd_mult2[OF H(1), of y]] xy |
542 have "e dvd ?gn" by (cases "a ^ n * x - b ^ n * y = gcd (a, b) ^ n", simp_all)} |
542 have "e dvd ?gn" by (cases "a ^ n * x - b ^ n * y = gcd a b ^ n", simp_all)} |
543 hence th: "\<forall>e. e dvd a^n \<and> e dvd b^n \<longrightarrow> e dvd ?gn" by blast |
543 hence th: "\<forall>e. e dvd a^n \<and> e dvd b^n \<longrightarrow> e dvd ?gn" by blast |
544 from divides_exp[OF gcd_dvd1[of a b], of n] divides_exp[OF gcd_dvd2[of a b], of n] th |
544 from divides_exp[OF gcd_dvd1[of a b], of n] divides_exp[OF gcd_dvd2[of a b], of n] th |
545 gcd_unique have "?gn = ?g" by blast thus ?thesis by simp |
545 gcd_unique have "?gn = ?g" by blast thus ?thesis by simp |
546 qed |
546 qed |
547 |
547 |
549 by (simp only: coprime_def gcd_exp exp_eq_1) simp |
549 by (simp only: coprime_def gcd_exp exp_eq_1) simp |
550 |
550 |
551 lemma division_decomp: assumes dc: "(a::nat) dvd b * c" |
551 lemma division_decomp: assumes dc: "(a::nat) dvd b * c" |
552 shows "\<exists>b' c'. a = b' * c' \<and> b' dvd b \<and> c' dvd c" |
552 shows "\<exists>b' c'. a = b' * c' \<and> b' dvd b \<and> c' dvd c" |
553 proof- |
553 proof- |
554 let ?g = "gcd (a,b)" |
554 let ?g = "gcd a b" |
555 {assume "?g = 0" with dc have ?thesis apply (simp add: gcd_zero) |
555 {assume "?g = 0" with dc have ?thesis apply (simp add: gcd_zero) |
556 apply (rule exI[where x="0"]) |
556 apply (rule exI[where x="0"]) |
557 by (rule exI[where x="c"], simp)} |
557 by (rule exI[where x="c"], simp)} |
558 moreover |
558 moreover |
559 {assume z: "?g \<noteq> 0" |
559 {assume z: "?g \<noteq> 0" |
573 |
573 |
574 lemma nat_power_eq_0_iff: "(m::nat) ^ n = 0 \<longleftrightarrow> n \<noteq> 0 \<and> m = 0" by (induct n, auto) |
574 lemma nat_power_eq_0_iff: "(m::nat) ^ n = 0 \<longleftrightarrow> n \<noteq> 0 \<and> m = 0" by (induct n, auto) |
575 |
575 |
576 lemma divides_rev: assumes ab: "(a::nat) ^ n dvd b ^n" and n:"n \<noteq> 0" shows "a dvd b" |
576 lemma divides_rev: assumes ab: "(a::nat) ^ n dvd b ^n" and n:"n \<noteq> 0" shows "a dvd b" |
577 proof- |
577 proof- |
578 let ?g = "gcd (a,b)" |
578 let ?g = "gcd a b" |
579 from n obtain m where m: "n = Suc m" by (cases n, simp_all) |
579 from n obtain m where m: "n = Suc m" by (cases n, simp_all) |
580 {assume "?g = 0" with ab n have ?thesis by (simp add: gcd_zero)} |
580 {assume "?g = 0" with ab n have ?thesis by (simp add: gcd_zero)} |
581 moreover |
581 moreover |
582 {assume z: "?g \<noteq> 0" |
582 {assume z: "?g \<noteq> 0" |
583 hence zn: "?g ^ n \<noteq> 0" using n by (simp add: neq0_conv) |
583 hence zn: "?g ^ n \<noteq> 0" using n by (simp add: neq0_conv) |