src/HOL/Number_Theory/Cong.thy
changeset 60526 fad653acf58f
parent 59816 034b13f4efae
child 60688 01488b559910
equal deleted inserted replaced
60525:278b65d9339c 60526:fad653acf58f
    21 extended to the natural numbers by Chaieb. Jeremy Avigad combined
    21 extended to the natural numbers by Chaieb. Jeremy Avigad combined
    22 these, revised and tidied them, made the development uniform for the
    22 these, revised and tidied them, made the development uniform for the
    23 natural numbers and the integers, and added a number of new theorems.
    23 natural numbers and the integers, and added a number of new theorems.
    24 *)
    24 *)
    25 
    25 
    26 section {* Congruence *}
    26 section \<open>Congruence\<close>
    27 
    27 
    28 theory Cong
    28 theory Cong
    29 imports Primes
    29 imports Primes
    30 begin
    30 begin
    31 
    31 
    32 subsection {* Turn off @{text One_nat_def} *}
    32 subsection \<open>Turn off @{text One_nat_def}\<close>
    33 
    33 
    34 lemma power_eq_one_eq_nat [simp]: "((x::nat)^m = 1) = (m = 0 | x = 1)"
    34 lemma power_eq_one_eq_nat [simp]: "((x::nat)^m = 1) = (m = 0 | x = 1)"
    35   by (induct m) auto
    35   by (induct m) auto
    36 
    36 
    37 declare mod_pos_pos_trivial [simp]
    37 declare mod_pos_pos_trivial [simp]
    38 
    38 
    39 
    39 
    40 subsection {* Main definitions *}
    40 subsection \<open>Main definitions\<close>
    41 
    41 
    42 class cong =
    42 class cong =
    43   fixes cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(()mod _'))")
    43   fixes cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(()mod _'))")
    44 begin
    44 begin
    45 
    45 
    72 instance ..
    72 instance ..
    73 
    73 
    74 end
    74 end
    75 
    75 
    76 
    76 
    77 subsection {* Set up Transfer *}
    77 subsection \<open>Set up Transfer\<close>
    78 
    78 
    79 
    79 
    80 lemma transfer_nat_int_cong:
    80 lemma transfer_nat_int_cong:
    81   "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> m >= 0 \<Longrightarrow>
    81   "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> m >= 0 \<Longrightarrow>
    82     ([(nat x) = (nat y)] (mod (nat m))) = ([x = y] (mod m))"
    82     ([(nat x) = (nat y)] (mod (nat m))) = ([x = y] (mod m))"
    95 
    95 
    96 declare transfer_morphism_int_nat[transfer add return:
    96 declare transfer_morphism_int_nat[transfer add return:
    97     transfer_int_nat_cong]
    97     transfer_int_nat_cong]
    98 
    98 
    99 
    99 
   100 subsection {* Congruence *}
   100 subsection \<open>Congruence\<close>
   101 
   101 
   102 (* was zcong_0, etc. *)
   102 (* was zcong_0, etc. *)
   103 lemma cong_0_nat [simp, presburger]: "([(a::nat) = b] (mod 0)) = (a = b)"
   103 lemma cong_0_nat [simp, presburger]: "([(a::nat) = b] (mod 0)) = (a = b)"
   104   unfolding cong_nat_def by auto
   104   unfolding cong_nat_def by auto
   105 
   105 
   631     by blast
   631     by blast
   632   let ?x = "u1 * b1 + u2 * b2"
   632   let ?x = "u1 * b1 + u2 * b2"
   633   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
   633   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
   634     apply (rule cong_add_nat)
   634     apply (rule cong_add_nat)
   635     apply (rule cong_scalar2_nat)
   635     apply (rule cong_scalar2_nat)
   636     apply (rule `[b1 = 1] (mod m1)`)
   636     apply (rule \<open>[b1 = 1] (mod m1)\<close>)
   637     apply (rule cong_scalar2_nat)
   637     apply (rule cong_scalar2_nat)
   638     apply (rule `[b2 = 0] (mod m1)`)
   638     apply (rule \<open>[b2 = 0] (mod m1)\<close>)
   639     done
   639     done
   640   then have "[?x = u1] (mod m1)" by simp
   640   then have "[?x = u1] (mod m1)" by simp
   641   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
   641   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
   642     apply (rule cong_add_nat)
   642     apply (rule cong_add_nat)
   643     apply (rule cong_scalar2_nat)
   643     apply (rule cong_scalar2_nat)
   644     apply (rule `[b1 = 0] (mod m2)`)
   644     apply (rule \<open>[b1 = 0] (mod m2)\<close>)
   645     apply (rule cong_scalar2_nat)
   645     apply (rule cong_scalar2_nat)
   646     apply (rule `[b2 = 1] (mod m2)`)
   646     apply (rule \<open>[b2 = 1] (mod m2)\<close>)
   647     done
   647     done
   648   then have "[?x = u2] (mod m2)" by simp
   648   then have "[?x = u2] (mod m2)" by simp
   649   with `[?x = u1] (mod m1)` show ?thesis by blast
   649   with \<open>[?x = u1] (mod m1)\<close> show ?thesis by blast
   650 qed
   650 qed
   651 
   651 
   652 lemma binary_chinese_remainder_int:
   652 lemma binary_chinese_remainder_int:
   653   assumes a: "coprime (m1::int) m2"
   653   assumes a: "coprime (m1::int) m2"
   654   shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
   654   shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
   659     by blast
   659     by blast
   660   let ?x = "u1 * b1 + u2 * b2"
   660   let ?x = "u1 * b1 + u2 * b2"
   661   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
   661   have "[?x = u1 * 1 + u2 * 0] (mod m1)"
   662     apply (rule cong_add_int)
   662     apply (rule cong_add_int)
   663     apply (rule cong_scalar2_int)
   663     apply (rule cong_scalar2_int)
   664     apply (rule `[b1 = 1] (mod m1)`)
   664     apply (rule \<open>[b1 = 1] (mod m1)\<close>)
   665     apply (rule cong_scalar2_int)
   665     apply (rule cong_scalar2_int)
   666     apply (rule `[b2 = 0] (mod m1)`)
   666     apply (rule \<open>[b2 = 0] (mod m1)\<close>)
   667     done
   667     done
   668   then have "[?x = u1] (mod m1)" by simp
   668   then have "[?x = u1] (mod m1)" by simp
   669   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
   669   have "[?x = u1 * 0 + u2 * 1] (mod m2)"
   670     apply (rule cong_add_int)
   670     apply (rule cong_add_int)
   671     apply (rule cong_scalar2_int)
   671     apply (rule cong_scalar2_int)
   672     apply (rule `[b1 = 0] (mod m2)`)
   672     apply (rule \<open>[b1 = 0] (mod m2)\<close>)
   673     apply (rule cong_scalar2_int)
   673     apply (rule cong_scalar2_int)
   674     apply (rule `[b2 = 1] (mod m2)`)
   674     apply (rule \<open>[b2 = 1] (mod m2)\<close>)
   675     done
   675     done
   676   then have "[?x = u2] (mod m2)" by simp
   676   then have "[?x = u2] (mod m2)" by simp
   677   with `[?x = u1] (mod m1)` show ?thesis by blast
   677   with \<open>[?x = u1] (mod m1)\<close> show ?thesis by blast
   678 qed
   678 qed
   679 
   679 
   680 lemma cong_modulus_mult_nat: "[(x::nat) = y] (mod m * n) \<Longrightarrow>
   680 lemma cong_modulus_mult_nat: "[(x::nat) = y] (mod m * n) \<Longrightarrow>
   681     [x = y] (mod m)"
   681     [x = y] (mod m)"
   682   apply (cases "y \<le> x")
   682   apply (cases "y \<le> x")
   710   from nz have less: "?x < m1 * m2"
   710   from nz have less: "?x < m1 * m2"
   711     by auto
   711     by auto
   712   have one: "[?x = u1] (mod m1)"
   712   have one: "[?x = u1] (mod m1)"
   713     apply (rule cong_trans_nat)
   713     apply (rule cong_trans_nat)
   714     prefer 2
   714     prefer 2
   715     apply (rule `[y = u1] (mod m1)`)
   715     apply (rule \<open>[y = u1] (mod m1)\<close>)
   716     apply (rule cong_modulus_mult_nat)
   716     apply (rule cong_modulus_mult_nat)
   717     apply (rule cong_mod_nat)
   717     apply (rule cong_mod_nat)
   718     using nz apply auto
   718     using nz apply auto
   719     done
   719     done
   720   have two: "[?x = u2] (mod m2)"
   720   have two: "[?x = u2] (mod m2)"
   721     apply (rule cong_trans_nat)
   721     apply (rule cong_trans_nat)
   722     prefer 2
   722     prefer 2
   723     apply (rule `[y = u2] (mod m2)`)
   723     apply (rule \<open>[y = u2] (mod m2)\<close>)
   724     apply (subst mult.commute)
   724     apply (subst mult.commute)
   725     apply (rule cong_modulus_mult_nat)
   725     apply (rule cong_modulus_mult_nat)
   726     apply (rule cong_mod_nat)
   726     apply (rule cong_mod_nat)
   727     using nz apply auto
   727     using nz apply auto
   728     done
   728     done
   731     fix z
   731     fix z
   732     assume "z < m1 * m2"
   732     assume "z < m1 * m2"
   733     assume "[z = u1] (mod m1)" and  "[z = u2] (mod m2)"
   733     assume "[z = u1] (mod m1)" and  "[z = u2] (mod m2)"
   734     have "[?x = z] (mod m1)"
   734     have "[?x = z] (mod m1)"
   735       apply (rule cong_trans_nat)
   735       apply (rule cong_trans_nat)
   736       apply (rule `[?x = u1] (mod m1)`)
   736       apply (rule \<open>[?x = u1] (mod m1)\<close>)
   737       apply (rule cong_sym_nat)
   737       apply (rule cong_sym_nat)
   738       apply (rule `[z = u1] (mod m1)`)
   738       apply (rule \<open>[z = u1] (mod m1)\<close>)
   739       done
   739       done
   740     moreover have "[?x = z] (mod m2)"
   740     moreover have "[?x = z] (mod m2)"
   741       apply (rule cong_trans_nat)
   741       apply (rule cong_trans_nat)
   742       apply (rule `[?x = u2] (mod m2)`)
   742       apply (rule \<open>[?x = u2] (mod m2)\<close>)
   743       apply (rule cong_sym_nat)
   743       apply (rule cong_sym_nat)
   744       apply (rule `[z = u2] (mod m2)`)
   744       apply (rule \<open>[z = u2] (mod m2)\<close>)
   745       done
   745       done
   746     ultimately have "[?x = z] (mod m1 * m2)"
   746     ultimately have "[?x = z] (mod m1 * m2)"
   747       by (auto intro: coprime_cong_mult_nat a)
   747       by (auto intro: coprime_cong_mult_nat a)
   748     with `z < m1 * m2` `?x < m1 * m2` show "z = ?x"
   748     with \<open>z < m1 * m2\<close> \<open>?x < m1 * m2\<close> show "z = ?x"
   749       apply (intro cong_less_modulus_unique_nat)
   749       apply (intro cong_less_modulus_unique_nat)
   750       apply (auto, erule cong_sym_nat)
   750       apply (auto, erule cong_sym_nat)
   751       done
   751       done
   752   qed
   752   qed
   753   with less one two show ?thesis by auto
   753   with less one two show ?thesis by auto