# HG changeset patch # User haftmann # Date 1510425668 0 # Node ID e7e54a0b9197aa002dcdcafef8588a76d7613767 # Parent 1e29e2666a158f136671e442647f6c8de52a9041 dedicated definition for coprimality diff -r 1e29e2666a15 -r e7e54a0b9197 NEWS --- a/NEWS Sat Nov 11 18:33:35 2017 +0000 +++ b/NEWS Sat Nov 11 18:41:08 2017 +0000 @@ -89,7 +89,10 @@ * Class linordered_semiring_1 covers zero_less_one also, ruling out pathologic instances. Minor INCOMPATIBILITY. -* Removed nat-int transfer machinery. Rare INCOMPATIBILITY. +* Removed nat-int transfer machinery. Rare INCOMPATIBILITY. + +* Predicate coprime is now a real definition, not a mere +abbreviation. INCOMPATIBILITY. *** System *** diff -r 1e29e2666a15 -r e7e54a0b9197 src/Doc/Corec/Corec.thy --- a/src/Doc/Corec/Corec.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/Doc/Corec/Corec.thy Sat Nov 11 18:41:08 2017 +0000 @@ -334,9 +334,9 @@ primes m (n + 1))" apply (relation "measure (\(m, n). if n = 0 then 1 else if coprime m n then 0 else m - n mod m)") - apply (auto simp: mod_Suc intro: Suc_lessI) - apply (metis One_nat_def coprime_Suc_nat gcd.commute gcd_red_nat) - by (metis diff_less_mono2 lessI mod_less_divisor) + apply (auto simp: mod_Suc diff_less_mono2 intro: Suc_lessI elim!: not_coprimeE) + apply (metis dvd_1_iff_1 dvd_eq_mod_eq_0 mod_0 mod_Suc mod_Suc_eq mod_mod_cancel) + done text \ \noindent diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Algebra/Multiplicative_Group.thy --- a/src/HOL/Algebra/Multiplicative_Group.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Algebra/Multiplicative_Group.thy Sat Nov 11 18:41:08 2017 +0000 @@ -139,7 +139,7 @@ (* Deviates from the definition given in the library in number theory *) definition phi' :: "nat => nat" - where "phi' m = card {x. 1 \ x \ x \ m \ gcd x m = 1}" + where "phi' m = card {x. 1 \ x \ x \ m \ coprime x m}" notation (latex output) phi' ("\ _") @@ -148,8 +148,8 @@ assumes "m > 0" shows "phi' m > 0" proof - - have "1 \ {x. 1 \ x \ x \ m \ gcd x m = 1}" using assms by simp - hence "card {x. 1 \ x \ x \ m \ gcd x m = 1} > 0" by (auto simp: card_gt_0_iff) + have "1 \ {x. 1 \ x \ x \ m \ coprime x m}" using assms by simp + hence "card {x. 1 \ x \ x \ m \ coprime x m} > 0" by (auto simp: card_gt_0_iff) thus ?thesis unfolding phi'_def by simp qed @@ -232,7 +232,7 @@ by (simp add: gcd_mult_distrib_nat q ac_simps) hence "n div gcd (a * n div d) n = d*n div (d*(n div d))" using a by simp hence "a * n div d \ ?F" - using ge_1 le_n by (fastforce simp add: `d dvd n` dvd_mult_div_cancel) + using ge_1 le_n by (fastforce simp add: `d dvd n`) } thus "(\a. a*n div d) ` ?RF \ ?F" by blast { fix m l assume A: "m \ ?F" "l \ ?F" "m div gcd m n = l div gcd l n" hence "gcd m n = gcd l n" using dvd_div_eq_2[OF assms] by fastforce @@ -256,7 +256,7 @@ proof fix m assume m: "m \ ?R" thus "m \ ?L" using dvd_triv_right[of "n div gcd m n" "gcd m n"] - by (simp add: dvd_mult_div_cancel) + by simp qed qed fastforce finally show ?thesis by force @@ -329,7 +329,7 @@ lemma ord_min: assumes "finite (carrier G)" "1 \ d" "a \ carrier G" "a (^) d = \" shows "ord a \ d" proof - - def Ord \ "{d \ {1..order G}. a (^) d = \}" + define Ord where "Ord = {d \ {1..order G}. a (^) d = \}" have fin: "finite Ord" by (auto simp: Ord_def) have in_ord: "ord a \ Ord" using assms pow_ord_eq_1 ord_ge_1 ord_le_group_order by (auto simp: Ord_def) @@ -411,7 +411,7 @@ show "?R \ ?L" by blast { fix y assume "y \ ?L" then obtain x::nat where x:"y = a(^)x" by auto - def r \ "x mod ord a" + define r where "r = x mod ord a" then obtain q where q:"x = q * ord a + r" using mod_eqD by atomize_elim presburger hence "y = (a(^)ord a)(^)q \ a(^)r" using x assms by (simp add: mult.commute nat_pow_mult nat_pow_pow) @@ -427,7 +427,7 @@ assumes "finite (carrier G)" "a \ carrier G" "a (^) k = \" shows "ord a dvd k" proof - - def r \ "k mod ord a" + define r where "r = k mod ord a" then obtain q where q:"k = q*ord a + r" using mod_eqD by atomize_elim presburger hence "a(^)k = (a(^)ord a)(^)q \ a(^)r" using assms by (simp add: mult.commute nat_pow_mult nat_pow_pow) @@ -486,15 +486,16 @@ proof - have "coprime (n div gcd n (ord a)) (ord a div gcd n (ord a))" using div_gcd_coprime[of n "ord a"] ge_1 by fastforce - thus ?thesis by (simp add: gcd.commute) + thus ?thesis by (simp add: ac_simps) qed have dvd_d:"(ord a div gcd n (ord a)) dvd d" proof - have "ord a div gcd n (ord a) dvd (n div gcd n (ord a)) * d" using prod_eq by (metis dvd_triv_right mult.commute) hence "ord a div gcd n (ord a) dvd d * (n div gcd n (ord a))" - by (simp add: mult.commute) - thus ?thesis using coprime_dvd_mult[OF cp, of d] by fastforce + by (simp add: mult.commute) + then show ?thesis + using cp by (simp add: coprime_dvd_mult_left_iff) qed have "d > 0" using d_elem by simp hence "ord a div gcd n (ord a) \ d" using dvd_d by (simp add : Nat.dvd_imp_le) @@ -744,7 +745,8 @@ shows pow_ord_eq_ord_iff: "group.ord G (a (^) k) = ord a \ coprime k (ord a)" (is "?L \ ?R") proof assume A: ?L then show ?R - using assms ord_ge_1[OF assms] by (auto simp: nat_div_eq ord_pow_dvd_ord_elem) + using assms ord_ge_1 [OF assms] + by (auto simp: nat_div_eq ord_pow_dvd_ord_elem coprime_iff_gcd_eq_1) next assume ?R then show ?L using ord_pow_dvd_ord_elem[OF assms, of k] by auto diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Factorial_Ring.thy --- a/src/HOL/Computational_Algebra/Factorial_Ring.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Factorial_Ring.thy Sat Nov 11 18:41:08 2017 +0000 @@ -13,12 +13,6 @@ subsection \Irreducible and prime elements\ -(* TODO: Move ? *) -lemma (in semiring_gcd) prod_coprime' [rule_format]: - "(\i\A. gcd a (f i) = 1) \ gcd a (\i\A. f i) = 1" - using prod_coprime[of A f a] by (simp add: gcd.commute) - - context comm_semiring_1 begin @@ -583,7 +577,7 @@ end -subsection \In a semiring with GCD, each irreducible element is a prime elements\ +subsection \In a semiring with GCD, each irreducible element is a prime element\ context semiring_gcd begin @@ -620,23 +614,26 @@ using assms by (simp add: prime_elem_imp_coprime) lemma prime_elem_imp_power_coprime: - "prime_elem p \ \p dvd a \ coprime a (p ^ m)" - by (auto intro!: coprime_exp dest: prime_elem_imp_coprime simp: gcd.commute) + "prime_elem p \ \ p dvd a \ coprime a (p ^ m)" + by (cases "m > 0") (auto dest: prime_elem_imp_coprime simp add: ac_simps) lemma prime_imp_power_coprime: - "prime p \ \p dvd a \ coprime a (p ^ m)" - by (simp add: prime_elem_imp_power_coprime) + "prime p \ \ p dvd a \ coprime a (p ^ m)" + by (rule prime_elem_imp_power_coprime) simp_all lemma prime_elem_divprod_pow: assumes p: "prime_elem p" and ab: "coprime a b" and pab: "p^n dvd a * b" shows "p^n dvd a \ p^n dvd b" using assms proof - - from ab p have "\p dvd a \ \p dvd b" - by (auto simp: coprime prime_elem_def) - with p have "coprime (p^n) a \ coprime (p^n) b" - by (auto intro: prime_elem_imp_coprime coprime_exp_left) - with pab show ?thesis by (auto intro: coprime_dvd_mult simp: mult_ac) + from p have "\ is_unit p" + by simp + with ab p have "\ p dvd a \ \ p dvd b" + using not_coprimeI by blast + with p have "coprime (p ^ n) a \ coprime (p ^ n) b" + by (auto dest: prime_elem_imp_power_coprime simp add: ac_simps) + with pab show ?thesis + by (auto simp add: coprime_dvd_mult_left_iff coprime_dvd_mult_right_iff) qed lemma primes_coprime: @@ -1524,6 +1521,27 @@ with assms[of P] assms[of Q] PQ show "P = Q" by simp qed +lemma divides_primepow: + assumes "prime p" and "a dvd p ^ n" + obtains m where "m \ n" and "normalize a = p ^ m" +proof - + from assms have "a \ 0" + by auto + with assms + have "prod_mset (prime_factorization a) dvd prod_mset (prime_factorization (p ^ n))" + by (simp add: prod_mset_prime_factorization) + then have "prime_factorization a \# prime_factorization (p ^ n)" + by (simp add: in_prime_factors_imp_prime prod_mset_dvd_prod_mset_primes_iff) + with assms have "prime_factorization a \# replicate_mset n p" + by (simp add: prime_factorization_prime_power) + then obtain m where "m \ n" and "prime_factorization a = replicate_mset m p" + by (rule msubseteq_replicate_msetE) + then have "prod_mset (prime_factorization a) = prod_mset (replicate_mset m p)" + by simp + with \a \ 0\ have "normalize a = p ^ m" + by (simp add: prod_mset_prime_factorization) + with \m \ n\ show thesis .. +qed subsection \GCD and LCM computation with unique factorizations\ diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Normalized_Fraction.thy --- a/src/HOL/Computational_Algebra/Normalized_Fraction.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Normalized_Fraction.thy Sat Nov 11 18:41:08 2017 +0000 @@ -16,6 +16,15 @@ "normalize_quot = (\(a,b). if b = 0 then (0,1) else let d = gcd a b * unit_factor b in (a div d, b div d))" +lemma normalize_quot_zero [simp]: + "normalize_quot (a, 0) = (0, 1)" + by (simp add: normalize_quot_def) + +lemma normalize_quot_proj [simp]: + "fst (normalize_quot (a, b)) = a div (gcd a b * unit_factor b)" + "snd (normalize_quot (a, b)) = normalize b div gcd a b" if "b \ 0" + using that by (simp_all add: normalize_quot_def Let_def mult.commute [of _ "unit_factor b"] dvd_div_mult2_eq mult_unit_dvd_iff') + definition normalized_fracts :: "('a :: {ring_gcd,idom_divide} \ 'a) set" where "normalized_fracts = {(a,b). coprime a b \ unit_factor b = 1}" @@ -61,8 +70,8 @@ lemma coprime_normalize_quot: "coprime (fst (normalize_quot x)) (snd (normalize_quot x))" - by (simp add: normalize_quot_def case_prod_unfold Let_def - div_mult_unit2 gcd_div_unit1 gcd_div_unit2 div_gcd_coprime) + by (simp add: normalize_quot_def case_prod_unfold div_mult_unit2) + (metis coprime_mult_self_right_iff div_gcd_coprime unit_div_mult_self unit_factor_is_unit) lemma normalize_quot_in_normalized_fracts [simp]: "normalize_quot x \ normalized_fracts" by (simp add: normalized_fracts_def coprime_normalize_quot case_prod_unfold) @@ -203,15 +212,26 @@ and "g \ fst (normalize_quot (c, b))" and "h \ snd (normalize_quot (c, b))" shows "normalize_quot (a * c, b * d) = (e * g, f * h)" proof (rule normalize_quotI) + from assms have "gcd a b = 1" "gcd c d = 1" + by simp_all from assms have "b \ 0" "d \ 0" by auto - from normalize_quotE[OF \b \ 0\, of c] guess k . note k = this [folded assms] - from normalize_quotE[OF \d \ 0\, of a] guess l . note l = this [folded assms] - from k l show "a * c * (f * h) = b * d * (e * g)" by (simp_all) + with assms have "normalize b = b" "normalize d = d" + by (auto intro: normalize_unit_factor_eqI) + from normalize_quotE [OF \b \ 0\, of c] guess k . + note k = this [folded \gcd a b = 1\ \gcd c d = 1\ assms(3) assms(4)] + from normalize_quotE [OF \d \ 0\, of a] guess l . + note l = this [folded \gcd a b = 1\ \gcd c d = 1\ assms(3) assms(4)] + from k l show "a * c * (f * h) = b * d * (e * g)" + by (metis e_def f_def g_def h_def mult.commute mult.left_commute) from assms have [simp]: "unit_factor f = 1" "unit_factor h = 1" by simp_all from assms have "coprime e f" "coprime g h" by (simp_all add: coprime_normalize_quot) - with k l assms(1,2) show "(e * g, f * h) \ normalized_fracts" - by (simp add: normalized_fracts_def unit_factor_mult coprime_mul_eq coprime_mul_eq') + with k l assms(1,2) \b \ 0\ \d \ 0\ \unit_factor b = 1\ \unit_factor d = 1\ + \normalize b = b\ \normalize d = d\ + show "(e * g, f * h) \ normalized_fracts" + by (simp add: normalized_fracts_def unit_factor_mult e_def f_def g_def h_def + coprime_normalize_quot dvd_unit_factor_div unit_factor_gcd) + (metis coprime_mult_left_iff coprime_mult_right_iff) qed (insert assms(3,4), auto) lemma normalize_quot_mult: @@ -230,8 +250,8 @@ (let (a,b) = quot_of_fract x; (c,d) = quot_of_fract y; (e,f) = normalize_quot (a,d); (g,h) = normalize_quot (c,b) in (e*g, f*h))" - by transfer (simp_all add: Let_def case_prod_unfold normalize_quot_mult_coprime [symmetric] - coprime_normalize_quot normalize_quot_mult [symmetric]) + by transfer + (simp add: split_def Let_def coprime_normalize_quot normalize_quot_mult normalize_quot_mult_coprime) lemma normalize_quot_0 [simp]: "normalize_quot (0, x) = (0, 1)" "normalize_quot (x, 0) = (0, 1)" @@ -254,7 +274,9 @@ by (simp add: div_unit_factor [symmetric] unit_div_mult_swap mult_ac del: div_unit_factor) have "coprime a' b'" by (simp add: a'_def b'_def coprime_normalize_quot) thus "(b' div unit_factor a', a' div unit_factor a') \ normalized_fracts" - using assms(1,2) d by (auto simp: normalized_fracts_def gcd_div_unit1 gcd_div_unit2 gcd.commute) + using assms(1,2) d + by (auto simp: normalized_fracts_def ac_simps) + (metis gcd.normalize_left_idem gcd_div_unit2 is_unit_gcd unit_factor_is_unit) qed fact+ lemma quot_of_fract_inverse: @@ -274,12 +296,19 @@ shows "normalize_quot (x div u, y) = (x' div u, y')" proof (cases "y = 0") case False - from normalize_quotE[OF this, of x] guess d . note d = this[folded assms(2,3)] - from assms have "coprime x' y'" "unit_factor y' = 1" by (simp_all add: coprime_normalize_quot) - with False d \is_unit u\ show ?thesis - by (intro normalize_quotI) - (auto simp: normalized_fracts_def unit_div_mult_swap unit_div_commute unit_div_cancel - gcd_div_unit1) + define v where "v = 1 div u" + with \is_unit u\ have "is_unit v" and u: "\a. a div u = a * v" + by simp_all + from \is_unit v\ have "coprime v = top" + by (simp add: fun_eq_iff is_unit_left_imp_coprime) + from normalize_quotE[OF False, of x] guess d . + note d = this[folded assms(2,3)] + from assms have "coprime x' y'" "unit_factor y' = 1" + by (simp_all add: coprime_normalize_quot) + with d \coprime v = top\ have "normalize_quot (x * v, y) = (x' * v, y')" + by (auto simp: normalized_fracts_def intro: normalize_quotI) + then show ?thesis + by (simp add: u) qed (simp_all add: assms) lemma normalize_quot_div_unit_right: @@ -291,10 +320,8 @@ case False from normalize_quotE[OF this, of x] guess d . note d = this[folded assms(2,3)] from assms have "coprime x' y'" "unit_factor y' = 1" by (simp_all add: coprime_normalize_quot) - with False d \is_unit u\ show ?thesis - by (intro normalize_quotI) - (auto simp: normalized_fracts_def unit_div_mult_swap unit_div_commute unit_div_cancel - gcd_mult_unit1 unit_div_eq_0_iff mult.assoc [symmetric]) + with d \is_unit u\ show ?thesis + by (auto simp add: normalized_fracts_def is_unit_left_imp_coprime unit_div_eq_0_iff intro: normalize_quotI) qed (simp_all add: assms) lemma normalize_quot_normalize_left: diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Nth_Powers.thy --- a/src/HOL/Computational_Algebra/Nth_Powers.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Nth_Powers.thy Sat Nov 11 18:41:08 2017 +0000 @@ -111,9 +111,10 @@ ultimately show "n dvd multiplicity p a" by (auto simp: not_dvd_imp_multiplicity_0) qed - from A[of a b] assms show "is_nth_power n a" by (cases "n = 0") simp_all - from A[of b a] assms show "is_nth_power n b" - by (cases "n = 0") (simp_all add: gcd.commute mult.commute) + from A [of a b] assms show "is_nth_power n a" + by (cases "n = 0") simp_all + from A [of b a] assms show "is_nth_power n b" + by (cases "n = 0") (simp_all add: ac_simps) qed lemma is_nth_power_mult_coprime_nat_iff: diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Polynomial_Factorial.thy --- a/src/HOL/Computational_Algebra/Polynomial_Factorial.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Polynomial_Factorial.thy Sat Nov 11 18:41:08 2017 +0000 @@ -171,7 +171,7 @@ hence "fract_poly (smult a q) = fract_poly (smult b p)" by (simp del: fract_poly_eq_iff) hence "smult b p = smult a q" by (simp only: fract_poly_eq_iff) moreover have "c = to_fract a / to_fract b" "coprime b a" "normalize b = b" - by (simp_all add: a_def b_def coprime_quot_of_fract gcd.commute + by (simp_all add: a_def b_def coprime_quot_of_fract [of c] ac_simps normalize_snd_quot_of_fract Fract_conv_to_fract [symmetric]) ultimately show ?thesis by (intro that[of a b]) qed @@ -513,9 +513,12 @@ from fract_poly_smult_eqE[OF this] guess a b . note ab = this hence "content (smult a p) = content (smult b (q' * r'))" by (simp only:) with ab(4) have a: "a = normalize b" by (simp add: content_mult q r) - hence "normalize b = gcd a b" by simp - also from ab(3) have "\ = 1" . - finally have "a = 1" "is_unit b" by (simp_all add: a normalize_1_iff) + then have "normalize b = gcd a b" + by simp + with \coprime a b\ have "normalize b = 1" + by simp + then have "a = 1" "is_unit b" + by (simp_all add: a normalize_1_iff) note eq also from ab(1) \a = 1\ have "cr * cg = to_fract b" by simp @@ -676,7 +679,8 @@ from fract_poly_smult_eqE[OF eq] guess a b . note ab = this from ab(2) have "content (smult a p) = content (smult b e)" by (simp only: ) with assms content_e have "a = normalize b" by (simp add: ab(4)) - with ab have ab': "a = 1" "is_unit b" by (simp_all add: normalize_1_iff) + with ab have ab': "a = 1" "is_unit b" + by (simp_all add: normalize_1_iff) with ab ab' have "c' = to_fract b" by auto from this and \is_unit b\ show ?thesis by (rule that) qed diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Primes.thy --- a/src/HOL/Computational_Algebra/Primes.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Primes.thy Sat Nov 11 18:41:08 2017 +0000 @@ -245,9 +245,9 @@ using prime_power_cancel [OF assms] assms by auto lemma prime_power_canonical: - fixes m::nat + fixes m :: nat assumes "prime p" "m > 0" - shows "\k n. \ p dvd n \ m = n * p^k" + shows "\k n. \ p dvd n \ m = n * p ^ k" using \m > 0\ proof (induction m rule: less_induct) case (less m) @@ -381,9 +381,9 @@ (* TODO: Generalise? *) lemma prime_power_mult_nat: - fixes p::nat + fixes p :: nat assumes p: "prime p" and xy: "x * y = p ^ k" - shows "\i j. x = p ^i \ y = p^ j" + shows "\i j. x = p ^ i \ y = p^ j" using xy proof(induct k arbitrary: x y) case 0 thus ?case apply simp by (rule exI[where x="0"], simp) @@ -429,25 +429,10 @@ qed lemma divides_primepow_nat: - fixes p::nat + fixes p :: nat assumes p: "prime p" - shows "d dvd p^k \ (\ i. i \ k \ d = p ^i)" -proof - assume H: "d dvd p^k" then obtain e where e: "d*e = p^k" - unfolding dvd_def apply (auto simp add: mult.commute) by blast - from prime_power_mult_nat[OF p e] obtain i j where ij: "d = p^i" "e=p^j" by blast - from e ij have "p^(i + j) = p^k" by (simp add: power_add) - hence "i + j = k" using p prime_gt_1_nat power_inject_exp[of p "i+j" k] by simp - hence "i \ k" by arith - with ij(1) show "\i\k. d = p ^ i" by blast -next - {fix i assume H: "i \ k" "d = p^i" - then obtain j where j: "k = i + j" - by (metis le_add_diff_inverse) - hence "p^k = p^j*d" using H(2) by (simp add: power_add) - hence "d dvd p^k" unfolding dvd_def by auto} - thus "\i\k. d = p ^ i \ d dvd p ^ k" by blast -qed + shows "d dvd p ^ k \ (\i\k. d = p ^ i)" + using assms divides_primepow [of p d k] by (auto intro: le_imp_power_dvd) subsection \Chinese Remainder Theorem Variants\ @@ -481,8 +466,8 @@ from bezout_add_strong_nat[OF a, of b] bezout_add_strong_nat[OF b, of a] obtain d1 x1 y1 d2 x2 y2 where dxy1: "d1 dvd a" "d1 dvd b" "a * x1 = b * y1 + d1" and dxy2: "d2 dvd b" "d2 dvd a" "b * x2 = a * y2 + d2" by blast - then have d12: "d1 = 1" "d2 =1" - by (metis ab coprime_nat)+ + then have d12: "d1 = 1" "d2 = 1" + using ab coprime_common_divisor_nat [of a b] by blast+ let ?x = "v * a * x1 + u * b * x2" let ?q1 = "v * x1 + u * y2" let ?q2 = "v * y1 + u * x2" @@ -497,14 +482,14 @@ lemma coprime_bezout_strong: fixes a::nat assumes "coprime a b" "b \ 1" shows "\x y. a * x = b * y + 1" -by (metis assms bezout_nat gcd_nat.left_neutral) + by (metis add.commute add.right_neutral assms(1) assms(2) chinese_remainder coprime_1_left coprime_1_right coprime_crossproduct_nat mult.commute mult.right_neutral mult_cancel_left) lemma bezout_prime: assumes p: "prime p" and pa: "\ p dvd a" shows "\x y. a*x = Suc (p*y)" proof - have ap: "coprime a p" - by (metis gcd.commute p pa prime_imp_coprime) + using coprime_commute p pa prime_imp_coprime by auto moreover from p have "p \ 1" by auto ultimately have "\x y. a * x = p * y + 1" by (rule coprime_bezout_strong) diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Computational_Algebra/Squarefree.thy --- a/src/HOL/Computational_Algebra/Squarefree.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Computational_Algebra/Squarefree.thy Sat Nov 11 18:41:08 2017 +0000 @@ -116,13 +116,16 @@ show ?thesis unfolding squarefree_factorial_semiring'[OF nz] proof fix p assume p: "p \ prime_factors (a * b)" - { + with nz have "prime p" + by (simp add: prime_factors_dvd) + have "\ (p dvd a \ p dvd b)" + proof assume "p dvd a \ p dvd b" - hence "p dvd gcd a b" by simp - also have "gcd a b = 1" by fact - finally have False using nz using p by (auto simp: prime_factors_dvd) - } - hence "\(p dvd a \ p dvd b)" by blast + with \coprime a b\ have "is_unit p" + by (auto intro: coprime_common_divisor) + with \prime p\ show False + by simp + qed moreover from p have "p dvd a \ p dvd b" using nz by (auto simp: prime_factors_dvd prime_dvd_mult_iff) ultimately show "multiplicity p (a * b) = 1" using nz p assms(2,3) @@ -138,7 +141,7 @@ shows "squarefree (prod f A)" using assms by (induction A rule: infinite_finite_induct) - (auto intro!: squarefree_mult_coprime prod_coprime') + (auto intro!: squarefree_mult_coprime prod_coprime_right) lemma squarefree_powerD: "m > 0 \ squarefree (n ^ m) \ squarefree n" by (cases m) (auto dest: squarefree_multD) diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Corec_Examples/Paper_Examples.thy --- a/src/HOL/Corec_Examples/Paper_Examples.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Corec_Examples/Paper_Examples.thy Sat Nov 11 18:41:08 2017 +0000 @@ -96,9 +96,9 @@ where "primes m n = (if (m = 0 \ n > 1) \ coprime m n then n \ primes (m * n) (n + 1) else primes m (n + 1))" apply (relation "measure (\(m, n). if n = 0 then 1 else if coprime m n then 0 else m - n mod m)") -apply (auto simp: mod_Suc intro: Suc_lessI ) -apply (metis One_nat_def coprime_Suc_nat gcd.commute gcd_red_nat) -by (metis diff_less_mono2 lessI mod_less_divisor) + apply (auto simp: mod_Suc diff_less_mono2 intro: Suc_lessI elim!: not_coprimeE) + apply (metis dvd_1_iff_1 dvd_eq_mod_eq_0 mod_0 mod_Suc mod_Suc_eq mod_mod_cancel) + done corec facC :: "nat \ nat \ nat \ nat stream" where "facC n a i = (if i = 0 then a \ facC (n + 1) 1 (n + 1) else facC n (a * i) (i - 1))" diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Decision_Procs/Rat_Pair.thy --- a/src/HOL/Decision_Procs/Rat_Pair.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Decision_Procs/Rat_Pair.thy Sat Nov 11 18:41:08 2017 +0000 @@ -51,7 +51,8 @@ from dvd_mult_div_cancel[OF gdvd(1)] dvd_mult_div_cancel[OF gdvd(2)] ab have nz': "?a' \ 0" "?b' \ 0" by - (rule notI, simp)+ from ab have stupid: "a \ 0 \ b \ 0" by arith - from div_gcd_coprime[OF stupid] have gp1: "?g' = 1" . + from div_gcd_coprime[OF stupid] have gp1: "?g' = 1" + by simp from ab consider "b < 0" | "b > 0" by arith then show ?thesis proof cases @@ -198,6 +199,8 @@ from \a \ 0\ \a' \ 0\ na nb have gcd1: "gcd a b = 1" "gcd b a = 1" "gcd a' b' = 1" "gcd b' a' = 1" by (simp_all add: x y isnormNum_def add: gcd.commute) + then have "coprime a b" "coprime b a" "coprime a' b'" "coprime b' a'" + by (simp_all add: coprime_iff_gcd_eq_1) from eq have raw_dvd: "a dvd a' * b" "b dvd b' * a" "a' dvd a * b'" "b' dvd b * a'" apply - apply algebra @@ -205,11 +208,11 @@ apply simp apply algebra done - from zdvd_antisym_abs[OF coprime_dvd_mult[OF gcd1(2) raw_dvd(2)] - coprime_dvd_mult[OF gcd1(4) raw_dvd(4)]] - have eq1: "b = b'" using pos by arith - with eq have "a = a'" using pos by simp - with eq1 show ?thesis by (simp add: x y) + then have eq1: "b = b'" + using pos \coprime b a\ \coprime b' a'\ + by (auto simp add: coprime_dvd_mult_left_iff intro: associated_eqI) + with eq have "a = a'" using pos by simp + with \b = b'\ show ?thesis by (simp add: x y) qed show ?lhs if ?rhs using that by simp diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Euclidean_Division.thy --- a/src/HOL/Euclidean_Division.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Euclidean_Division.thy Sat Nov 11 18:41:08 2017 +0000 @@ -125,6 +125,15 @@ "a mod b = 0" if "is_unit b" using that by (simp add: mod_eq_0_iff_dvd unit_imp_dvd) +lemma coprime_mod_left_iff [simp]: + "coprime (a mod b) b \ coprime a b" if "b \ 0" + by (rule; rule coprimeI) + (use that in \auto dest!: dvd_mod_imp_dvd coprime_common_divisor simp add: dvd_mod_iff\) + +lemma coprime_mod_right_iff [simp]: + "coprime a (b mod a) \ coprime a b" if "a \ 0" + using that coprime_mod_left_iff [of a b] by (simp add: ac_simps) + end class euclidean_ring = idom_modulo + euclidean_semiring @@ -533,6 +542,10 @@ with that show thesis . qed +lemma invertible_coprime: + "coprime a c" if "a * b mod c = 1" + by (rule coprimeI) (use that dvd_mod_iff [of _ c "a * b"] in auto) + end @@ -772,6 +785,18 @@ end +lemma coprime_Suc_0_left [simp]: + "coprime (Suc 0) n" + using coprime_1_left [of n] by simp + +lemma coprime_Suc_0_right [simp]: + "coprime n (Suc 0)" + using coprime_1_right [of n] by simp + +lemma coprime_common_divisor_nat: "coprime a b \ x dvd a \ x dvd b \ x = 1" + for a b :: nat + by (drule coprime_common_divisor [of _ _ x]) simp_all + instantiation nat :: unique_euclidean_semiring begin @@ -1422,6 +1447,64 @@ end +lemma coprime_int_iff [simp]: + "coprime (int m) (int n) \ coprime m n" (is "?P \ ?Q") +proof + assume ?P + show ?Q + proof (rule coprimeI) + fix q + assume "q dvd m" "q dvd n" + then have "int q dvd int m" "int q dvd int n" + by (simp_all add: zdvd_int) + with \?P\ have "is_unit (int q)" + by (rule coprime_common_divisor) + then show "is_unit q" + by simp + qed +next + assume ?Q + show ?P + proof (rule coprimeI) + fix k + assume "k dvd int m" "k dvd int n" + then have "nat \k\ dvd m" "nat \k\ dvd n" + by (simp_all add: zdvd_int) + with \?Q\ have "is_unit (nat \k\)" + by (rule coprime_common_divisor) + then show "is_unit k" + by simp + qed +qed + +lemma coprime_abs_left_iff [simp]: + "coprime \k\ l \ coprime k l" for k l :: int + using coprime_normalize_left_iff [of k l] by simp + +lemma coprime_abs_right_iff [simp]: + "coprime k \l\ \ coprime k l" for k l :: int + using coprime_abs_left_iff [of l k] by (simp add: ac_simps) + +lemma coprime_nat_abs_left_iff [simp]: + "coprime (nat \k\) n \ coprime k (int n)" +proof - + define m where "m = nat \k\" + then have "\k\ = int m" + by simp + moreover have "coprime k (int n) \ coprime \k\ (int n)" + by simp + ultimately show ?thesis + by simp +qed + +lemma coprime_nat_abs_right_iff [simp]: + "coprime n (nat \k\) \ coprime (int n) k" + using coprime_nat_abs_left_iff [of k n] by (simp add: ac_simps) + +lemma coprime_common_divisor_int: "coprime a b \ x dvd a \ x dvd b \ \x\ = 1" + for a b :: int + by (drule coprime_common_divisor [of _ _ x]) simp_all + instantiation int :: idom_modulo begin diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/GCD.thy --- a/src/HOL/GCD.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/GCD.thy Sat Nov 11 18:41:08 2017 +0000 @@ -142,12 +142,6 @@ class gcd = zero + one + dvd + fixes gcd :: "'a \ 'a \ 'a" and lcm :: "'a \ 'a \ 'a" -begin - -abbreviation coprime :: "'a \ 'a \ bool" - where "coprime x y \ gcd x y = 1" - -end class Gcd = gcd + fixes Gcd :: "'a set \ 'a" @@ -243,7 +237,8 @@ by simp qed -lemma is_unit_gcd [simp]: "is_unit (gcd a b) \ coprime a b" +lemma is_unit_gcd_iff [simp]: + "is_unit (gcd a b) \ gcd a b = 1" by (cases "a = 0 \ b = 0") (auto simp add: unit_factor_gcd dest: is_unit_unit_factor) sublocale gcd: abel_semigroup gcd @@ -279,7 +274,7 @@ show "gcd (normalize a) b = gcd a b" for a b using gcd_dvd1 [of "normalize a" b] by (auto intro: associated_eqI) - show "coprime 1 a" for a + show "gcd 1 a = 1" for a by (rule associated_eqI) simp_all qed simp_all @@ -292,12 +287,6 @@ lemma gcd_right_idem: "gcd (gcd a b) b = gcd a b" by (fact gcd.right_idem) -lemma coprime_1_left: "coprime 1 a" - by (fact gcd.bottom_left_bottom) - -lemma coprime_1_right: "coprime a 1" - by (fact gcd.bottom_right_bottom) - lemma gcd_mult_left: "gcd (c * a) (c * b) = normalize c * gcd a b" proof (cases "c = 0") case True @@ -634,70 +623,6 @@ by (rule dvd_trans) qed -lemma coprime_dvd_mult: - assumes "coprime a b" and "a dvd c * b" - shows "a dvd c" -proof (cases "c = 0") - case True - then show ?thesis by simp -next - case False - then have unit: "is_unit (unit_factor c)" - by simp - from \coprime a b\ mult_gcd_left [of c a b] - have "gcd (c * a) (c * b) * unit_factor c = c" - by (simp add: ac_simps) - moreover from \a dvd c * b\ have "a dvd gcd (c * a) (c * b) * unit_factor c" - by (simp add: dvd_mult_unit_iff unit) - ultimately show ?thesis - by simp -qed - -lemma coprime_dvd_mult_iff: "coprime a c \ a dvd b * c \ a dvd b" - by (auto intro: coprime_dvd_mult) - -lemma gcd_mult_cancel: "coprime c b \ gcd (c * a) b = gcd a b" - apply (rule associated_eqI) - apply (rule gcd_greatest) - apply (rule_tac b = c in coprime_dvd_mult) - apply (simp add: gcd.assoc) - apply (simp_all add: ac_simps) - done - -lemma coprime_crossproduct: - fixes a b c d :: 'a - assumes "coprime a d" and "coprime b c" - shows "normalize a * normalize c = normalize b * normalize d \ - normalize a = normalize b \ normalize c = normalize d" - (is "?lhs \ ?rhs") -proof - assume ?rhs - then show ?lhs by simp -next - assume ?lhs - from \?lhs\ have "normalize a dvd normalize b * normalize d" - by (auto intro: dvdI dest: sym) - with \coprime a d\ have "a dvd b" - by (simp add: coprime_dvd_mult_iff normalize_mult [symmetric]) - from \?lhs\ have "normalize b dvd normalize a * normalize c" - by (auto intro: dvdI dest: sym) - with \coprime b c\ have "b dvd a" - by (simp add: coprime_dvd_mult_iff normalize_mult [symmetric]) - from \?lhs\ have "normalize c dvd normalize d * normalize b" - by (auto intro: dvdI dest: sym simp add: mult.commute) - with \coprime b c\ have "c dvd d" - by (simp add: coprime_dvd_mult_iff gcd.commute normalize_mult [symmetric]) - from \?lhs\ have "normalize d dvd normalize c * normalize a" - by (auto intro: dvdI dest: sym simp add: mult.commute) - with \coprime a d\ have "d dvd c" - by (simp add: coprime_dvd_mult_iff gcd.commute normalize_mult [symmetric]) - from \a dvd b\ \b dvd a\ have "normalize a = normalize b" - by (rule associatedI) - moreover from \c dvd d\ \d dvd c\ have "normalize c = normalize d" - by (rule associatedI) - ultimately show ?rhs .. -qed - lemma gcd_add1 [simp]: "gcd (m + n) n = gcd m n" by (rule gcdI [symmetric]) (simp_all add: dvd_add_left_iff) @@ -707,285 +632,6 @@ lemma gcd_add_mult: "gcd m (k * m + n) = gcd m n" by (rule gcdI [symmetric]) (simp_all add: dvd_add_right_iff) -lemma coprimeI: "(\l. l dvd a \ l dvd b \ l dvd 1) \ gcd a b = 1" - by (rule sym, rule gcdI) simp_all - -lemma coprime: "gcd a b = 1 \ (\d. d dvd a \ d dvd b \ is_unit d)" - by (auto intro: coprimeI gcd_greatest dvd_gcdD1 dvd_gcdD2) - -lemma div_gcd_coprime: - assumes nz: "a \ 0 \ b \ 0" - shows "coprime (a div gcd a b) (b div gcd a b)" -proof - - let ?g = "gcd a b" - let ?a' = "a div ?g" - let ?b' = "b div ?g" - let ?g' = "gcd ?a' ?b'" - have dvdg: "?g dvd a" "?g dvd b" - by simp_all - have dvdg': "?g' dvd ?a'" "?g' dvd ?b'" - by simp_all - from dvdg dvdg' obtain ka kb ka' kb' where - kab: "a = ?g * ka" "b = ?g * kb" "?a' = ?g' * ka'" "?b' = ?g' * kb'" - unfolding dvd_def by blast - from this [symmetric] have "?g * ?a' = (?g * ?g') * ka'" "?g * ?b' = (?g * ?g') * kb'" - by (simp_all add: mult.assoc mult.left_commute [of "gcd a b"]) - then have dvdgg':"?g * ?g' dvd a" "?g* ?g' dvd b" - by (auto simp add: dvd_mult_div_cancel [OF dvdg(1)] dvd_mult_div_cancel [OF dvdg(2)] dvd_def) - have "?g \ 0" - using nz by simp - moreover from gcd_greatest [OF dvdgg'] have "?g * ?g' dvd ?g" . - ultimately show ?thesis - using dvd_times_left_cancel_iff [of "gcd a b" _ 1] by simp -qed - -lemma divides_mult: - assumes "a dvd c" and nr: "b dvd c" and "coprime a b" - shows "a * b dvd c" -proof - - from \b dvd c\ obtain b' where"c = b * b'" .. - with \a dvd c\ have "a dvd b' * b" - by (simp add: ac_simps) - with \coprime a b\ have "a dvd b'" - by (simp add: coprime_dvd_mult_iff) - then obtain a' where "b' = a * a'" .. - with \c = b * b'\ have "c = (a * b) * a'" - by (simp add: ac_simps) - then show ?thesis .. -qed - -lemma coprime_lmult: - assumes dab: "gcd d (a * b) = 1" - shows "gcd d a = 1" -proof (rule coprimeI) - fix l - assume "l dvd d" and "l dvd a" - then have "l dvd a * b" - by simp - with \l dvd d\ and dab show "l dvd 1" - by (auto intro: gcd_greatest) -qed - -lemma coprime_rmult: - assumes dab: "gcd d (a * b) = 1" - shows "gcd d b = 1" -proof (rule coprimeI) - fix l - assume "l dvd d" and "l dvd b" - then have "l dvd a * b" - by simp - with \l dvd d\ and dab show "l dvd 1" - by (auto intro: gcd_greatest) -qed - -lemma coprime_mult: - assumes "coprime d a" - and "coprime d b" - shows "coprime d (a * b)" - apply (subst gcd.commute) - using assms(1) apply (subst gcd_mult_cancel) - apply (subst gcd.commute) - apply assumption - apply (subst gcd.commute) - apply (rule assms(2)) - done - -lemma coprime_mul_eq: "gcd d (a * b) = 1 \ gcd d a = 1 \ gcd d b = 1" - using coprime_rmult[of d a b] coprime_lmult[of d a b] coprime_mult[of d a b] - by blast - -lemma coprime_mul_eq': - "coprime (a * b) d \ coprime a d \ coprime b d" - using coprime_mul_eq [of d a b] by (simp add: gcd.commute) - -lemma gcd_coprime: - assumes c: "gcd a b \ 0" - and a: "a = a' * gcd a b" - and b: "b = b' * gcd a b" - shows "gcd a' b' = 1" -proof - - from c have "a \ 0 \ b \ 0" - by simp - with div_gcd_coprime have "gcd (a div gcd a b) (b div gcd a b) = 1" . - also from assms have "a div gcd a b = a'" - using dvd_div_eq_mult local.gcd_dvd1 by blast - also from assms have "b div gcd a b = b'" - using dvd_div_eq_mult local.gcd_dvd1 by blast - finally show ?thesis . -qed - -lemma coprime_power: - assumes "0 < n" - shows "gcd a (b ^ n) = 1 \ gcd a b = 1" - using assms -proof (induct n) - case 0 - then show ?case by simp -next - case (Suc n) - then show ?case - by (cases n) (simp_all add: coprime_mul_eq) -qed - -lemma gcd_coprime_exists: - assumes "gcd a b \ 0" - shows "\a' b'. a = a' * gcd a b \ b = b' * gcd a b \ gcd a' b' = 1" - apply (rule_tac x = "a div gcd a b" in exI) - apply (rule_tac x = "b div gcd a b" in exI) - using assms - apply (auto intro: div_gcd_coprime) - done - -lemma coprime_exp: "gcd d a = 1 \ gcd d (a^n) = 1" - by (induct n) (simp_all add: coprime_mult) - -lemma coprime_exp_left: "coprime a b \ coprime (a ^ n) b" - by (induct n) (simp_all add: gcd_mult_cancel) - -lemma coprime_exp2: - assumes "coprime a b" - shows "coprime (a ^ n) (b ^ m)" -proof (rule coprime_exp_left) - from assms show "coprime a (b ^ m)" - by (induct m) (simp_all add: gcd_mult_cancel gcd.commute [of a]) -qed - -lemma gcd_exp: "gcd (a ^ n) (b ^ n) = gcd a b ^ n" -proof (cases "a = 0 \ b = 0") - case True - then show ?thesis - by (cases n) simp_all -next - case False - then have "1 = gcd ((a div gcd a b) ^ n) ((b div gcd a b) ^ n)" - using coprime_exp2[OF div_gcd_coprime[of a b], of n n, symmetric] by simp - then have "gcd a b ^ n = gcd a b ^ n * \" - by simp - also note gcd_mult_distrib - also have "unit_factor (gcd a b ^ n) = 1" - using False by (auto simp add: unit_factor_power unit_factor_gcd) - also have "(gcd a b)^n * (a div gcd a b)^n = a^n" - apply (subst ac_simps) - apply (subst div_power) - apply simp - apply (rule dvd_div_mult_self) - apply (rule dvd_power_same) - apply simp - done - also have "(gcd a b)^n * (b div gcd a b)^n = b^n" - apply (subst ac_simps) - apply (subst div_power) - apply simp - apply (rule dvd_div_mult_self) - apply (rule dvd_power_same) - apply simp - done - finally show ?thesis by simp -qed - -lemma coprime_common_divisor: "gcd a b = 1 \ a dvd a \ a dvd b \ is_unit a" - apply (subgoal_tac "a dvd gcd a b") - apply simp - apply (erule (1) gcd_greatest) - done - -lemma division_decomp: - assumes "a dvd b * c" - shows "\b' c'. a = b' * c' \ b' dvd b \ c' dvd c" -proof (cases "gcd a b = 0") - case True - then have "a = 0 \ b = 0" - by simp - then have "a = 0 * c \ 0 dvd b \ c dvd c" - by simp - then show ?thesis by blast -next - case False - let ?d = "gcd a b" - from gcd_coprime_exists [OF False] - obtain a' b' where ab': "a = a' * ?d" "b = b' * ?d" "gcd a' b' = 1" - by blast - from ab'(1) have "a' dvd a" - unfolding dvd_def by blast - with assms have "a' dvd b * c" - using dvd_trans [of a' a "b * c"] by simp - from assms ab'(1,2) have "a' * ?d dvd (b' * ?d) * c" - by simp - then have "?d * a' dvd ?d * (b' * c)" - by (simp add: mult_ac) - with \?d \ 0\ have "a' dvd b' * c" - by simp - with coprime_dvd_mult[OF ab'(3)] have "a' dvd c" - by (subst (asm) ac_simps) blast - with ab'(1) have "a = ?d * a' \ ?d dvd b \ a' dvd c" - by (simp add: mult_ac) - then show ?thesis by blast -qed - -lemma pow_divs_pow: - assumes ab: "a ^ n dvd b ^ n" and n: "n \ 0" - shows "a dvd b" -proof (cases "gcd a b = 0") - case True - then show ?thesis by simp -next - case False - let ?d = "gcd a b" - from n obtain m where m: "n = Suc m" - by (cases n) simp_all - from False have zn: "?d ^ n \ 0" - by (rule power_not_zero) - from gcd_coprime_exists [OF False] - obtain a' b' where ab': "a = a' * ?d" "b = b' * ?d" "gcd a' b' = 1" - by blast - from ab have "(a' * ?d) ^ n dvd (b' * ?d) ^ n" - by (simp add: ab'(1,2)[symmetric]) - then have "?d^n * a'^n dvd ?d^n * b'^n" - by (simp only: power_mult_distrib ac_simps) - with zn have "a'^n dvd b'^n" - by simp - then have "a' dvd b'^n" - using dvd_trans[of a' "a'^n" "b'^n"] by (simp add: m) - then have "a' dvd b'^m * b'" - by (simp add: m ac_simps) - with coprime_dvd_mult[OF coprime_exp[OF ab'(3), of m]] - have "a' dvd b'" by (subst (asm) ac_simps) blast - then have "a' * ?d dvd b' * ?d" - by (rule mult_dvd_mono) simp - with ab'(1,2) show ?thesis - by simp -qed - -lemma pow_divs_eq [simp]: "n \ 0 \ a ^ n dvd b ^ n \ a dvd b" - by (auto intro: pow_divs_pow dvd_power_same) - -lemma coprime_plus_one [simp]: "gcd (n + 1) n = 1" - by (subst add_commute) simp - -lemma prod_coprime [rule_format]: "(\i\A. gcd (f i) a = 1) \ gcd (\i\A. f i) a = 1" - by (induct A rule: infinite_finite_induct) (auto simp add: gcd_mult_cancel) - -lemma prod_list_coprime: "(\x. x \ set xs \ coprime x y) \ coprime (prod_list xs) y" - by (induct xs) (simp_all add: gcd_mult_cancel) - -lemma coprime_divisors: - assumes "d dvd a" "e dvd b" "gcd a b = 1" - shows "gcd d e = 1" -proof - - from assms obtain k l where "a = d * k" "b = e * l" - unfolding dvd_def by blast - with assms have "gcd (d * k) (e * l) = 1" - by simp - then have "gcd (d * k) e = 1" - by (rule coprime_lmult) - also have "gcd (d * k) e = gcd e (d * k)" - by (simp add: ac_simps) - finally have "gcd e d = 1" - by (rule coprime_lmult) - then show ?thesis - by (simp add: ac_simps) -qed - lemma lcm_gcd_prod: "lcm a b * gcd a b = normalize (a * b)" by (simp add: lcm_gcd) @@ -1006,9 +652,6 @@ "a dvd d \ b dvd d \ normalize d = d \ (\e. a dvd e \ b dvd e \ d dvd e) \ d = lcm a b" by rule (auto intro: lcmI simp: lcm_least lcm_eq_0_iff) -lemma lcm_coprime: "gcd a b = 1 \ lcm a b = normalize (a * b)" - by (subst lcm_gcd) simp - lemma lcm_proj1_if_dvd: "b dvd a \ lcm a b = normalize a" apply (cases "a = 0") apply simp @@ -1058,7 +701,7 @@ qed lemma dvd_productE: - assumes "p dvd (a * b)" + assumes "p dvd a * b" obtains x y where "p = x * y" "x dvd a" "y dvd b" proof (cases "a = 0") case True @@ -1076,32 +719,11 @@ ultimately show ?thesis by (rule that) qed -lemma coprime_crossproduct': - fixes a b c d - assumes "b \ 0" - assumes unit_factors: "unit_factor b = unit_factor d" - assumes coprime: "coprime a b" "coprime c d" - shows "a * d = b * c \ a = c \ b = d" -proof safe - assume eq: "a * d = b * c" - hence "normalize a * normalize d = normalize c * normalize b" - by (simp only: normalize_mult [symmetric] mult_ac) - with coprime have "normalize b = normalize d" - by (subst (asm) coprime_crossproduct) simp_all - from this and unit_factors show "b = d" - by (rule normalize_unit_factor_eqI) - from eq have "a * d = c * d" by (simp only: \b = d\ mult_ac) - with \b \ 0\ \b = d\ show "a = c" by simp -qed (simp_all add: mult_ac) - end class ring_gcd = comm_ring_1 + semiring_gcd begin -lemma coprime_minus_one: "coprime (n - 1) n" - using coprime_plus_one[of "n - 1"] by (simp add: gcd.commute) - lemma gcd_neg1 [simp]: "gcd (-a) b = gcd a b" by (rule sym, rule gcdI) (simp_all add: gcd_greatest) @@ -1471,36 +1093,6 @@ lemma Lcm_2 [simp]: "Lcm {a, b} = lcm a b" by simp -lemma Lcm_coprime: - assumes "finite A" - and "A \ {}" - and "\a b. a \ A \ b \ A \ a \ b \ gcd a b = 1" - shows "Lcm A = normalize (\A)" - using assms -proof (induct rule: finite_ne_induct) - case singleton - then show ?case by simp -next - case (insert a A) - have "Lcm (insert a A) = lcm a (Lcm A)" - by simp - also from insert have "Lcm A = normalize (\A)" - by blast - also have "lcm a \ = lcm a (\A)" - by (cases "\A = 0") (simp_all add: lcm_div_unit2) - also from insert have "gcd a (\A) = 1" - by (subst gcd.commute, intro prod_coprime) auto - with insert have "lcm a (\A) = normalize (\(insert a A))" - by (simp add: lcm_coprime) - finally show ?case . -qed - -lemma Lcm_coprime': - "card A \ 0 \ - (\a b. a \ A \ b \ A \ a \ b \ gcd a b = 1) \ - Lcm A = normalize (\A)" - by (rule Lcm_coprime) (simp_all add: card_eq_0_iff) - lemma Gcd_1: "1 \ A \ Gcd A = 1" by (auto intro!: Gcd_eq_1_I) @@ -1677,6 +1269,465 @@ end + +subsection \Coprimality\ + +context semiring_gcd +begin + +lemma coprime_imp_gcd_eq_1 [simp]: + "gcd a b = 1" if "coprime a b" +proof - + define t r s where "t = gcd a b" and "r = a div t" and "s = b div t" + then have "a = t * r" and "b = t * s" + by simp_all + with that have "coprime (t * r) (t * s)" + by simp + then show ?thesis + by (simp add: t_def) +qed + +lemma gcd_eq_1_imp_coprime: + "coprime a b" if "gcd a b = 1" +proof (rule coprimeI) + fix c + assume "c dvd a" and "c dvd b" + then have "c dvd gcd a b" + by (rule gcd_greatest) + with that show "is_unit c" + by simp +qed + +lemma coprime_iff_gcd_eq_1 [presburger, code]: + "coprime a b \ gcd a b = 1" + by rule (simp_all add: gcd_eq_1_imp_coprime) + +lemma is_unit_gcd [simp]: + "is_unit (gcd a b) \ coprime a b" + by (simp add: coprime_iff_gcd_eq_1) + +lemma coprime_add_one_left [simp]: "coprime (a + 1) a" + by (simp add: gcd_eq_1_imp_coprime ac_simps) + +lemma coprime_add_one_right [simp]: "coprime a (a + 1)" + using coprime_add_one_left [of a] by (simp add: ac_simps) + +lemma coprime_mult_left_iff [simp]: + "coprime (a * b) c \ coprime a c \ coprime b c" +proof + assume "coprime (a * b) c" + with coprime_common_divisor [of "a * b" c] + have *: "is_unit d" if "d dvd a * b" and "d dvd c" for d + using that by blast + have "coprime a c" + by (rule coprimeI, rule *) simp_all + moreover have "coprime b c" + by (rule coprimeI, rule *) simp_all + ultimately show "coprime a c \ coprime b c" .. +next + assume "coprime a c \ coprime b c" + then have "coprime a c" "coprime b c" + by simp_all + show "coprime (a * b) c" + proof (rule coprimeI) + fix d + assume "d dvd a * b" + then obtain r s where d: "d = r * s" "r dvd a" "s dvd b" + by (rule dvd_productE) + assume "d dvd c" + with d have "r * s dvd c" + by simp + then have "r dvd c" "s dvd c" + by (auto intro: dvd_mult_left dvd_mult_right) + from \coprime a c\ \r dvd a\ \r dvd c\ + have "is_unit r" + by (rule coprime_common_divisor) + moreover from \coprime b c\ \s dvd b\ \s dvd c\ + have "is_unit s" + by (rule coprime_common_divisor) + ultimately show "is_unit d" + by (simp add: d is_unit_mult_iff) + qed +qed + +lemma coprime_mult_right_iff [simp]: + "coprime c (a * b) \ coprime c a \ coprime c b" + using coprime_mult_left_iff [of a b c] by (simp add: ac_simps) + +lemma coprime_power_left_iff [simp]: + "coprime (a ^ n) b \ coprime a b \ n = 0" +proof (cases "n = 0") + case True + then show ?thesis + by simp +next + case False + then have "n > 0" + by simp + then show ?thesis + by (induction n rule: nat_induct_non_zero) simp_all +qed + +lemma coprime_power_right_iff [simp]: + "coprime a (b ^ n) \ coprime a b \ n = 0" + using coprime_power_left_iff [of b n a] by (simp add: ac_simps) + +lemma prod_coprime_left: + "coprime (\i\A. f i) a" if "\i. i \ A \ coprime (f i) a" + using that by (induct A rule: infinite_finite_induct) simp_all + +lemma prod_coprime_right: + "coprime a (\i\A. f i)" if "\i. i \ A \ coprime a (f i)" + using that prod_coprime_left [of A f a] by (simp add: ac_simps) + +lemma prod_list_coprime_left: + "coprime (prod_list xs) a" if "\x. x \ set xs \ coprime x a" + using that by (induct xs) simp_all + +lemma prod_list_coprime_right: + "coprime a (prod_list xs)" if "\x. x \ set xs \ coprime a x" + using that prod_list_coprime_left [of xs a] by (simp add: ac_simps) + +lemma coprime_dvd_mult_left_iff: + "a dvd b * c \ a dvd b" if "coprime a c" +proof + assume "a dvd b" + then show "a dvd b * c" + by simp +next + assume "a dvd b * c" + show "a dvd b" + proof (cases "b = 0") + case True + then show ?thesis + by simp + next + case False + then have unit: "is_unit (unit_factor b)" + by simp + from \coprime a c\ mult_gcd_left [of b a c] + have "gcd (b * a) (b * c) * unit_factor b = b" + by (simp add: ac_simps) + moreover from \a dvd b * c\ + have "a dvd gcd (b * a) (b * c) * unit_factor b" + by (simp add: dvd_mult_unit_iff unit) + ultimately show ?thesis + by simp + qed +qed + +lemma coprime_dvd_mult_right_iff: + "a dvd c * b \ a dvd b" if "coprime a c" + using that coprime_dvd_mult_left_iff [of a c b] by (simp add: ac_simps) + +lemma divides_mult: + "a * b dvd c" if "a dvd c" and "b dvd c" and "coprime a b" +proof - + from \b dvd c\ obtain b' where "c = b * b'" .. + with \a dvd c\ have "a dvd b' * b" + by (simp add: ac_simps) + with \coprime a b\ have "a dvd b'" + by (simp add: coprime_dvd_mult_left_iff) + then obtain a' where "b' = a * a'" .. + with \c = b * b'\ have "c = (a * b) * a'" + by (simp add: ac_simps) + then show ?thesis .. +qed + +lemma div_gcd_coprime: + assumes "a \ 0 \ b \ 0" + shows "coprime (a div gcd a b) (b div gcd a b)" +proof - + let ?g = "gcd a b" + let ?a' = "a div ?g" + let ?b' = "b div ?g" + let ?g' = "gcd ?a' ?b'" + have dvdg: "?g dvd a" "?g dvd b" + by simp_all + have dvdg': "?g' dvd ?a'" "?g' dvd ?b'" + by simp_all + from dvdg dvdg' obtain ka kb ka' kb' where + kab: "a = ?g * ka" "b = ?g * kb" "?a' = ?g' * ka'" "?b' = ?g' * kb'" + unfolding dvd_def by blast + from this [symmetric] have "?g * ?a' = (?g * ?g') * ka'" "?g * ?b' = (?g * ?g') * kb'" + by (simp_all add: mult.assoc mult.left_commute [of "gcd a b"]) + then have dvdgg':"?g * ?g' dvd a" "?g* ?g' dvd b" + by (auto simp add: dvd_mult_div_cancel [OF dvdg(1)] dvd_mult_div_cancel [OF dvdg(2)] dvd_def) + have "?g \ 0" + using assms by simp + moreover from gcd_greatest [OF dvdgg'] have "?g * ?g' dvd ?g" . + ultimately show ?thesis + using dvd_times_left_cancel_iff [of "gcd a b" _ 1] + by simp (simp only: coprime_iff_gcd_eq_1) +qed + +lemma gcd_coprime: + assumes c: "gcd a b \ 0" + and a: "a = a' * gcd a b" + and b: "b = b' * gcd a b" + shows "coprime a' b'" +proof - + from c have "a \ 0 \ b \ 0" + by simp + with div_gcd_coprime have "coprime (a div gcd a b) (b div gcd a b)" . + also from assms have "a div gcd a b = a'" + using dvd_div_eq_mult local.gcd_dvd1 by blast + also from assms have "b div gcd a b = b'" + using dvd_div_eq_mult local.gcd_dvd1 by blast + finally show ?thesis . +qed + +lemma gcd_coprime_exists: + assumes "gcd a b \ 0" + shows "\a' b'. a = a' * gcd a b \ b = b' * gcd a b \ coprime a' b'" + apply (rule_tac x = "a div gcd a b" in exI) + apply (rule_tac x = "b div gcd a b" in exI) + using assms + apply (auto intro: div_gcd_coprime) + done + +lemma pow_divides_pow_iff [simp]: + "a ^ n dvd b ^ n \ a dvd b" if "n > 0" +proof (cases "gcd a b = 0") + case True + then show ?thesis + by simp +next + case False + show ?thesis + proof + let ?d = "gcd a b" + from \n > 0\ obtain m where m: "n = Suc m" + by (cases n) simp_all + from False have zn: "?d ^ n \ 0" + by (rule power_not_zero) + from gcd_coprime_exists [OF False] + obtain a' b' where ab': "a = a' * ?d" "b = b' * ?d" "coprime a' b'" + by blast + assume "a ^ n dvd b ^ n" + then have "(a' * ?d) ^ n dvd (b' * ?d) ^ n" + by (simp add: ab'(1,2)[symmetric]) + then have "?d^n * a'^n dvd ?d^n * b'^n" + by (simp only: power_mult_distrib ac_simps) + with zn have "a' ^ n dvd b' ^ n" + by simp + then have "a' dvd b' ^ n" + using dvd_trans[of a' "a'^n" "b'^n"] by (simp add: m) + then have "a' dvd b' ^ m * b'" + by (simp add: m ac_simps) + moreover have "coprime a' (b' ^ n)" + using \coprime a' b'\ by simp + then have "a' dvd b'" + using \a' dvd b' ^ n\ coprime_dvd_mult_left_iff dvd_mult by blast + then have "a' * ?d dvd b' * ?d" + by (rule mult_dvd_mono) simp + with ab'(1,2) show "a dvd b" + by simp + next + assume "a dvd b" + with \n > 0\ show "a ^ n dvd b ^ n" + by (induction rule: nat_induct_non_zero) + (simp_all add: mult_dvd_mono) + qed +qed + +lemma coprime_crossproduct: + fixes a b c d :: 'a + assumes "coprime a d" and "coprime b c" + shows "normalize a * normalize c = normalize b * normalize d \ + normalize a = normalize b \ normalize c = normalize d" + (is "?lhs \ ?rhs") +proof + assume ?rhs + then show ?lhs by simp +next + assume ?lhs + from \?lhs\ have "normalize a dvd normalize b * normalize d" + by (auto intro: dvdI dest: sym) + with \coprime a d\ have "a dvd b" + by (simp add: coprime_dvd_mult_left_iff normalize_mult [symmetric]) + from \?lhs\ have "normalize b dvd normalize a * normalize c" + by (auto intro: dvdI dest: sym) + with \coprime b c\ have "b dvd a" + by (simp add: coprime_dvd_mult_left_iff normalize_mult [symmetric]) + from \?lhs\ have "normalize c dvd normalize d * normalize b" + by (auto intro: dvdI dest: sym simp add: mult.commute) + with \coprime b c\ have "c dvd d" + by (simp add: coprime_dvd_mult_left_iff coprime_commute normalize_mult [symmetric]) + from \?lhs\ have "normalize d dvd normalize c * normalize a" + by (auto intro: dvdI dest: sym simp add: mult.commute) + with \coprime a d\ have "d dvd c" + by (simp add: coprime_dvd_mult_left_iff coprime_commute normalize_mult [symmetric]) + from \a dvd b\ \b dvd a\ have "normalize a = normalize b" + by (rule associatedI) + moreover from \c dvd d\ \d dvd c\ have "normalize c = normalize d" + by (rule associatedI) + ultimately show ?rhs .. +qed + +lemma coprime_crossproduct': + fixes a b c d + assumes "b \ 0" + assumes unit_factors: "unit_factor b = unit_factor d" + assumes coprime: "coprime a b" "coprime c d" + shows "a * d = b * c \ a = c \ b = d" +proof safe + assume eq: "a * d = b * c" + hence "normalize a * normalize d = normalize c * normalize b" + by (simp only: normalize_mult [symmetric] mult_ac) + with coprime have "normalize b = normalize d" + by (subst (asm) coprime_crossproduct) simp_all + from this and unit_factors show "b = d" + by (rule normalize_unit_factor_eqI) + from eq have "a * d = c * d" by (simp only: \b = d\ mult_ac) + with \b \ 0\ \b = d\ show "a = c" by simp +qed (simp_all add: mult_ac) + +lemma gcd_mult_left_left_cancel: + "gcd (c * a) b = gcd a b" if "coprime b c" +proof - + have "coprime (gcd b (a * c)) c" + by (rule coprimeI) (auto intro: that coprime_common_divisor) + then have "gcd b (a * c) dvd a" + using coprime_dvd_mult_left_iff [of "gcd b (a * c)" c a] + by simp + then show ?thesis + by (auto intro: associated_eqI simp add: ac_simps) +qed + +lemma gcd_mult_left_right_cancel: + "gcd (a * c) b = gcd a b" if "coprime b c" + using that gcd_mult_left_left_cancel [of b c a] + by (simp add: ac_simps) + +lemma gcd_mult_right_left_cancel: + "gcd a (c * b) = gcd a b" if "coprime a c" + using that gcd_mult_left_left_cancel [of a c b] + by (simp add: ac_simps) + +lemma gcd_mult_right_right_cancel: + "gcd a (b * c) = gcd a b" if "coprime a c" + using that gcd_mult_right_left_cancel [of a c b] + by (simp add: ac_simps) + +lemma gcd_exp [simp]: + "gcd (a ^ n) (b ^ n) = gcd a b ^ n" +proof (cases "a = 0 \ b = 0 \ n = 0") + case True + then show ?thesis + by (cases n) simp_all +next + case False + then have "coprime (a div gcd a b) (b div gcd a b)" and "n > 0" + by (auto intro: div_gcd_coprime) + then have "coprime ((a div gcd a b) ^ n) ((b div gcd a b) ^ n)" + by simp + then have "1 = gcd ((a div gcd a b) ^ n) ((b div gcd a b) ^ n)" + by simp + then have "gcd a b ^ n = gcd a b ^ n * \" + by simp + also note gcd_mult_distrib + also have "unit_factor (gcd a b ^ n) = 1" + using False by (auto simp add: unit_factor_power unit_factor_gcd) + also have "(gcd a b) ^ n * (a div gcd a b) ^ n = a ^ n" + by (simp add: ac_simps div_power dvd_power_same) + also have "(gcd a b) ^ n * (b div gcd a b) ^ n = b ^ n" + by (simp add: ac_simps div_power dvd_power_same) + finally show ?thesis by simp +qed + +lemma division_decomp: + assumes "a dvd b * c" + shows "\b' c'. a = b' * c' \ b' dvd b \ c' dvd c" +proof (cases "gcd a b = 0") + case True + then have "a = 0 \ b = 0" + by simp + then have "a = 0 * c \ 0 dvd b \ c dvd c" + by simp + then show ?thesis by blast +next + case False + let ?d = "gcd a b" + from gcd_coprime_exists [OF False] + obtain a' b' where ab': "a = a' * ?d" "b = b' * ?d" "coprime a' b'" + by blast + from ab'(1) have "a' dvd a" .. + with assms have "a' dvd b * c" + using dvd_trans [of a' a "b * c"] by simp + from assms ab'(1,2) have "a' * ?d dvd (b' * ?d) * c" + by simp + then have "?d * a' dvd ?d * (b' * c)" + by (simp add: mult_ac) + with \?d \ 0\ have "a' dvd b' * c" + by simp + then have "a' dvd c" + using \coprime a' b'\ by (simp add: coprime_dvd_mult_right_iff) + with ab'(1) have "a = ?d * a' \ ?d dvd b \ a' dvd c" + by (simp add: ac_simps) + then show ?thesis by blast +qed + +lemma lcm_coprime: "coprime a b \ lcm a b = normalize (a * b)" + by (subst lcm_gcd) simp + +end + +context ring_gcd +begin + +lemma coprime_minus_left_iff [simp]: + "coprime (- a) b \ coprime a b" + by (rule; rule coprimeI) (auto intro: coprime_common_divisor) + +lemma coprime_minus_right_iff [simp]: + "coprime a (- b) \ coprime a b" + using coprime_minus_left_iff [of b a] by (simp add: ac_simps) + +lemma coprime_diff_one_left [simp]: "coprime (a - 1) a" + using coprime_add_one_right [of "a - 1"] by simp + +lemma coprime_doff_one_right [simp]: "coprime a (a - 1)" + using coprime_diff_one_left [of a] by (simp add: ac_simps) + +end + +context semiring_Gcd +begin + +lemma Lcm_coprime: + assumes "finite A" + and "A \ {}" + and "\a b. a \ A \ b \ A \ a \ b \ coprime a b" + shows "Lcm A = normalize (\A)" + using assms +proof (induct rule: finite_ne_induct) + case singleton + then show ?case by simp +next + case (insert a A) + have "Lcm (insert a A) = lcm a (Lcm A)" + by simp + also from insert have "Lcm A = normalize (\A)" + by blast + also have "lcm a \ = lcm a (\A)" + by (cases "\A = 0") (simp_all add: lcm_div_unit2) + also from insert have "coprime a (\A)" + by (subst coprime_commute, intro prod_coprime_left) auto + with insert have "lcm a (\A) = normalize (\(insert a A))" + by (simp add: lcm_coprime) + finally show ?case . +qed + +lemma Lcm_coprime': + "card A \ 0 \ + (\a b. a \ A \ b \ A \ a \ b \ coprime a b) \ + Lcm A = normalize (\A)" + by (rule Lcm_coprime) (simp_all add: card_eq_0_iff) + +end + + subsection \GCD and LCM on @{typ nat} and @{typ int}\ instantiation nat :: gcd @@ -1716,9 +1767,6 @@ apply simp_all done - -text \Specific to \int\.\ - lemma gcd_eq_int_iff: "gcd k l = int n \ gcd (nat \k\) (nat \l\) = n" by (simp add: gcd_int_def) @@ -1949,19 +1997,6 @@ for k m n :: int by (simp add: gcd_int_def abs_mult nat_mult_distrib gcd_mult_distrib_nat [symmetric]) -lemma coprime_crossproduct_nat: - fixes a b c d :: nat - assumes "coprime a d" and "coprime b c" - shows "a * c = b * d \ a = b \ c = d" - using assms coprime_crossproduct [of a d b c] by simp - -lemma coprime_crossproduct_int: - fixes a b c d :: int - assumes "coprime a d" and "coprime b c" - shows "\a\ * \c\ = \b\ * \d\ \ \a\ = \b\ \ \c\ = \d\" - using assms coprime_crossproduct [of a d b c] by simp - - text \\medskip Addition laws.\ (* TODO: add the other variations? *) @@ -2064,53 +2099,33 @@ for k l :: int by (simp add: gcd_int_def nat_mod_distrib gcd_non_0_nat) - -subsection \Coprimality\ - -lemma coprime_nat: "coprime a b \ (\d. d dvd a \ d dvd b \ d = 1)" - for a b :: nat - using coprime [of a b] by simp - -lemma coprime_Suc_0_nat: "coprime a b \ (\d. d dvd a \ d dvd b \ d = Suc 0)" - for a b :: nat - using coprime_nat by simp - -lemma coprime_int: "coprime a b \ (\d. d \ 0 \ d dvd a \ d dvd b \ d = 1)" - for a b :: int - using gcd_unique_int [of 1 a b] - apply clarsimp - apply (erule subst) - apply (rule iffI) - apply force - using abs_dvd_iff abs_ge_zero apply blast - done - -lemma pow_divides_eq_nat [simp]: "n > 0 \ a^n dvd b^n \ a dvd b" - for a b n :: nat - using pow_divs_eq[of n] by simp - -lemma coprime_Suc_nat [simp]: "coprime (Suc n) n" - using coprime_plus_one[of n] by simp - -lemma coprime_minus_one_nat: "n \ 0 \ coprime (n - 1) n" - for n :: nat - using coprime_Suc_nat [of "n - 1"] gcd.commute [of "n - 1" n] by auto - -lemma coprime_common_divisor_nat: "coprime a b \ x dvd a \ x dvd b \ x = 1" - for a b :: nat - by (metis gcd_greatest_iff nat_dvd_1_iff_1) - -lemma coprime_common_divisor_int: "coprime a b \ x dvd a \ x dvd b \ \x\ = 1" - for a b :: int - using gcd_greatest_iff [of x a b] by auto - -lemma invertible_coprime_nat: "x * y mod m = 1 \ coprime x m" - for m x y :: nat - by (metis coprime_lmult gcd_1_nat gcd.commute gcd_red_nat) - -lemma invertible_coprime_int: "x * y mod m = 1 \ coprime x m" - for m x y :: int - by (metis coprime_lmult gcd_1_int gcd.commute gcd_red_int) +lemma coprime_Suc_left_nat [simp]: + "coprime (Suc n) n" + using coprime_add_one_left [of n] by simp + +lemma coprime_Suc_right_nat [simp]: + "coprime n (Suc n)" + using coprime_Suc_left_nat [of n] by (simp add: ac_simps) + +lemma coprime_diff_one_left_nat [simp]: + "coprime (n - 1) n" if "n > 0" for n :: nat + using that coprime_Suc_right_nat [of "n - 1"] by simp + +lemma coprime_diff_one_right_nat [simp]: + "coprime n (n - 1)" if "n > 0" for n :: nat + using that coprime_diff_one_left_nat [of n] by (simp add: ac_simps) + +lemma coprime_crossproduct_nat: + fixes a b c d :: nat + assumes "coprime a d" and "coprime b c" + shows "a * c = b * d \ a = b \ c = d" + using assms coprime_crossproduct [of a d b c] by simp + +lemma coprime_crossproduct_int: + fixes a b c d :: int + assumes "coprime a d" and "coprime b c" + shows "\a\ * \c\ = \b\ * \d\ \ \a\ = \b\ \ \c\ = \d\" + using assms coprime_crossproduct [of a d b c] by simp subsection \Bezout's theorem\ @@ -2742,14 +2757,6 @@ for i m n :: int by (fact dvd_lcmI2) -lemma coprime_exp2_nat [intro]: "coprime a b \ coprime (a^n) (b^m)" - for a b :: nat - by (fact coprime_exp2) - -lemma coprime_exp2_int [intro]: "coprime a b \ coprime (a^n) (b^m)" - for a b :: int - by (fact coprime_exp2) - lemmas Gcd_dvd_nat [simp] = Gcd_dvd [where ?'a = nat] lemmas Gcd_dvd_int [simp] = Gcd_dvd [where ?'a = int] lemmas Gcd_greatest_nat [simp] = Gcd_greatest [where ?'a = nat] diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Isar_Examples/Fibonacci.thy --- a/src/HOL/Isar_Examples/Fibonacci.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Isar_Examples/Fibonacci.thy Sat Nov 11 18:41:08 2017 +0000 @@ -21,10 +21,6 @@ text_raw \\<^footnote>\Isar version by Gertrud Bauer. Original tactic script by Larry Paulson. A few proofs of laws taken from @{cite "Concrete-Math"}.\\ - -declare One_nat_def [simp] - - subsection \Fibonacci numbers\ fun fib :: "nat \ nat" @@ -65,12 +61,13 @@ finally show "?P (n + 2)" . qed -lemma gcd_fib_Suc_eq_1: "gcd (fib n) (fib (n + 1)) = 1" +lemma coprime_fib_Suc: "coprime (fib n) (fib (n + 1))" (is "?P n") proof (induct n rule: fib_induct) show "?P 0" by simp show "?P 1" by simp fix n + assume P: "coprime (fib (n + 1)) (fib (n + 1 + 1))" have "fib (n + 2 + 1) = fib (n + 1) + fib (n + 2)" by simp also have "\ = fib (n + 2) + fib (n + 1)" @@ -79,8 +76,10 @@ by (rule gcd_add2) also have "\ = gcd (fib (n + 1)) (fib (n + 1 + 1))" by (simp add: gcd.commute) - also assume "\ = 1" - finally show "?P (n + 2)" . + also have "\ = 1" + using P by simp + finally show "?P (n + 2)" + by (simp add: coprime_iff_gcd_eq_1) qed lemma gcd_mult_add: "(0::nat) < n \ gcd (n * k + m) n = gcd m n" @@ -106,7 +105,8 @@ also have "gcd \ (fib (k + 1)) = gcd (fib k * fib n) (fib (k + 1))" by (simp add: gcd_mult_add) also have "\ = gcd (fib n) (fib (k + 1))" - by (simp only: gcd_fib_Suc_eq_1 gcd_mult_cancel) + using coprime_fib_Suc [of k] gcd_mult_left_right_cancel [of "fib (k + 1)" "fib k" "fib n"] + by (simp add: ac_simps) also have "\ = gcd (fib m) (fib n)" using Suc by (simp add: gcd.commute) finally show ?thesis . diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Library/Multiset.thy --- a/src/HOL/Library/Multiset.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Library/Multiset.thy Sat Nov 11 18:41:08 2017 +0000 @@ -2155,6 +2155,42 @@ "image_mset f (replicate_mset n a) = replicate_mset n (f a)" by (induct n) simp_all +lemma replicate_mset_msubseteq_iff: + "replicate_mset m a \# replicate_mset n b \ m = 0 \ a = b \ m \ n" + by (cases m) + (auto simp add: insert_subset_eq_iff count_le_replicate_mset_subset_eq [symmetric]) + +lemma msubseteq_replicate_msetE: + assumes "A \# replicate_mset n a" + obtains m where "m \ n" and "A = replicate_mset m a" +proof (cases "n = 0") + case True + with assms that show thesis + by simp +next + case False + from assms have "set_mset A \ set_mset (replicate_mset n a)" + by (rule set_mset_mono) + with False have "set_mset A \ {a}" + by simp + then have "\m. A = replicate_mset m a" + proof (induction A) + case empty + then show ?case + by simp + next + case (add b A) + then obtain m where "A = replicate_mset m a" + by auto + with add.prems show ?case + by (auto intro: exI [of _ "Suc m"]) + qed + then obtain m where A: "A = replicate_mset m a" .. + with assms have "m \ n" + by (auto simp add: replicate_mset_msubseteq_iff) + then show thesis using A .. +qed + subsection \Big operators\ diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Map.thy --- a/src/HOL/Map.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Map.thy Sat Nov 11 18:41:08 2017 +0000 @@ -782,6 +782,20 @@ with * \x = (k, v)\ show ?case by simp qed +lemma eq_key_imp_eq_value: + "v1 = v2" + if "distinct (map fst xs)" "(k, v1) \ set xs" "(k, v2) \ set xs" +proof - + from that have "inj_on fst (set xs)" + by (simp add: distinct_map) + moreover have "fst (k, v1) = fst (k, v2)" + by simp + ultimately have "(k, v1) = (k, v2)" + by (rule inj_onD) (fact that)+ + then show ?thesis + by simp +qed + lemma map_of_inject_set: assumes distinct: "distinct (map fst xs)" "distinct (map fst ys)" shows "map_of xs = map_of ys \ set xs = set ys" (is "?lhs \ ?rhs") diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Nitpick.thy --- a/src/HOL/Nitpick.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Nitpick.thy Sat Nov 11 18:41:08 2017 +0000 @@ -137,7 +137,7 @@ by (simp only: lcm_nat_def Nitpick.nat_lcm_def gcd_eq_nitpick_gcd) definition Frac :: "int \ int \ bool" where - "Frac \ \(a, b). b > 0 \ gcd a b = 1" + "Frac \ \(a, b). b > 0 \ coprime a b" consts Abs_Frac :: "int \ int \ 'a" diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Cong.thy --- a/src/HOL/Number_Theory/Cong.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Cong.thy Sat Nov 11 18:41:08 2017 +0000 @@ -229,7 +229,8 @@ lemma cong_mult_rcancel_int: "[a * k = b * k] (mod m) \ [a = b] (mod m)" if "coprime k m" for a k m :: int - by (metis that cong_altdef_int left_diff_distrib coprime_dvd_mult_iff gcd.commute) + using that by (simp add: cong_altdef_int) + (metis coprime_commute coprime_dvd_mult_right_iff mult.commute right_diff_distrib') lemma cong_mult_rcancel_nat: "[a * k = b * k] (mod m) \ [a = b] (mod m)" @@ -242,7 +243,7 @@ also have "\ \ m dvd nat \int a - int b\ * k" by (simp add: abs_mult nat_times_as_int) also have "\ \ m dvd nat \int a - int b\" - by (rule coprime_dvd_mult_iff) (use \coprime k m\ in \simp add: ac_simps\) + by (rule coprime_dvd_mult_left_iff) (use \coprime k m\ in \simp add: ac_simps\) also have "\ \ [a = b] (mod m)" by (simp add: cong_altdef_nat') finally show ?thesis . @@ -320,11 +321,11 @@ lemma cong_imp_coprime_nat: "[a = b] (mod m) \ coprime a m \ coprime b m" for a b :: nat - by (auto simp add: cong_gcd_eq_nat) + by (auto simp add: cong_gcd_eq_nat coprime_iff_gcd_eq_1) lemma cong_imp_coprime_int: "[a = b] (mod m) \ coprime a m \ coprime b m" for a b :: int - by (auto simp add: cong_gcd_eq_int) + by (auto simp add: cong_gcd_eq_int coprime_iff_gcd_eq_1) lemma cong_cong_mod_nat: "[a = b] (mod m) \ [a mod m = b mod m] (mod m)" for a b :: nat @@ -490,36 +491,24 @@ qed lemma cong_solve_coprime_nat: - fixes a :: nat - assumes "coprime a n" - shows "\x. [a * x = 1] (mod n)" -proof (cases "a = 0") - case True - with assms show ?thesis - by (simp add: cong_0_1_nat') -next - case False - with assms show ?thesis - by (metis cong_solve_nat) -qed + "\x. [a * x = Suc 0] (mod n)" if "coprime a n" + using that cong_solve_nat [of a n] by (cases "a = 0") simp_all -lemma cong_solve_coprime_int: "coprime (a::int) n \ \x. [a * x = 1] (mod n)" - apply (cases "a = 0") - apply auto - apply (cases "n \ 0") - apply auto - apply (metis cong_solve_int) - done +lemma cong_solve_coprime_int: + "\x. [a * x = 1] (mod n)" if "coprime a n" for a n x :: int + using that cong_solve_int [of a n] by (cases "a = 0") + (auto simp add: zabs_def split: if_splits) lemma coprime_iff_invertible_nat: - "m > 0 \ coprime a m = (\x. [a * x = Suc 0] (mod m))" - by (metis One_nat_def cong_gcd_eq_nat cong_solve_coprime_nat coprime_lmult gcd.commute gcd_Suc_0) + "m > 0 \ coprime a m \ (\x. [a * x = Suc 0] (mod m))" + by (auto intro: cong_solve_coprime_nat) + (use cong_imp_coprime_nat cong_sym coprime_Suc_0_left coprime_mult_left_iff in blast) -lemma coprime_iff_invertible_int: "m > 0 \ coprime a m \ (\x. [a * x = 1] (mod m))" +lemma coprime_iff_invertible_int: + "m > 0 \ coprime a m \ (\x. [a * x = 1] (mod m))" for m :: int - apply (auto intro: cong_solve_coprime_int) - using cong_gcd_eq_int coprime_mul_eq' apply fastforce - done + by (auto intro: cong_solve_coprime_int) + (meson cong_imp_coprime_int cong_sym coprime_1_left coprime_mult_left_iff) lemma coprime_iff_invertible'_nat: "m > 0 \ coprime a m \ (\x. 0 \ x \ x < m \ [a * x = Suc 0] (mod m))" @@ -554,16 +543,16 @@ and "(\i\A. (\j\A. i \ j \ coprime (m i) (m j)))" using that apply (induct A rule: infinite_finite_induct) apply auto - apply (metis One_nat_def coprime_cong_mult_nat gcd.commute prod_coprime) + apply (metis coprime_cong_mult_nat prod_coprime_right) done -lemma cong_cong_prod_coprime_int [rule_format]: +lemma cong_cong_prod_coprime_int: "[x = y] (mod (\i\A. m i))" if "(\i\A. [(x::int) = y] (mod m i))" "(\i\A. (\j\A. i \ j \ coprime (m i) (m j)))" using that apply (induct A rule: infinite_finite_induct) - apply auto - apply (metis coprime_cong_mult_int gcd.commute prod_coprime) + apply auto + apply (metis coprime_cong_mult_int prod_coprime_right) done lemma binary_chinese_remainder_aux_nat: @@ -574,7 +563,7 @@ from cong_solve_coprime_nat [OF a] obtain x1 where 1: "[m1 * x1 = 1] (mod m2)" by auto from a have b: "coprime m2 m1" - by (subst gcd.commute) + by (simp add: ac_simps) from cong_solve_coprime_nat [OF b] obtain x2 where 2: "[m2 * x2 = 1] (mod m1)" by auto have "[m1 * x1 = 0] (mod m1)" @@ -593,7 +582,7 @@ from cong_solve_coprime_int [OF a] obtain x1 where 1: "[m1 * x1 = 1] (mod m2)" by auto from a have b: "coprime m2 m1" - by (subst gcd.commute) + by (simp add: ac_simps) from cong_solve_coprime_int [OF b] obtain x2 where 2: "[m2 * x2 = 1] (mod m1)" by auto have "[m1 * x1 = 0] (mod m1)" @@ -730,8 +719,8 @@ fix i assume "i \ A" with cop have "coprime (\j \ A - {i}. m j) (m i)" - by (intro prod_coprime) auto - then have "\x. [(\j \ A - {i}. m j) * x = 1] (mod m i)" + by (intro prod_coprime_left) auto + then have "\x. [(\j \ A - {i}. m j) * x = Suc 0] (mod m i)" by (elim cong_solve_coprime_nat) then obtain x where "[(\j \ A - {i}. m j) * x = 1] (mod m i)" by auto @@ -789,8 +778,8 @@ if "\i\A. (\j\A. i \ j \ coprime (m i) (m j))" and "\i\A. [x = y] (mod m i)" for x y :: nat using that apply (induct A rule: infinite_finite_induct) - apply auto - apply (metis One_nat_def coprime_cong_mult_nat gcd.commute prod_coprime) + apply auto + apply (metis coprime_cong_mult_nat prod_coprime_right) done lemma chinese_remainder_unique_nat: diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Euler_Criterion.thy --- a/src/HOL/Number_Theory/Euler_Criterion.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Euler_Criterion.thy Sat Nov 11 18:41:08 2017 +0000 @@ -65,7 +65,7 @@ proof - have "~ p dvd x" using assms zdvd_not_zless S1_def by auto hence co_xp: "coprime x p" using p_prime prime_imp_coprime_int[of p x] - by (simp add: gcd.commute) + by (simp add: ac_simps) then obtain y' where y': "[x * y' = 1] (mod p)" using cong_solve_coprime_int by blast moreover define y where "y = y' * a mod p" ultimately have "[x * y = a] (mod p)" using mod_mult_right_eq[of x "y' * a" p] diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Fib.thy --- a/src/HOL/Number_Theory/Fib.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Fib.thy Sat Nov 11 18:41:08 2017 +0000 @@ -87,17 +87,34 @@ lemma coprime_fib_Suc_nat: "coprime (fib n) (fib (Suc n))" apply (induct n rule: fib.induct) - apply auto - apply (metis gcd_add1 add.commute) + apply (simp_all add: coprime_iff_gcd_eq_1 algebra_simps) + apply (simp add: add.assoc [symmetric]) done -lemma gcd_fib_add: "gcd (fib m) (fib (n + m)) = gcd (fib m) (fib n)" - apply (simp add: gcd.commute [of "fib m"]) - apply (cases m) - apply (auto simp add: fib_add) - apply (metis gcd.commute mult.commute coprime_fib_Suc_nat - gcd_add_mult gcd_mult_cancel gcd.commute) - done +lemma gcd_fib_add: + "gcd (fib m) (fib (n + m)) = gcd (fib m) (fib n)" +proof (cases m) + case 0 + then show ?thesis + by simp +next + case (Suc q) + from coprime_fib_Suc_nat [of q] + have "coprime (fib (Suc q)) (fib q)" + by (simp add: ac_simps) + have "gcd (fib q) (fib (Suc q)) = Suc 0" + using coprime_fib_Suc_nat [of q] by simp + then have *: "gcd (fib n * fib q) (fib n * fib (Suc q)) = fib n" + by (simp add: gcd_mult_distrib_nat [symmetric]) + moreover have "gcd (fib (Suc q)) (fib n * fib q + fib (Suc n) * fib (Suc q)) = + gcd (fib (Suc q)) (fib n * fib q)" + using gcd_add_mult [of "fib (Suc q)"] by (simp add: ac_simps) + moreover have "gcd (fib (Suc q)) (fib n * fib (Suc q)) = fib (Suc q)" + by simp + ultimately show ?thesis + using Suc \coprime (fib (Suc q)) (fib q)\ + by (auto simp add: fib_add algebra_simps gcd_mult_right_right_cancel) +qed lemma gcd_fib_diff: "m \ n \ gcd (fib m) (fib (n - m)) = gcd (fib m) (fib n)" by (simp add: gcd_fib_add [symmetric, of _ "n-m"]) diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Gauss.thy --- a/src/HOL/Number_Theory/Gauss.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Gauss.thy Sat Nov 11 18:41:08 2017 +0000 @@ -115,8 +115,9 @@ proof - from p_a_relprime have "\ p dvd a" by (simp add: cong_altdef_int) - with p_prime have "coprime a (int p)" - by (subst gcd.commute, intro prime_imp_coprime) auto + with p_prime prime_imp_coprime [of _ "nat \a\"] + have "coprime a (int p)" + by (simp_all add: zdvd_int ac_simps) with a cong_mult_rcancel_int [of a "int p" x y] have "[x = y] (mod p)" by simp with cong_less_imp_eq_int [of x y p] p_minus_one_l @@ -149,8 +150,9 @@ using cong_def by blast from p_a_relprime have "\p dvd a" by (simp add: cong_altdef_int) - with p_prime have "coprime a (int p)" - by (subst gcd.commute, intro prime_imp_coprime) auto + with p_prime prime_imp_coprime [of _ "nat \a\"] + have "coprime a (int p)" + by (simp_all add: zdvd_int ac_simps) with a' cong_mult_rcancel_int [of a "int p" x y] have "[x = y] (mod p)" by simp with cong_less_imp_eq_int [of x y p] p_minus_one_l @@ -219,13 +221,16 @@ by (auto simp add: D_def C_def B_def A_def) lemma all_A_relprime: - assumes "x \ A" - shows "gcd x p = 1" - using p_prime A_ncong_p [OF assms] - by (auto simp: cong_altdef_int gcd.commute[of _ "int p"] intro!: prime_imp_coprime) - -lemma A_prod_relprime: "gcd (prod id A) p = 1" - by (metis id_def all_A_relprime prod_coprime) + "coprime x p" if "x \ A" +proof - + from A_ncong_p [OF that] have "\ int p dvd x" + by (simp add: cong_altdef_int) + with p_prime show ?thesis + by (metis (no_types) coprime_commute prime_imp_coprime prime_nat_int_transfer) +qed + +lemma A_prod_relprime: "coprime (prod id A) p" + by (auto intro: prod_coprime_left all_A_relprime) subsection \Relationships Between Gauss Sets\ diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Pocklington.thy --- a/src/HOL/Number_Theory/Pocklington.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Pocklington.thy Sat Nov 11 18:41:08 2017 +0000 @@ -11,18 +11,11 @@ subsection \Lemmas about previously defined terms\ lemma prime_nat_iff'': "prime (p::nat) \ p \ 0 \ p \ 1 \ (\m. 0 < m \ m < p \ coprime p m)" - unfolding prime_nat_iff -proof safe - fix m - assume p: "p > 0" "p \ 1" - and m: "m dvd p" "m \ p" - and *: "\m. m > 0 \ m < p \ coprime p m" - from p m have "m \ 0" by (intro notI) auto - moreover from p m have "m < p" by (auto dest: dvd_imp_le) - ultimately have "coprime p m" - using * by blast - with m show "m = 1" by simp -qed (auto simp: prime_nat_iff simp del: One_nat_def intro!: prime_imp_coprime dest: dvd_imp_le) + apply (auto simp add: prime_nat_iff) + apply (rule coprimeI) + apply (auto dest: nat_dvd_not_less simp add: ac_simps) + apply (metis One_nat_def dvd_1_iff_1 dvd_pos_nat gcd_nat.order_iff is_unit_gcd linorder_neqE_nat nat_dvd_not_less) + done lemma finite_number_segment: "card { m. 0 < m \ m < n } = n - 1" proof - @@ -46,7 +39,7 @@ from bezout_add_strong_nat [OF this] obtain d x y where dxy: "d dvd a" "d dvd n" "a * x = n * y + d" by blast from dxy(1,2) have d1: "d = 1" - by (metis assms coprime_nat) + using assms coprime_common_divisor [of a n d] by simp with dxy(3) have "a * x * b = (n * y + 1) * b" by simp then have "a * (x * b) = n * (y * b) + b" @@ -94,9 +87,9 @@ shows "\!y. 0 < y \ y < p \ [x * y = a] (mod p)" proof - from pa have ap: "coprime a p" - by (metis gcd.commute) - have px: "coprime x p" - by (metis gcd.commute p prime_nat_iff'' x0 xp) + by (simp add: ac_simps) + from x0 xp p have px: "coprime x p" + by (auto simp add: prime_nat_iff'' ac_simps) obtain y where y: "y < p" "[x * y = a] (mod p)" "\z. z < p \ [x * z = a] (mod p) \ z = y" by (metis cong_solve_unique neq0_conv p prime_gt_0_nat px) have "y \ 0" @@ -104,8 +97,8 @@ assume "y = 0" with y(2) have "p dvd a" using cong_dvd_iff by auto - then show False - by (metis gcd_nat.absorb1 not_prime_1 p pa) + with not_prime_1 p pa show False + by (auto simp add: gcd_nat.order_iff) qed with y show ?thesis by blast @@ -128,9 +121,9 @@ obtain x where x: "x < a * b" "[x = m] (mod a)" "[x = n] (mod b)" "\y. ?P y \ y = x" by blast from ma nb x have "coprime x a" "coprime x b" - by (metis cong_gcd_eq_nat)+ + using cong_imp_coprime_nat cong_sym by blast+ then have "coprime x (a*b)" - by (metis coprime_mul_eq) + by simp with x show ?thesis by blast qed @@ -164,7 +157,8 @@ from dvd_mod_iff[OF d(2), of "a^m"] dam am1 show ?thesis by simp qed - then show ?thesis by blast + then show ?thesis + by (auto intro: coprimeI) qed qed @@ -216,8 +210,8 @@ from mod_less_divisor[of n 1] n01 have onen: "1 mod n = 1" by simp from lucas_coprime_lemma[OF n01(3) an1] cong_imp_coprime_nat an1 - have an: "coprime a n" "coprime (a^(n - 1)) n" - by (auto simp add: coprime_exp gcd.commute) + have an: "coprime a n" "coprime (a ^ (n - 1)) n" + using \n \ 2\ by simp_all have False if H0: "\m. 0 < m \ m < n - 1 \ [a ^ m = 1] (mod n)" (is "EX m. ?P m") proof - from H0[unfolded nat_exists_least_iff[of ?P]] obtain m where @@ -229,7 +223,7 @@ let ?y = "a^ ((n - 1) div m * m)" note mdeq = div_mult_mod_eq[of "(n - 1)" m] have yn: "coprime ?y n" - by (metis an(1) coprime_exp gcd.commute) + using an(1) by (cases "(n - Suc 0) div m * m = 0") auto have "?y mod n = (a^m)^((n - 1) div m) mod n" by (simp add: algebra_simps power_mult) also have "\ = (a^m mod n)^((n - 1) div m) mod n" @@ -359,9 +353,11 @@ next case (Suc d') then have d0: "d \ 0" by simp - from prem obtain p where p: "p dvd n" "p dvd a" "p \ 1" by auto + from prem obtain p where p: "p dvd n" "p dvd a" "p \ 1" + by (auto elim: not_coprimeE) from \?lhs\ obtain q1 q2 where q12: "a ^ d + n * q1 = 1 + n * q2" - by (metis prem d0 gcd.commute lucas_coprime_lemma) + using prem d0 lucas_coprime_lemma + by (auto elim: not_coprimeE simp add: ac_simps) then have "a ^ d + n * q1 - n * q2 = 1" by simp with dvd_diff_nat [OF dvd_add [OF divides_rexp]] dvd_mult2 Suc p have "p dvd 1" by metis @@ -398,8 +394,10 @@ qed qed -lemma order_divides_totient: "ord n a dvd totient n" if "coprime n a" - by (metis euler_theorem gcd.commute ord_divides that) +lemma order_divides_totient: + "ord n a dvd totient n" if "coprime n a" + using that euler_theorem [of a n] + by (simp add: ord_divides [symmetric] ac_simps) lemma order_divides_expdiff: fixes n::nat and a::nat assumes na: "coprime n a" @@ -412,11 +410,11 @@ from na ed have "\c. d = e + c" by presburger then obtain c where c: "d = e + c" .. from na have an: "coprime a n" - by (metis gcd.commute) - have aen: "coprime (a^e) n" - by (metis coprime_exp gcd.commute na) - have acn: "coprime (a^c) n" - by (metis coprime_exp gcd.commute na) + by (simp add: ac_simps) + then have aen: "coprime (a ^ e) n" + by (cases "e > 0") simp_all + from an have acn: "coprime (a ^ c) n" + by (cases "c > 0") simp_all from c have "[a^d = a^e] (mod n) \ [a^(e + c) = a^(e + 0)] (mod n)" by simp also have "\ \ [a^e* a^c = a^e *a^0] (mod n)" by (simp add: power_add) @@ -620,8 +618,9 @@ by (metis cong_to_1_nat exps) from nqr s s' have "(n - 1) div P = ord p (a^r) * t*r" using P0 by simp - with caP have "coprime (a^(ord p (a^r) * t*r) - 1) n" by simp - with p01 pn pd0 coprime_common_divisor_nat show False + with caP have "coprime (a ^ (ord p (a ^ r) * t * r) - 1) n" + by simp + with p01 pn pd0 coprime_common_divisor [of _ n p] show False by auto qed with d have o: "ord p (a^r) = q" by simp @@ -632,12 +631,14 @@ assume d: "d dvd p" "d dvd a" "d \ 1" from pp[unfolded prime_nat_iff] d have dp: "d = p" by blast from n have "n \ 0" by simp - then have False using d dp pn - by auto (metis One_nat_def Suc_pred an dvd_1_iff_1 gcd_greatest_iff lucas_coprime_lemma) + then have False using d dp pn an + by auto (metis One_nat_def Suc_lessI + \1 < p \ (\m. m dvd p \ m = 1 \ m = p)\ \a ^ (q * r) = p * l * k + 1\ add_diff_cancel_left' dvd_diff_nat dvd_power dvd_triv_left gcd_nat.trans nat_dvd_not_less nqr zero_less_diff zero_less_one) } - then have cpa: "coprime p a" by auto - have arp: "coprime (a^r) p" - by (metis coprime_exp cpa gcd.commute) + then have cpa: "coprime p a" + by (auto intro: coprimeI) + then have arp: "coprime (a ^ r) p" + by (cases "r > 0") (simp_all add: ac_simps) from euler_theorem [OF arp, simplified ord_divides] o totient_eq have "q dvd (p - 1)" by simp then obtain d where d:"p - 1 = q * d" diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Residues.thy --- a/src/HOL/Number_Theory/Residues.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Residues.thy Sat Nov 11 18:41:08 2017 +0000 @@ -106,13 +106,9 @@ lemma res_units_eq: "Units R = {x. 0 < x \ x < m \ coprime x m}" using m_gt_one - unfolding Units_def R_def residue_ring_def - apply auto - apply (subgoal_tac "x \ 0") - apply auto - apply (metis invertible_coprime_int) + apply (auto simp add: Units_def R_def residue_ring_def ac_simps invertible_coprime intro: ccontr) apply (subst (asm) coprime_iff_invertible'_int) - apply (auto simp add: cong_def mult.commute) + apply (auto simp add: cong_def) done lemma res_neg_eq: "\ x = (- x) mod m" @@ -220,6 +216,22 @@ context residues_prime begin +lemma p_coprime_left: + "coprime p a \ \ p dvd a" + using p_prime by (auto intro: prime_imp_coprime dest: coprime_common_divisor) + +lemma p_coprime_right: + "coprime a p \ \ p dvd a" + using p_coprime_left [of a] by (simp add: ac_simps) + +lemma p_coprime_left_int: + "coprime (int p) a \ \ int p dvd a" + using p_prime by (auto intro: prime_imp_coprime dest: coprime_common_divisor) + +lemma p_coprime_right_int: + "coprime a (int p) \ \ int p dvd a" + using p_coprime_left_int [of a] by (simp add: ac_simps) + lemma is_field: "field R" proof - have "0 < x \ x < int p \ coprime (int p) x" for x @@ -231,9 +243,7 @@ lemma res_prime_units_eq: "Units R = {1..p - 1}" apply (subst res_units_eq) - apply auto - apply (subst gcd.commute) - apply (auto simp add: p_prime prime_imp_coprime_int zdvd_not_zless) + apply (auto simp add: p_coprime_right_int zdvd_not_zless) done end @@ -246,26 +256,27 @@ subsection \Euler's theorem\ -lemma (in residues) totient_eq: "totient (nat m) = card (Units R)" +lemma (in residues) totatives_eq: + "totatives (nat m) = nat ` Units R" proof - + from m_gt_one have "\m\ > 1" + by simp + then have "totatives (nat \m\) = nat ` abs ` Units R" + by (auto simp add: totatives_def res_units_eq image_iff le_less) + (use m_gt_one zless_nat_eq_int_zless in force) + moreover have "\m\ = m" "abs ` Units R = Units R" + using m_gt_one by (auto simp add: res_units_eq image_iff) + ultimately show ?thesis + by simp +qed + +lemma (in residues) totient_eq: + "totient (nat m) = card (Units R)" +proof - have *: "inj_on nat (Units R)" by (rule inj_onI) (auto simp add: res_units_eq) - define m' where "m' = nat m" - from m_gt_one have "m = int m'" "m' > 1" - by (simp_all add: m'_def) - then have "x \ Units R \ x \ int ` totatives m'" for x - unfolding res_units_eq - by (cases x; cases "x = m") (auto simp: totatives_def gcd_int_def) - then have "Units R = int ` totatives m'" - by blast - then have "totatives m' = nat ` Units R" - by (simp add: image_image) - then have "card (totatives (nat m)) = card (nat ` Units R)" - by (simp add: m'_def) - also have "\ = card (Units R)" - using * card_image [of nat "Units R"] by auto - finally show ?thesis - by (simp add: totient_def) + then show ?thesis + by (simp add: totient_def totatives_eq card_image) qed lemma (in residues_prime) totient_eq: "totient p = p - 1" diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Number_Theory/Totient.thy --- a/src/HOL/Number_Theory/Totient.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Number_Theory/Totient.thy Sat Nov 11 18:41:08 2017 +0000 @@ -15,7 +15,7 @@ definition totatives :: "nat \ nat set" where "totatives n = {k \ {0<..n}. coprime k n}" - + lemma in_totatives_iff: "k \ totatives n \ k > 0 \ k \ n \ coprime k n" by (simp add: totatives_def) @@ -60,7 +60,7 @@ lemma minus_one_in_totatives: assumes "n \ 2" shows "n - 1 \ totatives n" - using assms coprime_minus_one_nat [of n] by (simp add: in_totatives_iff) + using assms coprime_diff_one_left_nat [of n] by (simp add: in_totatives_iff) lemma totatives_prime_power_Suc: assumes "prime p" @@ -72,7 +72,8 @@ fix k assume k: "k \ {0<..p^Suc n}" "k \ (\m. p * m) ` {0<..p^n}" from k have "\(p dvd k)" by (auto elim!: dvdE) hence "coprime k (p ^ Suc n)" - using prime_imp_coprime[OF assms, of k] by (intro coprime_exp) (simp_all add: gcd.commute) + using prime_imp_coprime [OF assms, of k] + by (cases "n > 0") (auto simp add: ac_simps) with k show "k \ totatives (p ^ Suc n)" by (simp add: totatives_def) qed (auto simp: totatives_def) @@ -101,14 +102,15 @@ proof safe fix x assume "x \ totatives (m1 * m2)" with assms show "x mod m1 \ totatives m1" "x mod m2 \ totatives m2" - by (auto simp: totatives_def coprime_mul_eq not_le simp del: One_nat_def intro!: Nat.gr0I) + using coprime_common_divisor [of x m1 m1] coprime_common_divisor [of x m2 m2] + by (auto simp add: in_totatives_iff mod_greater_zero_iff_not_dvd) next fix a b assume ab: "a \ totatives m1" "b \ totatives m2" with assms have ab': "a < m1" "b < m2" by (auto simp: totatives_less) with binary_chinese_remainder_unique_nat[OF assms(3), of a b] obtain x where x: "x < m1 * m2" "x mod m1 = a" "x mod m2 = b" by (auto simp: cong_def) from x ab assms(3) have "x \ totatives (m1 * m2)" - by (auto simp: totatives_def coprime_mul_eq simp del: One_nat_def intro!: Nat.gr0I) + by (auto intro: ccontr simp add: in_totatives_iff) with x show "(a, b) \ (\x. (x mod m1, x mod m2)) ` totatives (m1*m2)" by blast qed qed @@ -125,21 +127,18 @@ show "(\k. k * d) ` totatives (n div d) = {k\{0<..n}. gcd k n = d}" proof (intro equalityI subsetI, goal_cases) case (1 k) - thus ?case using assms - by (auto elim!: dvdE simp: inj_on_def totatives_def mult.commute[of d] - gcd_mult_right gcd.commute) + then show ?case using assms + by (auto elim: dvdE simp add: in_totatives_iff ac_simps gcd_mult_right) next case (2 k) hence "d dvd k" by auto then obtain l where k: "k = l * d" by (elim dvdE) auto - from 2 and assms show ?case unfolding k - by (intro imageI) (auto simp: totatives_def gcd.commute mult.commute[of d] - gcd_mult_right elim!: dvdE) + from 2 assms show ?case + using gcd_mult_right [of _ d l] + by (auto intro: gcd_eq_1_imp_coprime elim!: dvdE simp add: k image_iff in_totatives_iff ac_simps) qed qed - - definition totient :: "nat \ nat" where "totient n = card (totatives n)" @@ -272,7 +271,8 @@ proof - from that have nz: "x \ 0" by (auto intro!: Nat.gr0I) from that and p have le: "x \ p" by (intro dvd_imp_le) auto - from that and nz have "\coprime x p" by auto + from that and nz have "\coprime x p" + by (auto elim: dvdE) hence "x \ totatives p" by (simp add: totatives_def) also note * finally show False using that and le by auto @@ -299,7 +299,8 @@ by simp_all lemma totient_6 [simp]: "totient 6 = 2" - using totient_mult_coprime[of 2 3] by (simp add: gcd_non_0_nat) + using totient_mult_coprime [of 2 3] coprime_add_one_right [of 2] + by simp lemma totient_even: assumes "n > 2" @@ -314,11 +315,14 @@ have "p ^ k dvd n" unfolding k_def by (simp add: multiplicity_dvd) then obtain m where m: "n = p ^ k * m" by (elim dvdE) with assms have m_pos: "m > 0" by (auto intro!: Nat.gr0I) - from k_def m_pos p have "\p dvd m" + from k_def m_pos p have "\ p dvd m" by (subst (asm) m) (auto intro!: Nat.gr0I simp: prime_elem_multiplicity_mult_distrib prime_elem_multiplicity_eq_zero_iff) - hence "coprime (p ^ k) m" by (intro coprime_exp_left prime_imp_coprime[OF p(1)]) - thus ?thesis using p k_pos \odd p\ + with \prime p\ have "coprime p m" + by (rule prime_imp_coprime) + with \k > 0\ have "coprime (p ^ k) m" + by simp + then show ?thesis using p k_pos \odd p\ by (auto simp add: m totient_mult_coprime totient_prime_power) next case False @@ -341,7 +345,7 @@ proof (induction A rule: infinite_finite_induct) case (insert x A) have *: "coprime (prod f A) (f x)" - proof (rule prod_coprime) + proof (rule prod_coprime_left) fix y assume "y \ A" with \x \ A\ have "y \ x" @@ -388,10 +392,12 @@ proof (rule totient_prod_coprime) show "pairwise coprime ((\p. p ^ multiplicity p n) ` prime_factors n)" proof (rule pairwiseI, clarify) - fix p q assume "p \# prime_factorization n" "q \# prime_factorization n" + fix p q assume *: "p \# prime_factorization n" "q \# prime_factorization n" "p ^ multiplicity p n \ q ^ multiplicity q n" - thus "coprime (p ^ multiplicity p n) (q ^ multiplicity q n)" - by (intro coprime_exp2 primes_coprime[of p q]) auto + then have "multiplicity p n > 0" "multiplicity q n > 0" + by (simp_all add: prime_factors_multiplicity) + with * primes_coprime [of p q] show "coprime (p ^ multiplicity p n) (q ^ multiplicity q n)" + by auto qed next show "inj_on (\p. p ^ multiplicity p n) (prime_factors n)" @@ -475,20 +481,22 @@ by (subst totient_gcd [symmetric]) simp lemma of_nat_eq_1_iff: "of_nat x = (1 :: 'a :: {semiring_1, semiring_char_0}) \ x = 1" - using of_nat_eq_iff[of x 1] by (simp del: of_nat_eq_iff) + by (fact of_nat_eq_1_iff) (* TODO Move *) -lemma gcd_2_odd: +lemma odd_imp_coprime_nat: assumes "odd (n::nat)" - shows "gcd n 2 = 1" + shows "coprime n 2" proof - from assms obtain k where n: "n = Suc (2 * k)" by (auto elim!: oddE) - have "coprime (Suc (2 * k)) (2 * k)" by (rule coprime_Suc_nat) - thus ?thesis using n by (subst (asm) coprime_mul_eq) simp_all + have "coprime (Suc (2 * k)) (2 * k)" + by (fact coprime_Suc_left_nat) + then show ?thesis using n + by simp qed lemma totient_double: "totient (2 * n) = (if even n then 2 * totient n else totient n)" - by (subst totient_mult) (auto simp: gcd.commute[of 2] gcd_2_odd) + by (simp add: totient_mult ac_simps odd_imp_coprime_nat) lemma totient_power_Suc: "totient (n ^ Suc m) = n ^ m * totient n" proof (induction m arbitrary: n) diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Parity.thy --- a/src/HOL/Parity.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Parity.thy Sat Nov 11 18:41:08 2017 +0000 @@ -318,6 +318,38 @@ using mult_div_mod_eq [of 2 a] by (simp add: even_iff_mod_2_eq_zero) +lemma coprime_left_2_iff_odd [simp]: + "coprime 2 a \ odd a" +proof + assume "odd a" + show "coprime 2 a" + proof (rule coprimeI) + fix b + assume "b dvd 2" "b dvd a" + then have "b dvd a mod 2" + by (auto intro: dvd_mod) + with \odd a\ show "is_unit b" + by (simp add: mod_2_eq_odd) + qed +next + assume "coprime 2 a" + show "odd a" + proof (rule notI) + assume "even a" + then obtain b where "a = 2 * b" .. + with \coprime 2 a\ have "coprime 2 (2 * b)" + by simp + moreover have "\ coprime 2 (2 * b)" + by (rule not_coprimeI [of 2]) simp_all + ultimately show False + by blast + qed +qed + +lemma coprime_right_2_iff_odd [simp]: + "coprime a 2 \ odd a" + using coprime_left_2_iff_odd [of a] by (simp add: ac_simps) + end class ring_parity = ring + semiring_parity diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Rat.thy --- a/src/HOL/Rat.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Rat.thy Sat Nov 11 18:41:08 2017 +0000 @@ -999,7 +999,7 @@ proof (cases p) case (Fract a b) then show ?thesis - by (cases "0::int" a rule: linorder_cases) (simp_all add: quotient_of_Fract gcd.commute) + by (cases "0::int" a rule: linorder_cases) (simp_all add: quotient_of_Fract ac_simps) qed lemma rat_divide_code [code abstract]: @@ -1008,9 +1008,10 @@ in normalize (a * d, c * b))" by (cases p, cases q) (simp add: quotient_of_Fract) -lemma rat_abs_code [code abstract]: "quotient_of \p\ = (let (a, b) = quotient_of p in (\a\, b))" +lemma rat_abs_code [code abstract]: + "quotient_of \p\ = (let (a, b) = quotient_of p in (\a\, b))" by (cases p) (simp add: quotient_of_Fract) - + lemma rat_sgn_code [code abstract]: "quotient_of (sgn p) = (sgn (fst (quotient_of p)), 1)" proof (cases p) case (Fract a b) diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Real.thy --- a/src/HOL/Real.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Real.thy Sat Nov 11 18:41:08 2017 +0000 @@ -1245,7 +1245,7 @@ lemma Rats_abs_nat_div_natE: assumes "x \ \" - obtains m n :: nat where "n \ 0" and "\x\ = real m / real n" and "gcd m n = 1" + obtains m n :: nat where "n \ 0" and "\x\ = real m / real n" and "coprime m n" proof - from \x \ \\ obtain i :: int and n :: nat where "n \ 0" and "x = real_of_int i / real n" by (auto simp add: Rats_eq_int_div_nat) @@ -1281,6 +1281,8 @@ with gcd_k gcd_l have "?gcd * ?gcd' = ?gcd" by simp with gcd show ?thesis by auto qed + then have "coprime ?k ?l" + by (simp only: coprime_iff_gcd_eq_1) ultimately show ?thesis .. qed @@ -1415,8 +1417,6 @@ for m :: nat by (metis not_le real_of_nat_less_numeral_iff) -declare of_int_floor_le [simp] (* FIXME duplicate!? *) - lemma of_int_floor_cancel [simp]: "of_int \x\ = x \ (\n::int. x = of_int n)" by (metis floor_of_int) @@ -1424,7 +1424,7 @@ by linarith lemma floor_eq2: "real_of_int n \ x \ x < real_of_int n + 1 \ \x\ = n" - by linarith + by (fact floor_unique) lemma floor_eq3: "real n < x \ x < real (Suc n) \ nat \x\ = n" by linarith diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Rings.thy --- a/src/HOL/Rings.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Rings.thy Sat Nov 11 18:41:08 2017 +0000 @@ -1161,6 +1161,108 @@ "is_unit c \ b dvd a \ a div (b * c) = a div b div c" by (rule dvd_div_mult2_eq) (simp_all add: mult_unit_dvd_iff) + +text \Coprimality\ + +definition coprime :: "'a \ 'a \ bool" + where "coprime a b \ (\c. c dvd a \ c dvd b \ is_unit c)" + +lemma coprimeI: + assumes "\c. c dvd a \ c dvd b \ is_unit c" + shows "coprime a b" + using assms by (auto simp: coprime_def) + +lemma not_coprimeI: + assumes "c dvd a" and "c dvd b" and "\ is_unit c" + shows "\ coprime a b" + using assms by (auto simp: coprime_def) + +lemma coprime_common_divisor: + "is_unit c" if "coprime a b" and "c dvd a" and "c dvd b" + using that by (auto simp: coprime_def) + +lemma not_coprimeE: + assumes "\ coprime a b" + obtains c where "c dvd a" and "c dvd b" and "\ is_unit c" + using assms by (auto simp: coprime_def) + +lemma coprime_imp_coprime: + "coprime a b" if "coprime c d" + and "\e. \ is_unit e \ e dvd a \ e dvd b \ e dvd c" + and "\e. \ is_unit e \ e dvd a \ e dvd b \ e dvd d" +proof (rule coprimeI) + fix e + assume "e dvd a" and "e dvd b" + with that have "e dvd c" and "e dvd d" + by (auto intro: dvd_trans) + with \coprime c d\ show "is_unit e" + by (rule coprime_common_divisor) +qed + +lemma coprime_divisors: + "coprime a b" if "a dvd c" "b dvd d" and "coprime c d" +using \coprime c d\ proof (rule coprime_imp_coprime) + fix e + assume "e dvd a" then show "e dvd c" + using \a dvd c\ by (rule dvd_trans) + assume "e dvd b" then show "e dvd d" + using \b dvd d\ by (rule dvd_trans) +qed + +lemma coprime_self [simp]: + "coprime a a \ is_unit a" (is "?P \ ?Q") +proof + assume ?P + then show ?Q + by (rule coprime_common_divisor) simp_all +next + assume ?Q + show ?P + by (rule coprimeI) (erule dvd_unit_imp_unit, rule \?Q\) +qed + +lemma coprime_commute [ac_simps]: + "coprime b a \ coprime a b" + unfolding coprime_def by auto + +lemma is_unit_left_imp_coprime: + "coprime a b" if "is_unit a" +proof (rule coprimeI) + fix c + assume "c dvd a" + with that show "is_unit c" + by (auto intro: dvd_unit_imp_unit) +qed + +lemma is_unit_right_imp_coprime: + "coprime a b" if "is_unit b" + using that is_unit_left_imp_coprime [of b a] by (simp add: ac_simps) + +lemma coprime_1_left [simp]: + "coprime 1 a" + by (rule coprimeI) + +lemma coprime_1_right [simp]: + "coprime a 1" + by (rule coprimeI) + +lemma coprime_0_left_iff [simp]: + "coprime 0 a \ is_unit a" + by (auto intro: coprimeI dvd_unit_imp_unit coprime_common_divisor [of 0 a a]) + +lemma coprime_0_right_iff [simp]: + "coprime a 0 \ is_unit a" + using coprime_0_left_iff [of a] by (simp add: ac_simps) + +lemma coprime_mult_self_left_iff [simp]: + "coprime (c * a) (c * b) \ is_unit c \ coprime a b" + by (auto intro: coprime_common_divisor) + (rule coprimeI, auto intro: coprime_common_divisor simp add: dvd_mult_unit_iff')+ + +lemma coprime_mult_self_right_iff [simp]: + "coprime (a * c) (b * c) \ is_unit c \ coprime a b" + using coprime_mult_self_left_iff [of c a b] by (simp add: ac_simps) + end class unit_factor = @@ -1430,6 +1532,14 @@ shows "is_unit a \ a = 1" using assms by (cases "a = 0") (auto dest: is_unit_normalize) +lemma coprime_normalize_left_iff [simp]: + "coprime (normalize a) b \ coprime a b" + by (rule; rule coprimeI) (auto intro: coprime_common_divisor) + +lemma coprime_normalize_right_iff [simp]: + "coprime a (normalize b) \ coprime a b" + using coprime_normalize_left_iff [of b a] by (simp add: ac_simps) + text \ We avoid an explicit definition of associated elements but prefer explicit normalisation instead. In theory we could define an abbreviation like @{prop @@ -2435,8 +2545,8 @@ subclass ordered_ring_abs by standard (auto simp: abs_if not_less mult_less_0_iff) -lemma abs_mult_self [simp]: "\a\ * \a\ = a * a" - by (simp add: abs_if) +lemma abs_mult_self: "\a\ * \a\ = a * a" + by (fact abs_mult_self_eq) lemma abs_mult_less: assumes ac: "\a\ < c" diff -r 1e29e2666a15 -r e7e54a0b9197 src/HOL/Set.thy --- a/src/HOL/Set.thy Sat Nov 11 18:33:35 2017 +0000 +++ b/src/HOL/Set.thy Sat Nov 11 18:41:08 2017 +0000 @@ -1874,6 +1874,11 @@ lemma pairwise_mono: "\pairwise P A; \x y. P x y \ Q x y\ \ pairwise Q A" by (auto simp: pairwise_def) +lemma pairwise_imageI: + "pairwise P (f ` A)" + if "\x y. x \ A \ y \ A \ x \ y \ f x \ f y \ P (f x) (f y)" + using that by (auto intro: pairwiseI) + lemma pairwise_image: "pairwise r (f ` s) \ pairwise (\x y. (f x \ f y) \ r (f x) (f y)) s" by (force simp: pairwise_def)