some reorganization of number theory
authorhaftmann
Tue Sep 01 15:39:33 2009 +0200 (2009-09-01)
changeset 32479521cc9bf2958
parent 32478 87201c60ae7d
child 32480 6c19da8e661a
some reorganization of number theory
NEWS
src/HOL/Extraction/Euclid.thy
src/HOL/Extraction/ROOT.ML
src/HOL/GCD.thy
src/HOL/Import/HOL4Compat.thy
src/HOL/IsaMakefile
src/HOL/Isar_examples/ROOT.ML
src/HOL/Library/Legacy_GCD.thy
src/HOL/Library/Library.thy
src/HOL/Library/Pocklington.thy
src/HOL/Library/Primes.thy
src/HOL/NSA/Examples/NSPrimes.thy
src/HOL/NewNumberTheory/Binomial.thy
src/HOL/NewNumberTheory/Cong.thy
src/HOL/NewNumberTheory/Fib.thy
src/HOL/NewNumberTheory/MiscAlgebra.thy
src/HOL/NewNumberTheory/ROOT.ML
src/HOL/NewNumberTheory/Residues.thy
src/HOL/NewNumberTheory/UniqueFactorization.thy
src/HOL/NumberTheory/BijectionRel.thy
src/HOL/NumberTheory/Chinese.thy
src/HOL/NumberTheory/Euler.thy
src/HOL/NumberTheory/EulerFermat.thy
src/HOL/NumberTheory/EvenOdd.thy
src/HOL/NumberTheory/Factorization.thy
src/HOL/NumberTheory/Fib.thy
src/HOL/NumberTheory/Finite2.thy
src/HOL/NumberTheory/Gauss.thy
src/HOL/NumberTheory/Int2.thy
src/HOL/NumberTheory/IntFact.thy
src/HOL/NumberTheory/IntPrimes.thy
src/HOL/NumberTheory/Quadratic_Reciprocity.thy
src/HOL/NumberTheory/ROOT.ML
src/HOL/NumberTheory/Residues.thy
src/HOL/NumberTheory/WilsonBij.thy
src/HOL/NumberTheory/WilsonRuss.thy
src/HOL/NumberTheory/document/root.tex
src/HOL/Number_Theory/Binomial.thy
src/HOL/Number_Theory/Cong.thy
src/HOL/Number_Theory/Fib.thy
src/HOL/Number_Theory/MiscAlgebra.thy
src/HOL/Number_Theory/Number_Theory.thy
src/HOL/Number_Theory/Primes.thy
src/HOL/Number_Theory/ROOT.ML
src/HOL/Number_Theory/Residues.thy
src/HOL/Number_Theory/UniqueFactorization.thy
src/HOL/Old_Number_Theory/BijectionRel.thy
src/HOL/Old_Number_Theory/Chinese.thy
src/HOL/Old_Number_Theory/Euler.thy
src/HOL/Old_Number_Theory/EulerFermat.thy
src/HOL/Old_Number_Theory/EvenOdd.thy
src/HOL/Old_Number_Theory/Factorization.thy
src/HOL/Old_Number_Theory/Fib.thy
src/HOL/Old_Number_Theory/Finite2.thy
src/HOL/Old_Number_Theory/Gauss.thy
src/HOL/Old_Number_Theory/Int2.thy
src/HOL/Old_Number_Theory/IntFact.thy
src/HOL/Old_Number_Theory/IntPrimes.thy
src/HOL/Old_Number_Theory/Legacy_GCD.thy
src/HOL/Old_Number_Theory/Pocklington.thy
src/HOL/Old_Number_Theory/Primes.thy
src/HOL/Old_Number_Theory/Quadratic_Reciprocity.thy
src/HOL/Old_Number_Theory/ROOT.ML
src/HOL/Old_Number_Theory/Residues.thy
src/HOL/Old_Number_Theory/WilsonBij.thy
src/HOL/Old_Number_Theory/WilsonRuss.thy
src/HOL/Old_Number_Theory/document/root.tex
src/HOL/ex/Codegenerator_Candidates.thy
src/HOL/ex/ROOT.ML
src/HOL/ex/Sqrt.thy
src/HOL/ex/Sqrt_Script.thy
     1.1 --- a/NEWS	Tue Sep 01 14:13:34 2009 +0200
     1.2 +++ b/NEWS	Tue Sep 01 15:39:33 2009 +0200
     1.3 @@ -18,6 +18,15 @@
     1.4  
     1.5  *** HOL ***
     1.6  
     1.7 +* Reorganization of number theory:
     1.8 +  * former session NumberTheory now names Old_Number_Theory; former session NewNumberTheory
     1.9 +    named NumberTheory;
    1.10 +  * split off prime number ingredients from theory GCD to theory Number_Theory/Primes;
    1.11 +  * moved legacy theories Legacy_GCD and Primes from Library/ to Old_Number_Theory/;
    1.12 +  * moved theory Pocklington from Library/ to Old_Number_Theory/;
    1.13 +  * removed various references to Old_Number_Theory from HOL distribution.
    1.14 +INCOMPATIBILITY.
    1.15 +
    1.16  * New testing tool "Mirabelle" for automated (proof) tools. Applies
    1.17  several tools and tactics like sledgehammer, metis, or quickcheck, to
    1.18  every proof step in a theory. To be used in batch mode via the
     2.1 --- a/src/HOL/Extraction/Euclid.thy	Tue Sep 01 14:13:34 2009 +0200
     2.2 +++ b/src/HOL/Extraction/Euclid.thy	Tue Sep 01 15:39:33 2009 +0200
     2.3 @@ -1,5 +1,4 @@
     2.4  (*  Title:      HOL/Extraction/Euclid.thy
     2.5 -    ID:         $Id$
     2.6      Author:     Markus Wenzel, TU Muenchen
     2.7                  Freek Wiedijk, Radboud University Nijmegen
     2.8                  Stefan Berghofer, TU Muenchen
     2.9 @@ -8,7 +7,7 @@
    2.10  header {* Euclid's theorem *}
    2.11  
    2.12  theory Euclid
    2.13 -imports "~~/src/HOL/NumberTheory/Factorization" Util Efficient_Nat
    2.14 +imports "~~/src/HOL/Old_Number_Theory/Factorization" Util Efficient_Nat
    2.15  begin
    2.16  
    2.17  text {*
     3.1 --- a/src/HOL/Extraction/ROOT.ML	Tue Sep 01 14:13:34 2009 +0200
     3.2 +++ b/src/HOL/Extraction/ROOT.ML	Tue Sep 01 15:39:33 2009 +0200
     3.3 @@ -1,5 +1,4 @@
     3.4  (*  Title:      HOL/Extraction/ROOT.ML
     3.5 -    ID:         $Id$
     3.6  
     3.7  Examples for program extraction in Higher-Order Logic.
     3.8  *)
     3.9 @@ -8,5 +7,5 @@
    3.10    warning "HOL proof terms required for running extraction examples"
    3.11  else
    3.12    (Proofterm.proofs := 2;
    3.13 -   no_document use_thys ["Efficient_Nat", "~~/src/HOL/NumberTheory/Factorization"];
    3.14 +   no_document use_thys ["Efficient_Nat", "~~/src/HOL/Old_Number_Theory/Factorization"];
    3.15     use_thys ["Greatest_Common_Divisor", "Warshall", "Higman", "Pigeonhole", "Euclid"]);
     4.1 --- a/src/HOL/GCD.thy	Tue Sep 01 14:13:34 2009 +0200
     4.2 +++ b/src/HOL/GCD.thy	Tue Sep 01 15:39:33 2009 +0200
     4.3 @@ -1,11 +1,9 @@
     4.4 -(*  Title:      GCD.thy
     4.5 -    Authors:    Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
     4.6 +(*  Authors:    Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
     4.7                  Thomas M. Rasmussen, Jeremy Avigad, Tobias Nipkow
     4.8  
     4.9  
    4.10 -This file deals with the functions gcd and lcm, and properties of
    4.11 -primes. Definitions and lemmas are proved uniformly for the natural
    4.12 -numbers and integers.
    4.13 +This file deals with the functions gcd and lcm.  Definitions and
    4.14 +lemmas are proved uniformly for the natural numbers and integers.
    4.15  
    4.16  This file combines and revises a number of prior developments.
    4.17  
    4.18 @@ -52,11 +50,6 @@
    4.19  
    4.20  end
    4.21  
    4.22 -class prime = one +
    4.23 -
    4.24 -fixes
    4.25 -  prime :: "'a \<Rightarrow> bool"
    4.26 -
    4.27  
    4.28  (* definitions for the natural numbers *)
    4.29  
    4.30 @@ -80,20 +73,6 @@
    4.31  end
    4.32  
    4.33  
    4.34 -instantiation nat :: prime
    4.35 -
    4.36 -begin
    4.37 -
    4.38 -definition
    4.39 -  prime_nat :: "nat \<Rightarrow> bool"
    4.40 -where
    4.41 -  [code del]: "prime_nat p = (1 < p \<and> (\<forall>m. m dvd p --> m = 1 \<or> m = p))"
    4.42 -
    4.43 -instance proof qed
    4.44 -
    4.45 -end
    4.46 -
    4.47 -
    4.48  (* definitions for the integers *)
    4.49  
    4.50  instantiation int :: gcd
    4.51 @@ -115,28 +94,13 @@
    4.52  end
    4.53  
    4.54  
    4.55 -instantiation int :: prime
    4.56 -
    4.57 -begin
    4.58 -
    4.59 -definition
    4.60 -  prime_int :: "int \<Rightarrow> bool"
    4.61 -where
    4.62 -  [code del]: "prime_int p = prime (nat p)"
    4.63 -
    4.64 -instance proof qed
    4.65 -
    4.66 -end
    4.67 -
    4.68 -
    4.69  subsection {* Set up Transfer *}
    4.70  
    4.71  
    4.72  lemma transfer_nat_int_gcd:
    4.73    "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> gcd (nat x) (nat y) = nat (gcd x y)"
    4.74    "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> lcm (nat x) (nat y) = nat (lcm x y)"
    4.75 -  "(x::int) >= 0 \<Longrightarrow> prime (nat x) = prime x"
    4.76 -  unfolding gcd_int_def lcm_int_def prime_int_def
    4.77 +  unfolding gcd_int_def lcm_int_def
    4.78    by auto
    4.79  
    4.80  lemma transfer_nat_int_gcd_closures:
    4.81 @@ -150,8 +114,7 @@
    4.82  lemma transfer_int_nat_gcd:
    4.83    "gcd (int x) (int y) = int (gcd x y)"
    4.84    "lcm (int x) (int y) = int (lcm x y)"
    4.85 -  "prime (int x) = prime x"
    4.86 -  by (unfold gcd_int_def lcm_int_def prime_int_def, auto)
    4.87 +  by (unfold gcd_int_def lcm_int_def, auto)
    4.88  
    4.89  lemma transfer_int_nat_gcd_closures:
    4.90    "is_nat x \<Longrightarrow> is_nat y \<Longrightarrow> gcd x y >= 0"
    4.91 @@ -1003,20 +966,6 @@
    4.92    apply (auto simp add: gcd_mult_cancel_int)
    4.93  done
    4.94  
    4.95 -lemma prime_odd_nat: "prime (p::nat) \<Longrightarrow> p > 2 \<Longrightarrow> odd p"
    4.96 -  unfolding prime_nat_def
    4.97 -  apply (subst even_mult_two_ex)
    4.98 -  apply clarify
    4.99 -  apply (drule_tac x = 2 in spec)
   4.100 -  apply auto
   4.101 -done
   4.102 -
   4.103 -lemma prime_odd_int: "prime (p::int) \<Longrightarrow> p > 2 \<Longrightarrow> odd p"
   4.104 -  unfolding prime_int_def
   4.105 -  apply (frule prime_odd_nat)
   4.106 -  apply (auto simp add: even_nat_def)
   4.107 -done
   4.108 -
   4.109  lemma coprime_common_divisor_nat: "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow>
   4.110      x dvd b \<Longrightarrow> x = 1"
   4.111    apply (subgoal_tac "x dvd gcd a b")
   4.112 @@ -1753,327 +1702,4 @@
   4.113    show ?thesis by(simp add: Gcd_def fold_set gcd_commute_int)
   4.114  qed
   4.115  
   4.116 -
   4.117 -subsection {* Primes *}
   4.118 -
   4.119 -(* FIXME Is there a better way to handle these, rather than making them elim rules? *)
   4.120 -
   4.121 -lemma prime_ge_0_nat [elim]: "prime (p::nat) \<Longrightarrow> p >= 0"
   4.122 -  by (unfold prime_nat_def, auto)
   4.123 -
   4.124 -lemma prime_gt_0_nat [elim]: "prime (p::nat) \<Longrightarrow> p > 0"
   4.125 -  by (unfold prime_nat_def, auto)
   4.126 -
   4.127 -lemma prime_ge_1_nat [elim]: "prime (p::nat) \<Longrightarrow> p >= 1"
   4.128 -  by (unfold prime_nat_def, auto)
   4.129 -
   4.130 -lemma prime_gt_1_nat [elim]: "prime (p::nat) \<Longrightarrow> p > 1"
   4.131 -  by (unfold prime_nat_def, auto)
   4.132 -
   4.133 -lemma prime_ge_Suc_0_nat [elim]: "prime (p::nat) \<Longrightarrow> p >= Suc 0"
   4.134 -  by (unfold prime_nat_def, auto)
   4.135 -
   4.136 -lemma prime_gt_Suc_0_nat [elim]: "prime (p::nat) \<Longrightarrow> p > Suc 0"
   4.137 -  by (unfold prime_nat_def, auto)
   4.138 -
   4.139 -lemma prime_ge_2_nat [elim]: "prime (p::nat) \<Longrightarrow> p >= 2"
   4.140 -  by (unfold prime_nat_def, auto)
   4.141 -
   4.142 -lemma prime_ge_0_int [elim]: "prime (p::int) \<Longrightarrow> p >= 0"
   4.143 -  by (unfold prime_int_def prime_nat_def) auto
   4.144 -
   4.145 -lemma prime_gt_0_int [elim]: "prime (p::int) \<Longrightarrow> p > 0"
   4.146 -  by (unfold prime_int_def prime_nat_def, auto)
   4.147 -
   4.148 -lemma prime_ge_1_int [elim]: "prime (p::int) \<Longrightarrow> p >= 1"
   4.149 -  by (unfold prime_int_def prime_nat_def, auto)
   4.150 -
   4.151 -lemma prime_gt_1_int [elim]: "prime (p::int) \<Longrightarrow> p > 1"
   4.152 -  by (unfold prime_int_def prime_nat_def, auto)
   4.153 -
   4.154 -lemma prime_ge_2_int [elim]: "prime (p::int) \<Longrightarrow> p >= 2"
   4.155 -  by (unfold prime_int_def prime_nat_def, auto)
   4.156 -
   4.157 -
   4.158 -lemma prime_int_altdef: "prime (p::int) = (1 < p \<and> (\<forall>m \<ge> 0. m dvd p \<longrightarrow>
   4.159 -    m = 1 \<or> m = p))"
   4.160 -  using prime_nat_def [transferred]
   4.161 -    apply (case_tac "p >= 0")
   4.162 -    by (blast, auto simp add: prime_ge_0_int)
   4.163 -
   4.164 -lemma prime_imp_coprime_nat: "prime (p::nat) \<Longrightarrow> \<not> p dvd n \<Longrightarrow> coprime p n"
   4.165 -  apply (unfold prime_nat_def)
   4.166 -  apply (metis gcd_dvd1_nat gcd_dvd2_nat)
   4.167 -  done
   4.168 -
   4.169 -lemma prime_imp_coprime_int: "prime (p::int) \<Longrightarrow> \<not> p dvd n \<Longrightarrow> coprime p n"
   4.170 -  apply (unfold prime_int_altdef)
   4.171 -  apply (metis gcd_dvd1_int gcd_dvd2_int gcd_ge_0_int)
   4.172 -  done
   4.173 -
   4.174 -lemma prime_dvd_mult_nat: "prime (p::nat) \<Longrightarrow> p dvd m * n \<Longrightarrow> p dvd m \<or> p dvd n"
   4.175 -  by (blast intro: coprime_dvd_mult_nat prime_imp_coprime_nat)
   4.176 -
   4.177 -lemma prime_dvd_mult_int: "prime (p::int) \<Longrightarrow> p dvd m * n \<Longrightarrow> p dvd m \<or> p dvd n"
   4.178 -  by (blast intro: coprime_dvd_mult_int prime_imp_coprime_int)
   4.179 -
   4.180 -lemma prime_dvd_mult_eq_nat [simp]: "prime (p::nat) \<Longrightarrow>
   4.181 -    p dvd m * n = (p dvd m \<or> p dvd n)"
   4.182 -  by (rule iffI, rule prime_dvd_mult_nat, auto)
   4.183 -
   4.184 -lemma prime_dvd_mult_eq_int [simp]: "prime (p::int) \<Longrightarrow>
   4.185 -    p dvd m * n = (p dvd m \<or> p dvd n)"
   4.186 -  by (rule iffI, rule prime_dvd_mult_int, auto)
   4.187 -
   4.188 -lemma not_prime_eq_prod_nat: "(n::nat) > 1 \<Longrightarrow> ~ prime n \<Longrightarrow>
   4.189 -    EX m k. n = m * k & 1 < m & m < n & 1 < k & k < n"
   4.190 -  unfolding prime_nat_def dvd_def apply auto
   4.191 -  by(metis mult_commute linorder_neq_iff linorder_not_le mult_1 n_less_n_mult_m one_le_mult_iff less_imp_le_nat)
   4.192 -
   4.193 -lemma not_prime_eq_prod_int: "(n::int) > 1 \<Longrightarrow> ~ prime n \<Longrightarrow>
   4.194 -    EX m k. n = m * k & 1 < m & m < n & 1 < k & k < n"
   4.195 -  unfolding prime_int_altdef dvd_def
   4.196 -  apply auto
   4.197 -  by(metis div_mult_self1_is_id div_mult_self2_is_id int_div_less_self int_one_le_iff_zero_less zero_less_mult_pos zless_le)
   4.198 -
   4.199 -lemma prime_dvd_power_nat [rule_format]: "prime (p::nat) -->
   4.200 -    n > 0 --> (p dvd x^n --> p dvd x)"
   4.201 -  by (induct n rule: nat_induct, auto)
   4.202 -
   4.203 -lemma prime_dvd_power_int [rule_format]: "prime (p::int) -->
   4.204 -    n > 0 --> (p dvd x^n --> p dvd x)"
   4.205 -  apply (induct n rule: nat_induct, auto)
   4.206 -  apply (frule prime_ge_0_int)
   4.207 -  apply auto
   4.208 -done
   4.209 -
   4.210 -subsubsection{* Make prime naively executable *}
   4.211 -
   4.212 -lemma zero_not_prime_nat [simp]: "~prime (0::nat)"
   4.213 -  by (simp add: prime_nat_def)
   4.214 -
   4.215 -lemma zero_not_prime_int [simp]: "~prime (0::int)"
   4.216 -  by (simp add: prime_int_def)
   4.217 -
   4.218 -lemma one_not_prime_nat [simp]: "~prime (1::nat)"
   4.219 -  by (simp add: prime_nat_def)
   4.220 -
   4.221 -lemma Suc_0_not_prime_nat [simp]: "~prime (Suc 0)"
   4.222 -  by (simp add: prime_nat_def One_nat_def)
   4.223 -
   4.224 -lemma one_not_prime_int [simp]: "~prime (1::int)"
   4.225 -  by (simp add: prime_int_def)
   4.226 -
   4.227 -lemma prime_nat_code[code]:
   4.228 - "prime(p::nat) = (p > 1 & (ALL n : {1<..<p}. ~(n dvd p)))"
   4.229 -apply(simp add: Ball_def)
   4.230 -apply (metis less_not_refl prime_nat_def dvd_triv_right not_prime_eq_prod_nat)
   4.231 -done
   4.232 -
   4.233 -lemma prime_nat_simp:
   4.234 - "prime(p::nat) = (p > 1 & (list_all (%n. ~ n dvd p) [2..<p]))"
   4.235 -apply(simp only:prime_nat_code list_ball_code greaterThanLessThan_upt)
   4.236 -apply(simp add:nat_number One_nat_def)
   4.237 -done
   4.238 -
   4.239 -lemmas prime_nat_simp_number_of[simp] = prime_nat_simp[of "number_of m", standard]
   4.240 -
   4.241 -lemma prime_int_code[code]:
   4.242 -  "prime(p::int) = (p > 1 & (ALL n : {1<..<p}. ~(n dvd p)))" (is "?L = ?R")
   4.243 -proof
   4.244 -  assume "?L" thus "?R"
   4.245 -    by (clarsimp simp: prime_gt_1_int) (metis int_one_le_iff_zero_less prime_int_altdef zless_le)
   4.246 -next
   4.247 -    assume "?R" thus "?L" by (clarsimp simp:Ball_def) (metis dvdI not_prime_eq_prod_int)
   4.248 -qed
   4.249 -
   4.250 -lemma prime_int_simp:
   4.251 -  "prime(p::int) = (p > 1 & (list_all (%n. ~ n dvd p) [2..p - 1]))"
   4.252 -apply(simp only:prime_int_code list_ball_code greaterThanLessThan_upto)
   4.253 -apply simp
   4.254 -done
   4.255 -
   4.256 -lemmas prime_int_simp_number_of[simp] = prime_int_simp[of "number_of m", standard]
   4.257 -
   4.258 -lemma two_is_prime_nat [simp]: "prime (2::nat)"
   4.259 -by simp
   4.260 -
   4.261 -lemma two_is_prime_int [simp]: "prime (2::int)"
   4.262 -by simp
   4.263 -
   4.264 -text{* A bit of regression testing: *}
   4.265 -
   4.266 -lemma "prime(97::nat)"
   4.267 -by simp
   4.268 -
   4.269 -lemma "prime(97::int)"
   4.270 -by simp
   4.271 -
   4.272 -lemma "prime(997::nat)"
   4.273 -by eval
   4.274 -
   4.275 -lemma "prime(997::int)"
   4.276 -by eval
   4.277 -
   4.278 -
   4.279 -lemma prime_imp_power_coprime_nat: "prime (p::nat) \<Longrightarrow> ~ p dvd a \<Longrightarrow> coprime a (p^m)"
   4.280 -  apply (rule coprime_exp_nat)
   4.281 -  apply (subst gcd_commute_nat)
   4.282 -  apply (erule (1) prime_imp_coprime_nat)
   4.283 -done
   4.284 -
   4.285 -lemma prime_imp_power_coprime_int: "prime (p::int) \<Longrightarrow> ~ p dvd a \<Longrightarrow> coprime a (p^m)"
   4.286 -  apply (rule coprime_exp_int)
   4.287 -  apply (subst gcd_commute_int)
   4.288 -  apply (erule (1) prime_imp_coprime_int)
   4.289 -done
   4.290 -
   4.291 -lemma primes_coprime_nat: "prime (p::nat) \<Longrightarrow> prime q \<Longrightarrow> p \<noteq> q \<Longrightarrow> coprime p q"
   4.292 -  apply (rule prime_imp_coprime_nat, assumption)
   4.293 -  apply (unfold prime_nat_def, auto)
   4.294 -done
   4.295 -
   4.296 -lemma primes_coprime_int: "prime (p::int) \<Longrightarrow> prime q \<Longrightarrow> p \<noteq> q \<Longrightarrow> coprime p q"
   4.297 -  apply (rule prime_imp_coprime_int, assumption)
   4.298 -  apply (unfold prime_int_altdef, clarify)
   4.299 -  apply (drule_tac x = q in spec)
   4.300 -  apply (drule_tac x = p in spec)
   4.301 -  apply auto
   4.302 -done
   4.303 -
   4.304 -lemma primes_imp_powers_coprime_nat: "prime (p::nat) \<Longrightarrow> prime q \<Longrightarrow> p ~= q \<Longrightarrow> coprime (p^m) (q^n)"
   4.305 -  by (rule coprime_exp2_nat, rule primes_coprime_nat)
   4.306 -
   4.307 -lemma primes_imp_powers_coprime_int: "prime (p::int) \<Longrightarrow> prime q \<Longrightarrow> p ~= q \<Longrightarrow> coprime (p^m) (q^n)"
   4.308 -  by (rule coprime_exp2_int, rule primes_coprime_int)
   4.309 -
   4.310 -lemma prime_factor_nat: "n \<noteq> (1::nat) \<Longrightarrow> \<exists> p. prime p \<and> p dvd n"
   4.311 -  apply (induct n rule: nat_less_induct)
   4.312 -  apply (case_tac "n = 0")
   4.313 -  using two_is_prime_nat apply blast
   4.314 -  apply (case_tac "prime n")
   4.315 -  apply blast
   4.316 -  apply (subgoal_tac "n > 1")
   4.317 -  apply (frule (1) not_prime_eq_prod_nat)
   4.318 -  apply (auto intro: dvd_mult dvd_mult2)
   4.319 -done
   4.320 -
   4.321 -(* An Isar version:
   4.322 -
   4.323 -lemma prime_factor_b_nat:
   4.324 -  fixes n :: nat
   4.325 -  assumes "n \<noteq> 1"
   4.326 -  shows "\<exists>p. prime p \<and> p dvd n"
   4.327 -
   4.328 -using `n ~= 1`
   4.329 -proof (induct n rule: less_induct_nat)
   4.330 -  fix n :: nat
   4.331 -  assume "n ~= 1" and
   4.332 -    ih: "\<forall>m<n. m \<noteq> 1 \<longrightarrow> (\<exists>p. prime p \<and> p dvd m)"
   4.333 -  thus "\<exists>p. prime p \<and> p dvd n"
   4.334 -  proof -
   4.335 -  {
   4.336 -    assume "n = 0"
   4.337 -    moreover note two_is_prime_nat
   4.338 -    ultimately have ?thesis
   4.339 -      by (auto simp del: two_is_prime_nat)
   4.340 -  }
   4.341 -  moreover
   4.342 -  {
   4.343 -    assume "prime n"
   4.344 -    hence ?thesis by auto
   4.345 -  }
   4.346 -  moreover
   4.347 -  {
   4.348 -    assume "n ~= 0" and "~ prime n"
   4.349 -    with `n ~= 1` have "n > 1" by auto
   4.350 -    with `~ prime n` and not_prime_eq_prod_nat obtain m k where
   4.351 -      "n = m * k" and "1 < m" and "m < n" by blast
   4.352 -    with ih obtain p where "prime p" and "p dvd m" by blast
   4.353 -    with `n = m * k` have ?thesis by auto
   4.354 -  }
   4.355 -  ultimately show ?thesis by blast
   4.356 -  qed
   4.357 -qed
   4.358 -
   4.359 -*)
   4.360 -
   4.361 -text {* One property of coprimality is easier to prove via prime factors. *}
   4.362 -
   4.363 -lemma prime_divprod_pow_nat:
   4.364 -  assumes p: "prime (p::nat)" and ab: "coprime a b" and pab: "p^n dvd a * b"
   4.365 -  shows "p^n dvd a \<or> p^n dvd b"
   4.366 -proof-
   4.367 -  {assume "n = 0 \<or> a = 1 \<or> b = 1" with pab have ?thesis
   4.368 -      apply (cases "n=0", simp_all)
   4.369 -      apply (cases "a=1", simp_all) done}
   4.370 -  moreover
   4.371 -  {assume n: "n \<noteq> 0" and a: "a\<noteq>1" and b: "b\<noteq>1"
   4.372 -    then obtain m where m: "n = Suc m" by (cases n, auto)
   4.373 -    from n have "p dvd p^n" by (intro dvd_power, auto)
   4.374 -    also note pab
   4.375 -    finally have pab': "p dvd a * b".
   4.376 -    from prime_dvd_mult_nat[OF p pab']
   4.377 -    have "p dvd a \<or> p dvd b" .
   4.378 -    moreover
   4.379 -    {assume pa: "p dvd a"
   4.380 -      have pnba: "p^n dvd b*a" using pab by (simp add: mult_commute)
   4.381 -      from coprime_common_divisor_nat [OF ab, OF pa] p have "\<not> p dvd b" by auto
   4.382 -      with p have "coprime b p"
   4.383 -        by (subst gcd_commute_nat, intro prime_imp_coprime_nat)
   4.384 -      hence pnb: "coprime (p^n) b"
   4.385 -        by (subst gcd_commute_nat, rule coprime_exp_nat)
   4.386 -      from coprime_divprod_nat[OF pnba pnb] have ?thesis by blast }
   4.387 -    moreover
   4.388 -    {assume pb: "p dvd b"
   4.389 -      have pnba: "p^n dvd b*a" using pab by (simp add: mult_commute)
   4.390 -      from coprime_common_divisor_nat [OF ab, of p] pb p have "\<not> p dvd a"
   4.391 -        by auto
   4.392 -      with p have "coprime a p"
   4.393 -        by (subst gcd_commute_nat, intro prime_imp_coprime_nat)
   4.394 -      hence pna: "coprime (p^n) a"
   4.395 -        by (subst gcd_commute_nat, rule coprime_exp_nat)
   4.396 -      from coprime_divprod_nat[OF pab pna] have ?thesis by blast }
   4.397 -    ultimately have ?thesis by blast}
   4.398 -  ultimately show ?thesis by blast
   4.399 -qed
   4.400 -
   4.401 -subsection {* Infinitely many primes *}
   4.402 -
   4.403 -lemma next_prime_bound: "\<exists>(p::nat). prime p \<and> n < p \<and> p <= fact n + 1"
   4.404 -proof-
   4.405 -  have f1: "fact n + 1 \<noteq> 1" using fact_ge_one_nat [of n] by arith 
   4.406 -  from prime_factor_nat [OF f1]
   4.407 -      obtain p where "prime p" and "p dvd fact n + 1" by auto
   4.408 -  hence "p \<le> fact n + 1" 
   4.409 -    by (intro dvd_imp_le, auto)
   4.410 -  {assume "p \<le> n"
   4.411 -    from `prime p` have "p \<ge> 1" 
   4.412 -      by (cases p, simp_all)
   4.413 -    with `p <= n` have "p dvd fact n" 
   4.414 -      by (intro dvd_fact_nat)
   4.415 -    with `p dvd fact n + 1` have "p dvd fact n + 1 - fact n"
   4.416 -      by (rule dvd_diff_nat)
   4.417 -    hence "p dvd 1" by simp
   4.418 -    hence "p <= 1" by auto
   4.419 -    moreover from `prime p` have "p > 1" by auto
   4.420 -    ultimately have False by auto}
   4.421 -  hence "n < p" by arith
   4.422 -  with `prime p` and `p <= fact n + 1` show ?thesis by auto
   4.423 -qed
   4.424 -
   4.425 -lemma bigger_prime: "\<exists>p. prime p \<and> p > (n::nat)" 
   4.426 -using next_prime_bound by auto
   4.427 -
   4.428 -lemma primes_infinite: "\<not> (finite {(p::nat). prime p})"
   4.429 -proof
   4.430 -  assume "finite {(p::nat). prime p}"
   4.431 -  with Max_ge have "(EX b. (ALL x : {(p::nat). prime p}. x <= b))"
   4.432 -    by auto
   4.433 -  then obtain b where "ALL (x::nat). prime x \<longrightarrow> x <= b"
   4.434 -    by auto
   4.435 -  with bigger_prime [of b] show False by auto
   4.436 -qed
   4.437 -
   4.438 -
   4.439  end
     5.1 --- a/src/HOL/Import/HOL4Compat.thy	Tue Sep 01 14:13:34 2009 +0200
     5.2 +++ b/src/HOL/Import/HOL4Compat.thy	Tue Sep 01 15:39:33 2009 +0200
     5.3 @@ -3,7 +3,7 @@
     5.4  *)
     5.5  
     5.6  theory HOL4Compat
     5.7 -imports HOL4Setup Complex_Main Primes ContNotDenum
     5.8 +imports HOL4Setup Complex_Main "~~/src/HOL/Old_Number_Theory/Primes" ContNotDenum
     5.9  begin
    5.10  
    5.11  no_notation differentiable (infixl "differentiable" 60)
     6.1 --- a/src/HOL/IsaMakefile	Tue Sep 01 14:13:34 2009 +0200
     6.2 +++ b/src/HOL/IsaMakefile	Tue Sep 01 15:39:33 2009 +0200
     6.3 @@ -34,8 +34,8 @@
     6.4    HOL-Modelcheck \
     6.5    HOL-NanoJava \
     6.6    HOL-Nominal-Examples \
     6.7 -  HOL-NewNumberTheory \
     6.8 -  HOL-NumberTheory \
     6.9 +  HOL-Number_Theory \
    6.10 +  HOL-Old_Number_Theory \
    6.11    HOL-Prolog \
    6.12    HOL-SET-Protocol \
    6.13    HOL-SizeChange \
    6.14 @@ -282,11 +282,13 @@
    6.15    Complex.thy \
    6.16    Deriv.thy \
    6.17    Fact.thy \
    6.18 +  GCD.thy \
    6.19    Integration.thy \
    6.20    Lim.thy \
    6.21    Limits.thy \
    6.22    Ln.thy \
    6.23    Log.thy \
    6.24 +  Lubs.thy \
    6.25    MacLaurin.thy \
    6.26    NatTransfer.thy \
    6.27    NthRoot.thy \
    6.28 @@ -294,9 +296,7 @@
    6.29    Series.thy \
    6.30    Taylor.thy \
    6.31    Transcendental.thy \
    6.32 -  GCD.thy \
    6.33    Parity.thy \
    6.34 -  Lubs.thy \
    6.35    PReal.thy \
    6.36    Rational.thy \
    6.37    RComplete.thy \
    6.38 @@ -330,10 +330,10 @@
    6.39    Library/Finite_Cartesian_Product.thy Library/FrechetDeriv.thy		\
    6.40    Library/Fraction_Field.thy Library/Fundamental_Theorem_Algebra.thy	\
    6.41    Library/Inner_Product.thy Library/Kleene_Algebra.thy			\
    6.42 -  Library/Lattice_Syntax.thy Library/Legacy_GCD.thy			\
    6.43 +  Library/Lattice_Syntax.thy			\
    6.44    Library/Library.thy Library/List_Prefix.thy Library/List_Set.thy	\
    6.45    Library/State_Monad.thy Library/Nat_Int_Bij.thy Library/Multiset.thy	\
    6.46 -  Library/Permutation.thy Library/Primes.thy Library/Pocklington.thy	\
    6.47 +  Library/Permutation.thy	\
    6.48    Library/Quotient.thy Library/Quicksort.thy Library/Nat_Infinity.thy	\
    6.49    Library/Word.thy Library/README.html Library/Continuity.thy		\
    6.50    Library/Order_Relation.thy Library/Nested_Environment.thy		\
    6.51 @@ -487,38 +487,39 @@
    6.52  	@cd Import/HOLLight; $(ISABELLE_TOOL) usedir -b $(OUT)/HOL HOLLight
    6.53  
    6.54  
    6.55 -## HOL-NewNumberTheory
    6.56 +## HOL-Number_Theory
    6.57  
    6.58 -HOL-NewNumberTheory: HOL $(LOG)/HOL-NewNumberTheory.gz
    6.59 +HOL-Number_Theory: HOL $(LOG)/HOL-Number_Theory.gz
    6.60  
    6.61 -$(LOG)/HOL-NewNumberTheory.gz: $(OUT)/HOL $(ALGEBRA_DEPENDENCIES) \
    6.62 +$(LOG)/HOL-Number_Theory.gz: $(OUT)/HOL $(ALGEBRA_DEPENDENCIES) \
    6.63    Library/Multiset.thy \
    6.64 -  NewNumberTheory/Binomial.thy \
    6.65 -  NewNumberTheory/Cong.thy \
    6.66 -  NewNumberTheory/Fib.thy \
    6.67 -  NewNumberTheory/MiscAlgebra.thy \
    6.68 -  NewNumberTheory/Residues.thy \
    6.69 -  NewNumberTheory/UniqueFactorization.thy  \
    6.70 -  NewNumberTheory/ROOT.ML
    6.71 -	@$(ISABELLE_TOOL) usedir -g true $(OUT)/HOL NewNumberTheory
    6.72 +  Number_Theory/Binomial.thy \
    6.73 +  Number_Theory/Cong.thy \
    6.74 +  Number_Theory/Fib.thy \
    6.75 +  Number_Theory/MiscAlgebra.thy \
    6.76 +  Number_Theory/Number_Theory.thy \
    6.77 +  Number_Theory/Residues.thy \
    6.78 +  Number_Theory/UniqueFactorization.thy  \
    6.79 +  Number_Theory/ROOT.ML
    6.80 +	@$(ISABELLE_TOOL) usedir -g true $(OUT)/HOL Number_Theory
    6.81  
    6.82  
    6.83 -## HOL-NumberTheory
    6.84 +## HOL-Old_Number_Theory
    6.85  
    6.86 -HOL-NumberTheory: HOL $(LOG)/HOL-NumberTheory.gz
    6.87 +HOL-Old_Number_Theory: HOL $(LOG)/HOL-Old_Number_Theory.gz
    6.88  
    6.89 -$(LOG)/HOL-NumberTheory.gz: $(OUT)/HOL Library/Permutation.thy		\
    6.90 -  Library/Primes.thy NumberTheory/Fib.thy				\
    6.91 -  NumberTheory/Factorization.thy NumberTheory/BijectionRel.thy		\
    6.92 -  NumberTheory/Chinese.thy NumberTheory/EulerFermat.thy			\
    6.93 -  NumberTheory/IntFact.thy NumberTheory/IntPrimes.thy			\
    6.94 -  NumberTheory/WilsonBij.thy NumberTheory/WilsonRuss.thy		\
    6.95 -  NumberTheory/Finite2.thy NumberTheory/Int2.thy			\
    6.96 -  NumberTheory/EvenOdd.thy NumberTheory/Residues.thy			\
    6.97 -  NumberTheory/Euler.thy NumberTheory/Gauss.thy				\
    6.98 -  NumberTheory/Quadratic_Reciprocity.thy Library/Infinite_Set.thy	\
    6.99 -  NumberTheory/ROOT.ML
   6.100 -	@$(ISABELLE_TOOL) usedir -g true $(OUT)/HOL NumberTheory
   6.101 +$(LOG)/HOL-Old_Number_Theory.gz: $(OUT)/HOL Library/Permutation.thy		\
   6.102 +  Old_Number_Theory/Primes.thy Old_Number_Theory/Fib.thy				\
   6.103 +  Old_Number_Theory/Factorization.thy Old_Number_Theory/BijectionRel.thy		\
   6.104 +  Old_Number_Theory/Chinese.thy Old_Number_Theory/EulerFermat.thy			\
   6.105 +  Old_Number_Theory/IntFact.thy Old_Number_Theory/IntPrimes.thy			\
   6.106 +  Old_Number_Theory/WilsonBij.thy Old_Number_Theory/WilsonRuss.thy		\
   6.107 +  Old_Number_Theory/Finite2.thy Old_Number_Theory/Int2.thy			\
   6.108 +  Old_Number_Theory/EvenOdd.thy Old_Number_Theory/Residues.thy			\
   6.109 +  Old_Number_Theory/Euler.thy Old_Number_Theory/Gauss.thy				\
   6.110 +  Old_Number_Theory/Quadratic_Reciprocity.thy Library/Infinite_Set.thy	\
   6.111 +  Old_Number_Theory/Legacy_GCD.thy Old_Number_Theory/Pocklington.thy Old_Number_Theory/ROOT.ML
   6.112 +	@$(ISABELLE_TOOL) usedir -g true $(OUT)/HOL Old_Number_Theory
   6.113  
   6.114  
   6.115  ## HOL-Hoare
   6.116 @@ -573,7 +574,7 @@
   6.117    Library/FuncSet.thy \
   6.118    Library/Multiset.thy \
   6.119    Library/Permutation.thy \
   6.120 -  Library/Primes.thy \
   6.121 +  Number_Theory/Primes.thy \
   6.122    Algebra/AbelCoset.thy \
   6.123    Algebra/Bij.thy \
   6.124    Algebra/Congruence.thy \
   6.125 @@ -876,7 +877,7 @@
   6.126  HOL-ex: HOL $(LOG)/HOL-ex.gz
   6.127  
   6.128  $(LOG)/HOL-ex.gz: $(OUT)/HOL Library/Commutative_Ring.thy		\
   6.129 -  Library/Primes.thy ex/Abstract_NAT.thy ex/Antiquote.thy		\
   6.130 +  Number_Theory/Primes.thy ex/Abstract_NAT.thy ex/Antiquote.thy		\
   6.131    ex/Arith_Examples.thy				\
   6.132    ex/Arithmetic_Series_Complex.thy ex/BT.thy ex/BinEx.thy		\
   6.133    ex/Binary.thy ex/CTL.thy ex/Chinese.thy ex/Classical.thy		\
     7.1 --- a/src/HOL/Isar_examples/ROOT.ML	Tue Sep 01 14:13:34 2009 +0200
     7.2 +++ b/src/HOL/Isar_examples/ROOT.ML	Tue Sep 01 15:39:33 2009 +0200
     7.3 @@ -4,7 +4,7 @@
     7.4  Miscellaneous Isabelle/Isar examples for Higher-Order Logic.
     7.5  *)
     7.6  
     7.7 -no_document use_thys ["../NumberTheory/Primes", "../NumberTheory/Fibonacci"];
     7.8 +no_document use_thys ["../Old_Number_Theory/Primes", "../Old_Number_Theory/Fibonacci"];
     7.9  
    7.10  use_thys [
    7.11    "Basic_Logic",
     8.1 --- a/src/HOL/Library/Legacy_GCD.thy	Tue Sep 01 14:13:34 2009 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,787 +0,0 @@
     8.4 -(*  Title:      HOL/GCD.thy
     8.5 -    Author:     Christophe Tabacznyj and Lawrence C Paulson
     8.6 -    Copyright   1996  University of Cambridge
     8.7 -*)
     8.8 -
     8.9 -header {* The Greatest Common Divisor *}
    8.10 -
    8.11 -theory Legacy_GCD
    8.12 -imports Main
    8.13 -begin
    8.14 -
    8.15 -text {*
    8.16 -  See \cite{davenport92}. \bigskip
    8.17 -*}
    8.18 -
    8.19 -subsection {* Specification of GCD on nats *}
    8.20 -
    8.21 -definition
    8.22 -  is_gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where -- {* @{term gcd} as a relation *}
    8.23 -  [code del]: "is_gcd m n p \<longleftrightarrow> p dvd m \<and> p dvd n \<and>
    8.24 -    (\<forall>d. d dvd m \<longrightarrow> d dvd n \<longrightarrow> d dvd p)"
    8.25 -
    8.26 -text {* Uniqueness *}
    8.27 -
    8.28 -lemma is_gcd_unique: "is_gcd a b m \<Longrightarrow> is_gcd a b n \<Longrightarrow> m = n"
    8.29 -  by (simp add: is_gcd_def) (blast intro: dvd_anti_sym)
    8.30 -
    8.31 -text {* Connection to divides relation *}
    8.32 -
    8.33 -lemma is_gcd_dvd: "is_gcd a b m \<Longrightarrow> k dvd a \<Longrightarrow> k dvd b \<Longrightarrow> k dvd m"
    8.34 -  by (auto simp add: is_gcd_def)
    8.35 -
    8.36 -text {* Commutativity *}
    8.37 -
    8.38 -lemma is_gcd_commute: "is_gcd m n k = is_gcd n m k"
    8.39 -  by (auto simp add: is_gcd_def)
    8.40 -
    8.41 -
    8.42 -subsection {* GCD on nat by Euclid's algorithm *}
    8.43 -
    8.44 -fun
    8.45 -  gcd  :: "nat => nat => nat"
    8.46 -where
    8.47 -  "gcd m n = (if n = 0 then m else gcd n (m mod n))"
    8.48 -lemma gcd_induct [case_names "0" rec]:
    8.49 -  fixes m n :: nat
    8.50 -  assumes "\<And>m. P m 0"
    8.51 -    and "\<And>m n. 0 < n \<Longrightarrow> P n (m mod n) \<Longrightarrow> P m n"
    8.52 -  shows "P m n"
    8.53 -proof (induct m n rule: gcd.induct)
    8.54 -  case (1 m n) with assms show ?case by (cases "n = 0") simp_all
    8.55 -qed
    8.56 -
    8.57 -lemma gcd_0 [simp, algebra]: "gcd m 0 = m"
    8.58 -  by simp
    8.59 -
    8.60 -lemma gcd_0_left [simp,algebra]: "gcd 0 m = m"
    8.61 -  by simp
    8.62 -
    8.63 -lemma gcd_non_0: "n > 0 \<Longrightarrow> gcd m n = gcd n (m mod n)"
    8.64 -  by simp
    8.65 -
    8.66 -lemma gcd_1 [simp, algebra]: "gcd m (Suc 0) = Suc 0"
    8.67 -  by simp
    8.68 -
    8.69 -lemma nat_gcd_1_right [simp, algebra]: "gcd m 1 = 1"
    8.70 -  unfolding One_nat_def by (rule gcd_1)
    8.71 -
    8.72 -declare gcd.simps [simp del]
    8.73 -
    8.74 -text {*
    8.75 -  \medskip @{term "gcd m n"} divides @{text m} and @{text n}.  The
    8.76 -  conjunctions don't seem provable separately.
    8.77 -*}
    8.78 -
    8.79 -lemma gcd_dvd1 [iff, algebra]: "gcd m n dvd m"
    8.80 -  and gcd_dvd2 [iff, algebra]: "gcd m n dvd n"
    8.81 -  apply (induct m n rule: gcd_induct)
    8.82 -     apply (simp_all add: gcd_non_0)
    8.83 -  apply (blast dest: dvd_mod_imp_dvd)
    8.84 -  done
    8.85 -
    8.86 -text {*
    8.87 -  \medskip Maximality: for all @{term m}, @{term n}, @{term k}
    8.88 -  naturals, if @{term k} divides @{term m} and @{term k} divides
    8.89 -  @{term n} then @{term k} divides @{term "gcd m n"}.
    8.90 -*}
    8.91 -
    8.92 -lemma gcd_greatest: "k dvd m \<Longrightarrow> k dvd n \<Longrightarrow> k dvd gcd m n"
    8.93 -  by (induct m n rule: gcd_induct) (simp_all add: gcd_non_0 dvd_mod)
    8.94 -
    8.95 -text {*
    8.96 -  \medskip Function gcd yields the Greatest Common Divisor.
    8.97 -*}
    8.98 -
    8.99 -lemma is_gcd: "is_gcd m n (gcd m n) "
   8.100 -  by (simp add: is_gcd_def gcd_greatest)
   8.101 -
   8.102 -
   8.103 -subsection {* Derived laws for GCD *}
   8.104 -
   8.105 -lemma gcd_greatest_iff [iff, algebra]: "k dvd gcd m n \<longleftrightarrow> k dvd m \<and> k dvd n"
   8.106 -  by (blast intro!: gcd_greatest intro: dvd_trans)
   8.107 -
   8.108 -lemma gcd_zero[algebra]: "gcd m n = 0 \<longleftrightarrow> m = 0 \<and> n = 0"
   8.109 -  by (simp only: dvd_0_left_iff [symmetric] gcd_greatest_iff)
   8.110 -
   8.111 -lemma gcd_commute: "gcd m n = gcd n m"
   8.112 -  apply (rule is_gcd_unique)
   8.113 -   apply (rule is_gcd)
   8.114 -  apply (subst is_gcd_commute)
   8.115 -  apply (simp add: is_gcd)
   8.116 -  done
   8.117 -
   8.118 -lemma gcd_assoc: "gcd (gcd k m) n = gcd k (gcd m n)"
   8.119 -  apply (rule is_gcd_unique)
   8.120 -   apply (rule is_gcd)
   8.121 -  apply (simp add: is_gcd_def)
   8.122 -  apply (blast intro: dvd_trans)
   8.123 -  done
   8.124 -
   8.125 -lemma gcd_1_left [simp, algebra]: "gcd (Suc 0) m = Suc 0"
   8.126 -  by (simp add: gcd_commute)
   8.127 -
   8.128 -lemma nat_gcd_1_left [simp, algebra]: "gcd 1 m = 1"
   8.129 -  unfolding One_nat_def by (rule gcd_1_left)
   8.130 -
   8.131 -text {*
   8.132 -  \medskip Multiplication laws
   8.133 -*}
   8.134 -
   8.135 -lemma gcd_mult_distrib2: "k * gcd m n = gcd (k * m) (k * n)"
   8.136 -    -- {* \cite[page 27]{davenport92} *}
   8.137 -  apply (induct m n rule: gcd_induct)
   8.138 -   apply simp
   8.139 -  apply (case_tac "k = 0")
   8.140 -   apply (simp_all add: mod_geq gcd_non_0 mod_mult_distrib2)
   8.141 -  done
   8.142 -
   8.143 -lemma gcd_mult [simp, algebra]: "gcd k (k * n) = k"
   8.144 -  apply (rule gcd_mult_distrib2 [of k 1 n, simplified, symmetric])
   8.145 -  done
   8.146 -
   8.147 -lemma gcd_self [simp, algebra]: "gcd k k = k"
   8.148 -  apply (rule gcd_mult [of k 1, simplified])
   8.149 -  done
   8.150 -
   8.151 -lemma relprime_dvd_mult: "gcd k n = 1 ==> k dvd m * n ==> k dvd m"
   8.152 -  apply (insert gcd_mult_distrib2 [of m k n])
   8.153 -  apply simp
   8.154 -  apply (erule_tac t = m in ssubst)
   8.155 -  apply simp
   8.156 -  done
   8.157 -
   8.158 -lemma relprime_dvd_mult_iff: "gcd k n = 1 ==> (k dvd m * n) = (k dvd m)"
   8.159 -  by (auto intro: relprime_dvd_mult dvd_mult2)
   8.160 -
   8.161 -lemma gcd_mult_cancel: "gcd k n = 1 ==> gcd (k * m) n = gcd m n"
   8.162 -  apply (rule dvd_anti_sym)
   8.163 -   apply (rule gcd_greatest)
   8.164 -    apply (rule_tac n = k in relprime_dvd_mult)
   8.165 -     apply (simp add: gcd_assoc)
   8.166 -     apply (simp add: gcd_commute)
   8.167 -    apply (simp_all add: mult_commute)
   8.168 -  done
   8.169 -
   8.170 -
   8.171 -text {* \medskip Addition laws *}
   8.172 -
   8.173 -lemma gcd_add1 [simp, algebra]: "gcd (m + n) n = gcd m n"
   8.174 -  by (cases "n = 0") (auto simp add: gcd_non_0)
   8.175 -
   8.176 -lemma gcd_add2 [simp, algebra]: "gcd m (m + n) = gcd m n"
   8.177 -proof -
   8.178 -  have "gcd m (m + n) = gcd (m + n) m" by (rule gcd_commute)
   8.179 -  also have "... = gcd (n + m) m" by (simp add: add_commute)
   8.180 -  also have "... = gcd n m" by simp
   8.181 -  also have  "... = gcd m n" by (rule gcd_commute)
   8.182 -  finally show ?thesis .
   8.183 -qed
   8.184 -
   8.185 -lemma gcd_add2' [simp, algebra]: "gcd m (n + m) = gcd m n"
   8.186 -  apply (subst add_commute)
   8.187 -  apply (rule gcd_add2)
   8.188 -  done
   8.189 -
   8.190 -lemma gcd_add_mult[algebra]: "gcd m (k * m + n) = gcd m n"
   8.191 -  by (induct k) (simp_all add: add_assoc)
   8.192 -
   8.193 -lemma gcd_dvd_prod: "gcd m n dvd m * n" 
   8.194 -  using mult_dvd_mono [of 1] by auto
   8.195 -
   8.196 -text {*
   8.197 -  \medskip Division by gcd yields rrelatively primes.
   8.198 -*}
   8.199 -
   8.200 -lemma div_gcd_relprime:
   8.201 -  assumes nz: "a \<noteq> 0 \<or> b \<noteq> 0"
   8.202 -  shows "gcd (a div gcd a b) (b div gcd a b) = 1"
   8.203 -proof -
   8.204 -  let ?g = "gcd a b"
   8.205 -  let ?a' = "a div ?g"
   8.206 -  let ?b' = "b div ?g"
   8.207 -  let ?g' = "gcd ?a' ?b'"
   8.208 -  have dvdg: "?g dvd a" "?g dvd b" by simp_all
   8.209 -  have dvdg': "?g' dvd ?a'" "?g' dvd ?b'" by simp_all
   8.210 -  from dvdg dvdg' obtain ka kb ka' kb' where
   8.211 -      kab: "a = ?g * ka" "b = ?g * kb" "?a' = ?g' * ka'" "?b' = ?g' * kb'"
   8.212 -    unfolding dvd_def by blast
   8.213 -  then have "?g * ?a' = (?g * ?g') * ka'" "?g * ?b' = (?g * ?g') * kb'" by simp_all
   8.214 -  then have dvdgg':"?g * ?g' dvd a" "?g* ?g' dvd b"
   8.215 -    by (auto simp add: dvd_mult_div_cancel [OF dvdg(1)]
   8.216 -      dvd_mult_div_cancel [OF dvdg(2)] dvd_def)
   8.217 -  have "?g \<noteq> 0" using nz by (simp add: gcd_zero)
   8.218 -  then have gp: "?g > 0" by simp
   8.219 -  from gcd_greatest [OF dvdgg'] have "?g * ?g' dvd ?g" .
   8.220 -  with dvd_mult_cancel1 [OF gp] show "?g' = 1" by simp
   8.221 -qed
   8.222 -
   8.223 -
   8.224 -lemma gcd_unique: "d dvd a\<and>d dvd b \<and> (\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d) \<longleftrightarrow> d = gcd a b"
   8.225 -proof(auto)
   8.226 -  assume H: "d dvd a" "d dvd b" "\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d"
   8.227 -  from H(3)[rule_format] gcd_dvd1[of a b] gcd_dvd2[of a b] 
   8.228 -  have th: "gcd a b dvd d" by blast
   8.229 -  from dvd_anti_sym[OF th gcd_greatest[OF H(1,2)]]  show "d = gcd a b" by blast 
   8.230 -qed
   8.231 -
   8.232 -lemma gcd_eq: assumes H: "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd u \<and> d dvd v"
   8.233 -  shows "gcd x y = gcd u v"
   8.234 -proof-
   8.235 -  from H have "\<forall>d. d dvd x \<and> d dvd y \<longleftrightarrow> d dvd gcd u v" by simp
   8.236 -  with gcd_unique[of "gcd u v" x y]  show ?thesis by auto
   8.237 -qed
   8.238 -
   8.239 -lemma ind_euclid: 
   8.240 -  assumes c: " \<forall>a b. P (a::nat) b \<longleftrightarrow> P b a" and z: "\<forall>a. P a 0" 
   8.241 -  and add: "\<forall>a b. P a b \<longrightarrow> P a (a + b)" 
   8.242 -  shows "P a b"
   8.243 -proof(induct n\<equiv>"a+b" arbitrary: a b rule: nat_less_induct)
   8.244 -  fix n a b
   8.245 -  assume H: "\<forall>m < n. \<forall>a b. m = a + b \<longrightarrow> P a b" "n = a + b"
   8.246 -  have "a = b \<or> a < b \<or> b < a" by arith
   8.247 -  moreover {assume eq: "a= b"
   8.248 -    from add[rule_format, OF z[rule_format, of a]] have "P a b" using eq by simp}
   8.249 -  moreover
   8.250 -  {assume lt: "a < b"
   8.251 -    hence "a + b - a < n \<or> a = 0"  using H(2) by arith
   8.252 -    moreover
   8.253 -    {assume "a =0" with z c have "P a b" by blast }
   8.254 -    moreover
   8.255 -    {assume ab: "a + b - a < n"
   8.256 -      have th0: "a + b - a = a + (b - a)" using lt by arith
   8.257 -      from add[rule_format, OF H(1)[rule_format, OF ab th0]]
   8.258 -      have "P a b" by (simp add: th0[symmetric])}
   8.259 -    ultimately have "P a b" by blast}
   8.260 -  moreover
   8.261 -  {assume lt: "a > b"
   8.262 -    hence "b + a - b < n \<or> b = 0"  using H(2) by arith
   8.263 -    moreover
   8.264 -    {assume "b =0" with z c have "P a b" by blast }
   8.265 -    moreover
   8.266 -    {assume ab: "b + a - b < n"
   8.267 -      have th0: "b + a - b = b + (a - b)" using lt by arith
   8.268 -      from add[rule_format, OF H(1)[rule_format, OF ab th0]]
   8.269 -      have "P b a" by (simp add: th0[symmetric])
   8.270 -      hence "P a b" using c by blast }
   8.271 -    ultimately have "P a b" by blast}
   8.272 -ultimately  show "P a b" by blast
   8.273 -qed
   8.274 -
   8.275 -lemma bezout_lemma: 
   8.276 -  assumes ex: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and> (a * x = b * y + d \<or> b * x = a * y + d)"
   8.277 -  shows "\<exists>d x y. d dvd a \<and> d dvd a + b \<and> (a * x = (a + b) * y + d \<or> (a + b) * x = a * y + d)"
   8.278 -using ex
   8.279 -apply clarsimp
   8.280 -apply (rule_tac x="d" in exI, simp add: dvd_add)
   8.281 -apply (case_tac "a * x = b * y + d" , simp_all)
   8.282 -apply (rule_tac x="x + y" in exI)
   8.283 -apply (rule_tac x="y" in exI)
   8.284 -apply algebra
   8.285 -apply (rule_tac x="x" in exI)
   8.286 -apply (rule_tac x="x + y" in exI)
   8.287 -apply algebra
   8.288 -done
   8.289 -
   8.290 -lemma bezout_add: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and> (a * x = b * y + d \<or> b * x = a * y + d)"
   8.291 -apply(induct a b rule: ind_euclid)
   8.292 -apply blast
   8.293 -apply clarify
   8.294 -apply (rule_tac x="a" in exI, simp add: dvd_add)
   8.295 -apply clarsimp
   8.296 -apply (rule_tac x="d" in exI)
   8.297 -apply (case_tac "a * x = b * y + d", simp_all add: dvd_add)
   8.298 -apply (rule_tac x="x+y" in exI)
   8.299 -apply (rule_tac x="y" in exI)
   8.300 -apply algebra
   8.301 -apply (rule_tac x="x" in exI)
   8.302 -apply (rule_tac x="x+y" in exI)
   8.303 -apply algebra
   8.304 -done
   8.305 -
   8.306 -lemma bezout: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and> (a * x - b * y = d \<or> b * x - a * y = d)"
   8.307 -using bezout_add[of a b]
   8.308 -apply clarsimp
   8.309 -apply (rule_tac x="d" in exI, simp)
   8.310 -apply (rule_tac x="x" in exI)
   8.311 -apply (rule_tac x="y" in exI)
   8.312 -apply auto
   8.313 -done
   8.314 -
   8.315 -
   8.316 -text {* We can get a stronger version with a nonzeroness assumption. *}
   8.317 -lemma divides_le: "m dvd n ==> m <= n \<or> n = (0::nat)" by (auto simp add: dvd_def)
   8.318 -
   8.319 -lemma bezout_add_strong: assumes nz: "a \<noteq> (0::nat)"
   8.320 -  shows "\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d"
   8.321 -proof-
   8.322 -  from nz have ap: "a > 0" by simp
   8.323 - from bezout_add[of a b] 
   8.324 - have "(\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d) \<or> (\<exists>d x y. d dvd a \<and> d dvd b \<and> b * x = a * y + d)" by blast
   8.325 - moreover
   8.326 - {fix d x y assume H: "d dvd a" "d dvd b" "a * x = b * y + d"
   8.327 -   from H have ?thesis by blast }
   8.328 - moreover
   8.329 - {fix d x y assume H: "d dvd a" "d dvd b" "b * x = a * y + d"
   8.330 -   {assume b0: "b = 0" with H  have ?thesis by simp}
   8.331 -   moreover 
   8.332 -   {assume b: "b \<noteq> 0" hence bp: "b > 0" by simp
   8.333 -     from divides_le[OF H(2)] b have "d < b \<or> d = b" using le_less by blast
   8.334 -     moreover
   8.335 -     {assume db: "d=b"
   8.336 -       from prems have ?thesis apply simp
   8.337 -	 apply (rule exI[where x = b], simp)
   8.338 -	 apply (rule exI[where x = b])
   8.339 -	by (rule exI[where x = "a - 1"], simp add: diff_mult_distrib2)}
   8.340 -    moreover
   8.341 -    {assume db: "d < b" 
   8.342 -	{assume "x=0" hence ?thesis  using prems by simp }
   8.343 -	moreover
   8.344 -	{assume x0: "x \<noteq> 0" hence xp: "x > 0" by simp
   8.345 -	  
   8.346 -	  from db have "d \<le> b - 1" by simp
   8.347 -	  hence "d*b \<le> b*(b - 1)" by simp
   8.348 -	  with xp mult_mono[of "1" "x" "d*b" "b*(b - 1)"]
   8.349 -	  have dble: "d*b \<le> x*b*(b - 1)" using bp by simp
   8.350 -	  from H (3) have "a * ((b - 1) * y) + d * (b - 1 + 1) = d + x*b*(b - 1)" by algebra
   8.351 -	  hence "a * ((b - 1) * y) = d + x*b*(b - 1) - d*b" using bp by simp
   8.352 -	  hence "a * ((b - 1) * y) = d + (x*b*(b - 1) - d*b)" 
   8.353 -	    by (simp only: diff_add_assoc[OF dble, of d, symmetric])
   8.354 -	  hence "a * ((b - 1) * y) = b*(x*(b - 1) - d) + d"
   8.355 -	    by (simp only: diff_mult_distrib2 add_commute mult_ac)
   8.356 -	  hence ?thesis using H(1,2)
   8.357 -	    apply -
   8.358 -	    apply (rule exI[where x=d], simp)
   8.359 -	    apply (rule exI[where x="(b - 1) * y"])
   8.360 -	    by (rule exI[where x="x*(b - 1) - d"], simp)}
   8.361 -	ultimately have ?thesis by blast}
   8.362 -    ultimately have ?thesis by blast}
   8.363 -  ultimately have ?thesis by blast}
   8.364 - ultimately show ?thesis by blast
   8.365 -qed
   8.366 -
   8.367 -
   8.368 -lemma bezout_gcd: "\<exists>x y. a * x - b * y = gcd a b \<or> b * x - a * y = gcd a b"
   8.369 -proof-
   8.370 -  let ?g = "gcd a b"
   8.371 -  from bezout[of a b] obtain d x y where d: "d dvd a" "d dvd b" "a * x - b * y = d \<or> b * x - a * y = d" by blast
   8.372 -  from d(1,2) have "d dvd ?g" by simp
   8.373 -  then obtain k where k: "?g = d*k" unfolding dvd_def by blast
   8.374 -  from d(3) have "(a * x - b * y)*k = d*k \<or> (b * x - a * y)*k = d*k" by blast 
   8.375 -  hence "a * x * k - b * y*k = d*k \<or> b * x * k - a * y*k = d*k" 
   8.376 -    by (algebra add: diff_mult_distrib)
   8.377 -  hence "a * (x * k) - b * (y*k) = ?g \<or> b * (x * k) - a * (y*k) = ?g" 
   8.378 -    by (simp add: k mult_assoc)
   8.379 -  thus ?thesis by blast
   8.380 -qed
   8.381 -
   8.382 -lemma bezout_gcd_strong: assumes a: "a \<noteq> 0" 
   8.383 -  shows "\<exists>x y. a * x = b * y + gcd a b"
   8.384 -proof-
   8.385 -  let ?g = "gcd a b"
   8.386 -  from bezout_add_strong[OF a, of b]
   8.387 -  obtain d x y where d: "d dvd a" "d dvd b" "a * x = b * y + d" by blast
   8.388 -  from d(1,2) have "d dvd ?g" by simp
   8.389 -  then obtain k where k: "?g = d*k" unfolding dvd_def by blast
   8.390 -  from d(3) have "a * x * k = (b * y + d) *k " by algebra
   8.391 -  hence "a * (x * k) = b * (y*k) + ?g" by (algebra add: k)
   8.392 -  thus ?thesis by blast
   8.393 -qed
   8.394 -
   8.395 -lemma gcd_mult_distrib: "gcd(a * c) (b * c) = c * gcd a b"
   8.396 -by(simp add: gcd_mult_distrib2 mult_commute)
   8.397 -
   8.398 -lemma gcd_bezout: "(\<exists>x y. a * x - b * y = d \<or> b * x - a * y = d) \<longleftrightarrow> gcd a b dvd d"
   8.399 -  (is "?lhs \<longleftrightarrow> ?rhs")
   8.400 -proof-
   8.401 -  let ?g = "gcd a b"
   8.402 -  {assume H: ?rhs then obtain k where k: "d = ?g*k" unfolding dvd_def by blast
   8.403 -    from bezout_gcd[of a b] obtain x y where xy: "a * x - b * y = ?g \<or> b * x - a * y = ?g"
   8.404 -      by blast
   8.405 -    hence "(a * x - b * y)*k = ?g*k \<or> (b * x - a * y)*k = ?g*k" by auto
   8.406 -    hence "a * x*k - b * y*k = ?g*k \<or> b * x * k - a * y*k = ?g*k" 
   8.407 -      by (simp only: diff_mult_distrib)
   8.408 -    hence "a * (x*k) - b * (y*k) = d \<or> b * (x * k) - a * (y*k) = d"
   8.409 -      by (simp add: k[symmetric] mult_assoc)
   8.410 -    hence ?lhs by blast}
   8.411 -  moreover
   8.412 -  {fix x y assume H: "a * x - b * y = d \<or> b * x - a * y = d"
   8.413 -    have dv: "?g dvd a*x" "?g dvd b * y" "?g dvd b*x" "?g dvd a * y"
   8.414 -      using dvd_mult2[OF gcd_dvd1[of a b]] dvd_mult2[OF gcd_dvd2[of a b]] by simp_all
   8.415 -    from dvd_diff_nat[OF dv(1,2)] dvd_diff_nat[OF dv(3,4)] H
   8.416 -    have ?rhs by auto}
   8.417 -  ultimately show ?thesis by blast
   8.418 -qed
   8.419 -
   8.420 -lemma gcd_bezout_sum: assumes H:"a * x + b * y = d" shows "gcd a b dvd d"
   8.421 -proof-
   8.422 -  let ?g = "gcd a b"
   8.423 -    have dv: "?g dvd a*x" "?g dvd b * y" 
   8.424 -      using dvd_mult2[OF gcd_dvd1[of a b]] dvd_mult2[OF gcd_dvd2[of a b]] by simp_all
   8.425 -    from dvd_add[OF dv] H
   8.426 -    show ?thesis by auto
   8.427 -qed
   8.428 -
   8.429 -lemma gcd_mult': "gcd b (a * b) = b"
   8.430 -by (simp add: gcd_mult mult_commute[of a b]) 
   8.431 -
   8.432 -lemma gcd_add: "gcd(a + b) b = gcd a b" 
   8.433 -  "gcd(b + a) b = gcd a b" "gcd a (a + b) = gcd a b" "gcd a (b + a) = gcd a b"
   8.434 -apply (simp_all add: gcd_add1)
   8.435 -by (simp add: gcd_commute gcd_add1)
   8.436 -
   8.437 -lemma gcd_sub: "b <= a ==> gcd(a - b) b = gcd a b" "a <= b ==> gcd a (b - a) = gcd a b"
   8.438 -proof-
   8.439 -  {fix a b assume H: "b \<le> (a::nat)"
   8.440 -    hence th: "a - b + b = a" by arith
   8.441 -    from gcd_add(1)[of "a - b" b] th  have "gcd(a - b) b = gcd a b" by simp}
   8.442 -  note th = this
   8.443 -{
   8.444 -  assume ab: "b \<le> a"
   8.445 -  from th[OF ab] show "gcd (a - b)  b = gcd a b" by blast
   8.446 -next
   8.447 -  assume ab: "a \<le> b"
   8.448 -  from th[OF ab] show "gcd a (b - a) = gcd a b" 
   8.449 -    by (simp add: gcd_commute)}
   8.450 -qed
   8.451 -
   8.452 -
   8.453 -subsection {* LCM defined by GCD *}
   8.454 -
   8.455 -
   8.456 -definition
   8.457 -  lcm :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   8.458 -where
   8.459 -  lcm_def: "lcm m n = m * n div gcd m n"
   8.460 -
   8.461 -lemma prod_gcd_lcm:
   8.462 -  "m * n = gcd m n * lcm m n"
   8.463 -  unfolding lcm_def by (simp add: dvd_mult_div_cancel [OF gcd_dvd_prod])
   8.464 -
   8.465 -lemma lcm_0 [simp]: "lcm m 0 = 0"
   8.466 -  unfolding lcm_def by simp
   8.467 -
   8.468 -lemma lcm_1 [simp]: "lcm m 1 = m"
   8.469 -  unfolding lcm_def by simp
   8.470 -
   8.471 -lemma lcm_0_left [simp]: "lcm 0 n = 0"
   8.472 -  unfolding lcm_def by simp
   8.473 -
   8.474 -lemma lcm_1_left [simp]: "lcm 1 m = m"
   8.475 -  unfolding lcm_def by simp
   8.476 -
   8.477 -lemma dvd_pos:
   8.478 -  fixes n m :: nat
   8.479 -  assumes "n > 0" and "m dvd n"
   8.480 -  shows "m > 0"
   8.481 -using assms by (cases m) auto
   8.482 -
   8.483 -lemma lcm_least:
   8.484 -  assumes "m dvd k" and "n dvd k"
   8.485 -  shows "lcm m n dvd k"
   8.486 -proof (cases k)
   8.487 -  case 0 then show ?thesis by auto
   8.488 -next
   8.489 -  case (Suc _) then have pos_k: "k > 0" by auto
   8.490 -  from assms dvd_pos [OF this] have pos_mn: "m > 0" "n > 0" by auto
   8.491 -  with gcd_zero [of m n] have pos_gcd: "gcd m n > 0" by simp
   8.492 -  from assms obtain p where k_m: "k = m * p" using dvd_def by blast
   8.493 -  from assms obtain q where k_n: "k = n * q" using dvd_def by blast
   8.494 -  from pos_k k_m have pos_p: "p > 0" by auto
   8.495 -  from pos_k k_n have pos_q: "q > 0" by auto
   8.496 -  have "k * k * gcd q p = k * gcd (k * q) (k * p)"
   8.497 -    by (simp add: mult_ac gcd_mult_distrib2)
   8.498 -  also have "\<dots> = k * gcd (m * p * q) (n * q * p)"
   8.499 -    by (simp add: k_m [symmetric] k_n [symmetric])
   8.500 -  also have "\<dots> = k * p * q * gcd m n"
   8.501 -    by (simp add: mult_ac gcd_mult_distrib2)
   8.502 -  finally have "(m * p) * (n * q) * gcd q p = k * p * q * gcd m n"
   8.503 -    by (simp only: k_m [symmetric] k_n [symmetric])
   8.504 -  then have "p * q * m * n * gcd q p = p * q * k * gcd m n"
   8.505 -    by (simp add: mult_ac)
   8.506 -  with pos_p pos_q have "m * n * gcd q p = k * gcd m n"
   8.507 -    by simp
   8.508 -  with prod_gcd_lcm [of m n]
   8.509 -  have "lcm m n * gcd q p * gcd m n = k * gcd m n"
   8.510 -    by (simp add: mult_ac)
   8.511 -  with pos_gcd have "lcm m n * gcd q p = k" by simp
   8.512 -  then show ?thesis using dvd_def by auto
   8.513 -qed
   8.514 -
   8.515 -lemma lcm_dvd1 [iff]:
   8.516 -  "m dvd lcm m n"
   8.517 -proof (cases m)
   8.518 -  case 0 then show ?thesis by simp
   8.519 -next
   8.520 -  case (Suc _)
   8.521 -  then have mpos: "m > 0" by simp
   8.522 -  show ?thesis
   8.523 -  proof (cases n)
   8.524 -    case 0 then show ?thesis by simp
   8.525 -  next
   8.526 -    case (Suc _)
   8.527 -    then have npos: "n > 0" by simp
   8.528 -    have "gcd m n dvd n" by simp
   8.529 -    then obtain k where "n = gcd m n * k" using dvd_def by auto
   8.530 -    then have "m * n div gcd m n = m * (gcd m n * k) div gcd m n" by (simp add: mult_ac)
   8.531 -    also have "\<dots> = m * k" using mpos npos gcd_zero by simp
   8.532 -    finally show ?thesis by (simp add: lcm_def)
   8.533 -  qed
   8.534 -qed
   8.535 -
   8.536 -lemma lcm_dvd2 [iff]: 
   8.537 -  "n dvd lcm m n"
   8.538 -proof (cases n)
   8.539 -  case 0 then show ?thesis by simp
   8.540 -next
   8.541 -  case (Suc _)
   8.542 -  then have npos: "n > 0" by simp
   8.543 -  show ?thesis
   8.544 -  proof (cases m)
   8.545 -    case 0 then show ?thesis by simp
   8.546 -  next
   8.547 -    case (Suc _)
   8.548 -    then have mpos: "m > 0" by simp
   8.549 -    have "gcd m n dvd m" by simp
   8.550 -    then obtain k where "m = gcd m n * k" using dvd_def by auto
   8.551 -    then have "m * n div gcd m n = (gcd m n * k) * n div gcd m n" by (simp add: mult_ac)
   8.552 -    also have "\<dots> = n * k" using mpos npos gcd_zero by simp
   8.553 -    finally show ?thesis by (simp add: lcm_def)
   8.554 -  qed
   8.555 -qed
   8.556 -
   8.557 -lemma gcd_add1_eq: "gcd (m + k) k = gcd (m + k) m"
   8.558 -  by (simp add: gcd_commute)
   8.559 -
   8.560 -lemma gcd_diff2: "m \<le> n ==> gcd n (n - m) = gcd n m"
   8.561 -  apply (subgoal_tac "n = m + (n - m)")
   8.562 -  apply (erule ssubst, rule gcd_add1_eq, simp)  
   8.563 -  done
   8.564 -
   8.565 -
   8.566 -subsection {* GCD and LCM on integers *}
   8.567 -
   8.568 -definition
   8.569 -  zgcd :: "int \<Rightarrow> int \<Rightarrow> int" where
   8.570 -  "zgcd i j = int (gcd (nat (abs i)) (nat (abs j)))"
   8.571 -
   8.572 -lemma zgcd_zdvd1 [iff,simp, algebra]: "zgcd i j dvd i"
   8.573 -by (simp add: zgcd_def int_dvd_iff)
   8.574 -
   8.575 -lemma zgcd_zdvd2 [iff,simp, algebra]: "zgcd i j dvd j"
   8.576 -by (simp add: zgcd_def int_dvd_iff)
   8.577 -
   8.578 -lemma zgcd_pos: "zgcd i j \<ge> 0"
   8.579 -by (simp add: zgcd_def)
   8.580 -
   8.581 -lemma zgcd0 [simp,algebra]: "(zgcd i j = 0) = (i = 0 \<and> j = 0)"
   8.582 -by (simp add: zgcd_def gcd_zero)
   8.583 -
   8.584 -lemma zgcd_commute: "zgcd i j = zgcd j i"
   8.585 -unfolding zgcd_def by (simp add: gcd_commute)
   8.586 -
   8.587 -lemma zgcd_zminus [simp, algebra]: "zgcd (- i) j = zgcd i j"
   8.588 -unfolding zgcd_def by simp
   8.589 -
   8.590 -lemma zgcd_zminus2 [simp, algebra]: "zgcd i (- j) = zgcd i j"
   8.591 -unfolding zgcd_def by simp
   8.592 -
   8.593 -  (* should be solved by algebra*)
   8.594 -lemma zrelprime_dvd_mult: "zgcd i j = 1 \<Longrightarrow> i dvd k * j \<Longrightarrow> i dvd k"
   8.595 -  unfolding zgcd_def
   8.596 -proof -
   8.597 -  assume "int (gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>)) = 1" "i dvd k * j"
   8.598 -  then have g: "gcd (nat \<bar>i\<bar>) (nat \<bar>j\<bar>) = 1" by simp
   8.599 -  from `i dvd k * j` obtain h where h: "k*j = i*h" unfolding dvd_def by blast
   8.600 -  have th: "nat \<bar>i\<bar> dvd nat \<bar>k\<bar> * nat \<bar>j\<bar>"
   8.601 -    unfolding dvd_def
   8.602 -    by (rule_tac x= "nat \<bar>h\<bar>" in exI, simp add: h nat_abs_mult_distrib [symmetric])
   8.603 -  from relprime_dvd_mult [OF g th] obtain h' where h': "nat \<bar>k\<bar> = nat \<bar>i\<bar> * h'"
   8.604 -    unfolding dvd_def by blast
   8.605 -  from h' have "int (nat \<bar>k\<bar>) = int (nat \<bar>i\<bar> * h')" by simp
   8.606 -  then have "\<bar>k\<bar> = \<bar>i\<bar> * int h'" by (simp add: int_mult)
   8.607 -  then show ?thesis
   8.608 -    apply (subst abs_dvd_iff [symmetric])
   8.609 -    apply (subst dvd_abs_iff [symmetric])
   8.610 -    apply (unfold dvd_def)
   8.611 -    apply (rule_tac x = "int h'" in exI, simp)
   8.612 -    done
   8.613 -qed
   8.614 -
   8.615 -lemma int_nat_abs: "int (nat (abs x)) = abs x" by arith
   8.616 -
   8.617 -lemma zgcd_greatest:
   8.618 -  assumes "k dvd m" and "k dvd n"
   8.619 -  shows "k dvd zgcd m n"
   8.620 -proof -
   8.621 -  let ?k' = "nat \<bar>k\<bar>"
   8.622 -  let ?m' = "nat \<bar>m\<bar>"
   8.623 -  let ?n' = "nat \<bar>n\<bar>"
   8.624 -  from `k dvd m` and `k dvd n` have dvd': "?k' dvd ?m'" "?k' dvd ?n'"
   8.625 -    unfolding zdvd_int by (simp_all only: int_nat_abs abs_dvd_iff dvd_abs_iff)
   8.626 -  from gcd_greatest [OF dvd'] have "int (nat \<bar>k\<bar>) dvd zgcd m n"
   8.627 -    unfolding zgcd_def by (simp only: zdvd_int)
   8.628 -  then have "\<bar>k\<bar> dvd zgcd m n" by (simp only: int_nat_abs)
   8.629 -  then show "k dvd zgcd m n" by simp
   8.630 -qed
   8.631 -
   8.632 -lemma div_zgcd_relprime:
   8.633 -  assumes nz: "a \<noteq> 0 \<or> b \<noteq> 0"
   8.634 -  shows "zgcd (a div (zgcd a b)) (b div (zgcd a b)) = 1"
   8.635 -proof -
   8.636 -  from nz have nz': "nat \<bar>a\<bar> \<noteq> 0 \<or> nat \<bar>b\<bar> \<noteq> 0" by arith 
   8.637 -  let ?g = "zgcd a b"
   8.638 -  let ?a' = "a div ?g"
   8.639 -  let ?b' = "b div ?g"
   8.640 -  let ?g' = "zgcd ?a' ?b'"
   8.641 -  have dvdg: "?g dvd a" "?g dvd b" by (simp_all add: zgcd_zdvd1 zgcd_zdvd2)
   8.642 -  have dvdg': "?g' dvd ?a'" "?g' dvd ?b'" by (simp_all add: zgcd_zdvd1 zgcd_zdvd2)
   8.643 -  from dvdg dvdg' obtain ka kb ka' kb' where
   8.644 -   kab: "a = ?g*ka" "b = ?g*kb" "?a' = ?g'*ka'" "?b' = ?g' * kb'"
   8.645 -    unfolding dvd_def by blast
   8.646 -  then have "?g* ?a' = (?g * ?g') * ka'" "?g* ?b' = (?g * ?g') * kb'" by simp_all
   8.647 -  then have dvdgg':"?g * ?g' dvd a" "?g* ?g' dvd b"
   8.648 -    by (auto simp add: zdvd_mult_div_cancel [OF dvdg(1)]
   8.649 -      zdvd_mult_div_cancel [OF dvdg(2)] dvd_def)
   8.650 -  have "?g \<noteq> 0" using nz by simp
   8.651 -  then have gp: "?g \<noteq> 0" using zgcd_pos[where i="a" and j="b"] by arith
   8.652 -  from zgcd_greatest [OF dvdgg'] have "?g * ?g' dvd ?g" .
   8.653 -  with zdvd_mult_cancel1 [OF gp] have "\<bar>?g'\<bar> = 1" by simp
   8.654 -  with zgcd_pos show "?g' = 1" by simp
   8.655 -qed
   8.656 -
   8.657 -lemma zgcd_0 [simp, algebra]: "zgcd m 0 = abs m"
   8.658 -  by (simp add: zgcd_def abs_if)
   8.659 -
   8.660 -lemma zgcd_0_left [simp, algebra]: "zgcd 0 m = abs m"
   8.661 -  by (simp add: zgcd_def abs_if)
   8.662 -
   8.663 -lemma zgcd_non_0: "0 < n ==> zgcd m n = zgcd n (m mod n)"
   8.664 -  apply (frule_tac b = n and a = m in pos_mod_sign)
   8.665 -  apply (simp del: pos_mod_sign add: zgcd_def abs_if nat_mod_distrib)
   8.666 -  apply (auto simp add: gcd_non_0 nat_mod_distrib [symmetric] zmod_zminus1_eq_if)
   8.667 -  apply (frule_tac a = m in pos_mod_bound)
   8.668 -  apply (simp del: pos_mod_bound add: nat_diff_distrib gcd_diff2 nat_le_eq_zle)
   8.669 -  done
   8.670 -
   8.671 -lemma zgcd_eq: "zgcd m n = zgcd n (m mod n)"
   8.672 -  apply (case_tac "n = 0", simp add: DIVISION_BY_ZERO)
   8.673 -  apply (auto simp add: linorder_neq_iff zgcd_non_0)
   8.674 -  apply (cut_tac m = "-m" and n = "-n" in zgcd_non_0, auto)
   8.675 -  done
   8.676 -
   8.677 -lemma zgcd_1 [simp, algebra]: "zgcd m 1 = 1"
   8.678 -  by (simp add: zgcd_def abs_if)
   8.679 -
   8.680 -lemma zgcd_0_1_iff [simp, algebra]: "zgcd 0 m = 1 \<longleftrightarrow> \<bar>m\<bar> = 1"
   8.681 -  by (simp add: zgcd_def abs_if)
   8.682 -
   8.683 -lemma zgcd_greatest_iff[algebra]: "k dvd zgcd m n = (k dvd m \<and> k dvd n)"
   8.684 -  by (simp add: zgcd_def abs_if int_dvd_iff dvd_int_iff nat_dvd_iff)
   8.685 -
   8.686 -lemma zgcd_1_left [simp, algebra]: "zgcd 1 m = 1"
   8.687 -  by (simp add: zgcd_def gcd_1_left)
   8.688 -
   8.689 -lemma zgcd_assoc: "zgcd (zgcd k m) n = zgcd k (zgcd m n)"
   8.690 -  by (simp add: zgcd_def gcd_assoc)
   8.691 -
   8.692 -lemma zgcd_left_commute: "zgcd k (zgcd m n) = zgcd m (zgcd k n)"
   8.693 -  apply (rule zgcd_commute [THEN trans])
   8.694 -  apply (rule zgcd_assoc [THEN trans])
   8.695 -  apply (rule zgcd_commute [THEN arg_cong])
   8.696 -  done
   8.697 -
   8.698 -lemmas zgcd_ac = zgcd_assoc zgcd_commute zgcd_left_commute
   8.699 -  -- {* addition is an AC-operator *}
   8.700 -
   8.701 -lemma zgcd_zmult_distrib2: "0 \<le> k ==> k * zgcd m n = zgcd (k * m) (k * n)"
   8.702 -  by (simp del: minus_mult_right [symmetric]
   8.703 -      add: minus_mult_right nat_mult_distrib zgcd_def abs_if
   8.704 -          mult_less_0_iff gcd_mult_distrib2 [symmetric] zmult_int [symmetric])
   8.705 -
   8.706 -lemma zgcd_zmult_distrib2_abs: "zgcd (k * m) (k * n) = abs k * zgcd m n"
   8.707 -  by (simp add: abs_if zgcd_zmult_distrib2)
   8.708 -
   8.709 -lemma zgcd_self [simp]: "0 \<le> m ==> zgcd m m = m"
   8.710 -  by (cut_tac k = m and m = 1 and n = 1 in zgcd_zmult_distrib2, simp_all)
   8.711 -
   8.712 -lemma zgcd_zmult_eq_self [simp]: "0 \<le> k ==> zgcd k (k * n) = k"
   8.713 -  by (cut_tac k = k and m = 1 and n = n in zgcd_zmult_distrib2, simp_all)
   8.714 -
   8.715 -lemma zgcd_zmult_eq_self2 [simp]: "0 \<le> k ==> zgcd (k * n) k = k"
   8.716 -  by (cut_tac k = k and m = n and n = 1 in zgcd_zmult_distrib2, simp_all)
   8.717 -
   8.718 -
   8.719 -definition "zlcm i j = int (lcm(nat(abs i)) (nat(abs j)))"
   8.720 -
   8.721 -lemma dvd_zlcm_self1[simp, algebra]: "i dvd zlcm i j"
   8.722 -by(simp add:zlcm_def dvd_int_iff)
   8.723 -
   8.724 -lemma dvd_zlcm_self2[simp, algebra]: "j dvd zlcm i j"
   8.725 -by(simp add:zlcm_def dvd_int_iff)
   8.726 -
   8.727 -
   8.728 -lemma dvd_imp_dvd_zlcm1:
   8.729 -  assumes "k dvd i" shows "k dvd (zlcm i j)"
   8.730 -proof -
   8.731 -  have "nat(abs k) dvd nat(abs i)" using `k dvd i`
   8.732 -    by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric])
   8.733 -  thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans)
   8.734 -qed
   8.735 -
   8.736 -lemma dvd_imp_dvd_zlcm2:
   8.737 -  assumes "k dvd j" shows "k dvd (zlcm i j)"
   8.738 -proof -
   8.739 -  have "nat(abs k) dvd nat(abs j)" using `k dvd j`
   8.740 -    by(simp add:int_dvd_iff[symmetric] dvd_int_iff[symmetric])
   8.741 -  thus ?thesis by(simp add:zlcm_def dvd_int_iff)(blast intro: dvd_trans)
   8.742 -qed
   8.743 -
   8.744 -
   8.745 -lemma zdvd_self_abs1: "(d::int) dvd (abs d)"
   8.746 -by (case_tac "d <0", simp_all)
   8.747 -
   8.748 -lemma zdvd_self_abs2: "(abs (d::int)) dvd d"
   8.749 -by (case_tac "d<0", simp_all)
   8.750 -
   8.751 -(* lcm a b is positive for positive a and b *)
   8.752 -
   8.753 -lemma lcm_pos: 
   8.754 -  assumes mpos: "m > 0"
   8.755 -  and npos: "n>0"
   8.756 -  shows "lcm m n > 0"
   8.757 -proof(rule ccontr, simp add: lcm_def gcd_zero)
   8.758 -assume h:"m*n div gcd m n = 0"
   8.759 -from mpos npos have "gcd m n \<noteq> 0" using gcd_zero by simp
   8.760 -hence gcdp: "gcd m n > 0" by simp
   8.761 -with h
   8.762 -have "m*n < gcd m n"
   8.763 -  by (cases "m * n < gcd m n") (auto simp add: div_if[OF gcdp, where m="m*n"])
   8.764 -moreover 
   8.765 -have "gcd m n dvd m" by simp
   8.766 - with mpos dvd_imp_le have t1:"gcd m n \<le> m" by simp
   8.767 - with npos have t1:"gcd m n *n \<le> m*n" by simp
   8.768 - have "gcd m n \<le> gcd m n*n" using npos by simp
   8.769 - with t1 have "gcd m n \<le> m*n" by arith
   8.770 -ultimately show "False" by simp
   8.771 -qed
   8.772 -
   8.773 -lemma zlcm_pos: 
   8.774 -  assumes anz: "a \<noteq> 0"
   8.775 -  and bnz: "b \<noteq> 0" 
   8.776 -  shows "0 < zlcm a b"
   8.777 -proof-
   8.778 -  let ?na = "nat (abs a)"
   8.779 -  let ?nb = "nat (abs b)"
   8.780 -  have nap: "?na >0" using anz by simp
   8.781 -  have nbp: "?nb >0" using bnz by simp
   8.782 -  have "0 < lcm ?na ?nb" by (rule lcm_pos[OF nap nbp])
   8.783 -  thus ?thesis by (simp add: zlcm_def)
   8.784 -qed
   8.785 -
   8.786 -lemma zgcd_code [code]:
   8.787 -  "zgcd k l = \<bar>if l = 0 then k else zgcd l (\<bar>k\<bar> mod \<bar>l\<bar>)\<bar>"
   8.788 -  by (simp add: zgcd_def gcd.simps [of "nat \<bar>k\<bar>"] nat_mod_distrib)
   8.789 -
   8.790 -end
     9.1 --- a/src/HOL/Library/Library.thy	Tue Sep 01 14:13:34 2009 +0200
     9.2 +++ b/src/HOL/Library/Library.thy	Tue Sep 01 15:39:33 2009 +0200
     9.3 @@ -43,11 +43,9 @@
     9.4    OptionalSugar
     9.5    Option_ord
     9.6    Permutation
     9.7 -  Pocklington
     9.8    Poly_Deriv
     9.9    Polynomial
    9.10    Preorder
    9.11 -  Primes
    9.12    Product_Vector
    9.13    Quicksort
    9.14    Quotient
    10.1 --- a/src/HOL/Library/Pocklington.thy	Tue Sep 01 14:13:34 2009 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,1263 +0,0 @@
    10.4 -(*  Title:      HOL/Library/Pocklington.thy
    10.5 -    Author:     Amine Chaieb
    10.6 -*)
    10.7 -
    10.8 -header {* Pocklington's Theorem for Primes *}
    10.9 -
   10.10 -theory Pocklington
   10.11 -imports Main Primes
   10.12 -begin
   10.13 -
   10.14 -definition modeq:: "nat => nat => nat => bool"    ("(1[_ = _] '(mod _'))")
   10.15 -  where "[a = b] (mod p) == ((a mod p) = (b mod p))"
   10.16 -
   10.17 -definition modneq:: "nat => nat => nat => bool"    ("(1[_ \<noteq> _] '(mod _'))")
   10.18 -  where "[a \<noteq> b] (mod p) == ((a mod p) \<noteq> (b mod p))"
   10.19 -
   10.20 -lemma modeq_trans:
   10.21 -  "\<lbrakk> [a = b] (mod p); [b = c] (mod p) \<rbrakk> \<Longrightarrow> [a = c] (mod p)"
   10.22 -  by (simp add:modeq_def)
   10.23 -
   10.24 -
   10.25 -lemma nat_mod_lemma: assumes xyn: "[x = y] (mod n)" and xy:"y \<le> x"
   10.26 -  shows "\<exists>q. x = y + n * q"
   10.27 -using xyn xy unfolding modeq_def using nat_mod_eq_lemma by blast
   10.28 -
   10.29 -lemma nat_mod[algebra]: "[x = y] (mod n) \<longleftrightarrow> (\<exists>q1 q2. x + n * q1 = y + n * q2)"
   10.30 -unfolding modeq_def nat_mod_eq_iff ..
   10.31 -
   10.32 -(* Lemmas about previously defined terms.                                    *)
   10.33 -
   10.34 -lemma prime: "prime p \<longleftrightarrow> p \<noteq> 0 \<and> p\<noteq>1 \<and> (\<forall>m. 0 < m \<and> m < p \<longrightarrow> coprime p m)"
   10.35 -  (is "?lhs \<longleftrightarrow> ?rhs")
   10.36 -proof-
   10.37 -  {assume "p=0 \<or> p=1" hence ?thesis using prime_0 prime_1 by (cases "p=0", simp_all)}
   10.38 -  moreover
   10.39 -  {assume p0: "p\<noteq>0" "p\<noteq>1"
   10.40 -    {assume H: "?lhs"
   10.41 -      {fix m assume m: "m > 0" "m < p"
   10.42 -	{assume "m=1" hence "coprime p m" by simp}
   10.43 -	moreover
   10.44 -	{assume "p dvd m" hence "p \<le> m" using dvd_imp_le m by blast with m(2)
   10.45 -	  have "coprime p m" by simp}
   10.46 -	ultimately have "coprime p m" using prime_coprime[OF H, of m] by blast}
   10.47 -      hence ?rhs using p0 by auto}
   10.48 -    moreover
   10.49 -    { assume H: "\<forall>m. 0 < m \<and> m < p \<longrightarrow> coprime p m"
   10.50 -      from prime_factor[OF p0(2)] obtain q where q: "prime q" "q dvd p" by blast
   10.51 -      from prime_ge_2[OF q(1)] have q0: "q > 0" by arith
   10.52 -      from dvd_imp_le[OF q(2)] p0 have qp: "q \<le> p" by arith
   10.53 -      {assume "q = p" hence ?lhs using q(1) by blast}
   10.54 -      moreover
   10.55 -      {assume "q\<noteq>p" with qp have qplt: "q < p" by arith
   10.56 -	from H[rule_format, of q] qplt q0 have "coprime p q" by arith
   10.57 -	with coprime_prime[of p q q] q have False by simp hence ?lhs by blast}
   10.58 -      ultimately have ?lhs by blast}
   10.59 -    ultimately have ?thesis by blast}
   10.60 -  ultimately show ?thesis  by (cases"p=0 \<or> p=1", auto)
   10.61 -qed
   10.62 -
   10.63 -lemma finite_number_segment: "card { m. 0 < m \<and> m < n } = n - 1"
   10.64 -proof-
   10.65 -  have "{ m. 0 < m \<and> m < n } = {1..<n}" by auto
   10.66 -  thus ?thesis by simp
   10.67 -qed
   10.68 -
   10.69 -lemma coprime_mod: assumes n: "n \<noteq> 0" shows "coprime (a mod n) n \<longleftrightarrow> coprime a n"
   10.70 -  using n dvd_mod_iff[of _ n a] by (auto simp add: coprime)
   10.71 -
   10.72 -(* Congruences.                                                              *)
   10.73 -
   10.74 -lemma cong_mod_01[simp,presburger]:
   10.75 -  "[x = y] (mod 0) \<longleftrightarrow> x = y" "[x = y] (mod 1)" "[x = 0] (mod n) \<longleftrightarrow> n dvd x"
   10.76 -  by (simp_all add: modeq_def, presburger)
   10.77 -
   10.78 -lemma cong_sub_cases:
   10.79 -  "[x = y] (mod n) \<longleftrightarrow> (if x <= y then [y - x = 0] (mod n) else [x - y = 0] (mod n))"
   10.80 -apply (auto simp add: nat_mod)
   10.81 -apply (rule_tac x="q2" in exI)
   10.82 -apply (rule_tac x="q1" in exI, simp)
   10.83 -apply (rule_tac x="q2" in exI)
   10.84 -apply (rule_tac x="q1" in exI, simp)
   10.85 -apply (rule_tac x="q1" in exI)
   10.86 -apply (rule_tac x="q2" in exI, simp)
   10.87 -apply (rule_tac x="q1" in exI)
   10.88 -apply (rule_tac x="q2" in exI, simp)
   10.89 -done
   10.90 -
   10.91 -lemma cong_mult_lcancel: assumes an: "coprime a n" and axy:"[a * x = a * y] (mod n)"
   10.92 -  shows "[x = y] (mod n)"
   10.93 -proof-
   10.94 -  {assume "a = 0" with an axy coprime_0'[of n] have ?thesis by (simp add: modeq_def) }
   10.95 -  moreover
   10.96 -  {assume az: "a\<noteq>0"
   10.97 -    {assume xy: "x \<le> y" hence axy': "a*x \<le> a*y" by simp
   10.98 -      with axy cong_sub_cases[of "a*x" "a*y" n]  have "[a*(y - x) = 0] (mod n)"
   10.99 -	by (simp only: if_True diff_mult_distrib2)
  10.100 -      hence th: "n dvd a*(y -x)" by simp
  10.101 -      from coprime_divprod[OF th] an have "n dvd y - x"
  10.102 -	by (simp add: coprime_commute)
  10.103 -      hence ?thesis using xy cong_sub_cases[of x y n] by simp}
  10.104 -    moreover
  10.105 -    {assume H: "\<not>x \<le> y" hence xy: "y \<le> x"  by arith
  10.106 -      from H az have axy': "\<not> a*x \<le> a*y" by auto
  10.107 -      with axy H cong_sub_cases[of "a*x" "a*y" n]  have "[a*(x - y) = 0] (mod n)"
  10.108 -	by (simp only: if_False diff_mult_distrib2)
  10.109 -      hence th: "n dvd a*(x - y)" by simp
  10.110 -      from coprime_divprod[OF th] an have "n dvd x - y"
  10.111 -	by (simp add: coprime_commute)
  10.112 -      hence ?thesis using xy cong_sub_cases[of x y n] by simp}
  10.113 -    ultimately have ?thesis by blast}
  10.114 -  ultimately show ?thesis by blast
  10.115 -qed
  10.116 -
  10.117 -lemma cong_mult_rcancel: assumes an: "coprime a n" and axy:"[x*a = y*a] (mod n)"
  10.118 -  shows "[x = y] (mod n)"
  10.119 -  using cong_mult_lcancel[OF an axy[unfolded mult_commute[of _a]]] .
  10.120 -
  10.121 -lemma cong_refl: "[x = x] (mod n)" by (simp add: modeq_def)
  10.122 -
  10.123 -lemma eq_imp_cong: "a = b \<Longrightarrow> [a = b] (mod n)" by (simp add: cong_refl)
  10.124 -
  10.125 -lemma cong_commute: "[x = y] (mod n) \<longleftrightarrow> [y = x] (mod n)"
  10.126 -  by (auto simp add: modeq_def)
  10.127 -
  10.128 -lemma cong_trans[trans]: "[x = y] (mod n) \<Longrightarrow> [y = z] (mod n) \<Longrightarrow> [x = z] (mod n)"
  10.129 -  by (simp add: modeq_def)
  10.130 -
  10.131 -lemma cong_add: assumes xx': "[x = x'] (mod n)" and yy':"[y = y'] (mod n)"
  10.132 -  shows "[x + y = x' + y'] (mod n)"
  10.133 -proof-
  10.134 -  have "(x + y) mod n = (x mod n + y mod n) mod n"
  10.135 -    by (simp add: mod_add_left_eq[of x y n] mod_add_right_eq[of "x mod n" y n])
  10.136 -  also have "\<dots> = (x' mod n + y' mod n) mod n" using xx' yy' modeq_def by simp
  10.137 -  also have "\<dots> = (x' + y') mod n"
  10.138 -    by (simp add: mod_add_left_eq[of x' y' n] mod_add_right_eq[of "x' mod n" y' n])
  10.139 -  finally show ?thesis unfolding modeq_def .
  10.140 -qed
  10.141 -
  10.142 -lemma cong_mult: assumes xx': "[x = x'] (mod n)" and yy':"[y = y'] (mod n)"
  10.143 -  shows "[x * y = x' * y'] (mod n)"
  10.144 -proof-
  10.145 -  have "(x * y) mod n = (x mod n) * (y mod n) mod n"
  10.146 -    by (simp add: mod_mult_left_eq[of x y n] mod_mult_right_eq[of "x mod n" y n])
  10.147 -  also have "\<dots> = (x' mod n) * (y' mod n) mod n" using xx'[unfolded modeq_def] yy'[unfolded modeq_def] by simp
  10.148 -  also have "\<dots> = (x' * y') mod n"
  10.149 -    by (simp add: mod_mult_left_eq[of x' y' n] mod_mult_right_eq[of "x' mod n" y' n])
  10.150 -  finally show ?thesis unfolding modeq_def .
  10.151 -qed
  10.152 -
  10.153 -lemma cong_exp: "[x = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
  10.154 -  by (induct k, auto simp add: cong_refl cong_mult)
  10.155 -lemma cong_sub: assumes xx': "[x = x'] (mod n)" and yy': "[y = y'] (mod n)"
  10.156 -  and yx: "y <= x" and yx': "y' <= x'"
  10.157 -  shows "[x - y = x' - y'] (mod n)"
  10.158 -proof-
  10.159 -  { fix x a x' a' y b y' b'
  10.160 -    have "(x::nat) + a = x' + a' \<Longrightarrow> y + b = y' + b' \<Longrightarrow> y <= x \<Longrightarrow> y' <= x'
  10.161 -      \<Longrightarrow> (x - y) + (a + b') = (x' - y') + (a' + b)" by arith}
  10.162 -  note th = this
  10.163 -  from xx' yy' obtain q1 q2 q1' q2' where q12: "x + n*q1 = x'+n*q2"
  10.164 -    and q12': "y + n*q1' = y'+n*q2'" unfolding nat_mod by blast+
  10.165 -  from th[OF q12 q12' yx yx']
  10.166 -  have "(x - y) + n*(q1 + q2') = (x' - y') + n*(q2 + q1')"
  10.167 -    by (simp add: right_distrib)
  10.168 -  thus ?thesis unfolding nat_mod by blast
  10.169 -qed
  10.170 -
  10.171 -lemma cong_mult_lcancel_eq: assumes an: "coprime a n"
  10.172 -  shows "[a * x = a * y] (mod n) \<longleftrightarrow> [x = y] (mod n)" (is "?lhs \<longleftrightarrow> ?rhs")
  10.173 -proof
  10.174 -  assume H: "?rhs" from cong_mult[OF cong_refl[of a n] H] show ?lhs .
  10.175 -next
  10.176 -  assume H: "?lhs" hence H': "[x*a = y*a] (mod n)" by (simp add: mult_commute)
  10.177 -  from cong_mult_rcancel[OF an H'] show ?rhs  .
  10.178 -qed
  10.179 -
  10.180 -lemma cong_mult_rcancel_eq: assumes an: "coprime a n"
  10.181 -  shows "[x * a = y * a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
  10.182 -using cong_mult_lcancel_eq[OF an, of x y] by (simp add: mult_commute)
  10.183 -
  10.184 -lemma cong_add_lcancel_eq: "[a + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)"
  10.185 -  by (simp add: nat_mod)
  10.186 -
  10.187 -lemma cong_add_rcancel_eq: "[x + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
  10.188 -  by (simp add: nat_mod)
  10.189 -
  10.190 -lemma cong_add_rcancel: "[x + a = y + a] (mod n) \<Longrightarrow> [x = y] (mod n)"
  10.191 -  by (simp add: nat_mod)
  10.192 -
  10.193 -lemma cong_add_lcancel: "[a + x = a + y] (mod n) \<Longrightarrow> [x = y] (mod n)"
  10.194 -  by (simp add: nat_mod)
  10.195 -
  10.196 -lemma cong_add_lcancel_eq_0: "[a + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)"
  10.197 -  by (simp add: nat_mod)
  10.198 -
  10.199 -lemma cong_add_rcancel_eq_0: "[x + a = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)"
  10.200 -  by (simp add: nat_mod)
  10.201 -
  10.202 -lemma cong_imp_eq: assumes xn: "x < n" and yn: "y < n" and xy: "[x = y] (mod n)"
  10.203 -  shows "x = y"
  10.204 -  using xy[unfolded modeq_def mod_less[OF xn] mod_less[OF yn]] .
  10.205 -
  10.206 -lemma cong_divides_modulus: "[x = y] (mod m) \<Longrightarrow> n dvd m ==> [x = y] (mod n)"
  10.207 -  apply (auto simp add: nat_mod dvd_def)
  10.208 -  apply (rule_tac x="k*q1" in exI)
  10.209 -  apply (rule_tac x="k*q2" in exI)
  10.210 -  by simp
  10.211 -
  10.212 -lemma cong_0_divides: "[x = 0] (mod n) \<longleftrightarrow> n dvd x" by simp
  10.213 -
  10.214 -lemma cong_1_divides:"[x = 1] (mod n) ==> n dvd x - 1"
  10.215 -  apply (cases "x\<le>1", simp_all)
  10.216 -  using cong_sub_cases[of x 1 n] by auto
  10.217 -
  10.218 -lemma cong_divides: "[x = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
  10.219 -apply (auto simp add: nat_mod dvd_def)
  10.220 -apply (rule_tac x="k + q1 - q2" in exI, simp add: add_mult_distrib2 diff_mult_distrib2)
  10.221 -apply (rule_tac x="k + q2 - q1" in exI, simp add: add_mult_distrib2 diff_mult_distrib2)
  10.222 -done
  10.223 -
  10.224 -lemma cong_coprime: assumes xy: "[x = y] (mod n)"
  10.225 -  shows "coprime n x \<longleftrightarrow> coprime n y"
  10.226 -proof-
  10.227 -  {assume "n=0" hence ?thesis using xy by simp}
  10.228 -  moreover
  10.229 -  {assume nz: "n \<noteq> 0"
  10.230 -  have "coprime n x \<longleftrightarrow> coprime (x mod n) n"
  10.231 -    by (simp add: coprime_mod[OF nz, of x] coprime_commute[of n x])
  10.232 -  also have "\<dots> \<longleftrightarrow> coprime (y mod n) n" using xy[unfolded modeq_def] by simp
  10.233 -  also have "\<dots> \<longleftrightarrow> coprime y n" by (simp add: coprime_mod[OF nz, of y])
  10.234 -  finally have ?thesis by (simp add: coprime_commute) }
  10.235 -ultimately show ?thesis by blast
  10.236 -qed
  10.237 -
  10.238 -lemma cong_mod: "~(n = 0) \<Longrightarrow> [a mod n = a] (mod n)" by (simp add: modeq_def)
  10.239 -
  10.240 -lemma mod_mult_cong: "~(a = 0) \<Longrightarrow> ~(b = 0)
  10.241 -  \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
  10.242 -  by (simp add: modeq_def mod_mult2_eq mod_add_left_eq)
  10.243 -
  10.244 -lemma cong_mod_mult: "[x = y] (mod n) \<Longrightarrow> m dvd n \<Longrightarrow> [x = y] (mod m)"
  10.245 -  apply (auto simp add: nat_mod dvd_def)
  10.246 -  apply (rule_tac x="k*q1" in exI)
  10.247 -  apply (rule_tac x="k*q2" in exI, simp)
  10.248 -  done
  10.249 -
  10.250 -(* Some things when we know more about the order.                            *)
  10.251 -
  10.252 -lemma cong_le: "y <= x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)"
  10.253 -  using nat_mod_lemma[of x y n]
  10.254 -  apply auto
  10.255 -  apply (simp add: nat_mod)
  10.256 -  apply (rule_tac x="q" in exI)
  10.257 -  apply (rule_tac x="q + q" in exI)
  10.258 -  by (auto simp: algebra_simps)
  10.259 -
  10.260 -lemma cong_to_1: "[a = 1] (mod n) \<longleftrightarrow> a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)"
  10.261 -proof-
  10.262 -  {assume "n = 0 \<or> n = 1\<or> a = 0 \<or> a = 1" hence ?thesis
  10.263 -      apply (cases "n=0", simp_all add: cong_commute)
  10.264 -      apply (cases "n=1", simp_all add: cong_commute modeq_def)
  10.265 -      apply arith
  10.266 -      by (cases "a=1", simp_all add: modeq_def cong_commute)}
  10.267 -  moreover
  10.268 -  {assume n: "n\<noteq>0" "n\<noteq>1" and a:"a\<noteq>0" "a \<noteq> 1" hence a': "a \<ge> 1" by simp
  10.269 -    hence ?thesis using cong_le[OF a', of n] by auto }
  10.270 -  ultimately show ?thesis by auto
  10.271 -qed
  10.272 -
  10.273 -(* Some basic theorems about solving congruences.                            *)
  10.274 -
  10.275 -
  10.276 -lemma cong_solve: assumes an: "coprime a n" shows "\<exists>x. [a * x = b] (mod n)"
  10.277 -proof-
  10.278 -  {assume "a=0" hence ?thesis using an by (simp add: modeq_def)}
  10.279 -  moreover
  10.280 -  {assume az: "a\<noteq>0"
  10.281 -  from bezout_add_strong[OF az, of n]
  10.282 -  obtain d x y where dxy: "d dvd a" "d dvd n" "a*x = n*y + d" by blast
  10.283 -  from an[unfolded coprime, rule_format, of d] dxy(1,2) have d1: "d = 1" by blast
  10.284 -  hence "a*x*b = (n*y + 1)*b" using dxy(3) by simp
  10.285 -  hence "a*(x*b) = n*(y*b) + b" by algebra
  10.286 -  hence "a*(x*b) mod n = (n*(y*b) + b) mod n" by simp
  10.287 -  hence "a*(x*b) mod n = b mod n" by (simp add: mod_add_left_eq)
  10.288 -  hence "[a*(x*b) = b] (mod n)" unfolding modeq_def .
  10.289 -  hence ?thesis by blast}
  10.290 -ultimately  show ?thesis by blast
  10.291 -qed
  10.292 -
  10.293 -lemma cong_solve_unique: assumes an: "coprime a n" and nz: "n \<noteq> 0"
  10.294 -  shows "\<exists>!x. x < n \<and> [a * x = b] (mod n)"
  10.295 -proof-
  10.296 -  let ?P = "\<lambda>x. x < n \<and> [a * x = b] (mod n)"
  10.297 -  from cong_solve[OF an] obtain x where x: "[a*x = b] (mod n)" by blast
  10.298 -  let ?x = "x mod n"
  10.299 -  from x have th: "[a * ?x = b] (mod n)"
  10.300 -    by (simp add: modeq_def mod_mult_right_eq[of a x n])
  10.301 -  from mod_less_divisor[ of n x] nz th have Px: "?P ?x" by simp
  10.302 -  {fix y assume Py: "y < n" "[a * y = b] (mod n)"
  10.303 -    from Py(2) th have "[a * y = a*?x] (mod n)" by (simp add: modeq_def)
  10.304 -    hence "[y = ?x] (mod n)" by (simp add: cong_mult_lcancel_eq[OF an])
  10.305 -    with mod_less[OF Py(1)] mod_less_divisor[ of n x] nz
  10.306 -    have "y = ?x" by (simp add: modeq_def)}
  10.307 -  with Px show ?thesis by blast
  10.308 -qed
  10.309 -
  10.310 -lemma cong_solve_unique_nontrivial:
  10.311 -  assumes p: "prime p" and pa: "coprime p a" and x0: "0 < x" and xp: "x < p"
  10.312 -  shows "\<exists>!y. 0 < y \<and> y < p \<and> [x * y = a] (mod p)"
  10.313 -proof-
  10.314 -  from p have p1: "p > 1" using prime_ge_2[OF p] by arith
  10.315 -  hence p01: "p \<noteq> 0" "p \<noteq> 1" by arith+
  10.316 -  from pa have ap: "coprime a p" by (simp add: coprime_commute)
  10.317 -  from prime_coprime[OF p, of x] dvd_imp_le[of p x] x0 xp have px:"coprime x p"
  10.318 -    by (auto simp add: coprime_commute)
  10.319 -  from cong_solve_unique[OF px p01(1)]
  10.320 -  obtain y where y: "y < p" "[x * y = a] (mod p)" "\<forall>z. z < p \<and> [x * z = a] (mod p) \<longrightarrow> z = y" by blast
  10.321 -  {assume y0: "y = 0"
  10.322 -    with y(2) have th: "p dvd a" by (simp add: cong_commute[of 0 a p])
  10.323 -    with p coprime_prime[OF pa, of p] have False by simp}
  10.324 -  with y show ?thesis unfolding Ex1_def using neq0_conv by blast
  10.325 -qed
  10.326 -lemma cong_unique_inverse_prime:
  10.327 -  assumes p: "prime p" and x0: "0 < x" and xp: "x < p"
  10.328 -  shows "\<exists>!y. 0 < y \<and> y < p \<and> [x * y = 1] (mod p)"
  10.329 -  using cong_solve_unique_nontrivial[OF p coprime_1[of p] x0 xp] .
  10.330 -
  10.331 -(* Forms of the Chinese remainder theorem.                                   *)
  10.332 -
  10.333 -lemma cong_chinese:
  10.334 -  assumes ab: "coprime a b" and  xya: "[x = y] (mod a)"
  10.335 -  and xyb: "[x = y] (mod b)"
  10.336 -  shows "[x = y] (mod a*b)"
  10.337 -  using ab xya xyb
  10.338 -  by (simp add: cong_sub_cases[of x y a] cong_sub_cases[of x y b]
  10.339 -    cong_sub_cases[of x y "a*b"])
  10.340 -(cases "x \<le> y", simp_all add: divides_mul[of a _ b])
  10.341 -
  10.342 -lemma chinese_remainder_unique:
  10.343 -  assumes ab: "coprime a b" and az: "a \<noteq> 0" and bz: "b\<noteq>0"
  10.344 -  shows "\<exists>!x. x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
  10.345 -proof-
  10.346 -  from az bz have abpos: "a*b > 0" by simp
  10.347 -  from chinese_remainder[OF ab az bz] obtain x q1 q2 where
  10.348 -    xq12: "x = m + q1 * a" "x = n + q2 * b" by blast
  10.349 -  let ?w = "x mod (a*b)"
  10.350 -  have wab: "?w < a*b" by (simp add: mod_less_divisor[OF abpos])
  10.351 -  from xq12(1) have "?w mod a = ((m + q1 * a) mod (a*b)) mod a" by simp
  10.352 -  also have "\<dots> = m mod a" apply (simp add: mod_mult2_eq)
  10.353 -    apply (subst mod_add_left_eq)
  10.354 -    by simp
  10.355 -  finally have th1: "[?w = m] (mod a)" by (simp add: modeq_def)
  10.356 -  from xq12(2) have "?w mod b = ((n + q2 * b) mod (a*b)) mod b" by simp
  10.357 -  also have "\<dots> = ((n + q2 * b) mod (b*a)) mod b" by (simp add: mult_commute)
  10.358 -  also have "\<dots> = n mod b" apply (simp add: mod_mult2_eq)
  10.359 -    apply (subst mod_add_left_eq)
  10.360 -    by simp
  10.361 -  finally have th2: "[?w = n] (mod b)" by (simp add: modeq_def)
  10.362 -  {fix y assume H: "y < a*b" "[y = m] (mod a)" "[y = n] (mod b)"
  10.363 -    with th1 th2 have H': "[y = ?w] (mod a)" "[y = ?w] (mod b)"
  10.364 -      by (simp_all add: modeq_def)
  10.365 -    from cong_chinese[OF ab H'] mod_less[OF H(1)] mod_less[OF wab]
  10.366 -    have "y = ?w" by (simp add: modeq_def)}
  10.367 -  with th1 th2 wab show ?thesis by blast
  10.368 -qed
  10.369 -
  10.370 -lemma chinese_remainder_coprime_unique:
  10.371 -  assumes ab: "coprime a b" and az: "a \<noteq> 0" and bz: "b \<noteq> 0"
  10.372 -  and ma: "coprime m a" and nb: "coprime n b"
  10.373 -  shows "\<exists>!x. coprime x (a * b) \<and> x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
  10.374 -proof-
  10.375 -  let ?P = "\<lambda>x. x < a * b \<and> [x = m] (mod a) \<and> [x = n] (mod b)"
  10.376 -  from chinese_remainder_unique[OF ab az bz]
  10.377 -  obtain x where x: "x < a * b" "[x = m] (mod a)" "[x = n] (mod b)"
  10.378 -    "\<forall>y. ?P y \<longrightarrow> y = x" by blast
  10.379 -  from ma nb cong_coprime[OF x(2)] cong_coprime[OF x(3)]
  10.380 -  have "coprime x a" "coprime x b" by (simp_all add: coprime_commute)
  10.381 -  with coprime_mul[of x a b] have "coprime x (a*b)" by simp
  10.382 -  with x show ?thesis by blast
  10.383 -qed
  10.384 -
  10.385 -(* Euler totient function.                                                   *)
  10.386 -
  10.387 -definition phi_def: "\<phi> n = card { m. 0 < m \<and> m <= n \<and> coprime m n }"
  10.388 -
  10.389 -lemma phi_0[simp]: "\<phi> 0 = 0"
  10.390 -  unfolding phi_def by auto
  10.391 -
  10.392 -lemma phi_finite[simp]: "finite ({ m. 0 < m \<and> m <= n \<and> coprime m n })"
  10.393 -proof-
  10.394 -  have "{ m. 0 < m \<and> m <= n \<and> coprime m n } \<subseteq> {0..n}" by auto
  10.395 -  thus ?thesis by (auto intro: finite_subset)
  10.396 -qed
  10.397 -
  10.398 -declare coprime_1[presburger]
  10.399 -lemma phi_1[simp]: "\<phi> 1 = 1"
  10.400 -proof-
  10.401 -  {fix m
  10.402 -    have "0 < m \<and> m <= 1 \<and> coprime m 1 \<longleftrightarrow> m = 1" by presburger }
  10.403 -  thus ?thesis by (simp add: phi_def)
  10.404 -qed
  10.405 -
  10.406 -lemma [simp]: "\<phi> (Suc 0) = Suc 0" using phi_1 by simp
  10.407 -
  10.408 -lemma phi_alt: "\<phi>(n) = card { m. coprime m n \<and> m < n}"
  10.409 -proof-
  10.410 -  {assume "n=0 \<or> n=1" hence ?thesis by (cases "n=0", simp_all)}
  10.411 -  moreover
  10.412 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.413 -    {fix m
  10.414 -      from n have "0 < m \<and> m <= n \<and> coprime m n \<longleftrightarrow> coprime m n \<and> m < n"
  10.415 -	apply (cases "m = 0", simp_all)
  10.416 -	apply (cases "m = 1", simp_all)
  10.417 -	apply (cases "m = n", auto)
  10.418 -	done }
  10.419 -    hence ?thesis unfolding phi_def by simp}
  10.420 -  ultimately show ?thesis by auto
  10.421 -qed
  10.422 -
  10.423 -lemma phi_finite_lemma[simp]: "finite {m. coprime m n \<and>  m < n}" (is "finite ?S")
  10.424 -  by (rule finite_subset[of "?S" "{0..n}"], auto)
  10.425 -
  10.426 -lemma phi_another: assumes n: "n\<noteq>1"
  10.427 -  shows "\<phi> n = card {m. 0 < m \<and> m < n \<and> coprime m n }"
  10.428 -proof-
  10.429 -  {fix m
  10.430 -    from n have "0 < m \<and> m < n \<and> coprime m n \<longleftrightarrow> coprime m n \<and> m < n"
  10.431 -      by (cases "m=0", auto)}
  10.432 -  thus ?thesis unfolding phi_alt by auto
  10.433 -qed
  10.434 -
  10.435 -lemma phi_limit: "\<phi> n \<le> n"
  10.436 -proof-
  10.437 -  have "{ m. coprime m n \<and> m < n} \<subseteq> {0 ..<n}" by auto
  10.438 -  with card_mono[of "{0 ..<n}" "{ m. coprime m n \<and> m < n}"]
  10.439 -  show ?thesis unfolding phi_alt by auto
  10.440 -qed
  10.441 -
  10.442 -lemma stupid[simp]: "{m. (0::nat) < m \<and> m < n} = {1..<n}"
  10.443 -  by auto
  10.444 -
  10.445 -lemma phi_limit_strong: assumes n: "n\<noteq>1"
  10.446 -  shows "\<phi>(n) \<le> n - 1"
  10.447 -proof-
  10.448 -  show ?thesis
  10.449 -    unfolding phi_another[OF n] finite_number_segment[of n, symmetric]
  10.450 -    by (rule card_mono[of "{m. 0 < m \<and> m < n}" "{m. 0 < m \<and> m < n \<and> coprime m n}"], auto)
  10.451 -qed
  10.452 -
  10.453 -lemma phi_lowerbound_1_strong: assumes n: "n \<ge> 1"
  10.454 -  shows "\<phi>(n) \<ge> 1"
  10.455 -proof-
  10.456 -  let ?S = "{ m. 0 < m \<and> m <= n \<and> coprime m n }"
  10.457 -  from card_0_eq[of ?S] n have "\<phi> n \<noteq> 0" unfolding phi_alt
  10.458 -    apply auto
  10.459 -    apply (cases "n=1", simp_all)
  10.460 -    apply (rule exI[where x=1], simp)
  10.461 -    done
  10.462 -  thus ?thesis by arith
  10.463 -qed
  10.464 -
  10.465 -lemma phi_lowerbound_1: "2 <= n ==> 1 <= \<phi>(n)"
  10.466 -  using phi_lowerbound_1_strong[of n] by auto
  10.467 -
  10.468 -lemma phi_lowerbound_2: assumes n: "3 <= n" shows "2 <= \<phi> (n)"
  10.469 -proof-
  10.470 -  let ?S = "{ m. 0 < m \<and> m <= n \<and> coprime m n }"
  10.471 -  have inS: "{1, n - 1} \<subseteq> ?S" using n coprime_plus1[of "n - 1"]
  10.472 -    by (auto simp add: coprime_commute)
  10.473 -  from n have c2: "card {1, n - 1} = 2" by (auto simp add: card_insert_if)
  10.474 -  from card_mono[of ?S "{1, n - 1}", simplified inS c2] show ?thesis
  10.475 -    unfolding phi_def by auto
  10.476 -qed
  10.477 -
  10.478 -lemma phi_prime: "\<phi> n = n - 1 \<and> n\<noteq>0 \<and> n\<noteq>1 \<longleftrightarrow> prime n"
  10.479 -proof-
  10.480 -  {assume "n=0 \<or> n=1" hence ?thesis by (cases "n=1", simp_all)}
  10.481 -  moreover
  10.482 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.483 -    let ?S = "{m. 0 < m \<and> m < n}"
  10.484 -    have fS: "finite ?S" by simp
  10.485 -    let ?S' = "{m. 0 < m \<and> m < n \<and> coprime m n}"
  10.486 -    have fS':"finite ?S'" apply (rule finite_subset[of ?S' ?S]) by auto
  10.487 -    {assume H: "\<phi> n = n - 1 \<and> n\<noteq>0 \<and> n\<noteq>1"
  10.488 -      hence ceq: "card ?S' = card ?S"
  10.489 -      using n finite_number_segment[of n] phi_another[OF n(2)] by simp
  10.490 -      {fix m assume m: "0 < m" "m < n" "\<not> coprime m n"
  10.491 -	hence mS': "m \<notin> ?S'" by auto
  10.492 -	have "insert m ?S' \<le> ?S" using m by auto
  10.493 -	from m have "card (insert m ?S') \<le> card ?S"
  10.494 -	  by - (rule card_mono[of ?S "insert m ?S'"], auto)
  10.495 -	hence False
  10.496 -	  unfolding card_insert_disjoint[of "?S'" m, OF fS' mS'] ceq
  10.497 -	  by simp }
  10.498 -      hence "\<forall>m. 0 <m \<and> m < n \<longrightarrow> coprime m n" by blast
  10.499 -      hence "prime n" unfolding prime using n by (simp add: coprime_commute)}
  10.500 -    moreover
  10.501 -    {assume H: "prime n"
  10.502 -      hence "?S = ?S'" unfolding prime using n
  10.503 -	by (auto simp add: coprime_commute)
  10.504 -      hence "card ?S = card ?S'" by simp
  10.505 -      hence "\<phi> n = n - 1" unfolding phi_another[OF n(2)] by simp}
  10.506 -    ultimately have ?thesis using n by blast}
  10.507 -  ultimately show ?thesis by (cases "n=0") blast+
  10.508 -qed
  10.509 -
  10.510 -(* Multiplicativity property.                                                *)
  10.511 -
  10.512 -lemma phi_multiplicative: assumes ab: "coprime a b"
  10.513 -  shows "\<phi> (a * b) = \<phi> a * \<phi> b"
  10.514 -proof-
  10.515 -  {assume "a = 0 \<or> b = 0 \<or> a = 1 \<or> b = 1"
  10.516 -    hence ?thesis
  10.517 -      by (cases "a=0", simp, cases "b=0", simp, cases"a=1", simp_all) }
  10.518 -  moreover
  10.519 -  {assume a: "a\<noteq>0" "a\<noteq>1" and b: "b\<noteq>0" "b\<noteq>1"
  10.520 -    hence ab0: "a*b \<noteq> 0" by simp
  10.521 -    let ?S = "\<lambda>k. {m. coprime m k \<and> m < k}"
  10.522 -    let ?f = "\<lambda>x. (x mod a, x mod b)"
  10.523 -    have eq: "?f ` (?S (a*b)) = (?S a \<times> ?S b)"
  10.524 -    proof-
  10.525 -      {fix x assume x:"x \<in> ?S (a*b)"
  10.526 -	hence x': "coprime x (a*b)" "x < a*b" by simp_all
  10.527 -	hence xab: "coprime x a" "coprime x b" by (simp_all add: coprime_mul_eq)
  10.528 -	from mod_less_divisor a b have xab':"x mod a < a" "x mod b < b" by auto
  10.529 -	from xab xab' have "?f x \<in> (?S a \<times> ?S b)"
  10.530 -	  by (simp add: coprime_mod[OF a(1)] coprime_mod[OF b(1)])}
  10.531 -      moreover
  10.532 -      {fix x y assume x: "x \<in> ?S a" and y: "y \<in> ?S b"
  10.533 -	hence x': "coprime x a" "x < a" and y': "coprime y b" "y < b" by simp_all
  10.534 -	from chinese_remainder_coprime_unique[OF ab a(1) b(1) x'(1) y'(1)]
  10.535 -	obtain z where z: "coprime z (a * b)" "z < a * b" "[z = x] (mod a)"
  10.536 -	  "[z = y] (mod b)" by blast
  10.537 -	hence "(x,y) \<in> ?f ` (?S (a*b))"
  10.538 -	  using y'(2) mod_less_divisor[of b y] x'(2) mod_less_divisor[of a x]
  10.539 -	  by (auto simp add: image_iff modeq_def)}
  10.540 -      ultimately show ?thesis by auto
  10.541 -    qed
  10.542 -    have finj: "inj_on ?f (?S (a*b))"
  10.543 -      unfolding inj_on_def
  10.544 -    proof(clarify)
  10.545 -      fix x y assume H: "coprime x (a * b)" "x < a * b" "coprime y (a * b)"
  10.546 -	"y < a * b" "x mod a = y mod a" "x mod b = y mod b"
  10.547 -      hence cp: "coprime x a" "coprime x b" "coprime y a" "coprime y b"
  10.548 -	by (simp_all add: coprime_mul_eq)
  10.549 -      from chinese_remainder_coprime_unique[OF ab a(1) b(1) cp(3,4)] H
  10.550 -      show "x = y" unfolding modeq_def by blast
  10.551 -    qed
  10.552 -    from card_image[OF finj, unfolded eq] have ?thesis
  10.553 -      unfolding phi_alt by simp }
  10.554 -  ultimately show ?thesis by auto
  10.555 -qed
  10.556 -
  10.557 -(* Fermat's Little theorem / Fermat-Euler theorem.                           *)
  10.558 -
  10.559 -
  10.560 -lemma nproduct_mod:
  10.561 -  assumes fS: "finite S" and n0: "n \<noteq> 0"
  10.562 -  shows "[setprod (\<lambda>m. a(m) mod n) S = setprod a S] (mod n)"
  10.563 -proof-
  10.564 -  have th1:"[1 = 1] (mod n)" by (simp add: modeq_def)
  10.565 -  from cong_mult
  10.566 -  have th3:"\<forall>x1 y1 x2 y2.
  10.567 -    [x1 = x2] (mod n) \<and> [y1 = y2] (mod n) \<longrightarrow> [x1 * y1 = x2 * y2] (mod n)"
  10.568 -    by blast
  10.569 -  have th4:"\<forall>x\<in>S. [a x mod n = a x] (mod n)" by (simp add: modeq_def)
  10.570 -  from fold_image_related[where h="(\<lambda>m. a(m) mod n)" and g=a, OF th1 th3 fS, OF th4] show ?thesis unfolding setprod_def by (simp add: fS)
  10.571 -qed
  10.572 -
  10.573 -lemma nproduct_cmul:
  10.574 -  assumes fS:"finite S"
  10.575 -  shows "setprod (\<lambda>m. (c::'a::{comm_monoid_mult})* a(m)) S = c ^ (card S) * setprod a S"
  10.576 -unfolding setprod_timesf setprod_constant[OF fS, of c] ..
  10.577 -
  10.578 -lemma coprime_nproduct:
  10.579 -  assumes fS: "finite S" and Sn: "\<forall>x\<in>S. coprime n (a x)"
  10.580 -  shows "coprime n (setprod a S)"
  10.581 -  using fS unfolding setprod_def by (rule finite_subset_induct)
  10.582 -    (insert Sn, auto simp add: coprime_mul)
  10.583 -
  10.584 -lemma fermat_little: assumes an: "coprime a n"
  10.585 -  shows "[a ^ (\<phi> n) = 1] (mod n)"
  10.586 -proof-
  10.587 -  {assume "n=0" hence ?thesis by simp}
  10.588 -  moreover
  10.589 -  {assume "n=1" hence ?thesis by (simp add: modeq_def)}
  10.590 -  moreover
  10.591 -  {assume nz: "n \<noteq> 0" and n1: "n \<noteq> 1"
  10.592 -    let ?S = "{m. coprime m n \<and> m < n}"
  10.593 -    let ?P = "\<Prod> ?S"
  10.594 -    have fS: "finite ?S" by simp
  10.595 -    have cardfS: "\<phi> n = card ?S" unfolding phi_alt ..
  10.596 -    {fix m assume m: "m \<in> ?S"
  10.597 -      hence "coprime m n" by simp
  10.598 -      with coprime_mul[of n a m] an have "coprime (a*m) n"
  10.599 -	by (simp add: coprime_commute)}
  10.600 -    hence Sn: "\<forall>m\<in> ?S. coprime (a*m) n " by blast
  10.601 -    from coprime_nproduct[OF fS, of n "\<lambda>m. m"] have nP:"coprime ?P n"
  10.602 -      by (simp add: coprime_commute)
  10.603 -    have Paphi: "[?P*a^ (\<phi> n) = ?P*1] (mod n)"
  10.604 -    proof-
  10.605 -      let ?h = "\<lambda>m. m mod n"
  10.606 -      {fix m assume mS: "m\<in> ?S"
  10.607 -	hence "?h m \<in> ?S" by simp}
  10.608 -      hence hS: "?h ` ?S = ?S"by (auto simp add: image_iff)
  10.609 -      have "a\<noteq>0" using an n1 nz apply- apply (rule ccontr) by simp
  10.610 -      hence inj: "inj_on (op * a) ?S" unfolding inj_on_def by simp
  10.611 -
  10.612 -      have eq0: "fold_image op * (?h \<circ> op * a) 1 {m. coprime m n \<and> m < n} =
  10.613 -     fold_image op * (\<lambda>m. m) 1 {m. coprime m n \<and> m < n}"
  10.614 -      proof (rule fold_image_eq_general[where h="?h o (op * a)"])
  10.615 -	show "finite ?S" using fS .
  10.616 -      next
  10.617 -	{fix y assume yS: "y \<in> ?S" hence y: "coprime y n" "y < n" by simp_all
  10.618 -	  from cong_solve_unique[OF an nz, of y]
  10.619 -	  obtain x where x:"x < n" "[a * x = y] (mod n)" "\<forall>z. z < n \<and> [a * z = y] (mod n) \<longrightarrow> z=x" by blast
  10.620 -	  from cong_coprime[OF x(2)] y(1)
  10.621 -	  have xm: "coprime x n" by (simp add: coprime_mul_eq coprime_commute)
  10.622 -	  {fix z assume "z \<in> ?S" "(?h \<circ> op * a) z = y"
  10.623 -	    hence z: "coprime z n" "z < n" "(?h \<circ> op * a) z = y" by simp_all
  10.624 -	    from x(3)[rule_format, of z] z(2,3) have "z=x"
  10.625 -	      unfolding modeq_def mod_less[OF y(2)] by simp}
  10.626 -	  with xm x(1,2) have "\<exists>!x. x \<in> ?S \<and> (?h \<circ> op * a) x = y"
  10.627 -	    unfolding modeq_def mod_less[OF y(2)] by auto }
  10.628 -	thus "\<forall>y\<in>{m. coprime m n \<and> m < n}.
  10.629 -       \<exists>!x. x \<in> {m. coprime m n \<and> m < n} \<and> ((\<lambda>m. m mod n) \<circ> op * a) x = y" by blast
  10.630 -      next
  10.631 -	{fix x assume xS: "x\<in> ?S"
  10.632 -	  hence x: "coprime x n" "x < n" by simp_all
  10.633 -	  with an have "coprime (a*x) n"
  10.634 -	    by (simp add: coprime_mul_eq[of n a x] coprime_commute)
  10.635 -	  hence "?h (a*x) \<in> ?S" using nz
  10.636 -	    by (simp add: coprime_mod[OF nz] mod_less_divisor)}
  10.637 -	thus " \<forall>x\<in>{m. coprime m n \<and> m < n}.
  10.638 -       ((\<lambda>m. m mod n) \<circ> op * a) x \<in> {m. coprime m n \<and> m < n} \<and>
  10.639 -       ((\<lambda>m. m mod n) \<circ> op * a) x = ((\<lambda>m. m mod n) \<circ> op * a) x" by simp
  10.640 -      qed
  10.641 -      from nproduct_mod[OF fS nz, of "op * a"]
  10.642 -      have "[(setprod (op *a) ?S) = (setprod (?h o (op * a)) ?S)] (mod n)"
  10.643 -	unfolding o_def
  10.644 -	by (simp add: cong_commute)
  10.645 -      also have "[setprod (?h o (op * a)) ?S = ?P ] (mod n)"
  10.646 -	using eq0 fS an by (simp add: setprod_def modeq_def o_def)
  10.647 -      finally show "[?P*a^ (\<phi> n) = ?P*1] (mod n)"
  10.648 -	unfolding cardfS mult_commute[of ?P "a^ (card ?S)"]
  10.649 -	  nproduct_cmul[OF fS, symmetric] mult_1_right by simp
  10.650 -    qed
  10.651 -    from cong_mult_lcancel[OF nP Paphi] have ?thesis . }
  10.652 -  ultimately show ?thesis by blast
  10.653 -qed
  10.654 -
  10.655 -lemma fermat_little_prime: assumes p: "prime p" and ap: "coprime a p"
  10.656 -  shows "[a^ (p - 1) = 1] (mod p)"
  10.657 -  using fermat_little[OF ap] p[unfolded phi_prime[symmetric]]
  10.658 -by simp
  10.659 -
  10.660 -
  10.661 -(* Lucas's theorem.                                                          *)
  10.662 -
  10.663 -lemma lucas_coprime_lemma:
  10.664 -  assumes m: "m\<noteq>0" and am: "[a^m = 1] (mod n)"
  10.665 -  shows "coprime a n"
  10.666 -proof-
  10.667 -  {assume "n=1" hence ?thesis by simp}
  10.668 -  moreover
  10.669 -  {assume "n = 0" hence ?thesis using am m exp_eq_1[of a m] by simp}
  10.670 -  moreover
  10.671 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.672 -    from m obtain m' where m': "m = Suc m'" by (cases m, blast+)
  10.673 -    {fix d
  10.674 -      assume d: "d dvd a" "d dvd n"
  10.675 -      from n have n1: "1 < n" by arith
  10.676 -      from am mod_less[OF n1] have am1: "a^m mod n = 1" unfolding modeq_def by simp
  10.677 -      from dvd_mult2[OF d(1), of "a^m'"] have dam:"d dvd a^m" by (simp add: m')
  10.678 -      from dvd_mod_iff[OF d(2), of "a^m"] dam am1
  10.679 -      have "d = 1" by simp }
  10.680 -    hence ?thesis unfolding coprime by auto
  10.681 -  }
  10.682 -  ultimately show ?thesis by blast
  10.683 -qed
  10.684 -
  10.685 -lemma lucas_weak:
  10.686 -  assumes n: "n \<ge> 2" and an:"[a^(n - 1) = 1] (mod n)"
  10.687 -  and nm: "\<forall>m. 0 <m \<and> m < n - 1 \<longrightarrow> \<not> [a^m = 1] (mod n)"
  10.688 -  shows "prime n"
  10.689 -proof-
  10.690 -  from n have n1: "n \<noteq> 1" "n\<noteq>0" "n - 1 \<noteq> 0" "n - 1 > 0" "n - 1 < n" by arith+
  10.691 -  from lucas_coprime_lemma[OF n1(3) an] have can: "coprime a n" .
  10.692 -  from fermat_little[OF can] have afn: "[a ^ \<phi> n = 1] (mod n)" .
  10.693 -  {assume "\<phi> n \<noteq> n - 1"
  10.694 -    with phi_limit_strong[OF n1(1)] phi_lowerbound_1[OF n]
  10.695 -    have c:"\<phi> n > 0 \<and> \<phi> n < n - 1" by arith
  10.696 -    from nm[rule_format, OF c] afn have False ..}
  10.697 -  hence "\<phi> n = n - 1" by blast
  10.698 -  with phi_prime[of n] n1(1,2) show ?thesis by simp
  10.699 -qed
  10.700 -
  10.701 -lemma nat_exists_least_iff: "(\<exists>(n::nat). P n) \<longleftrightarrow> (\<exists>n. P n \<and> (\<forall>m < n. \<not> P m))"
  10.702 -  (is "?lhs \<longleftrightarrow> ?rhs")
  10.703 -proof
  10.704 -  assume ?rhs thus ?lhs by blast
  10.705 -next
  10.706 -  assume H: ?lhs then obtain n where n: "P n" by blast
  10.707 -  let ?x = "Least P"
  10.708 -  {fix m assume m: "m < ?x"
  10.709 -    from not_less_Least[OF m] have "\<not> P m" .}
  10.710 -  with LeastI_ex[OF H] show ?rhs by blast
  10.711 -qed
  10.712 -
  10.713 -lemma nat_exists_least_iff': "(\<exists>(n::nat). P n) \<longleftrightarrow> (P (Least P) \<and> (\<forall>m < (Least P). \<not> P m))"
  10.714 -  (is "?lhs \<longleftrightarrow> ?rhs")
  10.715 -proof-
  10.716 -  {assume ?rhs hence ?lhs by blast}
  10.717 -  moreover
  10.718 -  { assume H: ?lhs then obtain n where n: "P n" by blast
  10.719 -    let ?x = "Least P"
  10.720 -    {fix m assume m: "m < ?x"
  10.721 -      from not_less_Least[OF m] have "\<not> P m" .}
  10.722 -    with LeastI_ex[OF H] have ?rhs by blast}
  10.723 -  ultimately show ?thesis by blast
  10.724 -qed
  10.725 -
  10.726 -lemma power_mod: "((x::nat) mod m)^n mod m = x^n mod m"
  10.727 -proof(induct n)
  10.728 -  case 0 thus ?case by simp
  10.729 -next
  10.730 -  case (Suc n)
  10.731 -  have "(x mod m)^(Suc n) mod m = ((x mod m) * (((x mod m) ^ n) mod m)) mod m"
  10.732 -    by (simp add: mod_mult_right_eq[symmetric])
  10.733 -  also have "\<dots> = ((x mod m) * (x^n mod m)) mod m" using Suc.hyps by simp
  10.734 -  also have "\<dots> = x^(Suc n) mod m"
  10.735 -    by (simp add: mod_mult_left_eq[symmetric] mod_mult_right_eq[symmetric])
  10.736 -  finally show ?case .
  10.737 -qed
  10.738 -
  10.739 -lemma lucas:
  10.740 -  assumes n2: "n \<ge> 2" and an1: "[a^(n - 1) = 1] (mod n)"
  10.741 -  and pn: "\<forall>p. prime p \<and> p dvd n - 1 \<longrightarrow> \<not> [a^((n - 1) div p) = 1] (mod n)"
  10.742 -  shows "prime n"
  10.743 -proof-
  10.744 -  from n2 have n01: "n\<noteq>0" "n\<noteq>1" "n - 1 \<noteq> 0" by arith+
  10.745 -  from mod_less_divisor[of n 1] n01 have onen: "1 mod n = 1" by simp
  10.746 -  from lucas_coprime_lemma[OF n01(3) an1] cong_coprime[OF an1]
  10.747 -  have an: "coprime a n" "coprime (a^(n - 1)) n" by (simp_all add: coprime_commute)
  10.748 -  {assume H0: "\<exists>m. 0 < m \<and> m < n - 1 \<and> [a ^ m = 1] (mod n)" (is "EX m. ?P m")
  10.749 -    from H0[unfolded nat_exists_least_iff[of ?P]] obtain m where
  10.750 -      m: "0 < m" "m < n - 1" "[a ^ m = 1] (mod n)" "\<forall>k <m. \<not>?P k" by blast
  10.751 -    {assume nm1: "(n - 1) mod m > 0"
  10.752 -      from mod_less_divisor[OF m(1)] have th0:"(n - 1) mod m < m" by blast
  10.753 -      let ?y = "a^ ((n - 1) div m * m)"
  10.754 -      note mdeq = mod_div_equality[of "(n - 1)" m]
  10.755 -      from coprime_exp[OF an(1)[unfolded coprime_commute[of a n]],
  10.756 -	of "(n - 1) div m * m"]
  10.757 -      have yn: "coprime ?y n" by (simp add: coprime_commute)
  10.758 -      have "?y mod n = (a^m)^((n - 1) div m) mod n"
  10.759 -	by (simp add: algebra_simps power_mult)
  10.760 -      also have "\<dots> = (a^m mod n)^((n - 1) div m) mod n"
  10.761 -	using power_mod[of "a^m" n "(n - 1) div m"] by simp
  10.762 -      also have "\<dots> = 1" using m(3)[unfolded modeq_def onen] onen
  10.763 -	by (simp add: power_Suc0)
  10.764 -      finally have th3: "?y mod n = 1"  .
  10.765 -      have th2: "[?y * a ^ ((n - 1) mod m) = ?y* 1] (mod n)"
  10.766 -	using an1[unfolded modeq_def onen] onen
  10.767 -	  mod_div_equality[of "(n - 1)" m, symmetric]
  10.768 -	by (simp add:power_add[symmetric] modeq_def th3 del: One_nat_def)
  10.769 -      from cong_mult_lcancel[of ?y n "a^((n - 1) mod m)" 1, OF yn th2]
  10.770 -      have th1: "[a ^ ((n - 1) mod m) = 1] (mod n)"  .
  10.771 -      from m(4)[rule_format, OF th0] nm1
  10.772 -	less_trans[OF mod_less_divisor[OF m(1), of "n - 1"] m(2)] th1
  10.773 -      have False by blast }
  10.774 -    hence "(n - 1) mod m = 0" by auto
  10.775 -    then have mn: "m dvd n - 1" by presburger
  10.776 -    then obtain r where r: "n - 1 = m*r" unfolding dvd_def by blast
  10.777 -    from n01 r m(2) have r01: "r\<noteq>0" "r\<noteq>1" by - (rule ccontr, simp)+
  10.778 -    from prime_factor[OF r01(2)] obtain p where p: "prime p" "p dvd r" by blast
  10.779 -    hence th: "prime p \<and> p dvd n - 1" unfolding r by (auto intro: dvd_mult)
  10.780 -    have "(a ^ ((n - 1) div p)) mod n = (a^(m*r div p)) mod n" using r
  10.781 -      by (simp add: power_mult)
  10.782 -    also have "\<dots> = (a^(m*(r div p))) mod n" using div_mult1_eq[of m r p] p(2)[unfolded dvd_eq_mod_eq_0] by simp
  10.783 -    also have "\<dots> = ((a^m)^(r div p)) mod n" by (simp add: power_mult)
  10.784 -    also have "\<dots> = ((a^m mod n)^(r div p)) mod n" using power_mod[of "a^m" "n" "r div p" ] ..
  10.785 -    also have "\<dots> = 1" using m(3) onen by (simp add: modeq_def power_Suc0)
  10.786 -    finally have "[(a ^ ((n - 1) div p))= 1] (mod n)"
  10.787 -      using onen by (simp add: modeq_def)
  10.788 -    with pn[rule_format, OF th] have False by blast}
  10.789 -  hence th: "\<forall>m. 0 < m \<and> m < n - 1 \<longrightarrow> \<not> [a ^ m = 1] (mod n)" by blast
  10.790 -  from lucas_weak[OF n2 an1 th] show ?thesis .
  10.791 -qed
  10.792 -
  10.793 -(* Definition of the order of a number mod n (0 in non-coprime case).        *)
  10.794 -
  10.795 -definition "ord n a = (if coprime n a then Least (\<lambda>d. d > 0 \<and> [a ^d = 1] (mod n)) else 0)"
  10.796 -
  10.797 -(* This has the expected properties.                                         *)
  10.798 -
  10.799 -lemma coprime_ord:
  10.800 -  assumes na: "coprime n a"
  10.801 -  shows "ord n a > 0 \<and> [a ^(ord n a) = 1] (mod n) \<and> (\<forall>m. 0 < m \<and> m < ord n a \<longrightarrow> \<not> [a^ m = 1] (mod n))"
  10.802 -proof-
  10.803 -  let ?P = "\<lambda>d. 0 < d \<and> [a ^ d = 1] (mod n)"
  10.804 -  from euclid[of a] obtain p where p: "prime p" "a < p" by blast
  10.805 -  from na have o: "ord n a = Least ?P" by (simp add: ord_def)
  10.806 -  {assume "n=0 \<or> n=1" with na have "\<exists>m>0. ?P m" apply auto apply (rule exI[where x=1]) by (simp  add: modeq_def)}
  10.807 -  moreover
  10.808 -  {assume "n\<noteq>0 \<and> n\<noteq>1" hence n2:"n \<ge> 2" by arith
  10.809 -    from na have na': "coprime a n" by (simp add: coprime_commute)
  10.810 -    from phi_lowerbound_1[OF n2] fermat_little[OF na']
  10.811 -    have ex: "\<exists>m>0. ?P m" by - (rule exI[where x="\<phi> n"], auto) }
  10.812 -  ultimately have ex: "\<exists>m>0. ?P m" by blast
  10.813 -  from nat_exists_least_iff'[of ?P] ex na show ?thesis
  10.814 -    unfolding o[symmetric] by auto
  10.815 -qed
  10.816 -(* With the special value 0 for non-coprime case, it's more convenient.      *)
  10.817 -lemma ord_works:
  10.818 - "[a ^ (ord n a) = 1] (mod n) \<and> (\<forall>m. 0 < m \<and> m < ord n a \<longrightarrow> ~[a^ m = 1] (mod n))"
  10.819 -apply (cases "coprime n a")
  10.820 -using coprime_ord[of n a]
  10.821 -by (blast, simp add: ord_def modeq_def)
  10.822 -
  10.823 -lemma ord: "[a^(ord n a) = 1] (mod n)" using ord_works by blast
  10.824 -lemma ord_minimal: "0 < m \<Longrightarrow> m < ord n a \<Longrightarrow> ~[a^m = 1] (mod n)"
  10.825 -  using ord_works by blast
  10.826 -lemma ord_eq_0: "ord n a = 0 \<longleftrightarrow> ~coprime n a"
  10.827 -by (cases "coprime n a", simp add: neq0_conv coprime_ord, simp add: neq0_conv ord_def)
  10.828 -
  10.829 -lemma ord_divides:
  10.830 - "[a ^ d = 1] (mod n) \<longleftrightarrow> ord n a dvd d" (is "?lhs \<longleftrightarrow> ?rhs")
  10.831 -proof
  10.832 -  assume rh: ?rhs
  10.833 -  then obtain k where "d = ord n a * k" unfolding dvd_def by blast
  10.834 -  hence "[a ^ d = (a ^ (ord n a) mod n)^k] (mod n)"
  10.835 -    by (simp add : modeq_def power_mult power_mod)
  10.836 -  also have "[(a ^ (ord n a) mod n)^k = 1] (mod n)"
  10.837 -    using ord[of a n, unfolded modeq_def]
  10.838 -    by (simp add: modeq_def power_mod power_Suc0)
  10.839 -  finally  show ?lhs .
  10.840 -next
  10.841 -  assume lh: ?lhs
  10.842 -  { assume H: "\<not> coprime n a"
  10.843 -    hence o: "ord n a = 0" by (simp add: ord_def)
  10.844 -    {assume d: "d=0" with o H have ?rhs by (simp add: modeq_def)}
  10.845 -    moreover
  10.846 -    {assume d0: "d\<noteq>0" then obtain d' where d': "d = Suc d'" by (cases d, auto)
  10.847 -      from H[unfolded coprime]
  10.848 -      obtain p where p: "p dvd n" "p dvd a" "p \<noteq> 1" by auto
  10.849 -      from lh[unfolded nat_mod]
  10.850 -      obtain q1 q2 where q12:"a ^ d + n * q1 = 1 + n * q2" by blast
  10.851 -      hence "a ^ d + n * q1 - n * q2 = 1" by simp
  10.852 -      with dvd_diff_nat [OF dvd_add [OF divides_rexp[OF p(2), of d'] dvd_mult2[OF p(1), of q1]] dvd_mult2[OF p(1), of q2]] d' have "p dvd 1" by simp
  10.853 -      with p(3) have False by simp
  10.854 -      hence ?rhs ..}
  10.855 -    ultimately have ?rhs by blast}
  10.856 -  moreover
  10.857 -  {assume H: "coprime n a"
  10.858 -    let ?o = "ord n a"
  10.859 -    let ?q = "d div ord n a"
  10.860 -    let ?r = "d mod ord n a"
  10.861 -    from cong_exp[OF ord[of a n], of ?q]
  10.862 -    have eqo: "[(a^?o)^?q = 1] (mod n)"  by (simp add: modeq_def power_Suc0)
  10.863 -    from H have onz: "?o \<noteq> 0" by (simp add: ord_eq_0)
  10.864 -    hence op: "?o > 0" by simp
  10.865 -    from mod_div_equality[of d "ord n a"] lh
  10.866 -    have "[a^(?o*?q + ?r) = 1] (mod n)" by (simp add: modeq_def mult_commute)
  10.867 -    hence "[(a^?o)^?q * (a^?r) = 1] (mod n)"
  10.868 -      by (simp add: modeq_def power_mult[symmetric] power_add[symmetric])
  10.869 -    hence th: "[a^?r = 1] (mod n)"
  10.870 -      using eqo mod_mult_left_eq[of "(a^?o)^?q" "a^?r" n]
  10.871 -      apply (simp add: modeq_def del: One_nat_def)
  10.872 -      by (simp add: mod_mult_left_eq[symmetric])
  10.873 -    {assume r: "?r = 0" hence ?rhs by (simp add: dvd_eq_mod_eq_0)}
  10.874 -    moreover
  10.875 -    {assume r: "?r \<noteq> 0"
  10.876 -      with mod_less_divisor[OF op, of d] have r0o:"?r >0 \<and> ?r < ?o" by simp
  10.877 -      from conjunct2[OF ord_works[of a n], rule_format, OF r0o] th
  10.878 -      have ?rhs by blast}
  10.879 -    ultimately have ?rhs by blast}
  10.880 -  ultimately  show ?rhs by blast
  10.881 -qed
  10.882 -
  10.883 -lemma order_divides_phi: "coprime n a \<Longrightarrow> ord n a dvd \<phi> n"
  10.884 -using ord_divides fermat_little coprime_commute by simp
  10.885 -lemma order_divides_expdiff:
  10.886 -  assumes na: "coprime n a"
  10.887 -  shows "[a^d = a^e] (mod n) \<longleftrightarrow> [d = e] (mod (ord n a))"
  10.888 -proof-
  10.889 -  {fix n a d e
  10.890 -    assume na: "coprime n a" and ed: "(e::nat) \<le> d"
  10.891 -    hence "\<exists>c. d = e + c" by arith
  10.892 -    then obtain c where c: "d = e + c" by arith
  10.893 -    from na have an: "coprime a n" by (simp add: coprime_commute)
  10.894 -    from coprime_exp[OF na, of e]
  10.895 -    have aen: "coprime (a^e) n" by (simp add: coprime_commute)
  10.896 -    from coprime_exp[OF na, of c]
  10.897 -    have acn: "coprime (a^c) n" by (simp add: coprime_commute)
  10.898 -    have "[a^d = a^e] (mod n) \<longleftrightarrow> [a^(e + c) = a^(e + 0)] (mod n)"
  10.899 -      using c by simp
  10.900 -    also have "\<dots> \<longleftrightarrow> [a^e* a^c = a^e *a^0] (mod n)" by (simp add: power_add)
  10.901 -    also have  "\<dots> \<longleftrightarrow> [a ^ c = 1] (mod n)"
  10.902 -      using cong_mult_lcancel_eq[OF aen, of "a^c" "a^0"] by simp
  10.903 -    also  have "\<dots> \<longleftrightarrow> ord n a dvd c" by (simp only: ord_divides)
  10.904 -    also have "\<dots> \<longleftrightarrow> [e + c = e + 0] (mod ord n a)"
  10.905 -      using cong_add_lcancel_eq[of e c 0 "ord n a", simplified cong_0_divides]
  10.906 -      by simp
  10.907 -    finally have "[a^d = a^e] (mod n) \<longleftrightarrow> [d = e] (mod (ord n a))"
  10.908 -      using c by simp }
  10.909 -  note th = this
  10.910 -  have "e \<le> d \<or> d \<le> e" by arith
  10.911 -  moreover
  10.912 -  {assume ed: "e \<le> d" from th[OF na ed] have ?thesis .}
  10.913 -  moreover
  10.914 -  {assume de: "d \<le> e"
  10.915 -    from th[OF na de] have ?thesis by (simp add: cong_commute) }
  10.916 -  ultimately show ?thesis by blast
  10.917 -qed
  10.918 -
  10.919 -(* Another trivial primality characterization.                               *)
  10.920 -
  10.921 -lemma prime_prime_factor:
  10.922 -  "prime n \<longleftrightarrow> n \<noteq> 1\<and> (\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n)"
  10.923 -proof-
  10.924 -  {assume n: "n=0 \<or> n=1" hence ?thesis using prime_0 two_is_prime by auto}
  10.925 -  moreover
  10.926 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.927 -    {assume pn: "prime n"
  10.928 -
  10.929 -      from pn[unfolded prime_def] have "\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n"
  10.930 -	using n
  10.931 -	apply (cases "n = 0 \<or> n=1",simp)
  10.932 -	by (clarsimp, erule_tac x="p" in allE, auto)}
  10.933 -    moreover
  10.934 -    {assume H: "\<forall>p. prime p \<and> p dvd n \<longrightarrow> p = n"
  10.935 -      from n have n1: "n > 1" by arith
  10.936 -      {fix m assume m: "m dvd n" "m\<noteq>1"
  10.937 -	from prime_factor[OF m(2)] obtain p where
  10.938 -	  p: "prime p" "p dvd m" by blast
  10.939 -	from dvd_trans[OF p(2) m(1)] p(1) H have "p = n" by blast
  10.940 -	with p(2) have "n dvd m"  by simp
  10.941 -	hence "m=n"  using dvd_anti_sym[OF m(1)] by simp }
  10.942 -      with n1 have "prime n"  unfolding prime_def by auto }
  10.943 -    ultimately have ?thesis using n by blast}
  10.944 -  ultimately       show ?thesis by auto
  10.945 -qed
  10.946 -
  10.947 -lemma prime_divisor_sqrt:
  10.948 -  "prime n \<longleftrightarrow> n \<noteq> 1 \<and> (\<forall>d. d dvd n \<and> d^2 \<le> n \<longrightarrow> d = 1)"
  10.949 -proof-
  10.950 -  {assume "n=0 \<or> n=1" hence ?thesis using prime_0 prime_1
  10.951 -    by (auto simp add: nat_power_eq_0_iff)}
  10.952 -  moreover
  10.953 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.954 -    hence np: "n > 1" by arith
  10.955 -    {fix d assume d: "d dvd n" "d^2 \<le> n" and H: "\<forall>m. m dvd n \<longrightarrow> m=1 \<or> m=n"
  10.956 -      from H d have d1n: "d = 1 \<or> d=n" by blast
  10.957 -      {assume dn: "d=n"
  10.958 -	have "n^2 > n*1" using n
  10.959 -	  by (simp add: power2_eq_square mult_less_cancel1)
  10.960 -	with dn d(2) have "d=1" by simp}
  10.961 -      with d1n have "d = 1" by blast  }
  10.962 -    moreover
  10.963 -    {fix d assume d: "d dvd n" and H: "\<forall>d'. d' dvd n \<and> d'^2 \<le> n \<longrightarrow> d' = 1"
  10.964 -      from d n have "d \<noteq> 0" apply - apply (rule ccontr) by simp
  10.965 -      hence dp: "d > 0" by simp
  10.966 -      from d[unfolded dvd_def] obtain e where e: "n= d*e" by blast
  10.967 -      from n dp e have ep:"e > 0" by simp
  10.968 -      have "d^2 \<le> n \<or> e^2 \<le> n" using dp ep
  10.969 -	by (auto simp add: e power2_eq_square mult_le_cancel_left)
  10.970 -      moreover
  10.971 -      {assume h: "d^2 \<le> n"
  10.972 -	from H[rule_format, of d] h d have "d = 1" by blast}
  10.973 -      moreover
  10.974 -      {assume h: "e^2 \<le> n"
  10.975 -	from e have "e dvd n" unfolding dvd_def by (simp add: mult_commute)
  10.976 -	with H[rule_format, of e] h have "e=1" by simp
  10.977 -	with e have "d = n" by simp}
  10.978 -      ultimately have "d=1 \<or> d=n"  by blast}
  10.979 -    ultimately have ?thesis unfolding prime_def using np n(2) by blast}
  10.980 -  ultimately show ?thesis by auto
  10.981 -qed
  10.982 -lemma prime_prime_factor_sqrt:
  10.983 -  "prime n \<longleftrightarrow> n \<noteq> 0 \<and> n \<noteq> 1 \<and> \<not> (\<exists>p. prime p \<and> p dvd n \<and> p^2 \<le> n)"
  10.984 -  (is "?lhs \<longleftrightarrow>?rhs")
  10.985 -proof-
  10.986 -  {assume "n=0 \<or> n=1" hence ?thesis using prime_0 prime_1 by auto}
  10.987 -  moreover
  10.988 -  {assume n: "n\<noteq>0" "n\<noteq>1"
  10.989 -    {assume H: ?lhs
  10.990 -      from H[unfolded prime_divisor_sqrt] n
  10.991 -      have ?rhs  apply clarsimp by (erule_tac x="p" in allE, simp add: prime_1)
  10.992 -    }
  10.993 -    moreover
  10.994 -    {assume H: ?rhs
  10.995 -      {fix d assume d: "d dvd n" "d^2 \<le> n" "d\<noteq>1"
  10.996 -	from prime_factor[OF d(3)]
  10.997 -	obtain p where p: "prime p" "p dvd d" by blast
  10.998 -	from n have np: "n > 0" by arith
  10.999 -	from d(1) n have "d \<noteq> 0" by - (rule ccontr, auto)
 10.1000 -	hence dp: "d > 0" by arith
 10.1001 -	from mult_mono[OF dvd_imp_le[OF p(2) dp] dvd_imp_le[OF p(2) dp]] d(2)
 10.1002 -	have "p^2 \<le> n" unfolding power2_eq_square by arith
 10.1003 -	with H n p(1) dvd_trans[OF p(2) d(1)] have False  by blast}
 10.1004 -      with n prime_divisor_sqrt  have ?lhs by auto}
 10.1005 -    ultimately have ?thesis by blast }
 10.1006 -  ultimately show ?thesis by (cases "n=0 \<or> n=1", auto)
 10.1007 -qed
 10.1008 -(* Pocklington theorem. *)
 10.1009 -
 10.1010 -lemma pocklington_lemma:
 10.1011 -  assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and an: "[a^ (n - 1) = 1] (mod n)"
 10.1012 -  and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a^ ((n - 1) div p) - 1) n"
 10.1013 -  and pp: "prime p" and pn: "p dvd n"
 10.1014 -  shows "[p = 1] (mod q)"
 10.1015 -proof-
 10.1016 -  from pp prime_0 prime_1 have p01: "p \<noteq> 0" "p \<noteq> 1" by - (rule ccontr, simp)+
 10.1017 -  from cong_1_divides[OF an, unfolded nqr, unfolded dvd_def]
 10.1018 -  obtain k where k: "a ^ (q * r) - 1 = n*k" by blast
 10.1019 -  from pn[unfolded dvd_def] obtain l where l: "n = p*l" by blast
 10.1020 -  {assume a0: "a = 0"
 10.1021 -    hence "a^ (n - 1) = 0" using n by (simp add: power_0_left)
 10.1022 -    with n an mod_less[of 1 n]  have False by (simp add: power_0_left modeq_def)}
 10.1023 -  hence a0: "a\<noteq>0" ..
 10.1024 -  from n nqr have aqr0: "a ^ (q * r) \<noteq> 0" using a0 by (simp add: neq0_conv)
 10.1025 -  hence "(a ^ (q * r) - 1) + 1  = a ^ (q * r)" by simp
 10.1026 -  with k l have "a ^ (q * r) = p*l*k + 1" by simp
 10.1027 -  hence "a ^ (r * q) + p * 0 = 1 + p * (l*k)" by (simp add: mult_ac)
 10.1028 -  hence odq: "ord p (a^r) dvd q"
 10.1029 -    unfolding ord_divides[symmetric] power_mult[symmetric] nat_mod  by blast
 10.1030 -  from odq[unfolded dvd_def] obtain d where d: "q = ord p (a^r) * d" by blast
 10.1031 -  {assume d1: "d \<noteq> 1"
 10.1032 -    from prime_factor[OF d1] obtain P where P: "prime P" "P dvd d" by blast
 10.1033 -    from d dvd_mult[OF P(2), of "ord p (a^r)"] have Pq: "P dvd q" by simp
 10.1034 -    from aq P(1) Pq have caP:"coprime (a^ ((n - 1) div P) - 1) n" by blast
 10.1035 -    from Pq obtain s where s: "q = P*s" unfolding dvd_def by blast
 10.1036 -    have P0: "P \<noteq> 0" using P(1) prime_0 by - (rule ccontr, simp)
 10.1037 -    from P(2) obtain t where t: "d = P*t" unfolding dvd_def by blast
 10.1038 -    from d s t P0  have s': "ord p (a^r) * t = s" by algebra
 10.1039 -    have "ord p (a^r) * t*r = r * ord p (a^r) * t" by algebra
 10.1040 -    hence exps: "a^(ord p (a^r) * t*r) = ((a ^ r) ^ ord p (a^r)) ^ t"
 10.1041 -      by (simp only: power_mult)
 10.1042 -    have "[((a ^ r) ^ ord p (a^r)) ^ t= 1^t] (mod p)"
 10.1043 -      by (rule cong_exp, rule ord)
 10.1044 -    then have th: "[((a ^ r) ^ ord p (a^r)) ^ t= 1] (mod p)"
 10.1045 -      by (simp add: power_Suc0)
 10.1046 -    from cong_1_divides[OF th] exps have pd0: "p dvd a^(ord p (a^r) * t*r) - 1" by simp
 10.1047 -    from nqr s s' have "(n - 1) div P = ord p (a^r) * t*r" using P0 by simp
 10.1048 -    with caP have "coprime (a^(ord p (a^r) * t*r) - 1) n" by simp
 10.1049 -    with p01 pn pd0 have False unfolding coprime by auto}
 10.1050 -  hence d1: "d = 1" by blast
 10.1051 -  hence o: "ord p (a^r) = q" using d by simp
 10.1052 -  from pp phi_prime[of p] have phip: " \<phi> p = p - 1" by simp
 10.1053 -  {fix d assume d: "d dvd p" "d dvd a" "d \<noteq> 1"
 10.1054 -    from pp[unfolded prime_def] d have dp: "d = p" by blast
 10.1055 -    from n have n12:"Suc (n - 2) = n - 1" by arith
 10.1056 -    with divides_rexp[OF d(2)[unfolded dp], of "n - 2"]
 10.1057 -    have th0: "p dvd a ^ (n - 1)" by simp
 10.1058 -    from n have n0: "n \<noteq> 0" by simp
 10.1059 -    from d(2) an n12[symmetric] have a0: "a \<noteq> 0"
 10.1060 -      by - (rule ccontr, simp add: modeq_def)
 10.1061 -    have th1: "a^ (n - 1) \<noteq> 0" using n d(2) dp a0 by (auto simp add: neq0_conv)
 10.1062 -    from coprime_minus1[OF th1, unfolded coprime]
 10.1063 -      dvd_trans[OF pn cong_1_divides[OF an]] th0 d(3) dp
 10.1064 -    have False by auto}
 10.1065 -  hence cpa: "coprime p a" using coprime by auto
 10.1066 -  from coprime_exp[OF cpa, of r] coprime_commute
 10.1067 -  have arp: "coprime (a^r) p" by blast
 10.1068 -  from fermat_little[OF arp, simplified ord_divides] o phip
 10.1069 -  have "q dvd (p - 1)" by simp
 10.1070 -  then obtain d where d:"p - 1 = q * d" unfolding dvd_def by blast
 10.1071 -  from prime_0 pp have p0:"p \<noteq> 0" by -  (rule ccontr, auto)
 10.1072 -  from p0 d have "p + q * 0 = 1 + q * d" by simp
 10.1073 -  with nat_mod[of p 1 q, symmetric]
 10.1074 -  show ?thesis by blast
 10.1075 -qed
 10.1076 -
 10.1077 -lemma pocklington:
 10.1078 -  assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and sqr: "n \<le> q^2"
 10.1079 -  and an: "[a^ (n - 1) = 1] (mod n)"
 10.1080 -  and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a^ ((n - 1) div p) - 1) n"
 10.1081 -  shows "prime n"
 10.1082 -unfolding prime_prime_factor_sqrt[of n]
 10.1083 -proof-
 10.1084 -  let ?ths = "n \<noteq> 0 \<and> n \<noteq> 1 \<and> \<not> (\<exists>p. prime p \<and> p dvd n \<and> p\<twosuperior> \<le> n)"
 10.1085 -  from n have n01: "n\<noteq>0" "n\<noteq>1" by arith+
 10.1086 -  {fix p assume p: "prime p" "p dvd n" "p^2 \<le> n"
 10.1087 -    from p(3) sqr have "p^(Suc 1) \<le> q^(Suc 1)" by (simp add: power2_eq_square)
 10.1088 -    hence pq: "p \<le> q" unfolding exp_mono_le .
 10.1089 -    from pocklington_lemma[OF n nqr an aq p(1,2)]  cong_1_divides
 10.1090 -    have th: "q dvd p - 1" by blast
 10.1091 -    have "p - 1 \<noteq> 0"using prime_ge_2[OF p(1)] by arith
 10.1092 -    with divides_ge[OF th] pq have False by arith }
 10.1093 -  with n01 show ?ths by blast
 10.1094 -qed
 10.1095 -
 10.1096 -(* Variant for application, to separate the exponentiation.                  *)
 10.1097 -lemma pocklington_alt:
 10.1098 -  assumes n: "n \<ge> 2" and nqr: "n - 1 = q*r" and sqr: "n \<le> q^2"
 10.1099 -  and an: "[a^ (n - 1) = 1] (mod n)"
 10.1100 -  and aq:"\<forall>p. prime p \<and> p dvd q \<longrightarrow> (\<exists>b. [a^((n - 1) div p) = b] (mod n) \<and> coprime (b - 1) n)"
 10.1101 -  shows "prime n"
 10.1102 -proof-
 10.1103 -  {fix p assume p: "prime p" "p dvd q"
 10.1104 -    from aq[rule_format] p obtain b where
 10.1105 -      b: "[a^((n - 1) div p) = b] (mod n)" "coprime (b - 1) n" by blast
 10.1106 -    {assume a0: "a=0"
 10.1107 -      from n an have "[0 = 1] (mod n)" unfolding a0 power_0_left by auto
 10.1108 -      hence False using n by (simp add: modeq_def dvd_eq_mod_eq_0[symmetric])}
 10.1109 -    hence a0: "a\<noteq> 0" ..
 10.1110 -    hence a1: "a \<ge> 1" by arith
 10.1111 -    from one_le_power[OF a1] have ath: "1 \<le> a ^ ((n - 1) div p)" .
 10.1112 -    {assume b0: "b = 0"
 10.1113 -      from p(2) nqr have "(n - 1) mod p = 0"
 10.1114 -	apply (simp only: dvd_eq_mod_eq_0[symmetric]) by (rule dvd_mult2, simp)
 10.1115 -      with mod_div_equality[of "n - 1" p]
 10.1116 -      have "(n - 1) div p * p= n - 1" by auto
 10.1117 -      hence eq: "(a^((n - 1) div p))^p = a^(n - 1)"
 10.1118 -	by (simp only: power_mult[symmetric])
 10.1119 -      from prime_ge_2[OF p(1)] have pS: "Suc (p - 1) = p" by arith
 10.1120 -      from b(1) have d: "n dvd a^((n - 1) div p)" unfolding b0 cong_0_divides .
 10.1121 -      from divides_rexp[OF d, of "p - 1"] pS eq cong_divides[OF an] n
 10.1122 -      have False by simp}
 10.1123 -    then have b0: "b \<noteq> 0" ..
 10.1124 -    hence b1: "b \<ge> 1" by arith
 10.1125 -    from cong_coprime[OF cong_sub[OF b(1) cong_refl[of 1] ath b1]] b(2) nqr
 10.1126 -    have "coprime (a ^ ((n - 1) div p) - 1) n" by (simp add: coprime_commute)}
 10.1127 -  hence th: "\<forall>p. prime p \<and> p dvd q \<longrightarrow> coprime (a ^ ((n - 1) div p) - 1) n "
 10.1128 -    by blast
 10.1129 -  from pocklington[OF n nqr sqr an th] show ?thesis .
 10.1130 -qed
 10.1131 -
 10.1132 -(* Prime factorizations.                                                     *)
 10.1133 -
 10.1134 -definition "primefact ps n = (foldr op * ps  1 = n \<and> (\<forall>p\<in> set ps. prime p))"
 10.1135 -
 10.1136 -lemma primefact: assumes n: "n \<noteq> 0"
 10.1137 -  shows "\<exists>ps. primefact ps n"
 10.1138 -using n
 10.1139 -proof(induct n rule: nat_less_induct)
 10.1140 -  fix n assume H: "\<forall>m<n. m \<noteq> 0 \<longrightarrow> (\<exists>ps. primefact ps m)" and n: "n\<noteq>0"
 10.1141 -  let ?ths = "\<exists>ps. primefact ps n"
 10.1142 -  {assume "n = 1"
 10.1143 -    hence "primefact [] n" by (simp add: primefact_def)
 10.1144 -    hence ?ths by blast }
 10.1145 -  moreover
 10.1146 -  {assume n1: "n \<noteq> 1"
 10.1147 -    with n have n2: "n \<ge> 2" by arith
 10.1148 -    from prime_factor[OF n1] obtain p where p: "prime p" "p dvd n" by blast
 10.1149 -    from p(2) obtain m where m: "n = p*m" unfolding dvd_def by blast
 10.1150 -    from n m have m0: "m > 0" "m\<noteq>0" by auto
 10.1151 -    from prime_ge_2[OF p(1)] have "1 < p" by arith
 10.1152 -    with m0 m have mn: "m < n" by auto
 10.1153 -    from H[rule_format, OF mn m0(2)] obtain ps where ps: "primefact ps m" ..
 10.1154 -    from ps m p(1) have "primefact (p#ps) n" by (simp add: primefact_def)
 10.1155 -    hence ?ths by blast}
 10.1156 -  ultimately show ?ths by blast
 10.1157 -qed
 10.1158 -
 10.1159 -lemma primefact_contains:
 10.1160 -  assumes pf: "primefact ps n" and p: "prime p" and pn: "p dvd n"
 10.1161 -  shows "p \<in> set ps"
 10.1162 -  using pf p pn
 10.1163 -proof(induct ps arbitrary: p n)
 10.1164 -  case Nil thus ?case by (auto simp add: primefact_def)
 10.1165 -next
 10.1166 -  case (Cons q qs p n)
 10.1167 -  from Cons.prems[unfolded primefact_def]
 10.1168 -  have q: "prime q" "q * foldr op * qs 1 = n" "\<forall>p \<in>set qs. prime p"  and p: "prime p" "p dvd q * foldr op * qs 1" by simp_all
 10.1169 -  {assume "p dvd q"
 10.1170 -    with p(1) q(1) have "p = q" unfolding prime_def by auto
 10.1171 -    hence ?case by simp}
 10.1172 -  moreover
 10.1173 -  { assume h: "p dvd foldr op * qs 1"
 10.1174 -    from q(3) have pqs: "primefact qs (foldr op * qs 1)"
 10.1175 -      by (simp add: primefact_def)
 10.1176 -    from Cons.hyps[OF pqs p(1) h] have ?case by simp}
 10.1177 -  ultimately show ?case using prime_divprod[OF p] by blast
 10.1178 -qed
 10.1179 -
 10.1180 -lemma primefact_variant: "primefact ps n \<longleftrightarrow> foldr op * ps 1 = n \<and> list_all prime ps" by (auto simp add: primefact_def list_all_iff)
 10.1181 -
 10.1182 -(* Variant of Lucas theorem.                                                 *)
 10.1183 -
 10.1184 -lemma lucas_primefact:
 10.1185 -  assumes n: "n \<ge> 2" and an: "[a^(n - 1) = 1] (mod n)"
 10.1186 -  and psn: "foldr op * ps 1 = n - 1"
 10.1187 -  and psp: "list_all (\<lambda>p. prime p \<and> \<not> [a^((n - 1) div p) = 1] (mod n)) ps"
 10.1188 -  shows "prime n"
 10.1189 -proof-
 10.1190 -  {fix p assume p: "prime p" "p dvd n - 1" "[a ^ ((n - 1) div p) = 1] (mod n)"
 10.1191 -    from psn psp have psn1: "primefact ps (n - 1)"
 10.1192 -      by (auto simp add: list_all_iff primefact_variant)
 10.1193 -    from p(3) primefact_contains[OF psn1 p(1,2)] psp
 10.1194 -    have False by (induct ps, auto)}
 10.1195 -  with lucas[OF n an] show ?thesis by blast
 10.1196 -qed
 10.1197 -
 10.1198 -(* Variant of Pocklington theorem.                                           *)
 10.1199 -
 10.1200 -lemma mod_le: assumes n: "n \<noteq> (0::nat)" shows "m mod n \<le> m"
 10.1201 -proof-
 10.1202 -    from mod_div_equality[of m n]
 10.1203 -    have "\<exists>x. x + m mod n = m" by blast
 10.1204 -    then show ?thesis by auto
 10.1205 -qed
 10.1206 -
 10.1207 -
 10.1208 -lemma pocklington_primefact:
 10.1209 -  assumes n: "n \<ge> 2" and qrn: "q*r = n - 1" and nq2: "n \<le> q^2"
 10.1210 -  and arnb: "(a^r) mod n = b" and psq: "foldr op * ps 1 = q"
 10.1211 -  and bqn: "(b^q) mod n = 1"
 10.1212 -  and psp: "list_all (\<lambda>p. prime p \<and> coprime ((b^(q div p)) mod n - 1) n) ps"
 10.1213 -  shows "prime n"
 10.1214 -proof-
 10.1215 -  from bqn psp qrn
 10.1216 -  have bqn: "a ^ (n - 1) mod n = 1"
 10.1217 -    and psp: "list_all (\<lambda>p. prime p \<and> coprime (a^(r *(q div p)) mod n - 1) n) ps"  unfolding arnb[symmetric] power_mod
 10.1218 -    by (simp_all add: power_mult[symmetric] algebra_simps)
 10.1219 -  from n  have n0: "n > 0" by arith
 10.1220 -  from mod_div_equality[of "a^(n - 1)" n]
 10.1221 -    mod_less_divisor[OF n0, of "a^(n - 1)"]
 10.1222 -  have an1: "[a ^ (n - 1) = 1] (mod n)"
 10.1223 -    unfolding nat_mod bqn
 10.1224 -    apply -
 10.1225 -    apply (rule exI[where x="0"])
 10.1226 -    apply (rule exI[where x="a^(n - 1) div n"])
 10.1227 -    by (simp add: algebra_simps)
 10.1228 -  {fix p assume p: "prime p" "p dvd q"
 10.1229 -    from psp psq have pfpsq: "primefact ps q"
 10.1230 -      by (auto simp add: primefact_variant list_all_iff)
 10.1231 -    from psp primefact_contains[OF pfpsq p]
 10.1232 -    have p': "coprime (a ^ (r * (q div p)) mod n - 1) n"
 10.1233 -      by (simp add: list_all_iff)
 10.1234 -    from prime_ge_2[OF p(1)] have p01: "p \<noteq> 0" "p \<noteq> 1" "p =Suc(p - 1)" by arith+
 10.1235 -    from div_mult1_eq[of r q p] p(2)
 10.1236 -    have eq1: "r* (q div p) = (n - 1) div p"
 10.1237 -      unfolding qrn[symmetric] dvd_eq_mod_eq_0 by (simp add: mult_commute)
 10.1238 -    have ath: "\<And>a (b::nat). a <= b \<Longrightarrow> a \<noteq> 0 ==> 1 <= a \<and> 1 <= b" by arith
 10.1239 -    from n0 have n00: "n \<noteq> 0" by arith
 10.1240 -    from mod_le[OF n00]
 10.1241 -    have th10: "a ^ ((n - 1) div p) mod n \<le> a ^ ((n - 1) div p)" .
 10.1242 -    {assume "a ^ ((n - 1) div p) mod n = 0"
 10.1243 -      then obtain s where s: "a ^ ((n - 1) div p) = n*s"
 10.1244 -	unfolding mod_eq_0_iff by blast
 10.1245 -      hence eq0: "(a^((n - 1) div p))^p = (n*s)^p" by simp
 10.1246 -      from qrn[symmetric] have qn1: "q dvd n - 1" unfolding dvd_def by auto
 10.1247 -      from dvd_trans[OF p(2) qn1] div_mod_equality'[of "n - 1" p]
 10.1248 -      have npp: "(n - 1) div p * p = n - 1" by (simp add: dvd_eq_mod_eq_0)
 10.1249 -      with eq0 have "a^ (n - 1) = (n*s)^p"
 10.1250 -	by (simp add: power_mult[symmetric])
 10.1251 -      hence "1 = (n*s)^(Suc (p - 1)) mod n" using bqn p01 by simp
 10.1252 -      also have "\<dots> = 0" by (simp add: mult_assoc)
 10.1253 -      finally have False by simp }
 10.1254 -      then have th11: "a ^ ((n - 1) div p) mod n \<noteq> 0" by auto
 10.1255 -    have th1: "[a ^ ((n - 1) div p) mod n = a ^ ((n - 1) div p)] (mod n)"
 10.1256 -      unfolding modeq_def by simp
 10.1257 -    from cong_sub[OF th1 cong_refl[of 1]]  ath[OF th10 th11]
 10.1258 -    have th: "[a ^ ((n - 1) div p) mod n - 1 = a ^ ((n - 1) div p) - 1] (mod n)"
 10.1259 -      by blast
 10.1260 -    from cong_coprime[OF th] p'[unfolded eq1]
 10.1261 -    have "coprime (a ^ ((n - 1) div p) - 1) n" by (simp add: coprime_commute) }
 10.1262 -  with pocklington[OF n qrn[symmetric] nq2 an1]
 10.1263 -  show ?thesis by blast
 10.1264 -qed
 10.1265 -
 10.1266 -end
    11.1 --- a/src/HOL/Library/Primes.thy	Tue Sep 01 14:13:34 2009 +0200
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,828 +0,0 @@
    11.4 -(*  Title:      HOL/Library/Primes.thy
    11.5 -    Author:     Amine Chaieb, Christophe Tabacznyj and Lawrence C Paulson
    11.6 -    Copyright   1996  University of Cambridge
    11.7 -*)
    11.8 -
    11.9 -header {* Primality on nat *}
   11.10 -
   11.11 -theory Primes
   11.12 -imports Complex_Main Legacy_GCD
   11.13 -begin
   11.14 -
   11.15 -hide (open) const GCD.gcd GCD.coprime GCD.prime
   11.16 -
   11.17 -definition
   11.18 -  coprime :: "nat => nat => bool" where
   11.19 -  "coprime m n \<longleftrightarrow> gcd m n = 1"
   11.20 -
   11.21 -definition
   11.22 -  prime :: "nat \<Rightarrow> bool" where
   11.23 -  [code del]: "prime p \<longleftrightarrow> (1 < p \<and> (\<forall>m. m dvd p --> m = 1 \<or> m = p))"
   11.24 -
   11.25 -
   11.26 -lemma two_is_prime: "prime 2"
   11.27 -  apply (auto simp add: prime_def)
   11.28 -  apply (case_tac m)
   11.29 -   apply (auto dest!: dvd_imp_le)
   11.30 -  done
   11.31 -
   11.32 -lemma prime_imp_relprime: "prime p ==> \<not> p dvd n ==> gcd p n = 1"
   11.33 -  apply (auto simp add: prime_def)
   11.34 -  apply (metis One_nat_def gcd_dvd1 gcd_dvd2)
   11.35 -  done
   11.36 -
   11.37 -text {*
   11.38 -  This theorem leads immediately to a proof of the uniqueness of
   11.39 -  factorization.  If @{term p} divides a product of primes then it is
   11.40 -  one of those primes.
   11.41 -*}
   11.42 -
   11.43 -lemma prime_dvd_mult: "prime p ==> p dvd m * n ==> p dvd m \<or> p dvd n"
   11.44 -  by (blast intro: relprime_dvd_mult prime_imp_relprime)
   11.45 -
   11.46 -lemma prime_dvd_square: "prime p ==> p dvd m^Suc (Suc 0) ==> p dvd m"
   11.47 -  by (auto dest: prime_dvd_mult)
   11.48 -
   11.49 -lemma prime_dvd_power_two: "prime p ==> p dvd m\<twosuperior> ==> p dvd m"
   11.50 -  by (rule prime_dvd_square) (simp_all add: power2_eq_square)
   11.51 -
   11.52 -
   11.53 -lemma exp_eq_1:"(x::nat)^n = 1 \<longleftrightarrow> x = 1 \<or> n = 0"
   11.54 -by (induct n, auto)
   11.55 -
   11.56 -lemma exp_mono_lt: "(x::nat) ^ (Suc n) < y ^ (Suc n) \<longleftrightarrow> x < y"
   11.57 -by(metis linorder_not_less not_less0 power_le_imp_le_base power_less_imp_less_base)
   11.58 -
   11.59 -lemma exp_mono_le: "(x::nat) ^ (Suc n) \<le> y ^ (Suc n) \<longleftrightarrow> x \<le> y"
   11.60 -by (simp only: linorder_not_less[symmetric] exp_mono_lt)
   11.61 -
   11.62 -lemma exp_mono_eq: "(x::nat) ^ Suc n = y ^ Suc n \<longleftrightarrow> x = y"
   11.63 -using power_inject_base[of x n y] by auto
   11.64 -
   11.65 -
   11.66 -lemma even_square: assumes e: "even (n::nat)" shows "\<exists>x. n ^ 2 = 4*x"
   11.67 -proof-
   11.68 -  from e have "2 dvd n" by presburger
   11.69 -  then obtain k where k: "n = 2*k" using dvd_def by auto
   11.70 -  hence "n^2 = 4* (k^2)" by (simp add: power2_eq_square)
   11.71 -  thus ?thesis by blast
   11.72 -qed
   11.73 -
   11.74 -lemma odd_square: assumes e: "odd (n::nat)" shows "\<exists>x. n ^ 2 = 4*x + 1"
   11.75 -proof-
   11.76 -  from e have np: "n > 0" by presburger
   11.77 -  from e have "2 dvd (n - 1)" by presburger
   11.78 -  then obtain k where "n - 1 = 2*k" using dvd_def by auto
   11.79 -  hence k: "n = 2*k + 1"  using e by presburger 
   11.80 -  hence "n^2 = 4* (k^2 + k) + 1" by algebra   
   11.81 -  thus ?thesis by blast
   11.82 -qed
   11.83 -
   11.84 -lemma diff_square: "(x::nat)^2 - y^2 = (x+y)*(x - y)" 
   11.85 -proof-
   11.86 -  have "x \<le> y \<or> y \<le> x" by (rule nat_le_linear)
   11.87 -  moreover
   11.88 -  {assume le: "x \<le> y"
   11.89 -    hence "x ^2 \<le> y^2" by (simp only: numeral_2_eq_2 exp_mono_le Let_def)
   11.90 -    with le have ?thesis by simp }
   11.91 -  moreover
   11.92 -  {assume le: "y \<le> x"
   11.93 -    hence le2: "y ^2 \<le> x^2" by (simp only: numeral_2_eq_2 exp_mono_le Let_def)
   11.94 -    from le have "\<exists>z. y + z = x" by presburger
   11.95 -    then obtain z where z: "x = y + z" by blast 
   11.96 -    from le2 have "\<exists>z. x^2 = y^2 + z" by presburger
   11.97 -    then obtain z2 where z2: "x^2 = y^2 + z2"  by blast
   11.98 -    from z z2 have ?thesis apply simp by algebra }
   11.99 -  ultimately show ?thesis by blast  
  11.100 -qed
  11.101 -
  11.102 -text {* Elementary theory of divisibility *}
  11.103 -lemma divides_ge: "(a::nat) dvd b \<Longrightarrow> b = 0 \<or> a \<le> b" unfolding dvd_def by auto
  11.104 -lemma divides_antisym: "(x::nat) dvd y \<and> y dvd x \<longleftrightarrow> x = y"
  11.105 -  using dvd_anti_sym[of x y] by auto
  11.106 -
  11.107 -lemma divides_add_revr: assumes da: "(d::nat) dvd a" and dab:"d dvd (a + b)"
  11.108 -  shows "d dvd b"
  11.109 -proof-
  11.110 -  from da obtain k where k:"a = d*k" by (auto simp add: dvd_def)
  11.111 -  from dab obtain k' where k': "a + b = d*k'" by (auto simp add: dvd_def)
  11.112 -  from k k' have "b = d *(k' - k)" by (simp add : diff_mult_distrib2)
  11.113 -  thus ?thesis unfolding dvd_def by blast
  11.114 -qed
  11.115 -
  11.116 -declare nat_mult_dvd_cancel_disj[presburger]
  11.117 -lemma nat_mult_dvd_cancel_disj'[presburger]: 
  11.118 -  "(m\<Colon>nat)*k dvd n*k \<longleftrightarrow> k = 0 \<or> m dvd n" unfolding mult_commute[of m k] mult_commute[of n k] by presburger 
  11.119 -
  11.120 -lemma divides_mul_l: "(a::nat) dvd b ==> (c * a) dvd (c * b)"
  11.121 -  by presburger
  11.122 -
  11.123 -lemma divides_mul_r: "(a::nat) dvd b ==> (a * c) dvd (b * c)" by presburger
  11.124 -lemma divides_cases: "(n::nat) dvd m ==> m = 0 \<or> m = n \<or> 2 * n <= m" 
  11.125 -  by (auto simp add: dvd_def)
  11.126 -
  11.127 -lemma divides_div_not: "(x::nat) = (q * n) + r \<Longrightarrow> 0 < r \<Longrightarrow> r < n ==> ~(n dvd x)"
  11.128 -proof(auto simp add: dvd_def)
  11.129 -  fix k assume H: "0 < r" "r < n" "q * n + r = n * k"
  11.130 -  from H(3) have r: "r = n* (k -q)" by(simp add: diff_mult_distrib2 mult_commute)
  11.131 -  {assume "k - q = 0" with r H(1) have False by simp}
  11.132 -  moreover
  11.133 -  {assume "k - q \<noteq> 0" with r have "r \<ge> n" by auto
  11.134 -    with H(2) have False by simp}
  11.135 -  ultimately show False by blast
  11.136 -qed
  11.137 -lemma divides_exp: "(x::nat) dvd y ==> x ^ n dvd y ^ n"
  11.138 -  by (auto simp add: power_mult_distrib dvd_def)
  11.139 -
  11.140 -lemma divides_exp2: "n \<noteq> 0 \<Longrightarrow> (x::nat) ^ n dvd y \<Longrightarrow> x dvd y" 
  11.141 -  by (induct n ,auto simp add: dvd_def)
  11.142 -
  11.143 -fun fact :: "nat \<Rightarrow> nat" where
  11.144 -  "fact 0 = 1"
  11.145 -| "fact (Suc n) = Suc n * fact n"	
  11.146 -
  11.147 -lemma fact_lt: "0 < fact n" by(induct n, simp_all)
  11.148 -lemma fact_le: "fact n \<ge> 1" using fact_lt[of n] by simp 
  11.149 -lemma fact_mono: assumes le: "m \<le> n" shows "fact m \<le> fact n"
  11.150 -proof-
  11.151 -  from le have "\<exists>i. n = m+i" by presburger
  11.152 -  then obtain i where i: "n = m+i" by blast 
  11.153 -  have "fact m \<le> fact (m + i)"
  11.154 -  proof(induct m)
  11.155 -    case 0 thus ?case using fact_le[of i] by simp
  11.156 -  next
  11.157 -    case (Suc m)
  11.158 -    have "fact (Suc m) = Suc m * fact m" by simp
  11.159 -    have th1: "Suc m \<le> Suc (m + i)" by simp
  11.160 -    from mult_le_mono[of "Suc m" "Suc (m+i)" "fact m" "fact (m+i)", OF th1 Suc.hyps]
  11.161 -    show ?case by simp
  11.162 -  qed
  11.163 -  thus ?thesis using i by simp
  11.164 -qed
  11.165 -
  11.166 -lemma divides_fact: "1 <= p \<Longrightarrow> p <= n ==> p dvd fact n"
  11.167 -proof(induct n arbitrary: p)
  11.168 -  case 0 thus ?case by simp
  11.169 -next
  11.170 -  case (Suc n p)
  11.171 -  from Suc.prems have "p = Suc n \<or> p \<le> n" by presburger 
  11.172 -  moreover
  11.173 -  {assume "p = Suc n" hence ?case  by (simp only: fact.simps dvd_triv_left)}
  11.174 -  moreover
  11.175 -  {assume "p \<le> n"
  11.176 -    with Suc.prems(1) Suc.hyps have th: "p dvd fact n" by simp
  11.177 -    from dvd_mult[OF th] have ?case by (simp only: fact.simps) }
  11.178 -  ultimately show ?case by blast
  11.179 -qed
  11.180 -
  11.181 -declare dvd_triv_left[presburger]
  11.182 -declare dvd_triv_right[presburger]
  11.183 -lemma divides_rexp: 
  11.184 -  "x dvd y \<Longrightarrow> (x::nat) dvd (y^(Suc n))" by (simp add: dvd_mult2[of x y])
  11.185 -
  11.186 -text {* Coprimality *}
  11.187 -
  11.188 -lemma coprime: "coprime a b \<longleftrightarrow> (\<forall>d. d dvd a \<and> d dvd b \<longleftrightarrow> d = 1)"
  11.189 -using gcd_unique[of 1 a b, simplified] by (auto simp add: coprime_def)
  11.190 -lemma coprime_commute: "coprime a b \<longleftrightarrow> coprime b a" by (simp add: coprime_def gcd_commute)
  11.191 -
  11.192 -lemma coprime_bezout: "coprime a b \<longleftrightarrow> (\<exists>x y. a * x - b * y = 1 \<or> b * x - a * y = 1)"
  11.193 -using coprime_def gcd_bezout by auto
  11.194 -
  11.195 -lemma coprime_divprod: "d dvd a * b  \<Longrightarrow> coprime d a \<Longrightarrow> d dvd b"
  11.196 -  using relprime_dvd_mult_iff[of d a b] by (auto simp add: coprime_def mult_commute)
  11.197 -
  11.198 -lemma coprime_1[simp]: "coprime a 1" by (simp add: coprime_def)
  11.199 -lemma coprime_1'[simp]: "coprime 1 a" by (simp add: coprime_def)
  11.200 -lemma coprime_Suc0[simp]: "coprime a (Suc 0)" by (simp add: coprime_def)
  11.201 -lemma coprime_Suc0'[simp]: "coprime (Suc 0) a" by (simp add: coprime_def)
  11.202 -
  11.203 -lemma gcd_coprime: 
  11.204 -  assumes z: "gcd a b \<noteq> 0" and a: "a = a' * gcd a b" and b: "b = b' * gcd a b" 
  11.205 -  shows    "coprime a' b'"
  11.206 -proof-
  11.207 -  let ?g = "gcd a b"
  11.208 -  {assume bz: "a = 0" from b bz z a have ?thesis by (simp add: gcd_zero coprime_def)}
  11.209 -  moreover 
  11.210 -  {assume az: "a\<noteq> 0" 
  11.211 -    from z have z': "?g > 0" by simp
  11.212 -    from bezout_gcd_strong[OF az, of b] 
  11.213 -    obtain x y where xy: "a*x = b*y + ?g" by blast
  11.214 -    from xy a b have "?g * a'*x = ?g * (b'*y + 1)" by (simp add: algebra_simps)
  11.215 -    hence "?g * (a'*x) = ?g * (b'*y + 1)" by (simp add: mult_assoc)
  11.216 -    hence "a'*x = (b'*y + 1)"
  11.217 -      by (simp only: nat_mult_eq_cancel1[OF z']) 
  11.218 -    hence "a'*x - b'*y = 1" by simp
  11.219 -    with coprime_bezout[of a' b'] have ?thesis by auto}
  11.220 -  ultimately show ?thesis by blast
  11.221 -qed
  11.222 -lemma coprime_0: "coprime d 0 \<longleftrightarrow> d = 1" by (simp add: coprime_def)
  11.223 -lemma coprime_mul: assumes da: "coprime d a" and db: "coprime d b"
  11.224 -  shows "coprime d (a * b)"
  11.225 -proof-
  11.226 -  from da have th: "gcd a d = 1" by (simp add: coprime_def gcd_commute)
  11.227 -  from gcd_mult_cancel[of a d b, OF th] db[unfolded coprime_def] have "gcd d (a*b) = 1"
  11.228 -    by (simp add: gcd_commute)
  11.229 -  thus ?thesis unfolding coprime_def .
  11.230 -qed
  11.231 -lemma coprime_lmul2: assumes dab: "coprime d (a * b)" shows "coprime d b"
  11.232 -using prems unfolding coprime_bezout
  11.233 -apply clarsimp
  11.234 -apply (case_tac "d * x - a * b * y = Suc 0 ", simp_all)
  11.235 -apply (rule_tac x="x" in exI)
  11.236 -apply (rule_tac x="a*y" in exI)
  11.237 -apply (simp add: mult_ac)
  11.238 -apply (rule_tac x="a*x" in exI)
  11.239 -apply (rule_tac x="y" in exI)
  11.240 -apply (simp add: mult_ac)
  11.241 -done
  11.242 -
  11.243 -lemma coprime_rmul2: "coprime d (a * b) \<Longrightarrow> coprime d a"
  11.244 -unfolding coprime_bezout
  11.245 -apply clarsimp
  11.246 -apply (case_tac "d * x - a * b * y = Suc 0 ", simp_all)
  11.247 -apply (rule_tac x="x" in exI)
  11.248 -apply (rule_tac x="b*y" in exI)
  11.249 -apply (simp add: mult_ac)
  11.250 -apply (rule_tac x="b*x" in exI)
  11.251 -apply (rule_tac x="y" in exI)
  11.252 -apply (simp add: mult_ac)
  11.253 -done
  11.254 -lemma coprime_mul_eq: "coprime d (a * b) \<longleftrightarrow> coprime d a \<and>  coprime d b"
  11.255 -  using coprime_rmul2[of d a b] coprime_lmul2[of d a b] coprime_mul[of d a b] 
  11.256 -  by blast
  11.257 -
  11.258 -lemma gcd_coprime_exists:
  11.259 -  assumes nz: "gcd a b \<noteq> 0" 
  11.260 -  shows "\<exists>a' b'. a = a' * gcd a b \<and> b = b' * gcd a b \<and> coprime a' b'"
  11.261 -proof-
  11.262 -  let ?g = "gcd a b"
  11.263 -  from gcd_dvd1[of a b] gcd_dvd2[of a b] 
  11.264 -  obtain a' b' where "a = ?g*a'"  "b = ?g*b'" unfolding dvd_def by blast
  11.265 -  hence ab': "a = a'*?g" "b = b'*?g" by algebra+
  11.266 -  from ab' gcd_coprime[OF nz ab'] show ?thesis by blast
  11.267 -qed
  11.268 -
  11.269 -lemma coprime_exp: "coprime d a ==> coprime d (a^n)" 
  11.270 -  by(induct n, simp_all add: coprime_mul)
  11.271 -
  11.272 -lemma coprime_exp_imp: "coprime a b ==> coprime (a ^n) (b ^n)"
  11.273 -  by (induct n, simp_all add: coprime_mul_eq coprime_commute coprime_exp)
  11.274 -lemma coprime_refl[simp]: "coprime n n \<longleftrightarrow> n = 1" by (simp add: coprime_def)
  11.275 -lemma coprime_plus1[simp]: "coprime (n + 1) n"
  11.276 -  apply (simp add: coprime_bezout)
  11.277 -  apply (rule exI[where x=1])
  11.278 -  apply (rule exI[where x=1])
  11.279 -  apply simp
  11.280 -  done
  11.281 -lemma coprime_minus1: "n \<noteq> 0 ==> coprime (n - 1) n"
  11.282 -  using coprime_plus1[of "n - 1"] coprime_commute[of "n - 1" n] by auto
  11.283 -
  11.284 -lemma bezout_gcd_pow: "\<exists>x y. a ^n * x - b ^ n * y = gcd a b ^ n \<or> b ^ n * x - a ^ n * y = gcd a b ^ n"
  11.285 -proof-
  11.286 -  let ?g = "gcd a b"
  11.287 -  {assume z: "?g = 0" hence ?thesis 
  11.288 -      apply (cases n, simp)
  11.289 -      apply arith
  11.290 -      apply (simp only: z power_0_Suc)
  11.291 -      apply (rule exI[where x=0])
  11.292 -      apply (rule exI[where x=0])
  11.293 -      by simp}
  11.294 -  moreover
  11.295 -  {assume z: "?g \<noteq> 0"
  11.296 -    from gcd_dvd1[of a b] gcd_dvd2[of a b] obtain a' b' where
  11.297 -      ab': "a = a'*?g" "b = b'*?g" unfolding dvd_def by (auto simp add: mult_ac)
  11.298 -    hence ab'': "?g*a' = a" "?g * b' = b" by algebra+
  11.299 -    from coprime_exp_imp[OF gcd_coprime[OF z ab'], unfolded coprime_bezout, of n]
  11.300 -    obtain x y where "a'^n * x - b'^n * y = 1 \<or> b'^n * x - a'^n * y = 1"  by blast
  11.301 -    hence "?g^n * (a'^n * x - b'^n * y) = ?g^n \<or> ?g^n*(b'^n * x - a'^n * y) = ?g^n"
  11.302 -      using z by auto 
  11.303 -    then have "a^n * x - b^n * y = ?g^n \<or> b^n * x - a^n * y = ?g^n"
  11.304 -      using z ab'' by (simp only: power_mult_distrib[symmetric] 
  11.305 -	diff_mult_distrib2 mult_assoc[symmetric])
  11.306 -    hence  ?thesis by blast }
  11.307 -  ultimately show ?thesis by blast
  11.308 -qed
  11.309 -
  11.310 -lemma gcd_exp: "gcd (a^n) (b^n) = gcd a b^n"
  11.311 -proof-
  11.312 -  let ?g = "gcd (a^n) (b^n)"
  11.313 -  let ?gn = "gcd a b^n"
  11.314 -  {fix e assume H: "e dvd a^n" "e dvd b^n"
  11.315 -    from bezout_gcd_pow[of a n b] obtain x y 
  11.316 -      where xy: "a ^ n * x - b ^ n * y = ?gn \<or> b ^ n * x - a ^ n * y = ?gn" by blast
  11.317 -    from dvd_diff_nat [OF dvd_mult2[OF H(1), of x] dvd_mult2[OF H(2), of y]]
  11.318 -      dvd_diff_nat [OF dvd_mult2[OF H(2), of x] dvd_mult2[OF H(1), of y]] xy
  11.319 -    have "e dvd ?gn" by (cases "a ^ n * x - b ^ n * y = gcd a b ^ n", simp_all)}
  11.320 -  hence th:  "\<forall>e. e dvd a^n \<and> e dvd b^n \<longrightarrow> e dvd ?gn" by blast
  11.321 -  from divides_exp[OF gcd_dvd1[of a b], of n] divides_exp[OF gcd_dvd2[of a b], of n] th
  11.322 -    gcd_unique have "?gn = ?g" by blast thus ?thesis by simp 
  11.323 -qed
  11.324 -
  11.325 -lemma coprime_exp2:  "coprime (a ^ Suc n) (b^ Suc n) \<longleftrightarrow> coprime a b"
  11.326 -by (simp only: coprime_def gcd_exp exp_eq_1) simp
  11.327 -
  11.328 -lemma division_decomp: assumes dc: "(a::nat) dvd b * c"
  11.329 -  shows "\<exists>b' c'. a = b' * c' \<and> b' dvd b \<and> c' dvd c"
  11.330 -proof-
  11.331 -  let ?g = "gcd a b"
  11.332 -  {assume "?g = 0" with dc have ?thesis apply (simp add: gcd_zero)
  11.333 -      apply (rule exI[where x="0"])
  11.334 -      by (rule exI[where x="c"], simp)}
  11.335 -  moreover
  11.336 -  {assume z: "?g \<noteq> 0"
  11.337 -    from gcd_coprime_exists[OF z]
  11.338 -    obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'" by blast
  11.339 -    from gcd_dvd2[of a b] have thb: "?g dvd b" .
  11.340 -    from ab'(1) have "a' dvd a"  unfolding dvd_def by blast  
  11.341 -    with dc have th0: "a' dvd b*c" using dvd_trans[of a' a "b*c"] by simp
  11.342 -    from dc ab'(1,2) have "a'*?g dvd (b'*?g) *c" by auto
  11.343 -    hence "?g*a' dvd ?g * (b' * c)" by (simp add: mult_assoc)
  11.344 -    with z have th_1: "a' dvd b'*c" by simp
  11.345 -    from coprime_divprod[OF th_1 ab'(3)] have thc: "a' dvd c" . 
  11.346 -    from ab' have "a = ?g*a'" by algebra
  11.347 -    with thb thc have ?thesis by blast }
  11.348 -  ultimately show ?thesis by blast
  11.349 -qed
  11.350 -
  11.351 -lemma nat_power_eq_0_iff: "(m::nat) ^ n = 0 \<longleftrightarrow> n \<noteq> 0 \<and> m = 0" by (induct n, auto)
  11.352 -
  11.353 -lemma divides_rev: assumes ab: "(a::nat) ^ n dvd b ^n" and n:"n \<noteq> 0" shows "a dvd b"
  11.354 -proof-
  11.355 -  let ?g = "gcd a b"
  11.356 -  from n obtain m where m: "n = Suc m" by (cases n, simp_all)
  11.357 -  {assume "?g = 0" with ab n have ?thesis by (simp add: gcd_zero)}
  11.358 -  moreover
  11.359 -  {assume z: "?g \<noteq> 0"
  11.360 -    hence zn: "?g ^ n \<noteq> 0" using n by (simp add: neq0_conv)
  11.361 -    from gcd_coprime_exists[OF z] 
  11.362 -    obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'" by blast
  11.363 -    from ab have "(a' * ?g) ^ n dvd (b' * ?g)^n" by (simp add: ab'(1,2)[symmetric])
  11.364 -    hence "?g^n*a'^n dvd ?g^n *b'^n" by (simp only: power_mult_distrib mult_commute)
  11.365 -    with zn z n have th0:"a'^n dvd b'^n" by (auto simp add: nat_power_eq_0_iff)
  11.366 -    have "a' dvd a'^n" by (simp add: m)
  11.367 -    with th0 have "a' dvd b'^n" using dvd_trans[of a' "a'^n" "b'^n"] by simp
  11.368 -    hence th1: "a' dvd b'^m * b'" by (simp add: m mult_commute)
  11.369 -    from coprime_divprod[OF th1 coprime_exp[OF ab'(3), of m]]
  11.370 -    have "a' dvd b'" .
  11.371 -    hence "a'*?g dvd b'*?g" by simp
  11.372 -    with ab'(1,2)  have ?thesis by simp }
  11.373 -  ultimately show ?thesis by blast
  11.374 -qed
  11.375 -
  11.376 -lemma divides_mul: assumes mr: "m dvd r" and nr: "n dvd r" and mn:"coprime m n" 
  11.377 -  shows "m * n dvd r"
  11.378 -proof-
  11.379 -  from mr nr obtain m' n' where m': "r = m*m'" and n': "r = n*n'"
  11.380 -    unfolding dvd_def by blast
  11.381 -  from mr n' have "m dvd n'*n" by (simp add: mult_commute)
  11.382 -  hence "m dvd n'" using relprime_dvd_mult_iff[OF mn[unfolded coprime_def]] by simp
  11.383 -  then obtain k where k: "n' = m*k" unfolding dvd_def by blast
  11.384 -  from n' k show ?thesis unfolding dvd_def by auto
  11.385 -qed
  11.386 -
  11.387 -
  11.388 -text {* A binary form of the Chinese Remainder Theorem. *}
  11.389 -
  11.390 -lemma chinese_remainder: assumes ab: "coprime a b" and a:"a \<noteq> 0" and b:"b \<noteq> 0"
  11.391 -  shows "\<exists>x q1 q2. x = u + q1 * a \<and> x = v + q2 * b"
  11.392 -proof-
  11.393 -  from bezout_add_strong[OF a, of b] bezout_add_strong[OF b, of a]
  11.394 -  obtain d1 x1 y1 d2 x2 y2 where dxy1: "d1 dvd a" "d1 dvd b" "a * x1 = b * y1 + d1" 
  11.395 -    and dxy2: "d2 dvd b" "d2 dvd a" "b * x2 = a * y2 + d2" by blast
  11.396 -  from gcd_unique[of 1 a b, simplified ab[unfolded coprime_def], simplified] 
  11.397 -    dxy1(1,2) dxy2(1,2) have d12: "d1 = 1" "d2 =1" by auto
  11.398 -  let ?x = "v * a * x1 + u * b * x2"
  11.399 -  let ?q1 = "v * x1 + u * y2"
  11.400 -  let ?q2 = "v * y1 + u * x2"
  11.401 -  from dxy2(3)[simplified d12] dxy1(3)[simplified d12] 
  11.402 -  have "?x = u + ?q1 * a" "?x = v + ?q2 * b" by algebra+ 
  11.403 -  thus ?thesis by blast
  11.404 -qed
  11.405 -
  11.406 -text {* Primality *}
  11.407 -
  11.408 -text {* A few useful theorems about primes *}
  11.409 -
  11.410 -lemma prime_0[simp]: "~prime 0" by (simp add: prime_def)
  11.411 -lemma prime_1[simp]: "~ prime 1"  by (simp add: prime_def)
  11.412 -lemma prime_Suc0[simp]: "~ prime (Suc 0)"  by (simp add: prime_def)
  11.413 -
  11.414 -lemma prime_ge_2: "prime p ==> p \<ge> 2" by (simp add: prime_def)
  11.415 -lemma prime_factor: assumes n: "n \<noteq> 1" shows "\<exists> p. prime p \<and> p dvd n"
  11.416 -using n
  11.417 -proof(induct n rule: nat_less_induct)
  11.418 -  fix n
  11.419 -  assume H: "\<forall>m<n. m \<noteq> 1 \<longrightarrow> (\<exists>p. prime p \<and> p dvd m)" "n \<noteq> 1"
  11.420 -  let ?ths = "\<exists>p. prime p \<and> p dvd n"
  11.421 -  {assume "n=0" hence ?ths using two_is_prime by auto}
  11.422 -  moreover
  11.423 -  {assume nz: "n\<noteq>0" 
  11.424 -    {assume "prime n" hence ?ths by - (rule exI[where x="n"], simp)}
  11.425 -    moreover
  11.426 -    {assume n: "\<not> prime n"
  11.427 -      with nz H(2) 
  11.428 -      obtain k where k:"k dvd n" "k \<noteq> 1" "k \<noteq> n" by (auto simp add: prime_def) 
  11.429 -      from dvd_imp_le[OF k(1)] nz k(3) have kn: "k < n" by simp
  11.430 -      from H(1)[rule_format, OF kn k(2)] obtain p where p: "prime p" "p dvd k" by blast
  11.431 -      from dvd_trans[OF p(2) k(1)] p(1) have ?ths by blast}
  11.432 -    ultimately have ?ths by blast}
  11.433 -  ultimately show ?ths by blast
  11.434 -qed
  11.435 -
  11.436 -lemma prime_factor_lt: assumes p: "prime p" and n: "n \<noteq> 0" and npm:"n = p * m"
  11.437 -  shows "m < n"
  11.438 -proof-
  11.439 -  {assume "m=0" with n have ?thesis by simp}
  11.440 -  moreover
  11.441 -  {assume m: "m \<noteq> 0"
  11.442 -    from npm have mn: "m dvd n" unfolding dvd_def by auto
  11.443 -    from npm m have "n \<noteq> m" using p by auto
  11.444 -    with dvd_imp_le[OF mn] n have ?thesis by simp}
  11.445 -  ultimately show ?thesis by blast
  11.446 -qed
  11.447 -
  11.448 -lemma euclid_bound: "\<exists>p. prime p \<and> n < p \<and>  p <= Suc (fact n)"
  11.449 -proof-
  11.450 -  have f1: "fact n + 1 \<noteq> 1" using fact_le[of n] by arith 
  11.451 -  from prime_factor[OF f1] obtain p where p: "prime p" "p dvd fact n + 1" by blast
  11.452 -  from dvd_imp_le[OF p(2)] have pfn: "p \<le> fact n + 1" by simp
  11.453 -  {assume np: "p \<le> n"
  11.454 -    from p(1) have p1: "p \<ge> 1" by (cases p, simp_all)
  11.455 -    from divides_fact[OF p1 np] have pfn': "p dvd fact n" .
  11.456 -    from divides_add_revr[OF pfn' p(2)] p(1) have False by simp}
  11.457 -  hence "n < p" by arith
  11.458 -  with p(1) pfn show ?thesis by auto
  11.459 -qed
  11.460 -
  11.461 -lemma euclid: "\<exists>p. prime p \<and> p > n" using euclid_bound by auto
  11.462 -
  11.463 -lemma primes_infinite: "\<not> (finite {p. prime p})"
  11.464 -apply(simp add: finite_nat_set_iff_bounded_le)
  11.465 -apply (metis euclid linorder_not_le)
  11.466 -done
  11.467 -
  11.468 -lemma coprime_prime: assumes ab: "coprime a b"
  11.469 -  shows "~(prime p \<and> p dvd a \<and> p dvd b)"
  11.470 -proof
  11.471 -  assume "prime p \<and> p dvd a \<and> p dvd b"
  11.472 -  thus False using ab gcd_greatest[of p a b] by (simp add: coprime_def)
  11.473 -qed
  11.474 -lemma coprime_prime_eq: "coprime a b \<longleftrightarrow> (\<forall>p. ~(prime p \<and> p dvd a \<and> p dvd b))" 
  11.475 -  (is "?lhs = ?rhs")
  11.476 -proof-
  11.477 -  {assume "?lhs" with coprime_prime  have ?rhs by blast}
  11.478 -  moreover
  11.479 -  {assume r: "?rhs" and c: "\<not> ?lhs"
  11.480 -    then obtain g where g: "g\<noteq>1" "g dvd a" "g dvd b" unfolding coprime_def by blast
  11.481 -    from prime_factor[OF g(1)] obtain p where p: "prime p" "p dvd g" by blast
  11.482 -    from dvd_trans [OF p(2) g(2)] dvd_trans [OF p(2) g(3)] 
  11.483 -    have "p dvd a" "p dvd b" . with p(1) r have False by blast}
  11.484 -  ultimately show ?thesis by blast
  11.485 -qed
  11.486 -
  11.487 -lemma prime_coprime: assumes p: "prime p" 
  11.488 -  shows "n = 1 \<or> p dvd n \<or> coprime p n"
  11.489 -using p prime_imp_relprime[of p n] by (auto simp add: coprime_def)
  11.490 -
  11.491 -lemma prime_coprime_strong: "prime p \<Longrightarrow> p dvd n \<or> coprime p n"
  11.492 -  using prime_coprime[of p n] by auto
  11.493 -
  11.494 -declare  coprime_0[simp]
  11.495 -
  11.496 -lemma coprime_0'[simp]: "coprime 0 d \<longleftrightarrow> d = 1" by (simp add: coprime_commute[of 0 d])
  11.497 -lemma coprime_bezout_strong: assumes ab: "coprime a b" and b: "b \<noteq> 1"
  11.498 -  shows "\<exists>x y. a * x = b * y + 1"
  11.499 -proof-
  11.500 -  from ab b have az: "a \<noteq> 0" by - (rule ccontr, auto)
  11.501 -  from bezout_gcd_strong[OF az, of b] ab[unfolded coprime_def]
  11.502 -  show ?thesis by auto
  11.503 -qed
  11.504 -
  11.505 -lemma bezout_prime: assumes p: "prime p"  and pa: "\<not> p dvd a"
  11.506 -  shows "\<exists>x y. a*x = p*y + 1"
  11.507 -proof-
  11.508 -  from p have p1: "p \<noteq> 1" using prime_1 by blast 
  11.509 -  from prime_coprime[OF p, of a] p1 pa have ap: "coprime a p" 
  11.510 -    by (auto simp add: coprime_commute)
  11.511 -  from coprime_bezout_strong[OF ap p1] show ?thesis . 
  11.512 -qed
  11.513 -lemma prime_divprod: assumes p: "prime p" and pab: "p dvd a*b"
  11.514 -  shows "p dvd a \<or> p dvd b"
  11.515 -proof-
  11.516 -  {assume "a=1" hence ?thesis using pab by simp }
  11.517 -  moreover
  11.518 -  {assume "p dvd a" hence ?thesis by blast}
  11.519 -  moreover
  11.520 -  {assume pa: "coprime p a" from coprime_divprod[OF pab pa]  have ?thesis .. }
  11.521 -  ultimately show ?thesis using prime_coprime[OF p, of a] by blast
  11.522 -qed
  11.523 -
  11.524 -lemma prime_divprod_eq: assumes p: "prime p"
  11.525 -  shows "p dvd a*b \<longleftrightarrow> p dvd a \<or> p dvd b"
  11.526 -using p prime_divprod dvd_mult dvd_mult2 by auto
  11.527 -
  11.528 -lemma prime_divexp: assumes p:"prime p" and px: "p dvd x^n"
  11.529 -  shows "p dvd x"
  11.530 -using px
  11.531 -proof(induct n)
  11.532 -  case 0 thus ?case by simp
  11.533 -next
  11.534 -  case (Suc n) 
  11.535 -  hence th: "p dvd x*x^n" by simp
  11.536 -  {assume H: "p dvd x^n"
  11.537 -    from Suc.hyps[OF H] have ?case .}
  11.538 -  with prime_divprod[OF p th] show ?case by blast
  11.539 -qed
  11.540 -
  11.541 -lemma prime_divexp_n: "prime p \<Longrightarrow> p dvd x^n \<Longrightarrow> p^n dvd x^n"
  11.542 -  using prime_divexp[of p x n] divides_exp[of p x n] by blast
  11.543 -
  11.544 -lemma coprime_prime_dvd_ex: assumes xy: "\<not>coprime x y"
  11.545 -  shows "\<exists>p. prime p \<and> p dvd x \<and> p dvd y"
  11.546 -proof-
  11.547 -  from xy[unfolded coprime_def] obtain g where g: "g \<noteq> 1" "g dvd x" "g dvd y" 
  11.548 -    by blast
  11.549 -  from prime_factor[OF g(1)] obtain p where p: "prime p" "p dvd g" by blast
  11.550 -  from g(2,3) dvd_trans[OF p(2)] p(1) show ?thesis by auto
  11.551 -qed
  11.552 -lemma coprime_sos: assumes xy: "coprime x y" 
  11.553 -  shows "coprime (x * y) (x^2 + y^2)"
  11.554 -proof-
  11.555 -  {assume c: "\<not> coprime (x * y) (x^2 + y^2)"
  11.556 -    from coprime_prime_dvd_ex[OF c] obtain p 
  11.557 -      where p: "prime p" "p dvd x*y" "p dvd x^2 + y^2" by blast
  11.558 -    {assume px: "p dvd x"
  11.559 -      from dvd_mult[OF px, of x] p(3) 
  11.560 -        obtain r s where "x * x = p * r" and "x^2 + y^2 = p * s"
  11.561 -          by (auto elim!: dvdE)
  11.562 -        then have "y^2 = p * (s - r)" 
  11.563 -          by (auto simp add: power2_eq_square diff_mult_distrib2)
  11.564 -        then have "p dvd y^2" ..
  11.565 -      with prime_divexp[OF p(1), of y 2] have py: "p dvd y" .
  11.566 -      from p(1) px py xy[unfolded coprime, rule_format, of p] prime_1  
  11.567 -      have False by simp }
  11.568 -    moreover
  11.569 -    {assume py: "p dvd y"
  11.570 -      from dvd_mult[OF py, of y] p(3)
  11.571 -        obtain r s where "y * y = p * r" and "x^2 + y^2 = p * s"
  11.572 -          by (auto elim!: dvdE)
  11.573 -        then have "x^2 = p * (s - r)" 
  11.574 -          by (auto simp add: power2_eq_square diff_mult_distrib2)
  11.575 -        then have "p dvd x^2" ..
  11.576 -      with prime_divexp[OF p(1), of x 2] have px: "p dvd x" .
  11.577 -      from p(1) px py xy[unfolded coprime, rule_format, of p] prime_1  
  11.578 -      have False by simp }
  11.579 -    ultimately have False using prime_divprod[OF p(1,2)] by blast}
  11.580 -  thus ?thesis by blast
  11.581 -qed
  11.582 -
  11.583 -lemma distinct_prime_coprime: "prime p \<Longrightarrow> prime q \<Longrightarrow> p \<noteq> q \<Longrightarrow> coprime p q"
  11.584 -  unfolding prime_def coprime_prime_eq by blast
  11.585 -
  11.586 -lemma prime_coprime_lt: assumes p: "prime p" and x: "0 < x" and xp: "x < p"
  11.587 -  shows "coprime x p"
  11.588 -proof-
  11.589 -  {assume c: "\<not> coprime x p"
  11.590 -    then obtain g where g: "g \<noteq> 1" "g dvd x" "g dvd p" unfolding coprime_def by blast
  11.591 -  from dvd_imp_le[OF g(2)] x xp have gp: "g < p" by arith
  11.592 -  from g(2) x have "g \<noteq> 0" by - (rule ccontr, simp)
  11.593 -  with g gp p[unfolded prime_def] have False by blast}
  11.594 -thus ?thesis by blast
  11.595 -qed
  11.596 -
  11.597 -lemma even_dvd[simp]: "even (n::nat) \<longleftrightarrow> 2 dvd n" by presburger
  11.598 -lemma prime_odd: "prime p \<Longrightarrow> p = 2 \<or> odd p" unfolding prime_def by auto
  11.599 -
  11.600 -
  11.601 -text {* One property of coprimality is easier to prove via prime factors. *}
  11.602 -
  11.603 -lemma prime_divprod_pow: 
  11.604 -  assumes p: "prime p" and ab: "coprime a b" and pab: "p^n dvd a * b"
  11.605 -  shows "p^n dvd a \<or> p^n dvd b"
  11.606 -proof-
  11.607 -  {assume "n = 0 \<or> a = 1 \<or> b = 1" with pab have ?thesis 
  11.608 -      apply (cases "n=0", simp_all)
  11.609 -      apply (cases "a=1", simp_all) done}
  11.610 -  moreover
  11.611 -  {assume n: "n \<noteq> 0" and a: "a\<noteq>1" and b: "b\<noteq>1" 
  11.612 -    then obtain m where m: "n = Suc m" by (cases n, auto)
  11.613 -    from divides_exp2[OF n pab] have pab': "p dvd a*b" .
  11.614 -    from prime_divprod[OF p pab'] 
  11.615 -    have "p dvd a \<or> p dvd b" .
  11.616 -    moreover
  11.617 -    {assume pa: "p dvd a"
  11.618 -      have pnba: "p^n dvd b*a" using pab by (simp add: mult_commute)
  11.619 -      from coprime_prime[OF ab, of p] p pa have "\<not> p dvd b" by blast
  11.620 -      with prime_coprime[OF p, of b] b 
  11.621 -      have cpb: "coprime b p" using coprime_commute by blast 
  11.622 -      from coprime_exp[OF cpb] have pnb: "coprime (p^n) b" 
  11.623 -	by (simp add: coprime_commute)
  11.624 -      from coprime_divprod[OF pnba pnb] have ?thesis by blast }
  11.625 -    moreover
  11.626 -    {assume pb: "p dvd b"
  11.627 -      have pnba: "p^n dvd b*a" using pab by (simp add: mult_commute)
  11.628 -      from coprime_prime[OF ab, of p] p pb have "\<not> p dvd a" by blast
  11.629 -      with prime_coprime[OF p, of a] a
  11.630 -      have cpb: "coprime a p" using coprime_commute by blast 
  11.631 -      from coprime_exp[OF cpb] have pnb: "coprime (p^n) a" 
  11.632 -	by (simp add: coprime_commute)
  11.633 -      from coprime_divprod[OF pab pnb] have ?thesis by blast }
  11.634 -    ultimately have ?thesis by blast}
  11.635 -  ultimately show ?thesis by blast
  11.636 -qed
  11.637 -
  11.638 -lemma nat_mult_eq_one: "(n::nat) * m = 1 \<longleftrightarrow> n = 1 \<and> m = 1" (is "?lhs \<longleftrightarrow> ?rhs")
  11.639 -proof
  11.640 -  assume H: "?lhs"
  11.641 -  hence "n dvd 1" "m dvd 1" unfolding dvd_def by (auto simp add: mult_commute)
  11.642 -  thus ?rhs by auto
  11.643 -next
  11.644 -  assume ?rhs then show ?lhs by auto
  11.645 -qed
  11.646 -  
  11.647 -lemma power_Suc0[simp]: "Suc 0 ^ n = Suc 0" 
  11.648 -  unfolding One_nat_def[symmetric] power_one ..
  11.649 -lemma coprime_pow: assumes ab: "coprime a b" and abcn: "a * b = c ^n"
  11.650 -  shows "\<exists>r s. a = r^n  \<and> b = s ^n"
  11.651 -  using ab abcn
  11.652 -proof(induct c arbitrary: a b rule: nat_less_induct)
  11.653 -  fix c a b
  11.654 -  assume H: "\<forall>m<c. \<forall>a b. coprime a b \<longrightarrow> a * b = m ^ n \<longrightarrow> (\<exists>r s. a = r ^ n \<and> b = s ^ n)" "coprime a b" "a * b = c ^ n" 
  11.655 -  let ?ths = "\<exists>r s. a = r^n  \<and> b = s ^n"
  11.656 -  {assume n: "n = 0"
  11.657 -    with H(3) power_one have "a*b = 1" by simp
  11.658 -    hence "a = 1 \<and> b = 1" by simp
  11.659 -    hence ?ths 
  11.660 -      apply -
  11.661 -      apply (rule exI[where x=1])
  11.662 -      apply (rule exI[where x=1])
  11.663 -      using power_one[of  n]
  11.664 -      by simp}
  11.665 -  moreover
  11.666 -  {assume n: "n \<noteq> 0" then obtain m where m: "n = Suc m" by (cases n, auto)
  11.667 -    {assume c: "c = 0"
  11.668 -      with H(3) m H(2) have ?ths apply simp 
  11.669 -	apply (cases "a=0", simp_all) 
  11.670 -	apply (rule exI[where x="0"], simp)
  11.671 -	apply (rule exI[where x="0"], simp)
  11.672 -	done}
  11.673 -    moreover
  11.674 -    {assume "c=1" with H(3) power_one have "a*b = 1" by simp 
  11.675 -	hence "a = 1 \<and> b = 1" by simp
  11.676 -	hence ?ths 
  11.677 -      apply -
  11.678 -      apply (rule exI[where x=1])
  11.679 -      apply (rule exI[where x=1])
  11.680 -      using power_one[of  n]
  11.681 -      by simp}
  11.682 -  moreover
  11.683 -  {assume c: "c\<noteq>1" "c \<noteq> 0"
  11.684 -    from prime_factor[OF c(1)] obtain p where p: "prime p" "p dvd c" by blast
  11.685 -    from prime_divprod_pow[OF p(1) H(2), unfolded H(3), OF divides_exp[OF p(2), of n]] 
  11.686 -    have pnab: "p ^ n dvd a \<or> p^n dvd b" . 
  11.687 -    from p(2) obtain l where l: "c = p*l" unfolding dvd_def by blast
  11.688 -    have pn0: "p^n \<noteq> 0" using n prime_ge_2 [OF p(1)] by (simp add: neq0_conv)
  11.689 -    {assume pa: "p^n dvd a"
  11.690 -      then obtain k where k: "a = p^n * k" unfolding dvd_def by blast
  11.691 -      from l have "l dvd c" by auto
  11.692 -      with dvd_imp_le[of l c] c have "l \<le> c" by auto
  11.693 -      moreover {assume "l = c" with l c  have "p = 1" by simp with p have False by simp}
  11.694 -      ultimately have lc: "l < c" by arith
  11.695 -      from coprime_lmul2 [OF H(2)[unfolded k coprime_commute[of "p^n*k" b]]]
  11.696 -      have kb: "coprime k b" by (simp add: coprime_commute) 
  11.697 -      from H(3) l k pn0 have kbln: "k * b = l ^ n" 
  11.698 -	by (auto simp add: power_mult_distrib)
  11.699 -      from H(1)[rule_format, OF lc kb kbln]
  11.700 -      obtain r s where rs: "k = r ^n" "b = s^n" by blast
  11.701 -      from k rs(1) have "a = (p*r)^n" by (simp add: power_mult_distrib)
  11.702 -      with rs(2) have ?ths by blast }
  11.703 -    moreover
  11.704 -    {assume pb: "p^n dvd b"
  11.705 -      then obtain k where k: "b = p^n * k" unfolding dvd_def by blast
  11.706 -      from l have "l dvd c" by auto
  11.707 -      with dvd_imp_le[of l c] c have "l \<le> c" by auto
  11.708 -      moreover {assume "l = c" with l c  have "p = 1" by simp with p have False by simp}
  11.709 -      ultimately have lc: "l < c" by arith
  11.710 -      from coprime_lmul2 [OF H(2)[unfolded k coprime_commute[of "p^n*k" a]]]
  11.711 -      have kb: "coprime k a" by (simp add: coprime_commute) 
  11.712 -      from H(3) l k pn0 n have kbln: "k * a = l ^ n" 
  11.713 -	by (simp add: power_mult_distrib mult_commute)
  11.714 -      from H(1)[rule_format, OF lc kb kbln]
  11.715 -      obtain r s where rs: "k = r ^n" "a = s^n" by blast
  11.716 -      from k rs(1) have "b = (p*r)^n" by (simp add: power_mult_distrib)
  11.717 -      with rs(2) have ?ths by blast }
  11.718 -    ultimately have ?ths using pnab by blast}
  11.719 -  ultimately have ?ths by blast}
  11.720 -ultimately show ?ths by blast
  11.721 -qed
  11.722 -
  11.723 -text {* More useful lemmas. *}
  11.724 -lemma prime_product: 
  11.725 -  assumes "prime (p * q)"
  11.726 -  shows "p = 1 \<or> q = 1"
  11.727 -proof -
  11.728 -  from assms have 
  11.729 -    "1 < p * q" and P: "\<And>m. m dvd p * q \<Longrightarrow> m = 1 \<or> m = p * q"
  11.730 -    unfolding prime_def by auto
  11.731 -  from `1 < p * q` have "p \<noteq> 0" by (cases p) auto
  11.732 -  then have Q: "p = p * q \<longleftrightarrow> q = 1" by auto
  11.733 -  have "p dvd p * q" by simp
  11.734 -  then have "p = 1 \<or> p = p * q" by (rule P)
  11.735 -  then show ?thesis by (simp add: Q)
  11.736 -qed
  11.737 -
  11.738 -lemma prime_exp: "prime (p^n) \<longleftrightarrow> prime p \<and> n = 1"
  11.739 -proof(induct n)
  11.740 -  case 0 thus ?case by simp
  11.741 -next
  11.742 -  case (Suc n)
  11.743 -  {assume "p = 0" hence ?case by simp}
  11.744 -  moreover
  11.745 -  {assume "p=1" hence ?case by simp}
  11.746 -  moreover
  11.747 -  {assume p: "p \<noteq> 0" "p\<noteq>1"
  11.748 -    {assume pp: "prime (p^Suc n)"
  11.749 -      hence "p = 1 \<or> p^n = 1" using prime_product[of p "p^n"] by simp
  11.750 -      with p have n: "n = 0" 
  11.751 -	by (simp only: exp_eq_1 ) simp
  11.752 -      with pp have "prime p \<and> Suc n = 1" by simp}
  11.753 -    moreover
  11.754 -    {assume n: "prime p \<and> Suc n = 1" hence "prime (p^Suc n)" by simp}
  11.755 -    ultimately have ?case by blast}
  11.756 -  ultimately show ?case by blast
  11.757 -qed
  11.758 -
  11.759 -lemma prime_power_mult: 
  11.760 -  assumes p: "prime p" and xy: "x * y = p ^ k"
  11.761 -  shows "\<exists>i j. x = p ^i \<and> y = p^ j"
  11.762 -  using xy
  11.763 -proof(induct k arbitrary: x y)
  11.764 -  case 0 thus ?case apply simp by (rule exI[where x="0"], simp)
  11.765 -next
  11.766 -  case (Suc k x y)
  11.767 -  from Suc.prems have pxy: "p dvd x*y" by auto
  11.768 -  from prime_divprod[OF p pxy] have pxyc: "p dvd x \<or> p dvd y" .
  11.769 -  from p have p0: "p \<noteq> 0" by - (rule ccontr, simp) 
  11.770 -  {assume px: "p dvd x"
  11.771 -    then obtain d where d: "x = p*d" unfolding dvd_def by blast
  11.772 -    from Suc.prems d  have "p*d*y = p^Suc k" by simp
  11.773 -    hence th: "d*y = p^k" using p0 by simp
  11.774 -    from Suc.hyps[OF th] obtain i j where ij: "d = p^i" "y = p^j" by blast
  11.775 -    with d have "x = p^Suc i" by simp 
  11.776 -    with ij(2) have ?case by blast}
  11.777 -  moreover 
  11.778 -  {assume px: "p dvd y"
  11.779 -    then obtain d where d: "y = p*d" unfolding dvd_def by blast
  11.780 -    from Suc.prems d  have "p*d*x = p^Suc k" by (simp add: mult_commute)
  11.781 -    hence th: "d*x = p^k" using p0 by simp
  11.782 -    from Suc.hyps[OF th] obtain i j where ij: "d = p^i" "x = p^j" by blast
  11.783 -    with d have "y = p^Suc i" by simp 
  11.784 -    with ij(2) have ?case by blast}
  11.785 -  ultimately show ?case  using pxyc by blast
  11.786 -qed
  11.787 -
  11.788 -lemma prime_power_exp: assumes p: "prime p" and n:"n \<noteq> 0" 
  11.789 -  and xn: "x^n = p^k" shows "\<exists>i. x = p^i"
  11.790 -  using n xn
  11.791 -proof(induct n arbitrary: k)
  11.792 -  case 0 thus ?case by simp
  11.793 -next
  11.794 -  case (Suc n k) hence th: "x*x^n = p^k" by simp
  11.795 -  {assume "n = 0" with prems have ?case apply simp 
  11.796 -      by (rule exI[where x="k"],simp)}
  11.797 -  moreover
  11.798 -  {assume n: "n \<noteq> 0"
  11.799 -    from prime_power_mult[OF p th] 
  11.800 -    obtain i j where ij: "x = p^i" "x^n = p^j"by blast
  11.801 -    from Suc.hyps[OF n ij(2)] have ?case .}
  11.802 -  ultimately show ?case by blast
  11.803 -qed
  11.804 -
  11.805 -lemma divides_primepow: assumes p: "prime p" 
  11.806 -  shows "d dvd p^k \<longleftrightarrow> (\<exists> i. i \<le> k \<and> d = p ^i)"
  11.807 -proof
  11.808 -  assume H: "d dvd p^k" then obtain e where e: "d*e = p^k" 
  11.809 -    unfolding dvd_def  apply (auto simp add: mult_commute) by blast
  11.810 -  from prime_power_mult[OF p e] obtain i j where ij: "d = p^i" "e=p^j" by blast
  11.811 -  from prime_ge_2[OF p] have p1: "p > 1" by arith
  11.812 -  from e ij have "p^(i + j) = p^k" by (simp add: power_add)
  11.813 -  hence "i + j = k" using power_inject_exp[of p "i+j" k, OF p1] by simp 
  11.814 -  hence "i \<le> k" by arith
  11.815 -  with ij(1) show "\<exists>i\<le>k. d = p ^ i" by blast
  11.816 -next
  11.817 -  {fix i assume H: "i \<le> k" "d = p^i"
  11.818 -    hence "\<exists>j. k = i + j" by arith
  11.819 -    then obtain j where j: "k = i + j" by blast
  11.820 -    hence "p^k = p^j*d" using H(2) by (simp add: power_add)
  11.821 -    hence "d dvd p^k" unfolding dvd_def by auto}
  11.822 -  thus "\<exists>i\<le>k. d = p ^ i \<Longrightarrow> d dvd p ^ k" by blast
  11.823 -qed
  11.824 -
  11.825 -lemma coprime_divisors: "d dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow> coprime d e"
  11.826 -  by (auto simp add: dvd_def coprime)
  11.827 -
  11.828 -declare power_Suc0[simp del]
  11.829 -declare even_dvd[simp del]
  11.830 -
  11.831 -end
    12.1 --- a/src/HOL/NSA/Examples/NSPrimes.thy	Tue Sep 01 14:13:34 2009 +0200
    12.2 +++ b/src/HOL/NSA/Examples/NSPrimes.thy	Tue Sep 01 15:39:33 2009 +0200
    12.3 @@ -7,7 +7,7 @@
    12.4  header{*The Nonstandard Primes as an Extension of the Prime Numbers*}
    12.5  
    12.6  theory NSPrimes
    12.7 -imports "~~/src/HOL/NumberTheory/Factorization" Hyperreal
    12.8 +imports "~~/src/HOL/Old_Number_Theory/Factorization" Hyperreal
    12.9  begin
   12.10  
   12.11  text{*These can be used to derive an alternative proof of the infinitude of
    13.1 --- a/src/HOL/NewNumberTheory/Binomial.thy	Tue Sep 01 14:13:34 2009 +0200
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,373 +0,0 @@
    13.4 -(*  Title:      Binomial.thy
    13.5 -    Authors:    Lawrence C. Paulson, Jeremy Avigad, Tobias Nipkow
    13.6 -
    13.7 -
    13.8 -Defines the "choose" function, and establishes basic properties.
    13.9 -
   13.10 -The original theory "Binomial" was by Lawrence C. Paulson, based on
   13.11 -the work of Andy Gordon and Florian Kammueller. The approach here,
   13.12 -which derives the definition of binomial coefficients in terms of the
   13.13 -factorial function, is due to Jeremy Avigad. The binomial theorem was
   13.14 -formalized by Tobias Nipkow.
   13.15 -
   13.16 -*)
   13.17 -
   13.18 -
   13.19 -header {* Binomial *}
   13.20 -
   13.21 -theory Binomial
   13.22 -imports Cong Fact
   13.23 -begin
   13.24 -
   13.25 -
   13.26 -subsection {* Main definitions *}
   13.27 -
   13.28 -class binomial =
   13.29 -
   13.30 -fixes 
   13.31 -  binomial :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" (infixl "choose" 65)
   13.32 -
   13.33 -(* definitions for the natural numbers *)
   13.34 -
   13.35 -instantiation nat :: binomial
   13.36 -
   13.37 -begin 
   13.38 -
   13.39 -fun
   13.40 -  binomial_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   13.41 -where
   13.42 -  "binomial_nat n k =
   13.43 -   (if k = 0 then 1 else
   13.44 -    if n = 0 then 0 else
   13.45 -      (binomial (n - 1) k) + (binomial (n - 1) (k - 1)))"
   13.46 -
   13.47 -instance proof qed
   13.48 -
   13.49 -end
   13.50 -
   13.51 -(* definitions for the integers *)
   13.52 -
   13.53 -instantiation int :: binomial
   13.54 -
   13.55 -begin 
   13.56 -
   13.57 -definition
   13.58 -  binomial_int :: "int => int \<Rightarrow> int"
   13.59 -where
   13.60 -  "binomial_int n k = (if n \<ge> 0 \<and> k \<ge> 0 then int (binomial (nat n) (nat k))
   13.61 -      else 0)"
   13.62 -instance proof qed
   13.63 -
   13.64 -end
   13.65 -
   13.66 -
   13.67 -subsection {* Set up Transfer *}
   13.68 -
   13.69 -lemma transfer_nat_int_binomial:
   13.70 -  "(n::int) >= 0 \<Longrightarrow> k >= 0 \<Longrightarrow> binomial (nat n) (nat k) = 
   13.71 -      nat (binomial n k)"
   13.72 -  unfolding binomial_int_def 
   13.73 -  by auto
   13.74 -
   13.75 -lemma transfer_nat_int_binomial_closure:
   13.76 -  "n >= (0::int) \<Longrightarrow> k >= 0 \<Longrightarrow> binomial n k >= 0"
   13.77 -  by (auto simp add: binomial_int_def)
   13.78 -
   13.79 -declare TransferMorphism_nat_int[transfer add return: 
   13.80 -    transfer_nat_int_binomial transfer_nat_int_binomial_closure]
   13.81 -
   13.82 -lemma transfer_int_nat_binomial:
   13.83 -  "binomial (int n) (int k) = int (binomial n k)"
   13.84 -  unfolding fact_int_def binomial_int_def by auto
   13.85 -
   13.86 -lemma transfer_int_nat_binomial_closure:
   13.87 -  "is_nat n \<Longrightarrow> is_nat k \<Longrightarrow> binomial n k >= 0"
   13.88 -  by (auto simp add: binomial_int_def)
   13.89 -
   13.90 -declare TransferMorphism_int_nat[transfer add return: 
   13.91 -    transfer_int_nat_binomial transfer_int_nat_binomial_closure]
   13.92 -
   13.93 -
   13.94 -subsection {* Binomial coefficients *}
   13.95 -
   13.96 -lemma choose_zero_nat [simp]: "(n::nat) choose 0 = 1"
   13.97 -  by simp
   13.98 -
   13.99 -lemma choose_zero_int [simp]: "n \<ge> 0 \<Longrightarrow> (n::int) choose 0 = 1"
  13.100 -  by (simp add: binomial_int_def)
  13.101 -
  13.102 -lemma zero_choose_nat [rule_format,simp]: "ALL (k::nat) > n. n choose k = 0"
  13.103 -  by (induct n rule: induct'_nat, auto)
  13.104 -
  13.105 -lemma zero_choose_int [rule_format,simp]: "(k::int) > n \<Longrightarrow> n choose k = 0"
  13.106 -  unfolding binomial_int_def apply (case_tac "n < 0")
  13.107 -  apply force
  13.108 -  apply (simp del: binomial_nat.simps)
  13.109 -done
  13.110 -
  13.111 -lemma choose_reduce_nat: "(n::nat) > 0 \<Longrightarrow> 0 < k \<Longrightarrow>
  13.112 -    (n choose k) = ((n - 1) choose k) + ((n - 1) choose (k - 1))"
  13.113 -  by simp
  13.114 -
  13.115 -lemma choose_reduce_int: "(n::int) > 0 \<Longrightarrow> 0 < k \<Longrightarrow>
  13.116 -    (n choose k) = ((n - 1) choose k) + ((n - 1) choose (k - 1))"
  13.117 -  unfolding binomial_int_def apply (subst choose_reduce_nat)
  13.118 -    apply (auto simp del: binomial_nat.simps 
  13.119 -      simp add: nat_diff_distrib)
  13.120 -done
  13.121 -
  13.122 -lemma choose_plus_one_nat: "((n::nat) + 1) choose (k + 1) = 
  13.123 -    (n choose (k + 1)) + (n choose k)"
  13.124 -  by (simp add: choose_reduce_nat)
  13.125 -
  13.126 -lemma choose_Suc_nat: "(Suc n) choose (Suc k) = 
  13.127 -    (n choose (Suc k)) + (n choose k)"
  13.128 -  by (simp add: choose_reduce_nat One_nat_def)
  13.129 -
  13.130 -lemma choose_plus_one_int: "n \<ge> 0 \<Longrightarrow> k \<ge> 0 \<Longrightarrow> ((n::int) + 1) choose (k + 1) = 
  13.131 -    (n choose (k + 1)) + (n choose k)"
  13.132 -  by (simp add: binomial_int_def choose_plus_one_nat nat_add_distrib del: binomial_nat.simps)
  13.133 -
  13.134 -declare binomial_nat.simps [simp del]
  13.135 -
  13.136 -lemma choose_self_nat [simp]: "((n::nat) choose n) = 1"
  13.137 -  by (induct n rule: induct'_nat, auto simp add: choose_plus_one_nat)
  13.138 -
  13.139 -lemma choose_self_int [simp]: "n \<ge> 0 \<Longrightarrow> ((n::int) choose n) = 1"
  13.140 -  by (auto simp add: binomial_int_def)
  13.141 -
  13.142 -lemma choose_one_nat [simp]: "(n::nat) choose 1 = n"
  13.143 -  by (induct n rule: induct'_nat, auto simp add: choose_reduce_nat)
  13.144 -
  13.145 -lemma choose_one_int [simp]: "n \<ge> 0 \<Longrightarrow> (n::int) choose 1 = n"
  13.146 -  by (auto simp add: binomial_int_def)
  13.147 -
  13.148 -lemma plus_one_choose_self_nat [simp]: "(n::nat) + 1 choose n = n + 1"
  13.149 -  apply (induct n rule: induct'_nat, force)
  13.150 -  apply (case_tac "n = 0")
  13.151 -  apply auto
  13.152 -  apply (subst choose_reduce_nat)
  13.153 -  apply (auto simp add: One_nat_def)  
  13.154 -  (* natdiff_cancel_numerals introduces Suc *)
  13.155 -done
  13.156 -
  13.157 -lemma Suc_choose_self_nat [simp]: "(Suc n) choose n = Suc n"
  13.158 -  using plus_one_choose_self_nat by (simp add: One_nat_def)
  13.159 -
  13.160 -lemma plus_one_choose_self_int [rule_format, simp]: 
  13.161 -    "(n::int) \<ge> 0 \<longrightarrow> n + 1 choose n = n + 1"
  13.162 -   by (auto simp add: binomial_int_def nat_add_distrib)
  13.163 -
  13.164 -(* bounded quantification doesn't work with the unicode characters? *)
  13.165 -lemma choose_pos_nat [rule_format]: "ALL k <= (n::nat). 
  13.166 -    ((n::nat) choose k) > 0"
  13.167 -  apply (induct n rule: induct'_nat) 
  13.168 -  apply force
  13.169 -  apply clarify
  13.170 -  apply (case_tac "k = 0")
  13.171 -  apply force
  13.172 -  apply (subst choose_reduce_nat)
  13.173 -  apply auto
  13.174 -done
  13.175 -
  13.176 -lemma choose_pos_int: "n \<ge> 0 \<Longrightarrow> k >= 0 \<Longrightarrow> k \<le> n \<Longrightarrow>
  13.177 -    ((n::int) choose k) > 0"
  13.178 -  by (auto simp add: binomial_int_def choose_pos_nat)
  13.179 -
  13.180 -lemma binomial_induct [rule_format]: "(ALL (n::nat). P n n) \<longrightarrow> 
  13.181 -    (ALL n. P (n + 1) 0) \<longrightarrow> (ALL n. (ALL k < n. P n k \<longrightarrow> P n (k + 1) \<longrightarrow>
  13.182 -    P (n + 1) (k + 1))) \<longrightarrow> (ALL k <= n. P n k)"
  13.183 -  apply (induct n rule: induct'_nat)
  13.184 -  apply auto
  13.185 -  apply (case_tac "k = 0")
  13.186 -  apply auto
  13.187 -  apply (case_tac "k = n + 1")
  13.188 -  apply auto
  13.189 -  apply (drule_tac x = n in spec) back back 
  13.190 -  apply (drule_tac x = "k - 1" in spec) back back back
  13.191 -  apply auto
  13.192 -done
  13.193 -
  13.194 -lemma choose_altdef_aux_nat: "(k::nat) \<le> n \<Longrightarrow> 
  13.195 -    fact k * fact (n - k) * (n choose k) = fact n"
  13.196 -  apply (rule binomial_induct [of _ k n])
  13.197 -  apply auto
  13.198 -proof -
  13.199 -  fix k :: nat and n
  13.200 -  assume less: "k < n"
  13.201 -  assume ih1: "fact k * fact (n - k) * (n choose k) = fact n"
  13.202 -  hence one: "fact (k + 1) * fact (n - k) * (n choose k) = (k + 1) * fact n"
  13.203 -    by (subst fact_plus_one_nat, auto)
  13.204 -  assume ih2: "fact (k + 1) * fact (n - (k + 1)) * (n choose (k + 1)) = 
  13.205 -      fact n"
  13.206 -  with less have "fact (k + 1) * fact ((n - (k + 1)) + 1) * 
  13.207 -      (n choose (k + 1)) = (n - k) * fact n"
  13.208 -    by (subst (2) fact_plus_one_nat, auto)
  13.209 -  with less have two: "fact (k + 1) * fact (n - k) * (n choose (k + 1)) = 
  13.210 -      (n - k) * fact n" by simp
  13.211 -  have "fact (k + 1) * fact (n - k) * (n + 1 choose (k + 1)) =
  13.212 -      fact (k + 1) * fact (n - k) * (n choose (k + 1)) + 
  13.213 -      fact (k + 1) * fact (n - k) * (n choose k)" 
  13.214 -    by (subst choose_reduce_nat, auto simp add: ring_simps)
  13.215 -  also note one
  13.216 -  also note two
  13.217 -  also with less have "(n - k) * fact n + (k + 1) * fact n= fact (n + 1)" 
  13.218 -    apply (subst fact_plus_one_nat)
  13.219 -    apply (subst left_distrib [symmetric])
  13.220 -    apply simp
  13.221 -    done
  13.222 -  finally show "fact (k + 1) * fact (n - k) * (n + 1 choose (k + 1)) = 
  13.223 -    fact (n + 1)" .
  13.224 -qed
  13.225 -
  13.226 -lemma choose_altdef_nat: "(k::nat) \<le> n \<Longrightarrow> 
  13.227 -    n choose k = fact n div (fact k * fact (n - k))"
  13.228 -  apply (frule choose_altdef_aux_nat)
  13.229 -  apply (erule subst)
  13.230 -  apply (simp add: mult_ac)
  13.231 -done
  13.232 -
  13.233 -
  13.234 -lemma choose_altdef_int: 
  13.235 -  assumes "(0::int) <= k" and "k <= n"
  13.236 -  shows "n choose k = fact n div (fact k * fact (n - k))"
  13.237 -  
  13.238 -  apply (subst tsub_eq [symmetric], rule prems)
  13.239 -  apply (rule choose_altdef_nat [transferred])
  13.240 -  using prems apply auto
  13.241 -done
  13.242 -
  13.243 -lemma choose_dvd_nat: "(k::nat) \<le> n \<Longrightarrow> fact k * fact (n - k) dvd fact n"
  13.244 -  unfolding dvd_def apply (frule choose_altdef_aux_nat)
  13.245 -  (* why don't blast and auto get this??? *)
  13.246 -  apply (rule exI)
  13.247 -  apply (erule sym)
  13.248 -done
  13.249 -
  13.250 -lemma choose_dvd_int: 
  13.251 -  assumes "(0::int) <= k" and "k <= n"
  13.252 -  shows "fact k * fact (n - k) dvd fact n"
  13.253 - 
  13.254 -  apply (subst tsub_eq [symmetric], rule prems)
  13.255 -  apply (rule choose_dvd_nat [transferred])
  13.256 -  using prems apply auto
  13.257 -done
  13.258 -
  13.259 -(* generalizes Tobias Nipkow's proof to any commutative semiring *)
  13.260 -theorem binomial: "(a+b::'a::{comm_ring_1,power})^n = 
  13.261 -  (SUM k=0..n. (of_nat (n choose k)) * a^k * b^(n-k))" (is "?P n")
  13.262 -proof (induct n rule: induct'_nat)
  13.263 -  show "?P 0" by simp
  13.264 -next
  13.265 -  fix n
  13.266 -  assume ih: "?P n"
  13.267 -  have decomp: "{0..n+1} = {0} Un {n+1} Un {1..n}"
  13.268 -    by auto
  13.269 -  have decomp2: "{0..n} = {0} Un {1..n}"
  13.270 -    by auto
  13.271 -  have decomp3: "{1..n+1} = {n+1} Un {1..n}"
  13.272 -    by auto
  13.273 -  have "(a+b)^(n+1) = 
  13.274 -      (a+b) * (SUM k=0..n. of_nat (n choose k) * a^k * b^(n-k))"
  13.275 -    using ih by (simp add: power_plus_one)
  13.276 -  also have "... =  a*(SUM k=0..n. of_nat (n choose k) * a^k * b^(n-k)) +
  13.277 -                   b*(SUM k=0..n. of_nat (n choose k) * a^k * b^(n-k))"
  13.278 -    by (rule distrib)
  13.279 -  also have "... = (SUM k=0..n. of_nat (n choose k) * a^(k+1) * b^(n-k)) +
  13.280 -                  (SUM k=0..n. of_nat (n choose k) * a^k * b^(n-k+1))"
  13.281 -    by (subst (1 2) power_plus_one, simp add: setsum_right_distrib mult_ac)
  13.282 -  also have "... = (SUM k=0..n. of_nat (n choose k) * a^k * b^(n+1-k)) +
  13.283 -                  (SUM k=1..n+1. of_nat (n choose (k - 1)) * a^k * b^(n+1-k))"
  13.284 -    by (simp add:setsum_shift_bounds_cl_Suc_ivl Suc_diff_le 
  13.285 -             power_Suc ring_simps One_nat_def del:setsum_cl_ivl_Suc)
  13.286 -  also have "... = a^(n+1) + b^(n+1) +
  13.287 -                  (SUM k=1..n. of_nat (n choose (k - 1)) * a^k * b^(n+1-k)) +
  13.288 -                  (SUM k=1..n. of_nat (n choose k) * a^k * b^(n+1-k))"
  13.289 -    by (simp add: decomp2 decomp3)
  13.290 -  also have
  13.291 -      "... = a^(n+1) + b^(n+1) + 
  13.292 -         (SUM k=1..n. of_nat(n+1 choose k) * a^k * b^(n+1-k))"
  13.293 -    by (auto simp add: ring_simps setsum_addf [symmetric]
  13.294 -      choose_reduce_nat)
  13.295 -  also have "... = (SUM k=0..n+1. of_nat (n+1 choose k) * a^k * b^(n+1-k))"
  13.296 -    using decomp by (simp add: ring_simps)
  13.297 -  finally show "?P (n + 1)" by simp
  13.298 -qed
  13.299 -
  13.300 -lemma set_explicit: "{S. S = T \<and> P S} = (if P T then {T} else {})"
  13.301 -  by auto
  13.302 -
  13.303 -lemma card_subsets_nat [rule_format]:
  13.304 -  fixes S :: "'a set"
  13.305 -  assumes "finite S"
  13.306 -  shows "ALL k. card {T. T \<le> S \<and> card T = k} = card S choose k" 
  13.307 -      (is "?P S")
  13.308 -using `finite S`
  13.309 -proof (induct set: finite)
  13.310 -  show "?P {}" by (auto simp add: set_explicit)
  13.311 -  next fix x :: "'a" and F
  13.312 -  assume iassms: "finite F" "x ~: F"
  13.313 -  assume ih: "?P F"
  13.314 -  show "?P (insert x F)" (is "ALL k. ?Q k")
  13.315 -  proof
  13.316 -    fix k
  13.317 -    show "card {T. T \<subseteq> (insert x F) \<and> card T = k} = 
  13.318 -        card (insert x F) choose k" (is "?Q k")
  13.319 -    proof (induct k rule: induct'_nat)
  13.320 -      from iassms have "{T. T \<le> (insert x F) \<and> card T = 0} = {{}}"
  13.321 -        apply auto
  13.322 -        apply (subst (asm) card_0_eq)
  13.323 -        apply (auto elim: finite_subset)
  13.324 -        done
  13.325 -      thus "?Q 0" 
  13.326 -        by auto
  13.327 -      next fix k
  13.328 -      show "?Q (k + 1)"
  13.329 -      proof -
  13.330 -        from iassms have fin: "finite (insert x F)" by auto
  13.331 -        hence "{ T. T \<subseteq> insert x F \<and> card T = k + 1} =
  13.332 -          {T. T \<le> F & card T = k + 1} Un 
  13.333 -          {T. T \<le> insert x F & x : T & card T = k + 1}"
  13.334 -          by (auto intro!: subsetI)
  13.335 -        with iassms fin have "card ({T. T \<le> insert x F \<and> card T = k + 1}) = 
  13.336 -          card ({T. T \<subseteq> F \<and> card T = k + 1}) + 
  13.337 -          card ({T. T \<subseteq> insert x F \<and> x : T \<and> card T = k + 1})"
  13.338 -          apply (subst card_Un_disjoint [symmetric])
  13.339 -          apply auto
  13.340 -          (* note: nice! Didn't have to say anything here *)
  13.341 -          done
  13.342 -        also from ih have "card ({T. T \<subseteq> F \<and> card T = k + 1}) = 
  13.343 -          card F choose (k+1)" by auto
  13.344 -        also have "card ({T. T \<subseteq> insert x F \<and> x : T \<and> card T = k + 1}) =
  13.345 -          card ({T. T <= F & card T = k})"
  13.346 -        proof -
  13.347 -          let ?f = "%T. T Un {x}"
  13.348 -          from iassms have "inj_on ?f {T. T <= F & card T = k}"
  13.349 -            unfolding inj_on_def by (auto intro!: subsetI)
  13.350 -          hence "card ({T. T <= F & card T = k}) = 
  13.351 -            card(?f ` {T. T <= F & card T = k})"
  13.352 -            by (rule card_image [symmetric])
  13.353 -          also from iassms fin have "?f ` {T. T <= F & card T = k} = 
  13.354 -            {T. T \<subseteq> insert x F \<and> x : T \<and> card T = k + 1}"
  13.355 -            unfolding image_def 
  13.356 -            (* I can't figure out why this next line takes so long *)
  13.357 -            apply auto
  13.358 -            apply (frule (1) finite_subset, force)
  13.359 -            apply (rule_tac x = "xa - {x}" in exI)
  13.360 -            apply (subst card_Diff_singleton)
  13.361 -            apply (auto elim: finite_subset)
  13.362 -            done
  13.363 -          finally show ?thesis by (rule sym)
  13.364 -        qed
  13.365 -        also from ih have "card ({T. T <= F & card T = k}) = card F choose k"
  13.366 -          by auto
  13.367 -        finally have "card ({T. T \<le> insert x F \<and> card T = k + 1}) = 
  13.368 -          card F choose (k + 1) + (card F choose k)".
  13.369 -        with iassms choose_plus_one_nat show ?thesis
  13.370 -          by auto
  13.371 -      qed
  13.372 -    qed
  13.373 -  qed
  13.374 -qed
  13.375 -
  13.376 -end
    14.1 --- a/src/HOL/NewNumberTheory/Cong.thy	Tue Sep 01 14:13:34 2009 +0200
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,1091 +0,0 @@
    14.4 -(*  Title:      HOL/Library/Cong.thy
    14.5 -    ID:         
    14.6 -    Authors:    Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
    14.7 -                Thomas M. Rasmussen, Jeremy Avigad
    14.8 -
    14.9 -
   14.10 -Defines congruence (notation: [x = y] (mod z)) for natural numbers and
   14.11 -integers.
   14.12 -
   14.13 -This file combines and revises a number of prior developments.
   14.14 -
   14.15 -The original theories "GCD" and "Primes" were by Christophe Tabacznyj
   14.16 -and Lawrence C. Paulson, based on \cite{davenport92}. They introduced
   14.17 -gcd, lcm, and prime for the natural numbers.
   14.18 -
   14.19 -The original theory "IntPrimes" was by Thomas M. Rasmussen, and
   14.20 -extended gcd, lcm, primes to the integers. Amine Chaieb provided
   14.21 -another extension of the notions to the integers, and added a number
   14.22 -of results to "Primes" and "GCD". 
   14.23 -
   14.24 -The original theory, "IntPrimes", by Thomas M. Rasmussen, defined and
   14.25 -developed the congruence relations on the integers. The notion was
   14.26 -extended to the natural numbers by Chiaeb. Jeremy Avigad combined
   14.27 -these, revised and tidied them, made the development uniform for the
   14.28 -natural numbers and the integers, and added a number of new theorems.
   14.29 -
   14.30 -*)
   14.31 -
   14.32 -
   14.33 -header {* Congruence *}
   14.34 -
   14.35 -theory Cong
   14.36 -imports GCD
   14.37 -begin
   14.38 -
   14.39 -subsection {* Turn off One_nat_def *}
   14.40 -
   14.41 -lemma induct'_nat [case_names zero plus1, induct type: nat]: 
   14.42 -    "\<lbrakk> P (0::nat); !!n. P n \<Longrightarrow> P (n + 1)\<rbrakk> \<Longrightarrow> P n"
   14.43 -by (erule nat_induct) (simp add:One_nat_def)
   14.44 -
   14.45 -lemma cases_nat [case_names zero plus1, cases type: nat]: 
   14.46 -    "P (0::nat) \<Longrightarrow> (!!n. P (n + 1)) \<Longrightarrow> P n"
   14.47 -by(metis induct'_nat)
   14.48 -
   14.49 -lemma power_plus_one [simp]: "(x::'a::power)^(n + 1) = x * x^n"
   14.50 -by (simp add: One_nat_def)
   14.51 -
   14.52 -lemma power_eq_one_eq_nat [simp]: 
   14.53 -  "((x::nat)^m = 1) = (m = 0 | x = 1)"
   14.54 -by (induct m, auto)
   14.55 -
   14.56 -lemma card_insert_if' [simp]: "finite A \<Longrightarrow>
   14.57 -  card (insert x A) = (if x \<in> A then (card A) else (card A) + 1)"
   14.58 -by (auto simp add: insert_absorb)
   14.59 -
   14.60 -(* why wasn't card_insert_if a simp rule? *)
   14.61 -declare card_insert_disjoint [simp del]
   14.62 -
   14.63 -lemma nat_1' [simp]: "nat 1 = 1"
   14.64 -by simp
   14.65 -
   14.66 -(* For those annoying moments where Suc reappears, use Suc_eq_plus1 *)
   14.67 -
   14.68 -declare nat_1 [simp del]
   14.69 -declare add_2_eq_Suc [simp del] 
   14.70 -declare add_2_eq_Suc' [simp del]
   14.71 -
   14.72 -
   14.73 -declare mod_pos_pos_trivial [simp]
   14.74 -
   14.75 -
   14.76 -subsection {* Main definitions *}
   14.77 -
   14.78 -class cong =
   14.79 -
   14.80 -fixes 
   14.81 -  cong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ = _] '(mod _'))")
   14.82 -
   14.83 -begin
   14.84 -
   14.85 -abbreviation
   14.86 -  notcong :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" ("(1[_ \<noteq> _] '(mod _'))")
   14.87 -where
   14.88 -  "notcong x y m == (~cong x y m)" 
   14.89 -
   14.90 -end
   14.91 -
   14.92 -(* definitions for the natural numbers *)
   14.93 -
   14.94 -instantiation nat :: cong
   14.95 -
   14.96 -begin 
   14.97 -
   14.98 -definition 
   14.99 -  cong_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
  14.100 -where 
  14.101 -  "cong_nat x y m = ((x mod m) = (y mod m))"
  14.102 -
  14.103 -instance proof qed
  14.104 -
  14.105 -end
  14.106 -
  14.107 -
  14.108 -(* definitions for the integers *)
  14.109 -
  14.110 -instantiation int :: cong
  14.111 -
  14.112 -begin 
  14.113 -
  14.114 -definition 
  14.115 -  cong_int :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool"
  14.116 -where 
  14.117 -  "cong_int x y m = ((x mod m) = (y mod m))"
  14.118 -
  14.119 -instance proof qed
  14.120 -
  14.121 -end
  14.122 -
  14.123 -
  14.124 -subsection {* Set up Transfer *}
  14.125 -
  14.126 -
  14.127 -lemma transfer_nat_int_cong:
  14.128 -  "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> m >= 0 \<Longrightarrow> 
  14.129 -    ([(nat x) = (nat y)] (mod (nat m))) = ([x = y] (mod m))"
  14.130 -  unfolding cong_int_def cong_nat_def 
  14.131 -  apply (auto simp add: nat_mod_distrib [symmetric])
  14.132 -  apply (subst (asm) eq_nat_nat_iff)
  14.133 -  apply (case_tac "m = 0", force, rule pos_mod_sign, force)+
  14.134 -  apply assumption
  14.135 -done
  14.136 -
  14.137 -declare TransferMorphism_nat_int[transfer add return: 
  14.138 -    transfer_nat_int_cong]
  14.139 -
  14.140 -lemma transfer_int_nat_cong:
  14.141 -  "[(int x) = (int y)] (mod (int m)) = [x = y] (mod m)"
  14.142 -  apply (auto simp add: cong_int_def cong_nat_def)
  14.143 -  apply (auto simp add: zmod_int [symmetric])
  14.144 -done
  14.145 -
  14.146 -declare TransferMorphism_int_nat[transfer add return: 
  14.147 -    transfer_int_nat_cong]
  14.148 -
  14.149 -
  14.150 -subsection {* Congruence *}
  14.151 -
  14.152 -(* was zcong_0, etc. *)
  14.153 -lemma cong_0_nat [simp, presburger]: "([(a::nat) = b] (mod 0)) = (a = b)"
  14.154 -  by (unfold cong_nat_def, auto)
  14.155 -
  14.156 -lemma cong_0_int [simp, presburger]: "([(a::int) = b] (mod 0)) = (a = b)"
  14.157 -  by (unfold cong_int_def, auto)
  14.158 -
  14.159 -lemma cong_1_nat [simp, presburger]: "[(a::nat) = b] (mod 1)"
  14.160 -  by (unfold cong_nat_def, auto)
  14.161 -
  14.162 -lemma cong_Suc_0_nat [simp, presburger]: "[(a::nat) = b] (mod Suc 0)"
  14.163 -  by (unfold cong_nat_def, auto simp add: One_nat_def)
  14.164 -
  14.165 -lemma cong_1_int [simp, presburger]: "[(a::int) = b] (mod 1)"
  14.166 -  by (unfold cong_int_def, auto)
  14.167 -
  14.168 -lemma cong_refl_nat [simp]: "[(k::nat) = k] (mod m)"
  14.169 -  by (unfold cong_nat_def, auto)
  14.170 -
  14.171 -lemma cong_refl_int [simp]: "[(k::int) = k] (mod m)"
  14.172 -  by (unfold cong_int_def, auto)
  14.173 -
  14.174 -lemma cong_sym_nat: "[(a::nat) = b] (mod m) \<Longrightarrow> [b = a] (mod m)"
  14.175 -  by (unfold cong_nat_def, auto)
  14.176 -
  14.177 -lemma cong_sym_int: "[(a::int) = b] (mod m) \<Longrightarrow> [b = a] (mod m)"
  14.178 -  by (unfold cong_int_def, auto)
  14.179 -
  14.180 -lemma cong_sym_eq_nat: "[(a::nat) = b] (mod m) = [b = a] (mod m)"
  14.181 -  by (unfold cong_nat_def, auto)
  14.182 -
  14.183 -lemma cong_sym_eq_int: "[(a::int) = b] (mod m) = [b = a] (mod m)"
  14.184 -  by (unfold cong_int_def, auto)
  14.185 -
  14.186 -lemma cong_trans_nat [trans]:
  14.187 -    "[(a::nat) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)"
  14.188 -  by (unfold cong_nat_def, auto)
  14.189 -
  14.190 -lemma cong_trans_int [trans]:
  14.191 -    "[(a::int) = b] (mod m) \<Longrightarrow> [b = c] (mod m) \<Longrightarrow> [a = c] (mod m)"
  14.192 -  by (unfold cong_int_def, auto)
  14.193 -
  14.194 -lemma cong_add_nat:
  14.195 -    "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)"
  14.196 -  apply (unfold cong_nat_def)
  14.197 -  apply (subst (1 2) mod_add_eq)
  14.198 -  apply simp
  14.199 -done
  14.200 -
  14.201 -lemma cong_add_int:
  14.202 -    "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a + c = b + d] (mod m)"
  14.203 -  apply (unfold cong_int_def)
  14.204 -  apply (subst (1 2) mod_add_left_eq)
  14.205 -  apply (subst (1 2) mod_add_right_eq)
  14.206 -  apply simp
  14.207 -done
  14.208 -
  14.209 -lemma cong_diff_int:
  14.210 -    "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a - c = b - d] (mod m)"
  14.211 -  apply (unfold cong_int_def)
  14.212 -  apply (subst (1 2) mod_diff_eq)
  14.213 -  apply simp
  14.214 -done
  14.215 -
  14.216 -lemma cong_diff_aux_int:
  14.217 -  "(a::int) >= c \<Longrightarrow> b >= d \<Longrightarrow> [(a::int) = b] (mod m) \<Longrightarrow> 
  14.218 -      [c = d] (mod m) \<Longrightarrow> [tsub a c = tsub b d] (mod m)"
  14.219 -  apply (subst (1 2) tsub_eq)
  14.220 -  apply (auto intro: cong_diff_int)
  14.221 -done;
  14.222 -
  14.223 -lemma cong_diff_nat:
  14.224 -  assumes "(a::nat) >= c" and "b >= d" and "[a = b] (mod m)" and
  14.225 -    "[c = d] (mod m)"
  14.226 -  shows "[a - c = b - d] (mod m)"
  14.227 -
  14.228 -  using prems by (rule cong_diff_aux_int [transferred]);
  14.229 -
  14.230 -lemma cong_mult_nat:
  14.231 -    "[(a::nat) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)"
  14.232 -  apply (unfold cong_nat_def)
  14.233 -  apply (subst (1 2) mod_mult_eq)
  14.234 -  apply simp
  14.235 -done
  14.236 -
  14.237 -lemma cong_mult_int:
  14.238 -    "[(a::int) = b] (mod m) \<Longrightarrow> [c = d] (mod m) \<Longrightarrow> [a * c = b * d] (mod m)"
  14.239 -  apply (unfold cong_int_def)
  14.240 -  apply (subst (1 2) zmod_zmult1_eq)
  14.241 -  apply (subst (1 2) mult_commute)
  14.242 -  apply (subst (1 2) zmod_zmult1_eq)
  14.243 -  apply simp
  14.244 -done
  14.245 -
  14.246 -lemma cong_exp_nat: "[(x::nat) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
  14.247 -  apply (induct k)
  14.248 -  apply (auto simp add: cong_refl_nat cong_mult_nat)
  14.249 -done
  14.250 -
  14.251 -lemma cong_exp_int: "[(x::int) = y] (mod n) \<Longrightarrow> [x^k = y^k] (mod n)"
  14.252 -  apply (induct k)
  14.253 -  apply (auto simp add: cong_refl_int cong_mult_int)
  14.254 -done
  14.255 -
  14.256 -lemma cong_setsum_nat [rule_format]: 
  14.257 -    "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> 
  14.258 -      [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)"
  14.259 -  apply (case_tac "finite A")
  14.260 -  apply (induct set: finite)
  14.261 -  apply (auto intro: cong_add_nat)
  14.262 -done
  14.263 -
  14.264 -lemma cong_setsum_int [rule_format]:
  14.265 -    "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> 
  14.266 -      [(SUM x:A. f x) = (SUM x:A. g x)] (mod m)"
  14.267 -  apply (case_tac "finite A")
  14.268 -  apply (induct set: finite)
  14.269 -  apply (auto intro: cong_add_int)
  14.270 -done
  14.271 -
  14.272 -lemma cong_setprod_nat [rule_format]: 
  14.273 -    "(ALL x: A. [((f x)::nat) = g x] (mod m)) \<longrightarrow> 
  14.274 -      [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)"
  14.275 -  apply (case_tac "finite A")
  14.276 -  apply (induct set: finite)
  14.277 -  apply (auto intro: cong_mult_nat)
  14.278 -done
  14.279 -
  14.280 -lemma cong_setprod_int [rule_format]: 
  14.281 -    "(ALL x: A. [((f x)::int) = g x] (mod m)) \<longrightarrow> 
  14.282 -      [(PROD x:A. f x) = (PROD x:A. g x)] (mod m)"
  14.283 -  apply (case_tac "finite A")
  14.284 -  apply (induct set: finite)
  14.285 -  apply (auto intro: cong_mult_int)
  14.286 -done
  14.287 -
  14.288 -lemma cong_scalar_nat: "[(a::nat)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)"
  14.289 -  by (rule cong_mult_nat, simp_all)
  14.290 -
  14.291 -lemma cong_scalar_int: "[(a::int)= b] (mod m) \<Longrightarrow> [a * k = b * k] (mod m)"
  14.292 -  by (rule cong_mult_int, simp_all)
  14.293 -
  14.294 -lemma cong_scalar2_nat: "[(a::nat)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)"
  14.295 -  by (rule cong_mult_nat, simp_all)
  14.296 -
  14.297 -lemma cong_scalar2_int: "[(a::int)= b] (mod m) \<Longrightarrow> [k * a = k * b] (mod m)"
  14.298 -  by (rule cong_mult_int, simp_all)
  14.299 -
  14.300 -lemma cong_mult_self_nat: "[(a::nat) * m = 0] (mod m)"
  14.301 -  by (unfold cong_nat_def, auto)
  14.302 -
  14.303 -lemma cong_mult_self_int: "[(a::int) * m = 0] (mod m)"
  14.304 -  by (unfold cong_int_def, auto)
  14.305 -
  14.306 -lemma cong_eq_diff_cong_0_int: "[(a::int) = b] (mod m) = [a - b = 0] (mod m)"
  14.307 -  apply (rule iffI)
  14.308 -  apply (erule cong_diff_int [of a b m b b, simplified])
  14.309 -  apply (erule cong_add_int [of "a - b" 0 m b b, simplified])
  14.310 -done
  14.311 -
  14.312 -lemma cong_eq_diff_cong_0_aux_int: "a >= b \<Longrightarrow>
  14.313 -    [(a::int) = b] (mod m) = [tsub a b = 0] (mod m)"
  14.314 -  by (subst tsub_eq, assumption, rule cong_eq_diff_cong_0_int)
  14.315 -
  14.316 -lemma cong_eq_diff_cong_0_nat:
  14.317 -  assumes "(a::nat) >= b"
  14.318 -  shows "[a = b] (mod m) = [a - b = 0] (mod m)"
  14.319 -
  14.320 -  using prems by (rule cong_eq_diff_cong_0_aux_int [transferred])
  14.321 -
  14.322 -lemma cong_diff_cong_0'_nat: 
  14.323 -  "[(x::nat) = y] (mod n) \<longleftrightarrow> 
  14.324 -    (if x <= y then [y - x = 0] (mod n) else [x - y = 0] (mod n))"
  14.325 -  apply (case_tac "y <= x")
  14.326 -  apply (frule cong_eq_diff_cong_0_nat [where m = n])
  14.327 -  apply auto [1]
  14.328 -  apply (subgoal_tac "x <= y")
  14.329 -  apply (frule cong_eq_diff_cong_0_nat [where m = n])
  14.330 -  apply (subst cong_sym_eq_nat)
  14.331 -  apply auto
  14.332 -done
  14.333 -
  14.334 -lemma cong_altdef_nat: "(a::nat) >= b \<Longrightarrow> [a = b] (mod m) = (m dvd (a - b))"
  14.335 -  apply (subst cong_eq_diff_cong_0_nat, assumption)
  14.336 -  apply (unfold cong_nat_def)
  14.337 -  apply (simp add: dvd_eq_mod_eq_0 [symmetric])
  14.338 -done
  14.339 -
  14.340 -lemma cong_altdef_int: "[(a::int) = b] (mod m) = (m dvd (a - b))"
  14.341 -  apply (subst cong_eq_diff_cong_0_int)
  14.342 -  apply (unfold cong_int_def)
  14.343 -  apply (simp add: dvd_eq_mod_eq_0 [symmetric])
  14.344 -done
  14.345 -
  14.346 -lemma cong_abs_int: "[(x::int) = y] (mod abs m) = [x = y] (mod m)"
  14.347 -  by (simp add: cong_altdef_int)
  14.348 -
  14.349 -lemma cong_square_int:
  14.350 -   "\<lbrakk> prime (p::int); 0 < a; [a * a = 1] (mod p) \<rbrakk>
  14.351 -    \<Longrightarrow> [a = 1] (mod p) \<or> [a = - 1] (mod p)"
  14.352 -  apply (simp only: cong_altdef_int)
  14.353 -  apply (subst prime_dvd_mult_eq_int [symmetric], assumption)
  14.354 -  (* any way around this? *)
  14.355 -  apply (subgoal_tac "a * a - 1 = (a - 1) * (a - -1)")
  14.356 -  apply (auto simp add: ring_simps)
  14.357 -done
  14.358 -
  14.359 -lemma cong_mult_rcancel_int:
  14.360 -  "coprime k (m::int) \<Longrightarrow> [a * k = b * k] (mod m) = [a = b] (mod m)"
  14.361 -  apply (subst (1 2) cong_altdef_int)
  14.362 -  apply (subst left_diff_distrib [symmetric])
  14.363 -  apply (rule coprime_dvd_mult_iff_int)
  14.364 -  apply (subst gcd_commute_int, assumption)
  14.365 -done
  14.366 -
  14.367 -lemma cong_mult_rcancel_nat:
  14.368 -  assumes  "coprime k (m::nat)"
  14.369 -  shows "[a * k = b * k] (mod m) = [a = b] (mod m)"
  14.370 -
  14.371 -  apply (rule cong_mult_rcancel_int [transferred])
  14.372 -  using prems apply auto
  14.373 -done
  14.374 -
  14.375 -lemma cong_mult_lcancel_nat:
  14.376 -  "coprime k (m::nat) \<Longrightarrow> [k * a = k * b ] (mod m) = [a = b] (mod m)"
  14.377 -  by (simp add: mult_commute cong_mult_rcancel_nat)
  14.378 -
  14.379 -lemma cong_mult_lcancel_int:
  14.380 -  "coprime k (m::int) \<Longrightarrow> [k * a = k * b] (mod m) = [a = b] (mod m)"
  14.381 -  by (simp add: mult_commute cong_mult_rcancel_int)
  14.382 -
  14.383 -(* was zcong_zgcd_zmult_zmod *)
  14.384 -lemma coprime_cong_mult_int:
  14.385 -  "[(a::int) = b] (mod m) \<Longrightarrow> [a = b] (mod n) \<Longrightarrow> coprime m n
  14.386 -    \<Longrightarrow> [a = b] (mod m * n)"
  14.387 -  apply (simp only: cong_altdef_int)
  14.388 -  apply (erule (2) divides_mult_int)
  14.389 -done
  14.390 -
  14.391 -lemma coprime_cong_mult_nat:
  14.392 -  assumes "[(a::nat) = b] (mod m)" and "[a = b] (mod n)" and "coprime m n"
  14.393 -  shows "[a = b] (mod m * n)"
  14.394 -
  14.395 -  apply (rule coprime_cong_mult_int [transferred])
  14.396 -  using prems apply auto
  14.397 -done
  14.398 -
  14.399 -lemma cong_less_imp_eq_nat: "0 \<le> (a::nat) \<Longrightarrow>
  14.400 -    a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b"
  14.401 -  by (auto simp add: cong_nat_def mod_pos_pos_trivial)
  14.402 -
  14.403 -lemma cong_less_imp_eq_int: "0 \<le> (a::int) \<Longrightarrow>
  14.404 -    a < m \<Longrightarrow> 0 \<le> b \<Longrightarrow> b < m \<Longrightarrow> [a = b] (mod m) \<Longrightarrow> a = b"
  14.405 -  by (auto simp add: cong_int_def mod_pos_pos_trivial)
  14.406 -
  14.407 -lemma cong_less_unique_nat:
  14.408 -    "0 < (m::nat) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
  14.409 -  apply auto
  14.410 -  apply (rule_tac x = "a mod m" in exI)
  14.411 -  apply (unfold cong_nat_def, auto)
  14.412 -done
  14.413 -
  14.414 -lemma cong_less_unique_int:
  14.415 -    "0 < (m::int) \<Longrightarrow> (\<exists>!b. 0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
  14.416 -  apply auto
  14.417 -  apply (rule_tac x = "a mod m" in exI)
  14.418 -  apply (unfold cong_int_def, auto simp add: mod_pos_pos_trivial)
  14.419 -done
  14.420 -
  14.421 -lemma cong_iff_lin_int: "([(a::int) = b] (mod m)) = (\<exists>k. b = a + m * k)"
  14.422 -  apply (auto simp add: cong_altdef_int dvd_def ring_simps)
  14.423 -  apply (rule_tac [!] x = "-k" in exI, auto)
  14.424 -done
  14.425 -
  14.426 -lemma cong_iff_lin_nat: "([(a::nat) = b] (mod m)) = 
  14.427 -    (\<exists>k1 k2. b + k1 * m = a + k2 * m)"
  14.428 -  apply (rule iffI)
  14.429 -  apply (case_tac "b <= a")
  14.430 -  apply (subst (asm) cong_altdef_nat, assumption)
  14.431 -  apply (unfold dvd_def, auto)
  14.432 -  apply (rule_tac x = k in exI)
  14.433 -  apply (rule_tac x = 0 in exI)
  14.434 -  apply (auto simp add: ring_simps)
  14.435 -  apply (subst (asm) cong_sym_eq_nat)
  14.436 -  apply (subst (asm) cong_altdef_nat)
  14.437 -  apply force
  14.438 -  apply (unfold dvd_def, auto)
  14.439 -  apply (rule_tac x = 0 in exI)
  14.440 -  apply (rule_tac x = k in exI)
  14.441 -  apply (auto simp add: ring_simps)
  14.442 -  apply (unfold cong_nat_def)
  14.443 -  apply (subgoal_tac "a mod m = (a + k2 * m) mod m")
  14.444 -  apply (erule ssubst)back
  14.445 -  apply (erule subst)
  14.446 -  apply auto
  14.447 -done
  14.448 -
  14.449 -lemma cong_gcd_eq_int: "[(a::int) = b] (mod m) \<Longrightarrow> gcd a m = gcd b m"
  14.450 -  apply (subst (asm) cong_iff_lin_int, auto)
  14.451 -  apply (subst add_commute) 
  14.452 -  apply (subst (2) gcd_commute_int)
  14.453 -  apply (subst mult_commute)
  14.454 -  apply (subst gcd_add_mult_int)
  14.455 -  apply (rule gcd_commute_int)
  14.456 -done
  14.457 -
  14.458 -lemma cong_gcd_eq_nat: 
  14.459 -  assumes "[(a::nat) = b] (mod m)"
  14.460 -  shows "gcd a m = gcd b m"
  14.461 -
  14.462 -  apply (rule cong_gcd_eq_int [transferred])
  14.463 -  using prems apply auto
  14.464 -done
  14.465 -
  14.466 -lemma cong_imp_coprime_nat: "[(a::nat) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> 
  14.467 -    coprime b m"
  14.468 -  by (auto simp add: cong_gcd_eq_nat)
  14.469 -
  14.470 -lemma cong_imp_coprime_int: "[(a::int) = b] (mod m) \<Longrightarrow> coprime a m \<Longrightarrow> 
  14.471 -    coprime b m"
  14.472 -  by (auto simp add: cong_gcd_eq_int)
  14.473 -
  14.474 -lemma cong_cong_mod_nat: "[(a::nat) = b] (mod m) = 
  14.475 -    [a mod m = b mod m] (mod m)"
  14.476 -  by (auto simp add: cong_nat_def)
  14.477 -
  14.478 -lemma cong_cong_mod_int: "[(a::int) = b] (mod m) = 
  14.479 -    [a mod m = b mod m] (mod m)"
  14.480 -  by (auto simp add: cong_int_def)
  14.481 -
  14.482 -lemma cong_minus_int [iff]: "[(a::int) = b] (mod -m) = [a = b] (mod m)"
  14.483 -  by (subst (1 2) cong_altdef_int, auto)
  14.484 -
  14.485 -lemma cong_zero_nat [iff]: "[(a::nat) = b] (mod 0) = (a = b)"
  14.486 -  by (auto simp add: cong_nat_def)
  14.487 -
  14.488 -lemma cong_zero_int [iff]: "[(a::int) = b] (mod 0) = (a = b)"
  14.489 -  by (auto simp add: cong_int_def)
  14.490 -
  14.491 -(*
  14.492 -lemma mod_dvd_mod_int:
  14.493 -    "0 < (m::int) \<Longrightarrow> m dvd b \<Longrightarrow> (a mod b mod m) = (a mod m)"
  14.494 -  apply (unfold dvd_def, auto)
  14.495 -  apply (rule mod_mod_cancel)
  14.496 -  apply auto
  14.497 -done
  14.498 -
  14.499 -lemma mod_dvd_mod:
  14.500 -  assumes "0 < (m::nat)" and "m dvd b"
  14.501 -  shows "(a mod b mod m) = (a mod m)"
  14.502 -
  14.503 -  apply (rule mod_dvd_mod_int [transferred])
  14.504 -  using prems apply auto
  14.505 -done
  14.506 -*)
  14.507 -
  14.508 -lemma cong_add_lcancel_nat: 
  14.509 -    "[(a::nat) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" 
  14.510 -  by (simp add: cong_iff_lin_nat)
  14.511 -
  14.512 -lemma cong_add_lcancel_int: 
  14.513 -    "[(a::int) + x = a + y] (mod n) \<longleftrightarrow> [x = y] (mod n)" 
  14.514 -  by (simp add: cong_iff_lin_int)
  14.515 -
  14.516 -lemma cong_add_rcancel_nat: "[(x::nat) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
  14.517 -  by (simp add: cong_iff_lin_nat)
  14.518 -
  14.519 -lemma cong_add_rcancel_int: "[(x::int) + a = y + a] (mod n) \<longleftrightarrow> [x = y] (mod n)"
  14.520 -  by (simp add: cong_iff_lin_int)
  14.521 -
  14.522 -lemma cong_add_lcancel_0_nat: "[(a::nat) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
  14.523 -  by (simp add: cong_iff_lin_nat)
  14.524 -
  14.525 -lemma cong_add_lcancel_0_int: "[(a::int) + x = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
  14.526 -  by (simp add: cong_iff_lin_int)
  14.527 -
  14.528 -lemma cong_add_rcancel_0_nat: "[x + (a::nat) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
  14.529 -  by (simp add: cong_iff_lin_nat)
  14.530 -
  14.531 -lemma cong_add_rcancel_0_int: "[x + (a::int) = a] (mod n) \<longleftrightarrow> [x = 0] (mod n)" 
  14.532 -  by (simp add: cong_iff_lin_int)
  14.533 -
  14.534 -lemma cong_dvd_modulus_nat: "[(x::nat) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> 
  14.535 -    [x = y] (mod n)"
  14.536 -  apply (auto simp add: cong_iff_lin_nat dvd_def)
  14.537 -  apply (rule_tac x="k1 * k" in exI)
  14.538 -  apply (rule_tac x="k2 * k" in exI)
  14.539 -  apply (simp add: ring_simps)
  14.540 -done
  14.541 -
  14.542 -lemma cong_dvd_modulus_int: "[(x::int) = y] (mod m) \<Longrightarrow> n dvd m \<Longrightarrow> 
  14.543 -    [x = y] (mod n)"
  14.544 -  by (auto simp add: cong_altdef_int dvd_def)
  14.545 -
  14.546 -lemma cong_dvd_eq_nat: "[(x::nat) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
  14.547 -  by (unfold cong_nat_def, auto simp add: dvd_eq_mod_eq_0)
  14.548 -
  14.549 -lemma cong_dvd_eq_int: "[(x::int) = y] (mod n) \<Longrightarrow> n dvd x \<longleftrightarrow> n dvd y"
  14.550 -  by (unfold cong_int_def, auto simp add: dvd_eq_mod_eq_0)
  14.551 -
  14.552 -lemma cong_mod_nat: "(n::nat) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" 
  14.553 -  by (simp add: cong_nat_def)
  14.554 -
  14.555 -lemma cong_mod_int: "(n::int) ~= 0 \<Longrightarrow> [a mod n = a] (mod n)" 
  14.556 -  by (simp add: cong_int_def)
  14.557 -
  14.558 -lemma mod_mult_cong_nat: "(a::nat) ~= 0 \<Longrightarrow> b ~= 0 
  14.559 -    \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
  14.560 -  by (simp add: cong_nat_def mod_mult2_eq  mod_add_left_eq)
  14.561 -
  14.562 -lemma neg_cong_int: "([(a::int) = b] (mod m)) = ([-a = -b] (mod m))"
  14.563 -  apply (simp add: cong_altdef_int)
  14.564 -  apply (subst dvd_minus_iff [symmetric])
  14.565 -  apply (simp add: ring_simps)
  14.566 -done
  14.567 -
  14.568 -lemma cong_modulus_neg_int: "([(a::int) = b] (mod m)) = ([a = b] (mod -m))"
  14.569 -  by (auto simp add: cong_altdef_int)
  14.570 -
  14.571 -lemma mod_mult_cong_int: "(a::int) ~= 0 \<Longrightarrow> b ~= 0 
  14.572 -    \<Longrightarrow> [x mod (a * b) = y] (mod a) \<longleftrightarrow> [x = y] (mod a)"
  14.573 -  apply (case_tac "b > 0")
  14.574 -  apply (simp add: cong_int_def mod_mod_cancel mod_add_left_eq)
  14.575 -  apply (subst (1 2) cong_modulus_neg_int)
  14.576 -  apply (unfold cong_int_def)
  14.577 -  apply (subgoal_tac "a * b = (-a * -b)")
  14.578 -  apply (erule ssubst)
  14.579 -  apply (subst zmod_zmult2_eq)
  14.580 -  apply (auto simp add: mod_add_left_eq) 
  14.581 -done
  14.582 -
  14.583 -lemma cong_to_1_nat: "([(a::nat) = 1] (mod n)) \<Longrightarrow> (n dvd (a - 1))"
  14.584 -  apply (case_tac "a = 0")
  14.585 -  apply force
  14.586 -  apply (subst (asm) cong_altdef_nat)
  14.587 -  apply auto
  14.588 -done
  14.589 -
  14.590 -lemma cong_0_1_nat: "[(0::nat) = 1] (mod n) = (n = 1)"
  14.591 -  by (unfold cong_nat_def, auto)
  14.592 -
  14.593 -lemma cong_0_1_int: "[(0::int) = 1] (mod n) = ((n = 1) | (n = -1))"
  14.594 -  by (unfold cong_int_def, auto simp add: zmult_eq_1_iff)
  14.595 -
  14.596 -lemma cong_to_1'_nat: "[(a::nat) = 1] (mod n) \<longleftrightarrow> 
  14.597 -    a = 0 \<and> n = 1 \<or> (\<exists>m. a = 1 + m * n)"
  14.598 -  apply (case_tac "n = 1")
  14.599 -  apply auto [1]
  14.600 -  apply (drule_tac x = "a - 1" in spec)
  14.601 -  apply force
  14.602 -  apply (case_tac "a = 0")
  14.603 -  apply (auto simp add: cong_0_1_nat) [1]
  14.604 -  apply (rule iffI)
  14.605 -  apply (drule cong_to_1_nat)
  14.606 -  apply (unfold dvd_def)
  14.607 -  apply auto [1]
  14.608 -  apply (rule_tac x = k in exI)
  14.609 -  apply (auto simp add: ring_simps) [1]
  14.610 -  apply (subst cong_altdef_nat)
  14.611 -  apply (auto simp add: dvd_def)
  14.612 -done
  14.613 -
  14.614 -lemma cong_le_nat: "(y::nat) <= x \<Longrightarrow> [x = y] (mod n) \<longleftrightarrow> (\<exists>q. x = q * n + y)"
  14.615 -  apply (subst cong_altdef_nat)
  14.616 -  apply assumption
  14.617 -  apply (unfold dvd_def, auto simp add: ring_simps)
  14.618 -  apply (rule_tac x = k in exI)
  14.619 -  apply auto
  14.620 -done
  14.621 -
  14.622 -lemma cong_solve_nat: "(a::nat) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)"
  14.623 -  apply (case_tac "n = 0")
  14.624 -  apply force
  14.625 -  apply (frule bezout_nat [of a n], auto)
  14.626 -  apply (rule exI, erule ssubst)
  14.627 -  apply (rule cong_trans_nat)
  14.628 -  apply (rule cong_add_nat)
  14.629 -  apply (subst mult_commute)
  14.630 -  apply (rule cong_mult_self_nat)
  14.631 -  prefer 2
  14.632 -  apply simp
  14.633 -  apply (rule cong_refl_nat)
  14.634 -  apply (rule cong_refl_nat)
  14.635 -done
  14.636 -
  14.637 -lemma cong_solve_int: "(a::int) \<noteq> 0 \<Longrightarrow> EX x. [a * x = gcd a n] (mod n)"
  14.638 -  apply (case_tac "n = 0")
  14.639 -  apply (case_tac "a \<ge> 0")
  14.640 -  apply auto
  14.641 -  apply (rule_tac x = "-1" in exI)
  14.642 -  apply auto
  14.643 -  apply (insert bezout_int [of a n], auto)
  14.644 -  apply (rule exI)
  14.645 -  apply (erule subst)
  14.646 -  apply (rule cong_trans_int)
  14.647 -  prefer 2
  14.648 -  apply (rule cong_add_int)
  14.649 -  apply (rule cong_refl_int)
  14.650 -  apply (rule cong_sym_int)
  14.651 -  apply (rule cong_mult_self_int)
  14.652 -  apply simp
  14.653 -  apply (subst mult_commute)
  14.654 -  apply (rule cong_refl_int)
  14.655 -done
  14.656 -  
  14.657 -lemma cong_solve_dvd_nat: 
  14.658 -  assumes a: "(a::nat) \<noteq> 0" and b: "gcd a n dvd d"
  14.659 -  shows "EX x. [a * x = d] (mod n)"
  14.660 -proof -
  14.661 -  from cong_solve_nat [OF a] obtain x where 
  14.662 -      "[a * x = gcd a n](mod n)"
  14.663 -    by auto
  14.664 -  hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" 
  14.665 -    by (elim cong_scalar2_nat)
  14.666 -  also from b have "(d div gcd a n) * gcd a n = d"
  14.667 -    by (rule dvd_div_mult_self)
  14.668 -  also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)"
  14.669 -    by auto
  14.670 -  finally show ?thesis
  14.671 -    by auto
  14.672 -qed
  14.673 -
  14.674 -lemma cong_solve_dvd_int: 
  14.675 -  assumes a: "(a::int) \<noteq> 0" and b: "gcd a n dvd d"
  14.676 -  shows "EX x. [a * x = d] (mod n)"
  14.677 -proof -
  14.678 -  from cong_solve_int [OF a] obtain x where 
  14.679 -      "[a * x = gcd a n](mod n)"
  14.680 -    by auto
  14.681 -  hence "[(d div gcd a n) * (a * x) = (d div gcd a n) * gcd a n] (mod n)" 
  14.682 -    by (elim cong_scalar2_int)
  14.683 -  also from b have "(d div gcd a n) * gcd a n = d"
  14.684 -    by (rule dvd_div_mult_self)
  14.685 -  also have "(d div gcd a n) * (a * x) = a * (d div gcd a n * x)"
  14.686 -    by auto
  14.687 -  finally show ?thesis
  14.688 -    by auto
  14.689 -qed
  14.690 -
  14.691 -lemma cong_solve_coprime_nat: "coprime (a::nat) n \<Longrightarrow> 
  14.692 -    EX x. [a * x = 1] (mod n)"
  14.693 -  apply (case_tac "a = 0")
  14.694 -  apply force
  14.695 -  apply (frule cong_solve_nat [of a n])
  14.696 -  apply auto
  14.697 -done
  14.698 -
  14.699 -lemma cong_solve_coprime_int: "coprime (a::int) n \<Longrightarrow> 
  14.700 -    EX x. [a * x = 1] (mod n)"
  14.701 -  apply (case_tac "a = 0")
  14.702 -  apply auto
  14.703 -  apply (case_tac "n \<ge> 0")
  14.704 -  apply auto
  14.705 -  apply (subst cong_int_def, auto)
  14.706 -  apply (frule cong_solve_int [of a n])
  14.707 -  apply auto
  14.708 -done
  14.709 -
  14.710 -lemma coprime_iff_invertible_nat: "m > (1::nat) \<Longrightarrow> coprime a m = 
  14.711 -    (EX x. [a * x = 1] (mod m))"
  14.712 -  apply (auto intro: cong_solve_coprime_nat)
  14.713 -  apply (unfold cong_nat_def, auto intro: invertible_coprime_nat)
  14.714 -done
  14.715 -
  14.716 -lemma coprime_iff_invertible_int: "m > (1::int) \<Longrightarrow> coprime a m = 
  14.717 -    (EX x. [a * x = 1] (mod m))"
  14.718 -  apply (auto intro: cong_solve_coprime_int)
  14.719 -  apply (unfold cong_int_def)
  14.720 -  apply (auto intro: invertible_coprime_int)
  14.721 -done
  14.722 -
  14.723 -lemma coprime_iff_invertible'_int: "m > (1::int) \<Longrightarrow> coprime a m = 
  14.724 -    (EX x. 0 <= x & x < m & [a * x = 1] (mod m))"
  14.725 -  apply (subst coprime_iff_invertible_int)
  14.726 -  apply auto
  14.727 -  apply (auto simp add: cong_int_def)
  14.728 -  apply (rule_tac x = "x mod m" in exI)
  14.729 -  apply (auto simp add: mod_mult_right_eq [symmetric])
  14.730 -done
  14.731 -
  14.732 -
  14.733 -lemma cong_cong_lcm_nat: "[(x::nat) = y] (mod a) \<Longrightarrow>
  14.734 -    [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)"
  14.735 -  apply (case_tac "y \<le> x")
  14.736 -  apply (auto simp add: cong_altdef_nat lcm_least_nat) [1]
  14.737 -  apply (rule cong_sym_nat)
  14.738 -  apply (subst (asm) (1 2) cong_sym_eq_nat)
  14.739 -  apply (auto simp add: cong_altdef_nat lcm_least_nat)
  14.740 -done
  14.741 -
  14.742 -lemma cong_cong_lcm_int: "[(x::int) = y] (mod a) \<Longrightarrow>
  14.743 -    [x = y] (mod b) \<Longrightarrow> [x = y] (mod lcm a b)"
  14.744 -  by (auto simp add: cong_altdef_int lcm_least_int) [1]
  14.745 -
  14.746 -lemma cong_cong_coprime_nat: "coprime a b \<Longrightarrow> [(x::nat) = y] (mod a) \<Longrightarrow>
  14.747 -    [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)"
  14.748 -  apply (frule (1) cong_cong_lcm_nat)back
  14.749 -  apply (simp add: lcm_nat_def)
  14.750 -done
  14.751 -
  14.752 -lemma cong_cong_coprime_int: "coprime a b \<Longrightarrow> [(x::int) = y] (mod a) \<Longrightarrow>
  14.753 -    [x = y] (mod b) \<Longrightarrow> [x = y] (mod a * b)"
  14.754 -  apply (frule (1) cong_cong_lcm_int)back
  14.755 -  apply (simp add: lcm_altdef_int cong_abs_int abs_mult [symmetric])
  14.756 -done
  14.757 -
  14.758 -lemma cong_cong_setprod_coprime_nat [rule_format]: "finite A \<Longrightarrow>
  14.759 -    (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
  14.760 -    (ALL i:A. [(x::nat) = y] (mod m i)) \<longrightarrow>
  14.761 -      [x = y] (mod (PROD i:A. m i))"
  14.762 -  apply (induct set: finite)
  14.763 -  apply auto
  14.764 -  apply (rule cong_cong_coprime_nat)
  14.765 -  apply (subst gcd_commute_nat)
  14.766 -  apply (rule setprod_coprime_nat)
  14.767 -  apply auto
  14.768 -done
  14.769 -
  14.770 -lemma cong_cong_setprod_coprime_int [rule_format]: "finite A \<Longrightarrow>
  14.771 -    (ALL i:A. (ALL j:A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
  14.772 -    (ALL i:A. [(x::int) = y] (mod m i)) \<longrightarrow>
  14.773 -      [x = y] (mod (PROD i:A. m i))"
  14.774 -  apply (induct set: finite)
  14.775 -  apply auto
  14.776 -  apply (rule cong_cong_coprime_int)
  14.777 -  apply (subst gcd_commute_int)
  14.778 -  apply (rule setprod_coprime_int)
  14.779 -  apply auto
  14.780 -done
  14.781 -
  14.782 -lemma binary_chinese_remainder_aux_nat: 
  14.783 -  assumes a: "coprime (m1::nat) m2"
  14.784 -  shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and>
  14.785 -    [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)"
  14.786 -proof -
  14.787 -  from cong_solve_coprime_nat [OF a]
  14.788 -      obtain x1 where one: "[m1 * x1 = 1] (mod m2)"
  14.789 -    by auto
  14.790 -  from a have b: "coprime m2 m1" 
  14.791 -    by (subst gcd_commute_nat)
  14.792 -  from cong_solve_coprime_nat [OF b]
  14.793 -      obtain x2 where two: "[m2 * x2 = 1] (mod m1)"
  14.794 -    by auto
  14.795 -  have "[m1 * x1 = 0] (mod m1)"
  14.796 -    by (subst mult_commute, rule cong_mult_self_nat)
  14.797 -  moreover have "[m2 * x2 = 0] (mod m2)"
  14.798 -    by (subst mult_commute, rule cong_mult_self_nat)
  14.799 -  moreover note one two
  14.800 -  ultimately show ?thesis by blast
  14.801 -qed
  14.802 -
  14.803 -lemma binary_chinese_remainder_aux_int: 
  14.804 -  assumes a: "coprime (m1::int) m2"
  14.805 -  shows "EX b1 b2. [b1 = 1] (mod m1) \<and> [b1 = 0] (mod m2) \<and>
  14.806 -    [b2 = 0] (mod m1) \<and> [b2 = 1] (mod m2)"
  14.807 -proof -
  14.808 -  from cong_solve_coprime_int [OF a]
  14.809 -      obtain x1 where one: "[m1 * x1 = 1] (mod m2)"
  14.810 -    by auto
  14.811 -  from a have b: "coprime m2 m1" 
  14.812 -    by (subst gcd_commute_int)
  14.813 -  from cong_solve_coprime_int [OF b]
  14.814 -      obtain x2 where two: "[m2 * x2 = 1] (mod m1)"
  14.815 -    by auto
  14.816 -  have "[m1 * x1 = 0] (mod m1)"
  14.817 -    by (subst mult_commute, rule cong_mult_self_int)
  14.818 -  moreover have "[m2 * x2 = 0] (mod m2)"
  14.819 -    by (subst mult_commute, rule cong_mult_self_int)
  14.820 -  moreover note one two
  14.821 -  ultimately show ?thesis by blast
  14.822 -qed
  14.823 -
  14.824 -lemma binary_chinese_remainder_nat:
  14.825 -  assumes a: "coprime (m1::nat) m2"
  14.826 -  shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
  14.827 -proof -
  14.828 -  from binary_chinese_remainder_aux_nat [OF a] obtain b1 b2
  14.829 -    where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and
  14.830 -          "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)"
  14.831 -    by blast
  14.832 -  let ?x = "u1 * b1 + u2 * b2"
  14.833 -  have "[?x = u1 * 1 + u2 * 0] (mod m1)"
  14.834 -    apply (rule cong_add_nat)
  14.835 -    apply (rule cong_scalar2_nat)
  14.836 -    apply (rule `[b1 = 1] (mod m1)`)
  14.837 -    apply (rule cong_scalar2_nat)
  14.838 -    apply (rule `[b2 = 0] (mod m1)`)
  14.839 -    done
  14.840 -  hence "[?x = u1] (mod m1)" by simp
  14.841 -  have "[?x = u1 * 0 + u2 * 1] (mod m2)"
  14.842 -    apply (rule cong_add_nat)
  14.843 -    apply (rule cong_scalar2_nat)
  14.844 -    apply (rule `[b1 = 0] (mod m2)`)
  14.845 -    apply (rule cong_scalar2_nat)
  14.846 -    apply (rule `[b2 = 1] (mod m2)`)
  14.847 -    done
  14.848 -  hence "[?x = u2] (mod m2)" by simp
  14.849 -  with `[?x = u1] (mod m1)` show ?thesis by blast
  14.850 -qed
  14.851 -
  14.852 -lemma binary_chinese_remainder_int:
  14.853 -  assumes a: "coprime (m1::int) m2"
  14.854 -  shows "EX x. [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
  14.855 -proof -
  14.856 -  from binary_chinese_remainder_aux_int [OF a] obtain b1 b2
  14.857 -    where "[b1 = 1] (mod m1)" and "[b1 = 0] (mod m2)" and
  14.858 -          "[b2 = 0] (mod m1)" and "[b2 = 1] (mod m2)"
  14.859 -    by blast
  14.860 -  let ?x = "u1 * b1 + u2 * b2"
  14.861 -  have "[?x = u1 * 1 + u2 * 0] (mod m1)"
  14.862 -    apply (rule cong_add_int)
  14.863 -    apply (rule cong_scalar2_int)
  14.864 -    apply (rule `[b1 = 1] (mod m1)`)
  14.865 -    apply (rule cong_scalar2_int)
  14.866 -    apply (rule `[b2 = 0] (mod m1)`)
  14.867 -    done
  14.868 -  hence "[?x = u1] (mod m1)" by simp
  14.869 -  have "[?x = u1 * 0 + u2 * 1] (mod m2)"
  14.870 -    apply (rule cong_add_int)
  14.871 -    apply (rule cong_scalar2_int)
  14.872 -    apply (rule `[b1 = 0] (mod m2)`)
  14.873 -    apply (rule cong_scalar2_int)
  14.874 -    apply (rule `[b2 = 1] (mod m2)`)
  14.875 -    done
  14.876 -  hence "[?x = u2] (mod m2)" by simp
  14.877 -  with `[?x = u1] (mod m1)` show ?thesis by blast
  14.878 -qed
  14.879 -
  14.880 -lemma cong_modulus_mult_nat: "[(x::nat) = y] (mod m * n) \<Longrightarrow> 
  14.881 -    [x = y] (mod m)"
  14.882 -  apply (case_tac "y \<le> x")
  14.883 -  apply (simp add: cong_altdef_nat)
  14.884 -  apply (erule dvd_mult_left)
  14.885 -  apply (rule cong_sym_nat)
  14.886 -  apply (subst (asm) cong_sym_eq_nat)
  14.887 -  apply (simp add: cong_altdef_nat) 
  14.888 -  apply (erule dvd_mult_left)
  14.889 -done
  14.890 -
  14.891 -lemma cong_modulus_mult_int: "[(x::int) = y] (mod m * n) \<Longrightarrow> 
  14.892 -    [x = y] (mod m)"
  14.893 -  apply (simp add: cong_altdef_int) 
  14.894 -  apply (erule dvd_mult_left)
  14.895 -done
  14.896 -
  14.897 -lemma cong_less_modulus_unique_nat: 
  14.898 -    "[(x::nat) = y] (mod m) \<Longrightarrow> x < m \<Longrightarrow> y < m \<Longrightarrow> x = y"
  14.899 -  by (simp add: cong_nat_def)
  14.900 -
  14.901 -lemma binary_chinese_remainder_unique_nat:
  14.902 -  assumes a: "coprime (m1::nat) m2" and
  14.903 -         nz: "m1 \<noteq> 0" "m2 \<noteq> 0"
  14.904 -  shows "EX! x. x < m1 * m2 \<and> [x = u1] (mod m1) \<and> [x = u2] (mod m2)"
  14.905 -proof -
  14.906 -  from binary_chinese_remainder_nat [OF a] obtain y where 
  14.907 -      "[y = u1] (mod m1)" and "[y = u2] (mod m2)"
  14.908 -    by blast
  14.909 -  let ?x = "y mod (m1 * m2)"
  14.910 -  from nz have less: "?x < m1 * m2"
  14.911 -    by auto   
  14.912 -  have one: "[?x = u1] (mod m1)"
  14.913 -    apply (rule cong_trans_nat)
  14.914 -    prefer 2
  14.915 -    apply (rule `[y = u1] (mod m1)`)
  14.916 -    apply (rule cong_modulus_mult_nat)
  14.917 -    apply (rule cong_mod_nat)
  14.918 -    using nz apply auto
  14.919 -    done
  14.920 -  have two: "[?x = u2] (mod m2)"
  14.921 -    apply (rule cong_trans_nat)
  14.922 -    prefer 2
  14.923 -    apply (rule `[y = u2] (mod m2)`)
  14.924 -    apply (subst mult_commute)
  14.925 -    apply (rule cong_modulus_mult_nat)
  14.926 -    apply (rule cong_mod_nat)
  14.927 -    using nz apply auto
  14.928 -    done
  14.929 -  have "ALL z. z < m1 * m2 \<and> [z = u1] (mod m1) \<and> [z = u2] (mod m2) \<longrightarrow>
  14.930 -      z = ?x"
  14.931 -  proof (clarify)
  14.932 -    fix z
  14.933 -    assume "z < m1 * m2"
  14.934 -    assume "[z = u1] (mod m1)" and  "[z = u2] (mod m2)"
  14.935 -    have "[?x = z] (mod m1)"
  14.936 -      apply (rule cong_trans_nat)
  14.937 -      apply (rule `[?x = u1] (mod m1)`)
  14.938 -      apply (rule cong_sym_nat)
  14.939 -      apply (rule `[z = u1] (mod m1)`)
  14.940 -      done
  14.941 -    moreover have "[?x = z] (mod m2)"
  14.942 -      apply (rule cong_trans_nat)
  14.943 -      apply (rule `[?x = u2] (mod m2)`)
  14.944 -      apply (rule cong_sym_nat)
  14.945 -      apply (rule `[z = u2] (mod m2)`)
  14.946 -      done
  14.947 -    ultimately have "[?x = z] (mod m1 * m2)"
  14.948 -      by (auto intro: coprime_cong_mult_nat a)
  14.949 -    with `z < m1 * m2` `?x < m1 * m2` show "z = ?x"
  14.950 -      apply (intro cong_less_modulus_unique_nat)
  14.951 -      apply (auto, erule cong_sym_nat)
  14.952 -      done
  14.953 -  qed  
  14.954 -  with less one two show ?thesis
  14.955 -    by auto
  14.956 - qed
  14.957 -
  14.958 -lemma chinese_remainder_aux_nat:
  14.959 -  fixes A :: "'a set" and
  14.960 -        m :: "'a \<Rightarrow> nat"
  14.961 -  assumes fin: "finite A" and
  14.962 -          cop: "ALL i : A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
  14.963 -  shows "EX b. (ALL i : A. 
  14.964 -      [b i = 1] (mod m i) \<and> [b i = 0] (mod (PROD j : A - {i}. m j)))"
  14.965 -proof (rule finite_set_choice, rule fin, rule ballI)
  14.966 -  fix i
  14.967 -  assume "i : A"
  14.968 -  with cop have "coprime (PROD j : A - {i}. m j) (m i)"
  14.969 -    by (intro setprod_coprime_nat, auto)
  14.970 -  hence "EX x. [(PROD j : A - {i}. m j) * x = 1] (mod m i)"
  14.971 -    by (elim cong_solve_coprime_nat)
  14.972 -  then obtain x where "[(PROD j : A - {i}. m j) * x = 1] (mod m i)"
  14.973 -    by auto
  14.974 -  moreover have "[(PROD j : A - {i}. m j) * x = 0] 
  14.975 -    (mod (PROD j : A - {i}. m j))"
  14.976 -    by (subst mult_commute, rule cong_mult_self_nat)
  14.977 -  ultimately show "\<exists>a. [a = 1] (mod m i) \<and> [a = 0] 
  14.978 -      (mod setprod m (A - {i}))"
  14.979 -    by blast
  14.980 -qed
  14.981 -
  14.982 -lemma chinese_remainder_nat:
  14.983 -  fixes A :: "'a set" and
  14.984 -        m :: "'a \<Rightarrow> nat" and
  14.985 -        u :: "'a \<Rightarrow> nat"
  14.986 -  assumes 
  14.987 -        fin: "finite A" and
  14.988 -        cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
  14.989 -  shows "EX x. (ALL i:A. [x = u i] (mod m i))"
  14.990 -proof -
  14.991 -  from chinese_remainder_aux_nat [OF fin cop] obtain b where
  14.992 -    bprop: "ALL i:A. [b i = 1] (mod m i) \<and> 
  14.993 -      [b i = 0] (mod (PROD j : A - {i}. m j))"
  14.994 -    by blast
  14.995 -  let ?x = "SUM i:A. (u i) * (b i)"
  14.996 -  show "?thesis"
  14.997 -  proof (rule exI, clarify)
  14.998 -    fix i
  14.999 -    assume a: "i : A"
 14.1000 -    show "[?x = u i] (mod m i)" 
 14.1001 -    proof -
 14.1002 -      from fin a have "?x = (SUM j:{i}. u j * b j) + 
 14.1003 -          (SUM j:A-{i}. u j * b j)"
 14.1004 -        by (subst setsum_Un_disjoint [symmetric], auto intro: setsum_cong)
 14.1005 -      hence "[?x = u i * b i + (SUM j:A-{i}. u j * b j)] (mod m i)"
 14.1006 -        by auto
 14.1007 -      also have "[u i * b i + (SUM j:A-{i}. u j * b j) =
 14.1008 -                  u i * 1 + (SUM j:A-{i}. u j * 0)] (mod m i)"
 14.1009 -        apply (rule cong_add_nat)
 14.1010 -        apply (rule cong_scalar2_nat)
 14.1011 -        using bprop a apply blast
 14.1012 -        apply (rule cong_setsum_nat)
 14.1013 -        apply (rule cong_scalar2_nat)
 14.1014 -        using bprop apply auto
 14.1015 -        apply (rule cong_dvd_modulus_nat)
 14.1016 -        apply (drule (1) bspec)
 14.1017 -        apply (erule conjE)
 14.1018 -        apply assumption
 14.1019 -        apply (rule dvd_setprod)
 14.1020 -        using fin a apply auto
 14.1021 -        done
 14.1022 -      finally show ?thesis
 14.1023 -        by simp
 14.1024 -    qed
 14.1025 -  qed
 14.1026 -qed
 14.1027 -
 14.1028 -lemma coprime_cong_prod_nat [rule_format]: "finite A \<Longrightarrow> 
 14.1029 -    (ALL i: A. (ALL j: A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))) \<longrightarrow>
 14.1030 -      (ALL i: A. [(x::nat) = y] (mod m i)) \<longrightarrow>
 14.1031 -         [x = y] (mod (PROD i:A. m i))" 
 14.1032 -  apply (induct set: finite)
 14.1033 -  apply auto
 14.1034 -  apply (erule (1) coprime_cong_mult_nat)
 14.1035 -  apply (subst gcd_commute_nat)
 14.1036 -  apply (rule setprod_coprime_nat)
 14.1037 -  apply auto
 14.1038 -done
 14.1039 -
 14.1040 -lemma chinese_remainder_unique_nat:
 14.1041 -  fixes A :: "'a set" and
 14.1042 -        m :: "'a \<Rightarrow> nat" and
 14.1043 -        u :: "'a \<Rightarrow> nat"
 14.1044 -  assumes 
 14.1045 -        fin: "finite A" and
 14.1046 -         nz: "ALL i:A. m i \<noteq> 0" and
 14.1047 -        cop: "ALL i:A. (ALL j : A. i \<noteq> j \<longrightarrow> coprime (m i) (m j))"
 14.1048 -  shows "EX! x. x < (PROD i:A. m i) \<and> (ALL i:A. [x = u i] (mod m i))"
 14.1049 -proof -
 14.1050 -  from chinese_remainder_nat [OF fin cop] obtain y where
 14.1051 -      one: "(ALL i:A. [y = u i] (mod m i))" 
 14.1052 -    by blast
 14.1053 -  let ?x = "y mod (PROD i:A. m i)"
 14.1054 -  from fin nz have prodnz: "(PROD i:A. m i) \<noteq> 0"
 14.1055 -    by auto
 14.1056 -  hence less: "?x < (PROD i:A. m i)"
 14.1057 -    by auto
 14.1058 -  have cong: "ALL i:A. [?x = u i] (mod m i)"
 14.1059 -    apply auto
 14.1060 -    apply (rule cong_trans_nat)
 14.1061 -    prefer 2
 14.1062 -    using one apply auto
 14.1063 -    apply (rule cong_dvd_modulus_nat)
 14.1064 -    apply (rule cong_mod_nat)
 14.1065 -    using prodnz apply auto
 14.1066 -    apply (rule dvd_setprod)
 14.1067 -    apply (rule fin)
 14.1068 -    apply assumption
 14.1069 -    done
 14.1070 -  have unique: "ALL z. z < (PROD i:A. m i) \<and> 
 14.1071 -      (ALL i:A. [z = u i] (mod m i)) \<longrightarrow> z = ?x"
 14.1072 -  proof (clarify)
 14.1073 -    fix z
 14.1074 -    assume zless: "z < (PROD i:A. m i)"
 14.1075 -    assume zcong: "(ALL i:A. [z = u i] (mod m i))"
 14.1076 -    have "ALL i:A. [?x = z] (mod m i)"
 14.1077 -      apply clarify     
 14.1078 -      apply (rule cong_trans_nat)
 14.1079 -      using cong apply (erule bspec)
 14.1080 -      apply (rule cong_sym_nat)
 14.1081 -      using zcong apply auto
 14.1082 -      done
 14.1083 -    with fin cop have "[?x = z] (mod (PROD i:A. m i))"
 14.1084 -      by (intro coprime_cong_prod_nat, auto)
 14.1085 -    with zless less show "z = ?x"
 14.1086 -      apply (intro cong_less_modulus_unique_nat)
 14.1087 -      apply (auto, erule cong_sym_nat)
 14.1088 -      done
 14.1089 -  qed 
 14.1090 -  from less cong unique show ?thesis
 14.1091 -    by blast  
 14.1092 -qed
 14.1093 -
 14.1094 -end
    15.1 --- a/src/HOL/NewNumberTheory/Fib.thy	Tue Sep 01 14:13:34 2009 +0200
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,319 +0,0 @@
    15.4 -(*  Title:      Fib.thy
    15.5 -    Authors:    Lawrence C. Paulson, Jeremy Avigad
    15.6 -
    15.7 -
    15.8 -Defines the fibonacci function.
    15.9 -
   15.10 -The original "Fib" is due to Lawrence C. Paulson, and was adapted by
   15.11 -Jeremy Avigad.
   15.12 -*)
   15.13 -
   15.14 -
   15.15 -header {* Fib *}
   15.16 -
   15.17 -theory Fib
   15.18 -imports Binomial
   15.19 -begin
   15.20 -
   15.21 -
   15.22 -subsection {* Main definitions *}
   15.23 -
   15.24 -class fib =
   15.25 -
   15.26 -fixes 
   15.27 -  fib :: "'a \<Rightarrow> 'a"
   15.28 -
   15.29 -
   15.30 -(* definition for the natural numbers *)
   15.31 -
   15.32 -instantiation nat :: fib
   15.33 -
   15.34 -begin 
   15.35 -
   15.36 -fun 
   15.37 -  fib_nat :: "nat \<Rightarrow> nat"
   15.38 -where
   15.39 -  "fib_nat n =
   15.40 -   (if n = 0 then 0 else
   15.41 -   (if n = 1 then 1 else
   15.42 -     fib (n - 1) + fib (n - 2)))"
   15.43 -
   15.44 -instance proof qed
   15.45 -
   15.46 -end
   15.47 -
   15.48 -(* definition for the integers *)
   15.49 -
   15.50 -instantiation int :: fib
   15.51 -
   15.52 -begin 
   15.53 -
   15.54 -definition
   15.55 -  fib_int :: "int \<Rightarrow> int"
   15.56 -where  
   15.57 -  "fib_int n = (if n >= 0 then int (fib (nat n)) else 0)"
   15.58 -
   15.59 -instance proof qed
   15.60 -
   15.61 -end
   15.62 -
   15.63 -
   15.64 -subsection {* Set up Transfer *}
   15.65 -
   15.66 -
   15.67 -lemma transfer_nat_int_fib:
   15.68 -  "(x::int) >= 0 \<Longrightarrow> fib (nat x) = nat (fib x)"
   15.69 -  unfolding fib_int_def by auto
   15.70 -
   15.71 -lemma transfer_nat_int_fib_closure:
   15.72 -  "n >= (0::int) \<Longrightarrow> fib n >= 0"
   15.73 -  by (auto simp add: fib_int_def)
   15.74 -
   15.75 -declare TransferMorphism_nat_int[transfer add return: 
   15.76 -    transfer_nat_int_fib transfer_nat_int_fib_closure]
   15.77 -
   15.78 -lemma transfer_int_nat_fib:
   15.79 -  "fib (int n) = int (fib n)"
   15.80 -  unfolding fib_int_def by auto
   15.81 -
   15.82 -lemma transfer_int_nat_fib_closure:
   15.83 -  "is_nat n \<Longrightarrow> fib n >= 0"
   15.84 -  unfolding fib_int_def by auto
   15.85 -
   15.86 -declare TransferMorphism_int_nat[transfer add return: 
   15.87 -    transfer_int_nat_fib transfer_int_nat_fib_closure]
   15.88 -
   15.89 -
   15.90 -subsection {* Fibonacci numbers *}
   15.91 -
   15.92 -lemma fib_0_nat [simp]: "fib (0::nat) = 0"
   15.93 -  by simp
   15.94 -
   15.95 -lemma fib_0_int [simp]: "fib (0::int) = 0"
   15.96 -  unfolding fib_int_def by simp
   15.97 -
   15.98 -lemma fib_1_nat [simp]: "fib (1::nat) = 1"
   15.99 -  by simp
  15.100 -
  15.101 -lemma fib_Suc_0_nat [simp]: "fib (Suc 0) = Suc 0"
  15.102 -  by simp
  15.103 -
  15.104 -lemma fib_1_int [simp]: "fib (1::int) = 1"
  15.105 -  unfolding fib_int_def by simp
  15.106 -
  15.107 -lemma fib_reduce_nat: "(n::nat) >= 2 \<Longrightarrow> fib n = fib (n - 1) + fib (n - 2)"
  15.108 -  by simp
  15.109 -
  15.110 -declare fib_nat.simps [simp del]
  15.111 -
  15.112 -lemma fib_reduce_int: "(n::int) >= 2 \<Longrightarrow> fib n = fib (n - 1) + fib (n - 2)"
  15.113 -  unfolding fib_int_def
  15.114 -  by (auto simp add: fib_reduce_nat nat_diff_distrib)
  15.115 -
  15.116 -lemma fib_neg_int [simp]: "(n::int) < 0 \<Longrightarrow> fib n = 0"
  15.117 -  unfolding fib_int_def by auto
  15.118 -
  15.119 -lemma fib_2_nat [simp]: "fib (2::nat) = 1"
  15.120 -  by (subst fib_reduce_nat, auto)
  15.121 -
  15.122 -lemma fib_2_int [simp]: "fib (2::int) = 1"
  15.123 -  by (subst fib_reduce_int, auto)
  15.124 -
  15.125 -lemma fib_plus_2_nat: "fib ((n::nat) + 2) = fib (n + 1) + fib n"
  15.126 -  by (subst fib_reduce_nat, auto simp add: One_nat_def)
  15.127 -(* the need for One_nat_def is due to the natdiff_cancel_numerals
  15.128 -   procedure *)
  15.129 -
  15.130 -lemma fib_induct_nat: "P (0::nat) \<Longrightarrow> P (1::nat) \<Longrightarrow> 
  15.131 -    (!!n. P n \<Longrightarrow> P (n + 1) \<Longrightarrow> P (n + 2)) \<Longrightarrow> P n"
  15.132 -  apply (atomize, induct n rule: nat_less_induct)
  15.133 -  apply auto
  15.134 -  apply (case_tac "n = 0", force)
  15.135 -  apply (case_tac "n = 1", force)
  15.136 -  apply (subgoal_tac "n >= 2")
  15.137 -  apply (frule_tac x = "n - 1" in spec)
  15.138 -  apply (drule_tac x = "n - 2" in spec)
  15.139 -  apply (drule_tac x = "n - 2" in spec)
  15.140 -  apply auto
  15.141 -  apply (auto simp add: One_nat_def) (* again, natdiff_cancel *)
  15.142 -done
  15.143 -
  15.144 -lemma fib_add_nat: "fib ((n::nat) + k + 1) = fib (k + 1) * fib (n + 1) + 
  15.145 -    fib k * fib n"
  15.146 -  apply (induct n rule: fib_induct_nat)
  15.147 -  apply auto
  15.148 -  apply (subst fib_reduce_nat)
  15.149 -  apply (auto simp add: ring_simps)
  15.150 -  apply (subst (1 3 5) fib_reduce_nat)
  15.151 -  apply (auto simp add: ring_simps Suc_eq_plus1)
  15.152 -(* hmmm. Why doesn't "n + (1 + (1 + k))" simplify to "n + k + 2"? *)
  15.153 -  apply (subgoal_tac "n + (k + 2) = n + (1 + (1 + k))")
  15.154 -  apply (erule ssubst) back back
  15.155 -  apply (erule ssubst) back 
  15.156 -  apply auto
  15.157 -done
  15.158 -
  15.159 -lemma fib_add'_nat: "fib (n + Suc k) = fib (Suc k) * fib (Suc n) + 
  15.160 -    fib k * fib n"
  15.161 -  using fib_add_nat by (auto simp add: One_nat_def)
  15.162 -
  15.163 -
  15.164 -(* transfer from nats to ints *)
  15.165 -lemma fib_add_int [rule_format]: "(n::int) >= 0 \<Longrightarrow> k >= 0 \<Longrightarrow>
  15.166 -    fib (n + k + 1) = fib (k + 1) * fib (n + 1) + 
  15.167 -    fib k * fib n "
  15.168 -
  15.169 -  by (rule fib_add_nat [transferred])
  15.170 -
  15.171 -lemma fib_neq_0_nat: "(n::nat) > 0 \<Longrightarrow> fib n ~= 0"
  15.172 -  apply (induct n rule: fib_induct_nat)
  15.173 -  apply (auto simp add: fib_plus_2_nat)
  15.174 -done
  15.175 -
  15.176 -lemma fib_gr_0_nat: "(n::nat) > 0 \<Longrightarrow> fib n > 0"
  15.177 -  by (frule fib_neq_0_nat, simp)
  15.178 -
  15.179 -lemma fib_gr_0_int: "(n::int) > 0 \<Longrightarrow> fib n > 0"
  15.180 -  unfolding fib_int_def by (simp add: fib_gr_0_nat)
  15.181 -
  15.182 -text {*
  15.183 -  \medskip Concrete Mathematics, page 278: Cassini's identity.  The proof is
  15.184 -  much easier using integers, not natural numbers!
  15.185 -*}
  15.186 -
  15.187 -lemma fib_Cassini_aux_int: "fib (int n + 2) * fib (int n) - 
  15.188 -    (fib (int n + 1))^2 = (-1)^(n + 1)"
  15.189 -  apply (induct n)
  15.190 -  apply (auto simp add: ring_simps power2_eq_square fib_reduce_int
  15.191 -      power_add)
  15.192 -done
  15.193 -
  15.194 -lemma fib_Cassini_int: "n >= 0 \<Longrightarrow> fib (n + 2) * fib n - 
  15.195 -    (fib (n + 1))^2 = (-1)^(nat n + 1)"
  15.196 -  by (insert fib_Cassini_aux_int [of "nat n"], auto)
  15.197 -
  15.198 -(*
  15.199 -lemma fib_Cassini'_int: "n >= 0 \<Longrightarrow> fib (n + 2) * fib n = 
  15.200 -    (fib (n + 1))^2 + (-1)^(nat n + 1)"
  15.201 -  by (frule fib_Cassini_int, simp) 
  15.202 -*)
  15.203 -
  15.204 -lemma fib_Cassini'_int: "n >= 0 \<Longrightarrow> fib ((n::int) + 2) * fib n =
  15.205 -  (if even n then tsub ((fib (n + 1))^2) 1
  15.206 -   else (fib (n + 1))^2 + 1)"
  15.207 -  apply (frule fib_Cassini_int, auto simp add: pos_int_even_equiv_nat_even)
  15.208 -  apply (subst tsub_eq)
  15.209 -  apply (insert fib_gr_0_int [of "n + 1"], force)
  15.210 -  apply auto
  15.211 -done
  15.212 -
  15.213 -lemma fib_Cassini_nat: "fib ((n::nat) + 2) * fib n =
  15.214 -  (if even n then (fib (n + 1))^2 - 1
  15.215 -   else (fib (n + 1))^2 + 1)"
  15.216 -
  15.217 -  by (rule fib_Cassini'_int [transferred, of n], auto)
  15.218 -
  15.219 -
  15.220 -text {* \medskip Toward Law 6.111 of Concrete Mathematics *}
  15.221 -
  15.222 -lemma coprime_fib_plus_1_nat: "coprime (fib (n::nat)) (fib (n + 1))"
  15.223 -  apply (induct n rule: fib_induct_nat)
  15.224 -  apply auto
  15.225 -  apply (subst (2) fib_reduce_nat)
  15.226 -  apply (auto simp add: Suc_eq_plus1) (* again, natdiff_cancel *)
  15.227 -  apply (subst add_commute, auto)
  15.228 -  apply (subst gcd_commute_nat, auto simp add: ring_simps)
  15.229 -done
  15.230 -
  15.231 -lemma coprime_fib_Suc_nat: "coprime (fib n) (fib (Suc n))"
  15.232 -  using coprime_fib_plus_1_nat by (simp add: One_nat_def)
  15.233 -
  15.234 -lemma coprime_fib_plus_1_int: 
  15.235 -    "n >= 0 \<Longrightarrow> coprime (fib (n::int)) (fib (n + 1))"
  15.236 -  by (erule coprime_fib_plus_1_nat [transferred])
  15.237 -
  15.238 -lemma gcd_fib_add_nat: "gcd (fib (m::nat)) (fib (n + m)) = gcd (fib m) (fib n)"
  15.239 -  apply (simp add: gcd_commute_nat [of "fib m"])
  15.240 -  apply (rule cases_nat [of _ m])
  15.241 -  apply simp
  15.242 -  apply (subst add_assoc [symmetric])
  15.243 -  apply (simp add: fib_add_nat)
  15.244 -  apply (subst gcd_commute_nat)
  15.245 -  apply (subst mult_commute)
  15.246 -  apply (subst gcd_add_mult_nat)
  15.247 -  apply (subst gcd_commute_nat)
  15.248 -  apply (rule gcd_mult_cancel_nat)
  15.249 -  apply (rule coprime_fib_plus_1_nat)
  15.250 -done
  15.251 -
  15.252 -lemma gcd_fib_add_int [rule_format]: "m >= 0 \<Longrightarrow> n >= 0 \<Longrightarrow> 
  15.253 -    gcd (fib (m::int)) (fib (n + m)) = gcd (fib m) (fib n)"
  15.254 -  by (erule gcd_fib_add_nat [transferred])
  15.255 -
  15.256 -lemma gcd_fib_diff_nat: "(m::nat) \<le> n \<Longrightarrow> 
  15.257 -    gcd (fib m) (fib (n - m)) = gcd (fib m) (fib n)"
  15.258 -  by (simp add: gcd_fib_add_nat [symmetric, of _ "n-m"])
  15.259 -
  15.260 -lemma gcd_fib_diff_int: "0 <= (m::int) \<Longrightarrow> m \<le> n \<Longrightarrow> 
  15.261 -    gcd (fib m) (fib (n - m)) = gcd (fib m) (fib n)"
  15.262 -  by (simp add: gcd_fib_add_int [symmetric, of _ "n-m"])
  15.263 -
  15.264 -lemma gcd_fib_mod_nat: "0 < (m::nat) \<Longrightarrow> 
  15.265 -    gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib n)"
  15.266 -proof (induct n rule: less_induct)
  15.267 -  case (less n)
  15.268 -  from less.prems have pos_m: "0 < m" .
  15.269 -  show "gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib n)"
  15.270 -  proof (cases "m < n")
  15.271 -    case True note m_n = True
  15.272 -    then have m_n': "m \<le> n" by auto
  15.273 -    with pos_m have pos_n: "0 < n" by auto
  15.274 -    with pos_m m_n have diff: "n - m < n" by auto
  15.275 -    have "gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib ((n - m) mod m))"
  15.276 -    by (simp add: mod_if [of n]) (insert m_n, auto)
  15.277 -    also have "\<dots> = gcd (fib m)  (fib (n - m))" 
  15.278 -      by (simp add: less.hyps diff pos_m)
  15.279 -    also have "\<dots> = gcd (fib m) (fib n)" by (simp add: gcd_fib_diff_nat m_n')
  15.280 -    finally show "gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib n)" .
  15.281 -  next
  15.282 -    case False then show "gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib n)"
  15.283 -    by (cases "m = n") auto
  15.284 -  qed
  15.285 -qed
  15.286 -
  15.287 -lemma gcd_fib_mod_int: 
  15.288 -  assumes "0 < (m::int)" and "0 <= n"
  15.289 -  shows "gcd (fib m) (fib (n mod m)) = gcd (fib m) (fib n)"
  15.290 -
  15.291 -  apply (rule gcd_fib_mod_nat [transferred])
  15.292 -  using prems apply auto
  15.293 -done
  15.294 -
  15.295 -lemma fib_gcd_nat: "fib (gcd (m::nat) n) = gcd (fib m) (fib n)"  
  15.296 -    -- {* Law 6.111 *}
  15.297 -  apply (induct m n rule: gcd_nat_induct)
  15.298 -  apply (simp_all add: gcd_non_0_nat gcd_commute_nat gcd_fib_mod_nat)
  15.299 -done
  15.300 -
  15.301 -lemma fib_gcd_int: "m >= 0 \<Longrightarrow> n >= 0 \<Longrightarrow>
  15.302 -    fib (gcd (m::int) n) = gcd (fib m) (fib n)"
  15.303 -  by (erule fib_gcd_nat [transferred])
  15.304 -
  15.305 -lemma atMost_plus_one_nat: "{..(k::nat) + 1} = insert (k + 1) {..k}" 
  15.306 -  by auto
  15.307 -
  15.308 -theorem fib_mult_eq_setsum_nat:
  15.309 -    "fib ((n::nat) + 1) * fib n = (\<Sum>k \<in> {..n}. fib k * fib k)"
  15.310 -  apply (induct n)
  15.311 -  apply (auto simp add: atMost_plus_one_nat fib_plus_2_nat ring_simps)
  15.312 -done
  15.313 -
  15.314 -theorem fib_mult_eq_setsum'_nat:
  15.315 -    "fib (Suc n) * fib n = (\<Sum>k \<in> {..n}. fib k * fib k)"
  15.316 -  using fib_mult_eq_setsum_nat by (simp add: One_nat_def)
  15.317 -
  15.318 -theorem fib_mult_eq_setsum_int [rule_format]:
  15.319 -    "n >= 0 \<Longrightarrow> fib ((n::int) + 1) * fib n = (\<Sum>k \<in> {0..n}. fib k * fib k)"
  15.320 -  by (erule fib_mult_eq_setsum_nat [transferred])
  15.321 -
  15.322 -end
    16.1 --- a/src/HOL/NewNumberTheory/MiscAlgebra.thy	Tue Sep 01 14:13:34 2009 +0200
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,355 +0,0 @@
    16.4 -(*  Title:      MiscAlgebra.thy
    16.5 -    Author:     Jeremy Avigad
    16.6 -
    16.7 -These are things that can be added to the Algebra library.
    16.8 -*)
    16.9 -
   16.10 -theory MiscAlgebra
   16.11 -imports
   16.12 -  "~~/src/HOL/Algebra/Ring"
   16.13 -  "~~/src/HOL/Algebra/FiniteProduct"
   16.14 -begin;
   16.15 -
   16.16 -(* finiteness stuff *)
   16.17 -
   16.18 -lemma bounded_set1_int [intro]: "finite {(x::int). a < x & x < b & P x}" 
   16.19 -  apply (subgoal_tac "{x. a < x & x < b & P x} <= {a<..<b}")
   16.20 -  apply (erule finite_subset)
   16.21 -  apply auto
   16.22 -done
   16.23 -
   16.24 -
   16.25 -(* The rest is for the algebra libraries *)
   16.26 -
   16.27 -(* These go in Group.thy. *)
   16.28 -
   16.29 -(*
   16.30 -  Show that the units in any monoid give rise to a group.
   16.31 -
   16.32 -  The file Residues.thy provides some infrastructure to use
   16.33 -  facts about the unit group within the ring locale.
   16.34 -*)
   16.35 -
   16.36 -
   16.37 -constdefs 
   16.38 -  units_of :: "('a, 'b) monoid_scheme => 'a monoid"
   16.39 -  "units_of G == (| carrier = Units G,
   16.40 -     Group.monoid.mult = Group.monoid.mult G,
   16.41 -     one  = one G |)";
   16.42 -
   16.43 -(*
   16.44 -
   16.45 -lemma (in monoid) Units_mult_closed [intro]:
   16.46 -  "x : Units G ==> y : Units G ==> x \<otimes> y : Units G"
   16.47 -  apply (unfold Units_def)
   16.48 -  apply (clarsimp)
   16.49 -  apply (rule_tac x = "xaa \<otimes> xa" in bexI)
   16.50 -  apply auto
   16.51 -  apply (subst m_assoc)
   16.52 -  apply auto
   16.53 -  apply (subst (2) m_assoc [symmetric])
   16.54 -  apply auto
   16.55 -  apply (subst m_assoc)
   16.56 -  apply auto
   16.57 -  apply (subst (2) m_assoc [symmetric])
   16.58 -  apply auto
   16.59 -done
   16.60 -
   16.61 -*)
   16.62 -
   16.63 -lemma (in monoid) units_group: "group(units_of G)"
   16.64 -  apply (unfold units_of_def)
   16.65 -  apply (rule groupI)
   16.66 -  apply auto
   16.67 -  apply (subst m_assoc)
   16.68 -  apply auto
   16.69 -  apply (rule_tac x = "inv x" in bexI)
   16.70 -  apply auto
   16.71 -done
   16.72 -
   16.73 -lemma (in comm_monoid) units_comm_group: "comm_group(units_of G)"
   16.74 -  apply (rule group.group_comm_groupI)
   16.75 -  apply (rule units_group)
   16.76 -  apply (insert prems)
   16.77 -  apply (unfold units_of_def Units_def comm_monoid_def comm_monoid_axioms_def)
   16.78 -  apply auto;
   16.79 -done;
   16.80 -
   16.81 -lemma units_of_carrier: "carrier (units_of G) = Units G"
   16.82 -  by (unfold units_of_def, auto)
   16.83 -
   16.84 -lemma units_of_mult: "mult(units_of G) = mult G"
   16.85 -  by (unfold units_of_def, auto)
   16.86 -
   16.87 -lemma units_of_one: "one(units_of G) = one G"
   16.88 -  by (unfold units_of_def, auto)
   16.89 -
   16.90 -lemma (in monoid) units_of_inv: "x : Units G ==> 
   16.91 -    m_inv (units_of G) x = m_inv G x"
   16.92 -  apply (rule sym)
   16.93 -  apply (subst m_inv_def)
   16.94 -  apply (rule the1_equality)
   16.95 -  apply (rule ex_ex1I)
   16.96 -  apply (subst (asm) Units_def)
   16.97 -  apply auto
   16.98 -  apply (erule inv_unique)
   16.99 -  apply auto
  16.100 -  apply (rule Units_closed)
  16.101 -  apply (simp_all only: units_of_carrier [symmetric])
  16.102 -  apply (insert units_group)
  16.103 -  apply auto
  16.104 -  apply (subst units_of_mult [symmetric])
  16.105 -  apply (subst units_of_one [symmetric])
  16.106 -  apply (erule group.r_inv, assumption)
  16.107 -  apply (subst units_of_mult [symmetric])
  16.108 -  apply (subst units_of_one [symmetric])
  16.109 -  apply (erule group.l_inv, assumption)
  16.110 -done
  16.111 -
  16.112 -lemma (in group) inj_on_const_mult: "a: (carrier G) ==> 
  16.113 -    inj_on (%x. a \<otimes> x) (carrier G)"
  16.114 -  by (unfold inj_on_def, auto)
  16.115 -
  16.116 -lemma (in group) surj_const_mult: "a : (carrier G) ==>
  16.117 -    (%x. a \<otimes> x) ` (carrier G) = (carrier G)" 
  16.118 -  apply (auto simp add: image_def)
  16.119 -  apply (rule_tac x = "(m_inv G a) \<otimes> x" in bexI)
  16.120 -  apply auto
  16.121 -(* auto should get this. I suppose we need "comm_monoid_simprules"
  16.122 -   for mult_ac rewriting. *)
  16.123 -  apply (subst m_assoc [symmetric])
  16.124 -  apply auto
  16.125 -done
  16.126 -
  16.127 -lemma (in group) l_cancel_one [simp]: "x : carrier G \<Longrightarrow> a : carrier G \<Longrightarrow>
  16.128 -    (x \<otimes> a = x) = (a = one G)"
  16.129 -  apply auto
  16.130 -  apply (subst l_cancel [symmetric])
  16.131 -  prefer 4
  16.132 -  apply (erule ssubst)
  16.133 -  apply auto
  16.134 -done
  16.135 -
  16.136 -lemma (in group) r_cancel_one [simp]: "x : carrier G \<Longrightarrow> a : carrier G \<Longrightarrow>
  16.137 -    (a \<otimes> x = x) = (a = one G)"
  16.138 -  apply auto
  16.139 -  apply (subst r_cancel [symmetric])
  16.140 -  prefer 4
  16.141 -  apply (erule ssubst)
  16.142 -  apply auto
  16.143 -done
  16.144 -
  16.145 -(* Is there a better way to do this? *)
  16.146 -
  16.147 -lemma (in group) l_cancel_one' [simp]: "x : carrier G \<Longrightarrow> a : carrier G \<Longrightarrow>
  16.148 -    (x = x \<otimes> a) = (a = one G)"
  16.149 -  by (subst eq_commute, simp)
  16.150 -
  16.151 -lemma (in group) r_cancel_one' [simp]: "x : carrier G \<Longrightarrow> a : carrier G \<Longrightarrow>
  16.152 -    (x = a \<otimes> x) = (a = one G)"
  16.153 -  by (subst eq_commute, simp)
  16.154 -
  16.155 -(* This should be generalized to arbitrary groups, not just commutative
  16.156 -   ones, using Lagrange's theorem. *)
  16.157 -
  16.158 -lemma (in comm_group) power_order_eq_one:
  16.159 -    assumes fin [simp]: "finite (carrier G)"
  16.160 -        and a [simp]: "a : carrier G" 
  16.161 -      shows "a (^) card(carrier G) = one G" 
  16.162 -proof -
  16.163 -  have "(\<Otimes>x:carrier G. x) = (\<Otimes>x:carrier G. a \<otimes> x)"
  16.164 -    by (subst (2) finprod_reindex [symmetric], 
  16.165 -      auto simp add: Pi_def inj_on_const_mult surj_const_mult)
  16.166 -  also have "\<dots> = (\<Otimes>x:carrier G. a) \<otimes> (\<Otimes>x:carrier G. x)"
  16.167 -    by (auto simp add: finprod_multf Pi_def)
  16.168 -  also have "(\<Otimes>x:carrier G. a) = a (^) card(carrier G)"
  16.169 -    by (auto simp add: finprod_const)
  16.170 -  finally show ?thesis
  16.171 -(* uses the preceeding lemma *)
  16.172 -    by auto
  16.173 -qed
  16.174 -
  16.175 -
  16.176 -(* Miscellaneous *)
  16.177 -
  16.178 -lemma (in cring) field_intro2: "\<zero>\<^bsub>R\<^esub> ~= \<one>\<^bsub>R\<^esub> \<Longrightarrow> ALL x : carrier R - {\<zero>\<^bsub>R\<^esub>}.
  16.179 -    x : Units R \<Longrightarrow> field R"
  16.180 -  apply (unfold_locales)
  16.181 -  apply (insert prems, auto)
  16.182 -  apply (rule trans)
  16.183 -  apply (subgoal_tac "a = (a \<otimes> b) \<otimes> inv b")
  16.184 -  apply assumption
  16.185 -  apply (subst m_assoc) 
  16.186 -  apply (auto simp add: Units_r_inv)
  16.187 -  apply (unfold Units_def)
  16.188 -  apply auto
  16.189 -done
  16.190 -
  16.191 -lemma (in monoid) inv_char: "x : carrier G \<Longrightarrow> y : carrier G \<Longrightarrow>
  16.192 -  x \<otimes> y = \<one> \<Longrightarrow> y \<otimes> x = \<one> \<Longrightarrow> inv x = y"
  16.193 -  apply (subgoal_tac "x : Units G")
  16.194 -  apply (subgoal_tac "y = inv x \<otimes> \<one>")
  16.195 -  apply simp
  16.196 -  apply (erule subst)
  16.197 -  apply (subst m_assoc [symmetric])
  16.198 -  apply auto
  16.199 -  apply (unfold Units_def)
  16.200 -  apply auto
  16.201 -done
  16.202 -
  16.203 -lemma (in comm_monoid) comm_inv_char: "x : carrier G \<Longrightarrow> y : carrier G \<Longrightarrow>
  16.204 -  x \<otimes> y = \<one> \<Longrightarrow> inv x = y"
  16.205 -  apply (rule inv_char)
  16.206 -  apply auto
  16.207 -  apply (subst m_comm, auto) 
  16.208 -done
  16.209 -
  16.210 -lemma (in ring) inv_neg_one [simp]: "inv (\<ominus> \<one>) = \<ominus> \<one>"  
  16.211 -  apply (rule inv_char)
  16.212 -  apply (auto simp add: l_minus r_minus)
  16.213 -done
  16.214 -
  16.215 -lemma (in monoid) inv_eq_imp_eq: "x : Units G \<Longrightarrow> y : Units G \<Longrightarrow> 
  16.216 -    inv x = inv y \<Longrightarrow> x = y"
  16.217 -  apply (subgoal_tac "inv(inv x) = inv(inv y)")
  16.218 -  apply (subst (asm) Units_inv_inv)+
  16.219 -  apply auto
  16.220 -done
  16.221 -
  16.222 -lemma (in ring) Units_minus_one_closed [intro]: "\<ominus> \<one> : Units R"
  16.223 -  apply (unfold Units_def)
  16.224 -  apply auto
  16.225 -  apply (rule_tac x = "\<ominus> \<one>" in bexI)
  16.226 -  apply auto
  16.227 -  apply (simp add: l_minus r_minus)
  16.228 -done
  16.229 -
  16.230 -lemma (in monoid) inv_one [simp]: "inv \<one> = \<one>"
  16.231 -  apply (rule inv_char)
  16.232 -  apply auto
  16.233 -done
  16.234 -
  16.235 -lemma (in ring) inv_eq_neg_one_eq: "x : Units R \<Longrightarrow> (inv x = \<ominus> \<one>) = (x = \<ominus> \<one>)"
  16.236 -  apply auto
  16.237 -  apply (subst Units_inv_inv [symmetric])
  16.238 -  apply auto
  16.239 -done
  16.240 -
  16.241 -lemma (in monoid) inv_eq_one_eq: "x : Units G \<Longrightarrow> (inv x = \<one>) = (x = \<one>)"
  16.242 -  apply auto
  16.243 -  apply (subst Units_inv_inv [symmetric])
  16.244 -  apply auto
  16.245 -done
  16.246 -
  16.247 -
  16.248 -(* This goes in FiniteProduct *)
  16.249 -
  16.250 -lemma (in comm_monoid) finprod_UN_disjoint:
  16.251 -  "finite I \<Longrightarrow> (ALL i:I. finite (A i)) \<longrightarrow> (ALL i:I. ALL j:I. i ~= j \<longrightarrow>
  16.252 -     (A i) Int (A j) = {}) \<longrightarrow>
  16.253 -      (ALL i:I. ALL x: (A i). g x : carrier G) \<longrightarrow>
  16.254 -        finprod G g (UNION I A) = finprod G (%i. finprod G g (A i)) I"
  16.255 -  apply (induct set: finite)
  16.256 -  apply force
  16.257 -  apply clarsimp
  16.258 -  apply (subst finprod_Un_disjoint)
  16.259 -  apply blast
  16.260 -  apply (erule finite_UN_I)
  16.261 -  apply blast
  16.262 -  apply (fastsimp)
  16.263 -  apply (auto intro!: funcsetI finprod_closed) 
  16.264 -done
  16.265 -
  16.266 -lemma (in comm_monoid) finprod_Union_disjoint:
  16.267 -  "[| finite C; (ALL A:C. finite A & (ALL x:A. f x : carrier G));
  16.268 -      (ALL A:C. ALL B:C. A ~= B --> A Int B = {}) |] 
  16.269 -   ==> finprod G f (Union C) = finprod G (finprod G f) C" 
  16.270 -  apply (frule finprod_UN_disjoint [of C id f])
  16.271 -  apply (unfold Union_def id_def, auto)
  16.272 -done
  16.273 -
  16.274 -lemma (in comm_monoid) finprod_one [rule_format]: 
  16.275 -  "finite A \<Longrightarrow> (ALL x:A. f x = \<one>) \<longrightarrow>
  16.276 -     finprod G f A = \<one>"
  16.277 -by (induct set: finite) auto
  16.278 -
  16.279 -
  16.280 -(* need better simplification rules for rings *)
  16.281 -(* the next one holds more generally for abelian groups *)
  16.282 -
  16.283 -lemma (in cring) sum_zero_eq_neg:
  16.284 -  "x : carrier R \<Longrightarrow> y : carrier R \<Longrightarrow> x \<oplus> y = \<zero> \<Longrightarrow> x = \<ominus> y"
  16.285 -  apply (subgoal_tac "\<ominus> y = \<zero> \<oplus> \<ominus> y") 
  16.286 -  apply (erule ssubst)back
  16.287 -  apply (erule subst)
  16.288 -  apply (simp add: ring_simprules)+
  16.289 -done
  16.290 -
  16.291 -(* there's a name conflict -- maybe "domain" should be
  16.292 -   "integral_domain" *)
  16.293 -
  16.294 -lemma (in Ring.domain) square_eq_one: 
  16.295 -  fixes x
  16.296 -  assumes [simp]: "x : carrier R" and
  16.297 -    "x \<otimes> x = \<one>"
  16.298 -  shows "x = \<one> | x = \<ominus>\<one>"
  16.299 -proof -
  16.300 -  have "(x \<oplus> \<one>) \<otimes> (x \<oplus> \<ominus> \<one>) = x \<otimes> x \<oplus> \<ominus> \<one>"
  16.301 -    by (simp add: ring_simprules)
  16.302 -  also with `x \<otimes> x = \<one>` have "\<dots> = \<zero>"
  16.303 -    by (simp add: ring_simprules)
  16.304 -  finally have "(x \<oplus> \<one>) \<otimes> (x \<oplus> \<ominus> \<one>) = \<zero>" .
  16.305 -  hence "(x \<oplus> \<one>) = \<zero> | (x \<oplus> \<ominus> \<one>) = \<zero>"
  16.306 -    by (intro integral, auto)
  16.307 -  thus ?thesis
  16.308 -    apply auto
  16.309 -    apply (erule notE)
  16.310 -    apply (rule sum_zero_eq_neg)
  16.311 -    apply auto
  16.312 -    apply (subgoal_tac "x = \<ominus> (\<ominus> \<one>)")
  16.313 -    apply (simp add: ring_simprules) 
  16.314 -    apply (rule sum_zero_eq_neg)
  16.315 -    apply auto
  16.316 -    done
  16.317 -qed
  16.318 -
  16.319 -lemma (in Ring.domain) inv_eq_self: "x : Units R \<Longrightarrow>
  16.320 -    x = inv x \<Longrightarrow> x = \<one> | x = \<ominus> \<one>"
  16.321 -  apply (rule square_eq_one)
  16.322 -  apply auto
  16.323 -  apply (erule ssubst)back
  16.324 -  apply (erule Units_r_inv)
  16.325 -done
  16.326 -
  16.327 -
  16.328 -(*
  16.329 -  The following translates theorems about groups to the facts about
  16.330 -  the units of a ring. (The list should be expanded as more things are
  16.331 -  needed.)
  16.332 -*)
  16.333 -
  16.334 -lemma (in ring) finite_ring_finite_units [intro]: "finite (carrier R) \<Longrightarrow> 
  16.335 -    finite (Units R)"
  16.336 -  by (rule finite_subset, auto)
  16.337 -
  16.338 -(* this belongs with MiscAlgebra.thy *)
  16.339 -lemma (in monoid) units_of_pow: 
  16.340 -    "x : Units G \<Longrightarrow> x (^)\<^bsub>units_of G\<^esub> (n::nat) = x (^)\<^bsub>G\<^esub> n"
  16.341 -  apply (induct n)
  16.342 -  apply (auto simp add: units_group group.is_monoid  
  16.343 -    monoid.nat_pow_0 monoid.nat_pow_Suc units_of_one units_of_mult
  16.344 -    One_nat_def)
  16.345 -done
  16.346 -
  16.347 -lemma (in cring) units_power_order_eq_one: "finite (Units R) \<Longrightarrow> a : Units R
  16.348 -    \<Longrightarrow> a (^) card(Units R) = \<one>"
  16.349 -  apply (subst units_of_carrier [symmetric])
  16.350 -  apply (subst units_of_one [symmetric])
  16.351 -  apply (subst units_of_pow [symmetric])
  16.352 -  apply assumption
  16.353 -  apply (rule comm_group.power_order_eq_one)
  16.354 -  apply (rule units_comm_group)
  16.355 -  apply (unfold units_of_def, auto)
  16.356 -done
  16.357 -
  16.358 -end
    17.1 --- a/src/HOL/NewNumberTheory/ROOT.ML	Tue Sep 01 14:13:34 2009 +0200
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,1 +0,0 @@
    17.4 -use_thys ["Fib","Residues"];
    18.1 --- a/src/HOL/NewNumberTheory/Residues.thy	Tue Sep 01 14:13:34 2009 +0200
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,466 +0,0 @@
    18.4 -(*  Title:      HOL/Library/Residues.thy
    18.5 -    ID:         
    18.6 -    Author:     Jeremy Avigad
    18.7 -
    18.8 -    An algebraic treatment of residue rings, and resulting proofs of
    18.9 -    Euler's theorem and Wilson's theorem. 
   18.10 -*)
   18.11 -
   18.12 -header {* Residue rings *}
   18.13 -
   18.14 -theory Residues
   18.15 -imports
   18.16 -   UniqueFactorization
   18.17 -   Binomial
   18.18 -   MiscAlgebra
   18.19 -begin
   18.20 -
   18.21 -
   18.22 -(*
   18.23 - 
   18.24 -  A locale for residue rings
   18.25 -
   18.26 -*)
   18.27 -
   18.28 -constdefs 
   18.29 -  residue_ring :: "int => int ring"
   18.30 -  "residue_ring m == (| 
   18.31 -    carrier =       {0..m - 1}, 
   18.32 -    mult =          (%x y. (x * y) mod m),
   18.33 -    one =           1,
   18.34 -    zero =          0,
   18.35 -    add =           (%x y. (x + y) mod m) |)"
   18.36 -
   18.37 -locale residues =
   18.38 -  fixes m :: int and R (structure)
   18.39 -  assumes m_gt_one: "m > 1"
   18.40 -  defines "R == residue_ring m"
   18.41 -
   18.42 -context residues begin
   18.43 -
   18.44 -lemma abelian_group: "abelian_group R"
   18.45 -  apply (insert m_gt_one)
   18.46 -  apply (rule abelian_groupI)
   18.47 -  apply (unfold R_def residue_ring_def)
   18.48 -  apply (auto simp add: mod_pos_pos_trivial mod_add_right_eq [symmetric]
   18.49 -    add_ac)
   18.50 -  apply (case_tac "x = 0")
   18.51 -  apply force
   18.52 -  apply (subgoal_tac "(x + (m - x)) mod m = 0")
   18.53 -  apply (erule bexI)
   18.54 -  apply auto
   18.55 -done
   18.56 -
   18.57 -lemma comm_monoid: "comm_monoid R"
   18.58 -  apply (insert m_gt_one)
   18.59 -  apply (unfold R_def residue_ring_def)
   18.60 -  apply (rule comm_monoidI)
   18.61 -  apply auto
   18.62 -  apply (subgoal_tac "x * y mod m * z mod m = z * (x * y mod m) mod m")
   18.63 -  apply (erule ssubst)
   18.64 -  apply (subst zmod_zmult1_eq [symmetric])+
   18.65 -  apply (simp_all only: mult_ac)
   18.66 -done
   18.67 -
   18.68 -lemma cring: "cring R"
   18.69 -  apply (rule cringI)
   18.70 -  apply (rule abelian_group)
   18.71 -  apply (rule comm_monoid)
   18.72 -  apply (unfold R_def residue_ring_def, auto)
   18.73 -  apply (subst mod_add_eq [symmetric])
   18.74 -  apply (subst mult_commute)
   18.75 -  apply (subst zmod_zmult1_eq [symmetric])
   18.76 -  apply (simp add: ring_simps)
   18.77 -done
   18.78 -
   18.79 -end
   18.80 -
   18.81 -sublocale residues < cring
   18.82 -  by (rule cring)
   18.83 -
   18.84 -
   18.85 -context residues begin
   18.86 -
   18.87 -(* These lemmas translate back and forth between internal and 
   18.88 -   external concepts *)
   18.89 -
   18.90 -lemma res_carrier_eq: "carrier R = {0..m - 1}"
   18.91 -  by (unfold R_def residue_ring_def, auto)
   18.92 -
   18.93 -lemma res_add_eq: "x \<oplus> y = (x + y) mod m"
   18.94 -  by (unfold R_def residue_ring_def, auto)
   18.95 -
   18.96 -lemma res_mult_eq: "x \<otimes> y = (x * y) mod m"
   18.97 -  by (unfold R_def residue_ring_def, auto)
   18.98 -
   18.99 -lemma res_zero_eq: "\<zero> = 0"
  18.100 -  by (unfold R_def residue_ring_def, auto)
  18.101 -
  18.102 -lemma res_one_eq: "\<one> = 1"
  18.103 -  by (unfold R_def residue_ring_def units_of_def residue_ring_def, auto)
  18.104 -
  18.105 -lemma res_units_eq: "Units R = { x. 0 < x & x < m & coprime x m}"
  18.106 -  apply (insert m_gt_one)
  18.107 -  apply (unfold Units_def R_def residue_ring_def)
  18.108 -  apply auto
  18.109 -  apply (subgoal_tac "x ~= 0")
  18.110 -  apply auto
  18.111 -  apply (rule invertible_coprime_int)
  18.112 -  apply (subgoal_tac "x ~= 0")
  18.113 -  apply auto
  18.114 -  apply (subst (asm) coprime_iff_invertible'_int)
  18.115 -  apply (rule m_gt_one)
  18.116 -  apply (auto simp add: cong_int_def mult_commute)
  18.117 -done
  18.118 -
  18.119 -lemma res_neg_eq: "\<ominus> x = (- x) mod m"
  18.120 -  apply (insert m_gt_one)
  18.121 -  apply (unfold R_def a_inv_def m_inv_def residue_ring_def)
  18.122 -  apply auto
  18.123 -  apply (rule the_equality)
  18.124 -  apply auto
  18.125 -  apply (subst mod_add_right_eq [symmetric])
  18.126 -  apply auto
  18.127 -  apply (subst mod_add_left_eq [symmetric])
  18.128 -  apply auto
  18.129 -  apply (subgoal_tac "y mod m = - x mod m")
  18.130 -  apply simp
  18.131 -  apply (subst zmod_eq_dvd_iff)
  18.132 -  apply auto
  18.133 -done
  18.134 -
  18.135 -lemma finite [iff]: "finite(carrier R)"
  18.136 -  by (subst res_carrier_eq, auto)
  18.137 -
  18.138 -lemma finite_Units [iff]: "finite(Units R)"
  18.139 -  by (subst res_units_eq, auto)
  18.140 -
  18.141 -(* The function a -> a mod m maps the integers to the 
  18.142 -   residue classes. The following lemmas show that this mapping 
  18.143 -   respects addition and multiplication on the integers. *)
  18.144 -
  18.145 -lemma mod_in_carrier [iff]: "a mod m : carrier R"
  18.146 -  apply (unfold res_carrier_eq)
  18.147 -  apply (insert m_gt_one, auto)
  18.148 -done
  18.149 -
  18.150 -lemma add_cong: "(x mod m) \<oplus> (y mod m) = (x + y) mod m"
  18.151 -  by (unfold R_def residue_ring_def, auto, arith)
  18.152 -
  18.153 -lemma mult_cong: "(x mod m) \<otimes> (y mod m) = (x * y) mod m"
  18.154 -  apply (unfold R_def residue_ring_def, auto)
  18.155 -  apply (subst zmod_zmult1_eq [symmetric])
  18.156 -  apply (subst mult_commute)
  18.157 -  apply (subst zmod_zmult1_eq [symmetric])
  18.158 -  apply (subst mult_commute)
  18.159 -  apply auto
  18.160 -done  
  18.161 -
  18.162 -lemma zero_cong: "\<zero> = 0"
  18.163 -  apply (unfold R_def residue_ring_def, auto)
  18.164 -done
  18.165 -
  18.166 -lemma one_cong: "\<one> = 1 mod m"
  18.167 -  apply (insert m_gt_one)
  18.168 -  apply (unfold R_def residue_ring_def, auto)
  18.169 -done
  18.170 -
  18.171 -(* revise algebra library to use 1? *)
  18.172 -lemma pow_cong: "(x mod m) (^) n = x^n mod m"
  18.173 -  apply (insert m_gt_one)
  18.174 -  apply (induct n)
  18.175 -  apply (auto simp add: nat_pow_def one_cong One_nat_def)
  18.176 -  apply (subst mult_commute)
  18.177 -  apply (rule mult_cong)
  18.178 -done
  18.179 -
  18.180 -lemma neg_cong: "\<ominus> (x mod m) = (- x) mod m"
  18.181 -  apply (rule sym)
  18.182 -  apply (rule sum_zero_eq_neg)
  18.183 -  apply auto
  18.184 -  apply (subst add_cong)
  18.185 -  apply (subst zero_cong)
  18.186 -  apply auto
  18.187 -done
  18.188 -
  18.189 -lemma (in residues) prod_cong: 
  18.190 -  "finite A \<Longrightarrow> (\<Otimes> i:A. (f i) mod m) = (PROD i:A. f i) mod m"
  18.191 -  apply (induct set: finite)
  18.192 -  apply (auto simp: one_cong mult_cong)
  18.193 -done
  18.194 -
  18.195 -lemma (in residues) sum_cong:
  18.196 -  "finite A \<Longrightarrow> (\<Oplus> i:A. (f i) mod m) = (SUM i: A. f i) mod m"
  18.197 -  apply (induct set: finite)
  18.198 -  apply (auto simp: zero_cong add_cong)
  18.199 -done
  18.200 -
  18.201 -lemma mod_in_res_units [simp]: "1 < m \<Longrightarrow> coprime a m \<Longrightarrow> 
  18.202 -    a mod m : Units R"
  18.203 -  apply (subst res_units_eq, auto)
  18.204 -  apply (insert pos_mod_sign [of m a])
  18.205 -  apply (subgoal_tac "a mod m ~= 0")
  18.206 -  apply arith
  18.207 -  apply auto
  18.208 -  apply (subst (asm) gcd_red_int)
  18.209 -  apply (subst gcd_commute_int, assumption)
  18.210 -done
  18.211 -
  18.212 -lemma res_eq_to_cong: "((a mod m) = (b mod m)) = [a = b] (mod (m::int))" 
  18.213 -  unfolding cong_int_def by auto
  18.214 -
  18.215 -(* Simplifying with these will translate a ring equation in R to a 
  18.216 -   congruence. *)
  18.217 -
  18.218 -lemmas res_to_cong_simps = add_cong mult_cong pow_cong one_cong
  18.219 -    prod_cong sum_cong neg_cong res_eq_to_cong
  18.220 -
  18.221 -(* Other useful facts about the residue ring *)
  18.222 -
  18.223 -lemma one_eq_neg_one: "\<one> = \<ominus> \<one> \<Longrightarrow> m = 2"
  18.224 -  apply (simp add: res_one_eq res_neg_eq)
  18.225 -  apply (insert m_gt_one)
  18.226 -  apply (subgoal_tac "~(m > 2)")
  18.227 -  apply arith
  18.228 -  apply (rule notI)
  18.229 -  apply (subgoal_tac "-1 mod m = m - 1")
  18.230 -  apply force
  18.231 -  apply (subst mod_add_self2 [symmetric])
  18.232 -  apply (subst mod_pos_pos_trivial)
  18.233 -  apply auto
  18.234 -done
  18.235 -
  18.236 -end
  18.237 -
  18.238 -
  18.239 -(* prime residues *)
  18.240 -
  18.241 -locale residues_prime =
  18.242 -  fixes p :: int and R (structure)
  18.243 -  assumes p_prime [intro]: "prime p"
  18.244 -  defines "R == residue_ring p"
  18.245 -
  18.246 -sublocale residues_prime < residues p
  18.247 -  apply (unfold R_def residues_def)
  18.248 -  using p_prime apply auto
  18.249 -done
  18.250 -
  18.251 -context residues_prime begin
  18.252 -
  18.253 -lemma is_field: "field R"
  18.254 -  apply (rule cring.field_intro2)
  18.255 -  apply (rule cring)
  18.256 -  apply (auto simp add: res_carrier_eq res_one_eq res_zero_eq
  18.257 -    res_units_eq)
  18.258 -  apply (rule classical)
  18.259 -  apply (erule notE)
  18.260 -  apply (subst gcd_commute_int)
  18.261 -  apply (rule prime_imp_coprime_int)
  18.262 -  apply (rule p_prime)
  18.263 -  apply (rule notI)
  18.264 -  apply (frule zdvd_imp_le)
  18.265 -  apply auto
  18.266 -done
  18.267 -
  18.268 -lemma res_prime_units_eq: "Units R = {1..p - 1}"
  18.269 -  apply (subst res_units_eq)
  18.270 -  apply auto
  18.271 -  apply (subst gcd_commute_int)
  18.272 -  apply (rule prime_imp_coprime_int)
  18.273 -  apply (rule p_prime)
  18.274 -  apply (rule zdvd_not_zless)
  18.275 -  apply auto
  18.276 -done
  18.277 -
  18.278 -end
  18.279 -
  18.280 -sublocale residues_prime < field
  18.281 -  by (rule is_field)
  18.282 -
  18.283 -
  18.284 -(*
  18.285 -  Test cases: Euler's theorem and Wilson's theorem.
  18.286 -*)
  18.287 -
  18.288 -
  18.289 -subsection{* Euler's theorem *}
  18.290 -
  18.291 -(* the definition of the phi function *)
  18.292 -
  18.293 -constdefs
  18.294 -  phi :: "int => nat"
  18.295 -  "phi m == card({ x. 0 < x & x < m & gcd x m = 1})" 
  18.296 -
  18.297 -lemma phi_zero [simp]: "phi 0 = 0"
  18.298 -  apply (subst phi_def)
  18.299 -(* Auto hangs here. Once again, where is the simplification rule 
  18.300 -   1 == Suc 0 coming from? *)
  18.301 -  apply (auto simp add: card_eq_0_iff)
  18.302 -(* Add card_eq_0_iff as a simp rule? delete card_empty_imp? *)
  18.303 -done
  18.304 -
  18.305 -lemma phi_one [simp]: "phi 1 = 0"
  18.306 -  apply (auto simp add: phi_def card_eq_0_iff)
  18.307 -done
  18.308 -
  18.309 -lemma (in residues) phi_eq: "phi m = card(Units R)"
  18.310 -  by (simp add: phi_def res_units_eq)
  18.311 -
  18.312 -lemma (in residues) euler_theorem1: 
  18.313 -  assumes a: "gcd a m = 1"
  18.314 -  shows "[a^phi m = 1] (mod m)"
  18.315 -proof -
  18.316 -  from a m_gt_one have [simp]: "a mod m : Units R"
  18.317 -    by (intro mod_in_res_units)
  18.318 -  from phi_eq have "(a mod m) (^) (phi m) = (a mod m) (^) (card (Units R))"
  18.319 -    by simp
  18.320 -  also have "\<dots> = \<one>" 
  18.321 -    by (intro units_power_order_eq_one, auto)
  18.322 -  finally show ?thesis
  18.323 -    by (simp add: res_to_cong_simps)
  18.324 -qed
  18.325 -
  18.326 -(* In fact, there is a two line proof!
  18.327 -
  18.328 -lemma (in residues) euler_theorem1: 
  18.329 -  assumes a: "gcd a m = 1"
  18.330 -  shows "[a^phi m = 1] (mod m)"
  18.331 -proof -
  18.332 -  have "(a mod m) (^) (phi m) = \<one>"
  18.333 -    by (simp add: phi_eq units_power_order_eq_one a m_gt_one)
  18.334 -  thus ?thesis
  18.335 -    by (simp add: res_to_cong_simps)
  18.336 -qed
  18.337 -
  18.338 -*)
  18.339 -
  18.340 -(* outside the locale, we can relax the restriction m > 1 *)
  18.341 -
  18.342 -lemma euler_theorem:
  18.343 -  assumes "m >= 0" and "gcd a m = 1"
  18.344 -  shows "[a^phi m = 1] (mod m)"
  18.345 -proof (cases)
  18.346 -  assume "m = 0 | m = 1"
  18.347 -  thus ?thesis by auto
  18.348 -next
  18.349 -  assume "~(m = 0 | m = 1)"
  18.350 -  with prems show ?thesis
  18.351 -    by (intro residues.euler_theorem1, unfold residues_def, auto)
  18.352 -qed
  18.353 -
  18.354 -lemma (in residues_prime) phi_prime: "phi p = (nat p - 1)"
  18.355 -  apply (subst phi_eq)
  18.356 -  apply (subst res_prime_units_eq)
  18.357 -  apply auto
  18.358 -done
  18.359 -
  18.360 -lemma phi_prime: "prime p \<Longrightarrow> phi p = (nat p - 1)"
  18.361 -  apply (rule residues_prime.phi_prime)
  18.362 -  apply (erule residues_prime.intro)
  18.363 -done
  18.364 -
  18.365 -lemma fermat_theorem:
  18.366 -  assumes "prime p" and "~ (p dvd a)"
  18.367 -  shows "[a^(nat p - 1) = 1] (mod p)"
  18.368 -proof -
  18.369 -  from prems have "[a^phi p = 1] (mod p)"
  18.370 -    apply (intro euler_theorem)
  18.371 -    (* auto should get this next part. matching across
  18.372 -       substitutions is needed. *)
  18.373 -    apply (frule prime_gt_1_int, arith)
  18.374 -    apply (subst gcd_commute_int, erule prime_imp_coprime_int, assumption)
  18.375 -    done
  18.376 -  also have "phi p = nat p - 1"
  18.377 -    by (rule phi_prime, rule prems)
  18.378 -  finally show ?thesis .
  18.379 -qed
  18.380 -
  18.381 -
  18.382 -subsection {* Wilson's theorem *}
  18.383 -
  18.384 -lemma (in field) inv_pair_lemma: "x : Units R \<Longrightarrow> y : Units R \<Longrightarrow> 
  18.385 -  {x, inv x} ~= {y, inv y} \<Longrightarrow> {x, inv x} Int {y, inv y} = {}" 
  18.386 -  apply auto
  18.387 -  apply (erule notE)
  18.388 -  apply (erule inv_eq_imp_eq)
  18.389 -  apply auto
  18.390 -  apply (erule notE)
  18.391 -  apply (erule inv_eq_imp_eq)
  18.392 -  apply auto
  18.393 -done
  18.394 -
  18.395 -lemma (in residues_prime) wilson_theorem1:
  18.396 -  assumes a: "p > 2"
  18.397 -  shows "[fact (p - 1) = - 1] (mod p)"
  18.398 -proof -
  18.399 -  let ?InversePairs = "{ {x, inv x} | x. x : Units R - {\<one>, \<ominus> \<one>}}" 
  18.400 -  have UR: "Units R = {\<one>, \<ominus> \<one>} Un (Union ?InversePairs)"
  18.401 -    by auto
  18.402 -  have "(\<Otimes>i: Units R. i) = 
  18.403 -    (\<Otimes>i: {\<one>, \<ominus> \<one>}. i) \<otimes> (\<Otimes>i: Union ?InversePairs. i)"
  18.404 -    apply (subst UR)
  18.405 -    apply (subst finprod_Un_disjoint)
  18.406 -    apply (auto intro:funcsetI)
  18.407 -    apply (drule sym, subst (asm) inv_eq_one_eq)
  18.408 -    apply auto
  18.409 -    apply (drule sym, subst (asm) inv_eq_neg_one_eq)
  18.410 -    apply auto
  18.411 -    done
  18.412 -  also have "(\<Otimes>i: {\<one>, \<ominus> \<one>}. i) = \<ominus> \<one>"
  18.413 -    apply (subst finprod_insert)
  18.414 -    apply auto
  18.415 -    apply (frule one_eq_neg_one)
  18.416 -    apply (insert a, force)
  18.417 -    done
  18.418 -  also have "(\<Otimes>i:(Union ?InversePairs). i) = 
  18.419 -      (\<Otimes> A: ?InversePairs. (\<Otimes> y:A. y))"
  18.420 -    apply (subst finprod_Union_disjoint)
  18.421 -    apply force
  18.422 -    apply force
  18.423 -    apply clarify
  18.424 -    apply (rule inv_pair_lemma)
  18.425 -    apply auto
  18.426 -    done
  18.427 -  also have "\<dots> = \<one>"
  18.428 -    apply (rule finprod_one)
  18.429 -    apply auto
  18.430 -    apply (subst finprod_insert)
  18.431 -    apply auto
  18.432 -    apply (frule inv_eq_self)
  18.433 -    apply (auto)
  18.434 -    done
  18.435 -  finally have "(\<Otimes>i: Units R. i) = \<ominus> \<one>"
  18.436 -    by simp
  18.437 -  also have "(\<Otimes>i: Units R. i) = (\<Otimes>i: Units R. i mod p)"
  18.438 -    apply (rule finprod_cong')
  18.439 -    apply (auto)
  18.440 -    apply (subst (asm) res_prime_units_eq)
  18.441 -    apply auto
  18.442 -    done
  18.443 -  also have "\<dots> = (PROD i: Units R. i) mod p"
  18.444 -    apply (rule prod_cong)
  18.445 -    apply auto
  18.446 -    done
  18.447 -  also have "\<dots> = fact (p - 1) mod p"
  18.448 -    apply (subst fact_altdef_int)
  18.449 -    apply (insert prems, force)
  18.450 -    apply (subst res_prime_units_eq, rule refl)
  18.451 -    done
  18.452 -  finally have "fact (p - 1) mod p = \<ominus> \<one>".
  18.453 -  thus ?thesis
  18.454 -    by (simp add: res_to_cong_simps)
  18.455 -qed
  18.456 -
  18.457 -lemma wilson_theorem: "prime (p::int) \<Longrightarrow> [fact (p - 1) = - 1] (mod p)"
  18.458 -  apply (frule prime_gt_1_int)
  18.459 -  apply (case_tac "p = 2")
  18.460 -  apply (subst fact_altdef_int, simp)
  18.461 -  apply (subst cong_int_def)
  18.462 -  apply simp
  18.463 -  apply (rule residues_prime.wilson_theorem1)
  18.464 -  apply (rule residues_prime.intro)
  18.465 -  apply auto
  18.466 -done
  18.467 -
  18.468 -
  18.469 -end
    19.1 --- a/src/HOL/NewNumberTheory/UniqueFactorization.thy	Tue Sep 01 14:13:34 2009 +0200
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,967 +0,0 @@
    19.4 -(*  Title:      UniqueFactorization.thy
    19.5 -    ID:         
    19.6 -    Author:     Jeremy Avigad
    19.7 -
    19.8 -    
    19.9 -    Unique factorization for the natural numbers and the integers.
   19.10 -
   19.11 -    Note: there were previous Isabelle formalizations of unique
   19.12 -    factorization due to Thomas Marthedal Rasmussen, and, building on
   19.13 -    that, by Jeremy Avigad and David Gray.  
   19.14 -*)
   19.15 -
   19.16 -header {* UniqueFactorization *}
   19.17 -
   19.18 -theory UniqueFactorization
   19.19 -imports Cong Multiset
   19.20 -begin
   19.21 -
   19.22 -(* inherited from Multiset *)
   19.23 -declare One_nat_def [simp del] 
   19.24 -
   19.25 -(* As a simp or intro rule,
   19.26 -
   19.27 -     prime p \<Longrightarrow> p > 0
   19.28 -
   19.29 -   wreaks havoc here. When the premise includes ALL x :# M. prime x, it 
   19.30 -   leads to the backchaining
   19.31 -
   19.32 -     x > 0  
   19.33 -     prime x 
   19.34 -     x :# M   which is, unfortunately,
   19.35 -     count M x > 0
   19.36 -*)
   19.37 -
   19.38 -
   19.39 -(* useful facts *)
   19.40 -
   19.41 -lemma setsum_Un2: "finite (A Un B) \<Longrightarrow> 
   19.42 -    setsum f (A Un B) = setsum f (A - B) + setsum f (B - A) + 
   19.43 -      setsum f (A Int B)"
   19.44 -  apply (subgoal_tac "A Un B = (A - B) Un (B - A) Un (A Int B)")
   19.45 -  apply (erule ssubst)
   19.46 -  apply (subst setsum_Un_disjoint)
   19.47 -  apply auto
   19.48 -  apply (subst setsum_Un_disjoint)
   19.49 -  apply auto
   19.50 -done
   19.51 -
   19.52 -lemma setprod_Un2: "finite (A Un B) \<Longrightarrow> 
   19.53 -    setprod f (A Un B) = setprod f (A - B) * setprod f (B - A) * 
   19.54 -      setprod f (A Int B)"
   19.55 -  apply (subgoal_tac "A Un B = (A - B) Un (B - A) Un (A Int B)")
   19.56 -  apply (erule ssubst)
   19.57 -  apply (subst setprod_Un_disjoint)
   19.58 -  apply auto
   19.59 -  apply (subst setprod_Un_disjoint)
   19.60 -  apply auto
   19.61 -done
   19.62 - 
   19.63 -(* Should this go in Multiset.thy? *)
   19.64 -(* TN: No longer an intro-rule; needed only once and might get in the way *)
   19.65 -lemma multiset_eqI: "[| !!x. count M x = count N x |] ==> M = N"
   19.66 -  by (subst multiset_eq_conv_count_eq, blast)
   19.67 -
   19.68 -(* Here is a version of set product for multisets. Is it worth moving
   19.69 -   to multiset.thy? If so, one should similarly define msetsum for abelian 
   19.70 -   semirings, using of_nat. Also, is it worth developing bounded quantifiers 
   19.71 -   "ALL i :# M. P i"? 
   19.72 -*)
   19.73 -
   19.74 -constdefs
   19.75 -  msetprod :: "('a => ('b::{power,comm_monoid_mult})) => 'a multiset => 'b"
   19.76 -  "msetprod f M == setprod (%x. (f x)^(count M x)) (set_of M)"
   19.77 -
   19.78 -syntax
   19.79 -  "_msetprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" 
   19.80 -      ("(3PROD _:#_. _)" [0, 51, 10] 10)
   19.81 -
   19.82 -translations
   19.83 -  "PROD i :# A. b" == "msetprod (%i. b) A"
   19.84 -
   19.85 -lemma msetprod_Un: "msetprod f (A+B) = msetprod f A * msetprod f B" 
   19.86 -  apply (simp add: msetprod_def power_add)
   19.87 -  apply (subst setprod_Un2)
   19.88 -  apply auto
   19.89 -  apply (subgoal_tac 
   19.90 -      "(PROD x:set_of A - set_of B. f x ^ count A x * f x ^ count B x) =
   19.91 -       (PROD x:set_of A - set_of B. f x ^ count A x)")
   19.92 -  apply (erule ssubst)
   19.93 -  apply (subgoal_tac 
   19.94 -      "(PROD x:set_of B - set_of A. f x ^ count A x * f x ^ count B x) =
   19.95 -       (PROD x:set_of B - set_of A. f x ^ count B x)")
   19.96 -  apply (erule ssubst)
   19.97 -  apply (subgoal_tac "(PROD x:set_of A. f x ^ count A x) = 
   19.98 -    (PROD x:set_of A - set_of B. f x ^ count A x) *
   19.99 -    (PROD x:set_of A Int set_of B. f x ^ count A x)")
  19.100 -  apply (erule ssubst)
  19.101 -  apply (subgoal_tac "(PROD x:set_of B. f x ^ count B x) = 
  19.102 -    (PROD x:set_of B - set_of A. f x ^ count B x) *
  19.103 -    (PROD x:set_of A Int set_of B. f x ^ count B x)")
  19.104 -  apply (erule ssubst)
  19.105 -  apply (subst setprod_timesf)
  19.106 -  apply (force simp add: mult_ac)
  19.107 -  apply (subst setprod_Un_disjoint [symmetric])
  19.108 -  apply (auto intro: setprod_cong)
  19.109 -  apply (subst setprod_Un_disjoint [symmetric])
  19.110 -  apply (auto intro: setprod_cong)
  19.111 -done
  19.112 -
  19.113 -
  19.114 -subsection {* unique factorization: multiset version *}
  19.115 -
  19.116 -lemma multiset_prime_factorization_exists [rule_format]: "n > 0 --> 
  19.117 -    (EX M. (ALL (p::nat) : set_of M. prime p) & n = (PROD i :# M. i))"
  19.118 -proof (rule nat_less_induct, clarify)
  19.119 -  fix n :: nat
  19.120 -  assume ih: "ALL m < n. 0 < m --> (EX M. (ALL p : set_of M. prime p) & m = 
  19.121 -      (PROD i :# M. i))"
  19.122 -  assume "(n::nat) > 0"
  19.123 -  then have "n = 1 | (n > 1 & prime n) | (n > 1 & ~ prime n)"
  19.124 -    by arith
  19.125 -  moreover 
  19.126 -  {
  19.127 -    assume "n = 1"
  19.128 -    then have "(ALL p : set_of {#}. prime p) & n = (PROD i :# {#}. i)"
  19.129 -        by (auto simp add: msetprod_def)
  19.130 -  } 
  19.131 -  moreover 
  19.132 -  {
  19.133 -    assume "n > 1" and "prime n"
  19.134 -    then have "(ALL p : set_of {# n #}. prime p) & n = (PROD i :# {# n #}. i)"
  19.135 -      by (auto simp add: msetprod_def)
  19.136 -  } 
  19.137 -  moreover 
  19.138 -  {
  19.139 -    assume "n > 1" and "~ prime n"
  19.140 -    from prems not_prime_eq_prod_nat
  19.141 -      obtain m k where "n = m * k & 1 < m & m < n & 1 < k & k < n"
  19.142 -        by blast
  19.143 -    with ih obtain Q R where "(ALL p : set_of Q. prime p) & m = (PROD i:#Q. i)"
  19.144 -        and "(ALL p: set_of R. prime p) & k = (PROD i:#R. i)"
  19.145 -      by blast
  19.146 -    hence "(ALL p: set_of (Q + R). prime p) & n = (PROD i :# Q + R. i)"
  19.147 -      by (auto simp add: prems msetprod_Un set_of_union)
  19.148 -    then have "EX M. (ALL p : set_of M. prime p) & n = (PROD i :# M. i)"..
  19.149 -  }
  19.150 -  ultimately show "EX M. (ALL p : set_of M. prime p) & n = (PROD i::nat:#M. i)"
  19.151 -    by blast
  19.152 -qed
  19.153 -
  19.154 -lemma multiset_prime_factorization_unique_aux:
  19.155 -  fixes a :: nat
  19.156 -  assumes "(ALL p : set_of M. prime p)" and
  19.157 -    "(ALL p : set_of N. prime p)" and
  19.158 -    "(PROD i :# M. i) dvd (PROD i:# N. i)"
  19.159 -  shows
  19.160 -    "count M a <= count N a"
  19.161 -proof cases
  19.162 -  assume "a : set_of M"
  19.163 -  with prems have a: "prime a"
  19.164 -    by auto
  19.165 -  with prems have "a ^ count M a dvd (PROD i :# M. i)"
  19.166 -    by (auto intro: dvd_setprod simp add: msetprod_def)
  19.167 -  also have "... dvd (PROD i :# N. i)"
  19.168 -    by (rule prems)
  19.169 -  also have "... = (PROD i : (set_of N). i ^ (count N i))"
  19.170 -    by (simp add: msetprod_def)
  19.171 -  also have "... = 
  19.172 -      a^(count N a) * (PROD i : (set_of N - {a}). i ^ (count N i))"
  19.173 -    proof (cases)
  19.174 -      assume "a : set_of N"
  19.175 -      hence b: "set_of N = {a} Un (set_of N - {a})"
  19.176 -        by auto
  19.177 -      thus ?thesis
  19.178 -        by (subst (1) b, subst setprod_Un_disjoint, auto)
  19.179 -    next
  19.180 -      assume "a ~: set_of N" 
  19.181 -      thus ?thesis
  19.182 -        by auto
  19.183 -    qed
  19.184 -  finally have "a ^ count M a dvd 
  19.185 -      a^(count N a) * (PROD i : (set_of N - {a}). i ^ (count N i))".
  19.186 -  moreover have "coprime (a ^ count M a)
  19.187 -      (PROD i : (set_of N - {a}). i ^ (count N i))"
  19.188 -    apply (subst gcd_commute_nat)
  19.189 -    apply (rule setprod_coprime_nat)
  19.190 -    apply (rule primes_imp_powers_coprime_nat)
  19.191 -    apply (insert prems, auto) 
  19.192 -    done
  19.193 -  ultimately have "a ^ count M a dvd a^(count N a)"
  19.194 -    by (elim coprime_dvd_mult_nat)
  19.195 -  with a show ?thesis 
  19.196 -    by (intro power_dvd_imp_le, auto)
  19.197 -next
  19.198 -  assume "a ~: set_of M"
  19.199 -  thus ?thesis by auto
  19.200 -qed
  19.201 -
  19.202 -lemma multiset_prime_factorization_unique:
  19.203 -  assumes "(ALL (p::nat) : set_of M. prime p)" and
  19.204 -    "(ALL p : set_of N. prime p)" and
  19.205 -    "(PROD i :# M. i) = (PROD i:# N. i)"
  19.206 -  shows
  19.207 -    "M = N"
  19.208 -proof -
  19.209 -  {
  19.210 -    fix a
  19.211 -    from prems have "count M a <= count N a"
  19.212 -      by (intro multiset_prime_factorization_unique_aux, auto) 
  19.213 -    moreover from prems have "count N a <= count M a"
  19.214 -      by (intro multiset_prime_factorization_unique_aux, auto) 
  19.215 -    ultimately have "count M a = count N a"
  19.216 -      by auto
  19.217 -  }
  19.218 -  thus ?thesis by (simp add:multiset_eq_conv_count_eq)
  19.219 -qed
  19.220 -
  19.221 -constdefs
  19.222 -  multiset_prime_factorization :: "nat => nat multiset"
  19.223 -  "multiset_prime_factorization n ==
  19.224 -     if n > 0 then (THE M. ((ALL p : set_of M. prime p) & 
  19.225 -       n = (PROD i :# M. i)))
  19.226 -     else {#}"
  19.227 -
  19.228 -lemma multiset_prime_factorization: "n > 0 ==>
  19.229 -    (ALL p : set_of (multiset_prime_factorization n). prime p) &
  19.230 -       n = (PROD i :# (multiset_prime_factorization n). i)"
  19.231 -  apply (unfold multiset_prime_factorization_def)
  19.232 -  apply clarsimp
  19.233 -  apply (frule multiset_prime_factorization_exists)
  19.234 -  apply clarify
  19.235 -  apply (rule theI)
  19.236 -  apply (insert multiset_prime_factorization_unique, blast)+
  19.237 -done
  19.238 -
  19.239 -
  19.240 -subsection {* Prime factors and multiplicity for nats and ints *}
  19.241 -
  19.242 -class unique_factorization =
  19.243 -
  19.244 -fixes
  19.245 -  multiplicity :: "'a \<Rightarrow> 'a \<Rightarrow> nat" and
  19.246 -  prime_factors :: "'a \<Rightarrow> 'a set"
  19.247 -
  19.248 -(* definitions for the natural numbers *)
  19.249 -
  19.250 -instantiation nat :: unique_factorization
  19.251 -
  19.252 -begin
  19.253 -
  19.254 -definition
  19.255 -  multiplicity_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat"
  19.256 -where
  19.257 -  "multiplicity_nat p n = count (multiset_prime_factorization n) p"
  19.258 -
  19.259 -definition
  19.260 -  prime_factors_nat :: "nat \<Rightarrow> nat set"
  19.261 -where
  19.262 -  "prime_factors_nat n = set_of (multiset_prime_factorization n)"
  19.263 -
  19.264 -instance proof qed
  19.265 -
  19.266 -end
  19.267 -
  19.268 -(* definitions for the integers *)
  19.269 -
  19.270 -instantiation int :: unique_factorization
  19.271 -
  19.272 -begin
  19.273 -
  19.274 -definition
  19.275 -  multiplicity_int :: "int \<Rightarrow> int \<Rightarrow> nat"
  19.276 -where
  19.277 -  "multiplicity_int p n = multiplicity (nat p) (nat n)"
  19.278 -
  19.279 -definition
  19.280 -  prime_factors_int :: "int \<Rightarrow> int set"
  19.281 -where
  19.282 -  "prime_factors_int n = int ` (prime_factors (nat n))"
  19.283 -
  19.284 -instance proof qed
  19.285 -
  19.286 -end
  19.287 -
  19.288 -
  19.289 -subsection {* Set up transfer *}
  19.290 -
  19.291 -lemma transfer_nat_int_prime_factors: 
  19.292 -  "prime_factors (nat n) = nat ` prime_factors n"
  19.293 -  unfolding prime_factors_int_def apply auto
  19.294 -  by (subst transfer_int_nat_set_return_embed, assumption)
  19.295 -
  19.296 -lemma transfer_nat_int_prime_factors_closure: "n >= 0 \<Longrightarrow> 
  19.297 -    nat_set (prime_factors n)"
  19.298 -  by (auto simp add: nat_set_def prime_factors_int_def)
  19.299 -
  19.300 -lemma transfer_nat_int_multiplicity: "p >= 0 \<Longrightarrow> n >= 0 \<Longrightarrow>
  19.301 -  multiplicity (nat p) (nat n) = multiplicity p n"
  19.302 -  by (auto simp add: multiplicity_int_def)
  19.303 -
  19.304 -declare TransferMorphism_nat_int[transfer add return: 
  19.305 -  transfer_nat_int_prime_factors transfer_nat_int_prime_factors_closure
  19.306 -  transfer_nat_int_multiplicity]
  19.307 -
  19.308 -
  19.309 -lemma transfer_int_nat_prime_factors:
  19.310 -    "prime_factors (int n) = int ` prime_factors n"
  19.311 -  unfolding prime_factors_int_def by auto
  19.312 -
  19.313 -lemma transfer_int_nat_prime_factors_closure: "is_nat n \<Longrightarrow> 
  19.314 -    nat_set (prime_factors n)"
  19.315 -  by (simp only: transfer_nat_int_prime_factors_closure is_nat_def)
  19.316 -
  19.317 -lemma transfer_int_nat_multiplicity: 
  19.318 -    "multiplicity (int p) (int n) = multiplicity p n"
  19.319 -  by (auto simp add: multiplicity_int_def)
  19.320 -
  19.321 -declare TransferMorphism_int_nat[transfer add return: 
  19.322 -  transfer_int_nat_prime_factors transfer_int_nat_prime_factors_closure
  19.323 -  transfer_int_nat_multiplicity]
  19.324 -
  19.325 -
  19.326 -subsection {* Properties of prime factors and multiplicity for nats and ints *}
  19.327 -
  19.328 -lemma prime_factors_ge_0_int [elim]: "p : prime_factors (n::int) \<Longrightarrow> p >= 0"
  19.329 -  by (unfold prime_factors_int_def, auto)
  19.330 -
  19.331 -lemma prime_factors_prime_nat [intro]: "p : prime_factors (n::nat) \<Longrightarrow> prime p"
  19.332 -  apply (case_tac "n = 0")
  19.333 -  apply (simp add: prime_factors_nat_def multiset_prime_factorization_def)
  19.334 -  apply (auto simp add: prime_factors_nat_def multiset_prime_factorization)
  19.335 -done
  19.336 -
  19.337 -lemma prime_factors_prime_int [intro]:
  19.338 -  assumes "n >= 0" and "p : prime_factors (n::int)"
  19.339 -  shows "prime p"
  19.340 -
  19.341 -  apply (rule prime_factors_prime_nat [transferred, of n p])
  19.342 -  using prems apply auto
  19.343 -done
  19.344 -
  19.345 -lemma prime_factors_gt_0_nat [elim]: "p : prime_factors x \<Longrightarrow> p > (0::nat)"
  19.346 -  by (frule prime_factors_prime_nat, auto)
  19.347 -
  19.348 -lemma prime_factors_gt_0_int [elim]: "x >= 0 \<Longrightarrow> p : prime_factors x \<Longrightarrow> 
  19.349 -    p > (0::int)"
  19.350 -  by (frule (1) prime_factors_prime_int, auto)
  19.351 -
  19.352 -lemma prime_factors_finite_nat [iff]: "finite (prime_factors (n::nat))"
  19.353 -  by (unfold prime_factors_nat_def, auto)
  19.354 -
  19.355 -lemma prime_factors_finite_int [iff]: "finite (prime_factors (n::int))"
  19.356 -  by (unfold prime_factors_int_def, auto)
  19.357 -
  19.358 -lemma prime_factors_altdef_nat: "prime_factors (n::nat) = 
  19.359 -    {p. multiplicity p n > 0}"
  19.360 -  by (force simp add: prime_factors_nat_def multiplicity_nat_def)
  19.361 -
  19.362 -lemma prime_factors_altdef_int: "prime_factors (n::int) = 
  19.363 -    {p. p >= 0 & multiplicity p n > 0}"
  19.364 -  apply (unfold prime_factors_int_def multiplicity_int_def)
  19.365 -  apply (subst prime_factors_altdef_nat)
  19.366 -  apply (auto simp add: image_def)
  19.367 -done
  19.368 -
  19.369 -lemma prime_factorization_nat: "(n::nat) > 0 \<Longrightarrow> 
  19.370 -    n = (PROD p : prime_factors n. p^(multiplicity p n))"
  19.371 -  by (frule multiset_prime_factorization, 
  19.372 -    simp add: prime_factors_nat_def multiplicity_nat_def msetprod_def)
  19.373 -
  19.374 -thm prime_factorization_nat [transferred] 
  19.375 -
  19.376 -lemma prime_factorization_int: 
  19.377 -  assumes "(n::int) > 0"
  19.378 -  shows "n = (PROD p : prime_factors n. p^(multiplicity p n))"
  19.379 -
  19.380 -  apply (rule prime_factorization_nat [transferred, of n])
  19.381 -  using prems apply auto
  19.382 -done
  19.383 -
  19.384 -lemma neq_zero_eq_gt_zero_nat: "((x::nat) ~= 0) = (x > 0)"
  19.385 -  by auto
  19.386 -
  19.387 -lemma prime_factorization_unique_nat: 
  19.388 -    "S = { (p::nat) . f p > 0} \<Longrightarrow> finite S \<Longrightarrow> (ALL p : S. prime p) \<Longrightarrow>
  19.389 -      n = (PROD p : S. p^(f p)) \<Longrightarrow>
  19.390 -        S = prime_factors n & (ALL p. f p = multiplicity p n)"
  19.391 -  apply (subgoal_tac "multiset_prime_factorization n = Abs_multiset
  19.392 -      f")
  19.393 -  apply (unfold prime_factors_nat_def multiplicity_nat_def)
  19.394 -  apply (simp add: set_of_def count_def Abs_multiset_inverse multiset_def)
  19.395 -  apply (unfold multiset_prime_factorization_def)
  19.396 -  apply (subgoal_tac "n > 0")
  19.397 -  prefer 2
  19.398 -  apply force
  19.399 -  apply (subst if_P, assumption)
  19.400 -  apply (rule the1_equality)
  19.401 -  apply (rule ex_ex1I)
  19.402 -  apply (rule multiset_prime_factorization_exists, assumption)
  19.403 -  apply (rule multiset_prime_factorization_unique)
  19.404 -  apply force
  19.405 -  apply force
  19.406 -  apply force
  19.407 -  unfolding set_of_def count_def msetprod_def
  19.408 -  apply (subgoal_tac "f : multiset")
  19.409 -  apply (auto simp only: Abs_multiset_inverse)
  19.410 -  unfolding multiset_def apply force 
  19.411 -done
  19.412 -
  19.413 -lemma prime_factors_characterization_nat: "S = {p. 0 < f (p::nat)} \<Longrightarrow> 
  19.414 -    finite S \<Longrightarrow> (ALL p:S. prime p) \<Longrightarrow> n = (PROD p:S. p ^ f p) \<Longrightarrow>
  19.415 -      prime_factors n = S"
  19.416 -  by (rule prime_factorization_unique_nat [THEN conjunct1, symmetric],
  19.417 -    assumption+)
  19.418 -
  19.419 -lemma prime_factors_characterization'_nat: 
  19.420 -  "finite {p. 0 < f (p::nat)} \<Longrightarrow>
  19.421 -    (ALL p. 0 < f p \<longrightarrow> prime p) \<Longrightarrow>
  19.422 -      prime_factors (PROD p | 0 < f p . p ^ f p) = {p. 0 < f p}"
  19.423 -  apply (rule prime_factors_characterization_nat)
  19.424 -  apply auto
  19.425 -done
  19.426 -
  19.427 -(* A minor glitch:*)
  19.428 -
  19.429 -thm prime_factors_characterization'_nat 
  19.430 -    [where f = "%x. f (int (x::nat))", 
  19.431 -      transferred direction: nat "op <= (0::int)", rule_format]
  19.432 -
  19.433 -(*
  19.434 -  Transfer isn't smart enough to know that the "0 < f p" should 
  19.435 -  remain a comparison between nats. But the transfer still works. 
  19.436 -*)
  19.437 -
  19.438 -lemma primes_characterization'_int [rule_format]: 
  19.439 -    "finite {p. p >= 0 & 0 < f (p::int)} \<Longrightarrow>
  19.440 -      (ALL p. 0 < f p \<longrightarrow> prime p) \<Longrightarrow>
  19.441 -        prime_factors (PROD p | p >=0 & 0 < f p . p ^ f p) = 
  19.442 -          {p. p >= 0 & 0 < f p}"
  19.443 -
  19.444 -  apply (insert prime_factors_characterization'_nat 
  19.445 -    [where f = "%x. f (int (x::nat))", 
  19.446 -    transferred direction: nat "op <= (0::int)"])
  19.447 -  apply auto
  19.448 -done
  19.449 -
  19.450 -lemma prime_factors_characterization_int: "S = {p. 0 < f (p::int)} \<Longrightarrow> 
  19.451 -    finite S \<Longrightarrow> (ALL p:S. prime p) \<Longrightarrow> n = (PROD p:S. p ^ f p) \<Longrightarrow>
  19.452 -      prime_factors n = S"
  19.453 -  apply simp
  19.454 -  apply (subgoal_tac "{p. 0 < f p} = {p. 0 <= p & 0 < f p}")
  19.455 -  apply (simp only:)
  19.456 -  apply (subst primes_characterization'_int)
  19.457 -  apply auto
  19.458 -  apply (auto simp add: prime_ge_0_int)
  19.459 -done
  19.460 -
  19.461 -lemma multiplicity_characterization_nat: "S = {p. 0 < f (p::nat)} \<Longrightarrow> 
  19.462 -    finite S \<Longrightarrow> (ALL p:S. prime p) \<Longrightarrow> n = (PROD p:S. p ^ f p) \<Longrightarrow>
  19.463 -      multiplicity p n = f p"
  19.464 -  by (frule prime_factorization_unique_nat [THEN conjunct2, rule_format, 
  19.465 -    symmetric], auto)
  19.466 -
  19.467 -lemma multiplicity_characterization'_nat: "finite {p. 0 < f (p::nat)} \<longrightarrow>
  19.468 -    (ALL p. 0 < f p \<longrightarrow> prime p) \<longrightarrow>
  19.469 -      multiplicity p (PROD p | 0 < f p . p ^ f p) = f p"
  19.470 -  apply (rule impI)+
  19.471 -  apply (rule multiplicity_characterization_nat)
  19.472 -  apply auto
  19.473 -done
  19.474 -
  19.475 -lemma multiplicity_characterization'_int [rule_format]: 
  19.476 -  "finite {p. p >= 0 & 0 < f (p::int)} \<Longrightarrow>
  19.477 -    (ALL p. 0 < f p \<longrightarrow> prime p) \<Longrightarrow> p >= 0 \<Longrightarrow>
  19.478 -      multiplicity p (PROD p | p >= 0 & 0 < f p . p ^ f p) = f p"
  19.479 -
  19.480 -  apply (insert multiplicity_characterization'_nat 
  19.481 -    [where f = "%x. f (int (x::nat))", 
  19.482 -      transferred direction: nat "op <= (0::int)", rule_format])
  19.483 -  apply auto
  19.484 -done
  19.485 -
  19.486 -lemma multiplicity_characterization_int: "S = {p. 0 < f (p::int)} \<Longrightarrow> 
  19.487 -    finite S \<Longrightarrow> (ALL p:S. prime p) \<Longrightarrow> n = (PROD p:S. p ^ f p) \<Longrightarrow>
  19.488 -      p >= 0 \<Longrightarrow> multiplicity p n = f p"
  19.489 -  apply simp
  19.490 -  apply (subgoal_tac "{p. 0 < f p} = {p. 0 <= p & 0 < f p}")
  19.491 -  apply (simp only:)
  19.492 -  apply (subst multiplicity_characterization'_int)
  19.493 -  apply auto
  19.494 -  apply (auto simp add: prime_ge_0_int)
  19.495 -done
  19.496 -
  19.497 -lemma multiplicity_zero_nat [simp]: "multiplicity (p::nat) 0 = 0"
  19.498 -  by (simp add: multiplicity_nat_def multiset_prime_factorization_def)
  19.499 -
  19.500 -lemma multiplicity_zero_int [simp]: "multiplicity (p::int) 0 = 0"
  19.501 -  by (simp add: multiplicity_int_def) 
  19.502 -
  19.503 -lemma multiplicity_one_nat [simp]: "multiplicity p (1::nat) = 0"
  19.504 -  by (subst multiplicity_characterization_nat [where f = "%x. 0"], auto)
  19.505 -
  19.506 -lemma multiplicity_one_int [simp]: "multiplicity p (1::int) = 0"
  19.507 -  by (simp add: multiplicity_int_def)
  19.508 -
  19.509 -lemma multiplicity_prime_nat [simp]: "prime (p::nat) \<Longrightarrow> multiplicity p p = 1"
  19.510 -  apply (subst multiplicity_characterization_nat
  19.511 -      [where f = "(%q. if q = p then 1 else 0)"])
  19.512 -  apply auto
  19.513 -  apply (case_tac "x = p")
  19.514 -  apply auto
  19.515 -done
  19.516 -
  19.517 -lemma multiplicity_prime_int [simp]: "prime (p::int) \<Longrightarrow> multiplicity p p = 1"
  19.518 -  unfolding prime_int_def multiplicity_int_def by auto
  19.519 -
  19.520 -lemma multiplicity_prime_power_nat [simp]: "prime (p::nat) \<Longrightarrow> 
  19.521 -    multiplicity p (p^n) = n"
  19.522 -  apply (case_tac "n = 0")
  19.523 -  apply auto
  19.524 -  apply (subst multiplicity_characterization_nat
  19.525 -      [where f = "(%q. if q = p then n else 0)"])
  19.526 -  apply auto
  19.527 -  apply (case_tac "x = p")
  19.528 -  apply auto
  19.529 -done
  19.530 -
  19.531 -lemma multiplicity_prime_power_int [simp]: "prime (p::int) \<Longrightarrow> 
  19.532 -    multiplicity p (p^n) = n"
  19.533 -  apply (frule prime_ge_0_int)
  19.534 -  apply (auto simp add: prime_int_def multiplicity_int_def nat_power_eq)
  19.535 -done
  19.536 -
  19.537 -lemma multiplicity_nonprime_nat [simp]: "~ prime (p::nat) \<Longrightarrow> 
  19.538 -    multiplicity p n = 0"
  19.539 -  apply (case_tac "n = 0")
  19.540 -  apply auto
  19.541 -  apply (frule multiset_prime_factorization)
  19.542 -  apply (auto simp add: set_of_def multiplicity_nat_def)
  19.543 -done
  19.544 -
  19.545 -lemma multiplicity_nonprime_int [simp]: "~ prime (p::int) \<Longrightarrow> multiplicity p n = 0"
  19.546 -  by (unfold multiplicity_int_def prime_int_def, auto)
  19.547 -
  19.548 -lemma multiplicity_not_factor_nat [simp]: 
  19.549 -    "p ~: prime_factors (n::nat) \<Longrightarrow> multiplicity p n = 0"
  19.550 -  by (subst (asm) prime_factors_altdef_nat, auto)
  19.551 -
  19.552 -lemma multiplicity_not_factor_int [simp]: 
  19.553 -    "p >= 0 \<Longrightarrow> p ~: prime_factors (n::int) \<Longrightarrow> multiplicity p n = 0"
  19.554 -  by (subst (asm) prime_factors_altdef_int, auto)
  19.555 -
  19.556 -lemma multiplicity_product_aux_nat: "(k::nat) > 0 \<Longrightarrow> l > 0 \<Longrightarrow>
  19.557 -    (prime_factors k) Un (prime_factors l) = prime_factors (k * l) &
  19.558 -    (ALL p. multiplicity p k + multiplicity p l = multiplicity p (k * l))"
  19.559 -  apply (rule prime_factorization_unique_nat)
  19.560 -  apply (simp only: prime_factors_altdef_nat)
  19.561 -  apply auto
  19.562 -  apply (subst power_add)
  19.563 -  apply (subst setprod_timesf)
  19.564 -  apply (rule arg_cong2)back back
  19.565 -  apply (subgoal_tac "prime_factors k Un prime_factors l = prime_factors k Un 
  19.566 -      (prime_factors l - prime_factors k)")
  19.567 -  apply (erule ssubst)
  19.568 -  apply (subst setprod_Un_disjoint)
  19.569 -  apply auto
  19.570 -  apply (subgoal_tac "(\<Prod>p\<in>prime_factors l - prime_factors k. p ^ multiplicity p k) = 
  19.571 -      (\<Prod>p\<in>prime_factors l - prime_factors k. 1)")
  19.572 -  apply (erule ssubst)
  19.573 -  apply (simp add: setprod_1)
  19.574 -  apply (erule prime_factorization_nat)
  19.575 -  apply (rule setprod_cong, auto)
  19.576 -  apply (subgoal_tac "prime_factors k Un prime_factors l = prime_factors l Un 
  19.577 -      (prime_factors k - prime_factors l)")
  19.578 -  apply (erule ssubst)
  19.579 -  apply (subst setprod_Un_disjoint)
  19.580 -  apply auto
  19.581 -  apply (subgoal_tac "(\<Prod>p\<in>prime_factors k - prime_factors l. p ^ multiplicity p l) = 
  19.582 -      (\<Prod>p\<in>prime_factors k - prime_factors l. 1)")
  19.583 -  apply (erule ssubst)
  19.584 -  apply (simp add: setprod_1)
  19.585 -  apply (erule prime_factorization_nat)
  19.586 -  apply (rule setprod_cong, auto)
  19.587 -done
  19.588 -
  19.589 -(* transfer doesn't have the same problem here with the right 
  19.590 -   choice of rules. *)
  19.591 -
  19.592 -lemma multiplicity_product_aux_int: 
  19.593 -  assumes "(k::int) > 0" and "l > 0"
  19.594 -  shows 
  19.595 -    "(prime_factors k) Un (prime_factors l) = prime_factors (k * l) &
  19.596 -    (ALL p >= 0. multiplicity p k + multiplicity p l = multiplicity p (k * l))"
  19.597 -
  19.598 -  apply (rule multiplicity_product_aux_nat [transferred, of l k])
  19.599 -  using prems apply auto
  19.600 -done
  19.601 -
  19.602 -lemma prime_factors_product_nat: "(k::nat) > 0 \<Longrightarrow> l > 0 \<Longrightarrow> prime_factors (k * l) = 
  19.603 -    prime_factors k Un prime_factors l"
  19.604 -  by (rule multiplicity_product_aux_nat [THEN conjunct1, symmetric])
  19.605 -
  19.606 -lemma prime_factors_product_int: "(k::int) > 0 \<Longrightarrow> l > 0 \<Longrightarrow> prime_factors (k * l) = 
  19.607 -    prime_factors k Un prime_factors l"
  19.608 -  by (rule multiplicity_product_aux_int [THEN conjunct1, symmetric])
  19.609 -
  19.610 -lemma multiplicity_product_nat: "(k::nat) > 0 \<Longrightarrow> l > 0 \<Longrightarrow> multiplicity p (k * l) = 
  19.611 -    multiplicity p k + multiplicity p l"
  19.612 -  by (rule multiplicity_product_aux_nat [THEN conjunct2, rule_format, 
  19.613 -      symmetric])
  19.614 -
  19.615 -lemma multiplicity_product_int: "(k::int) > 0 \<Longrightarrow> l > 0 \<Longrightarrow> p >= 0 \<Longrightarrow> 
  19.616 -    multiplicity p (k * l) = multiplicity p k + multiplicity p l"
  19.617 -  by (rule multiplicity_product_aux_int [THEN conjunct2, rule_format, 
  19.618 -      symmetric])
  19.619 -
  19.620 -lemma multiplicity_setprod_nat: "finite S \<Longrightarrow> (ALL x : S. f x > 0) \<Longrightarrow> 
  19.621 -    multiplicity (p::nat) (PROD x : S. f x) = 
  19.622 -      (SUM x : S. multiplicity p (f x))"
  19.623 -  apply (induct set: finite)
  19.624 -  apply auto
  19.625 -  apply (subst multiplicity_product_nat)
  19.626 -  apply auto
  19.627 -done
  19.628 -
  19.629 -(* Transfer is delicate here for two reasons: first, because there is
  19.630 -   an implicit quantifier over functions (f), and, second, because the 
  19.631 -   product over the multiplicity should not be translated to an integer 
  19.632 -   product.
  19.633 -
  19.634 -   The way to handle the first is to use quantifier rules for functions.
  19.635 -   The way to handle the second is to turn off the offending rule.
  19.636 -*)
  19.637 -
  19.638 -lemma transfer_nat_int_sum_prod_closure3:
  19.639 -  "(SUM x : A. int (f x)) >= 0"
  19.640 -  "(PROD x : A. int (f x)) >= 0"
  19.641 -  apply (rule setsum_nonneg, auto)
  19.642 -  apply (rule setprod_nonneg, auto)
  19.643 -done
  19.644 -
  19.645 -declare TransferMorphism_nat_int[transfer 
  19.646 -  add return: transfer_nat_int_sum_prod_closure3
  19.647 -  del: transfer_nat_int_sum_prod2 (1)]
  19.648 -
  19.649 -lemma multiplicity_setprod_int: "p >= 0 \<Longrightarrow> finite S \<Longrightarrow> 
  19.650 -  (ALL x : S. f x > 0) \<Longrightarrow> 
  19.651 -    multiplicity (p::int) (PROD x : S. f x) = 
  19.652 -      (SUM x : S. multiplicity p (f x))"
  19.653 -
  19.654 -  apply (frule multiplicity_setprod_nat
  19.655 -    [where f = "%x. nat(int(nat(f x)))", 
  19.656 -      transferred direction: nat "op <= (0::int)"])
  19.657 -  apply auto
  19.658 -  apply (subst (asm) setprod_cong)
  19.659 -  apply (rule refl)
  19.660 -  apply (rule if_P)
  19.661 -  apply auto
  19.662 -  apply (rule setsum_cong)
  19.663 -  apply auto
  19.664 -done
  19.665 -
  19.666 -declare TransferMorphism_nat_int[transfer 
  19.667 -  add return: transfer_nat_int_sum_prod2 (1)]
  19.668 -
  19.669 -lemma multiplicity_prod_prime_powers_nat:
  19.670 -    "finite S \<Longrightarrow> (ALL p : S. prime (p::nat)) \<Longrightarrow>
  19.671 -       multiplicity p (PROD p : S. p ^ f p) = (if p : S then f p else 0)"
  19.672 -  apply (subgoal_tac "(PROD p : S. p ^ f p) = 
  19.673 -      (PROD p : S. p ^ (%x. if x : S then f x else 0) p)")
  19.674 -  apply (erule ssubst)
  19.675 -  apply (subst multiplicity_characterization_nat)
  19.676 -  prefer 5 apply (rule refl)
  19.677 -  apply (rule refl)
  19.678 -  apply auto
  19.679 -  apply (subst setprod_mono_one_right)
  19.680 -  apply assumption
  19.681 -  prefer 3
  19.682 -  apply (rule setprod_cong)
  19.683 -  apply (rule refl)
  19.684 -  apply auto
  19.685 -done
  19.686 -
  19.687 -(* Here the issue with transfer is the implicit quantifier over S *)
  19.688 -
  19.689 -lemma multiplicity_prod_prime_powers_int:
  19.690 -    "(p::int) >= 0 \<Longrightarrow> finite S \<Longrightarrow> (ALL p : S. prime p) \<Longrightarrow>
  19.691 -       multiplicity p (PROD p : S. p ^ f p) = (if p : S then f p else 0)"
  19.692 -
  19.693 -  apply (subgoal_tac "int ` nat ` S = S")
  19.694 -  apply (frule multiplicity_prod_prime_powers_nat [where f = "%x. f(int x)" 
  19.695 -    and S = "nat ` S", transferred])
  19.696 -  apply auto
  19.697 -  apply (subst prime_int_def [symmetric])
  19.698 -  apply auto
  19.699 -  apply (subgoal_tac "xb >= 0")
  19.700 -  apply force
  19.701 -  apply (rule prime_ge_0_int)
  19.702 -  apply force
  19.703 -  apply (subst transfer_nat_int_set_return_embed)
  19.704 -  apply (unfold nat_set_def, auto)
  19.705 -done
  19.706 -
  19.707 -lemma multiplicity_distinct_prime_power_nat: "prime (p::nat) \<Longrightarrow> prime q \<Longrightarrow>
  19.708 -    p ~= q \<Longrightarrow> multiplicity p (q^n) = 0"
  19.709 -  apply (subgoal_tac "q^n = setprod (%x. x^n) {q}")
  19.710 -  apply (erule ssubst)
  19.711 -  apply (subst multiplicity_prod_prime_powers_nat)
  19.712 -  apply auto
  19.713 -done
  19.714 -
  19.715 -lemma multiplicity_distinct_prime_power_int: "prime (p::int) \<Longrightarrow> prime q \<Longrightarrow>
  19.716 -    p ~= q \<Longrightarrow> multiplicity p (q^n) = 0"
  19.717 -  apply (frule prime_ge_0_int [of q])
  19.718 -  apply (frule multiplicity_distinct_prime_power_nat [transferred leaving: n]) 
  19.719 -  prefer 4
  19.720 -  apply assumption
  19.721 -  apply auto
  19.722 -done
  19.723 -
  19.724 -lemma dvd_multiplicity_nat: 
  19.725 -    "(0::nat) < y \<Longrightarrow> x dvd y \<Longrightarrow> multiplicity p x <= multiplicity p y"
  19.726 -  apply (case_tac "x = 0")
  19.727 -  apply (auto simp add: dvd_def multiplicity_product_nat)
  19.728 -done
  19.729 -
  19.730 -lemma dvd_multiplicity_int: 
  19.731 -    "(0::int) < y \<Longrightarrow> 0 <= x \<Longrightarrow> x dvd y \<Longrightarrow> p >= 0 \<Longrightarrow> 
  19.732 -      multiplicity p x <= multiplicity p y"
  19.733 -  apply (case_tac "x = 0")
  19.734 -  apply (auto simp add: dvd_def)
  19.735 -  apply (subgoal_tac "0 < k")
  19.736 -  apply (auto simp add: multiplicity_product_int)
  19.737 -  apply (erule zero_less_mult_pos)
  19.738 -  apply arith
  19.739 -done
  19.740 -
  19.741 -lemma dvd_prime_factors_nat [intro]:
  19.742 -    "0 < (y::nat) \<Longrightarrow> x dvd y \<Longrightarrow> prime_factors x <= prime_factors y"
  19.743 -  apply (simp only: prime_factors_altdef_nat)
  19.744 -  apply auto
  19.745 -  apply (frule dvd_multiplicity_nat)
  19.746 -  apply auto
  19.747 -(* It is a shame that auto and arith don't get this. *)
  19.748 -  apply (erule order_less_le_trans)back
  19.749 -  apply assumption
  19.750 -done
  19.751 -
  19.752 -lemma dvd_prime_factors_int [intro]:
  19.753 -    "0 < (y::int) \<Longrightarrow> 0 <= x \<Longrightarrow> x dvd y \<Longrightarrow> prime_factors x <= prime_factors y"
  19.754 -  apply (auto simp add: prime_factors_altdef_int)
  19.755 -  apply (erule order_less_le_trans)
  19.756 -  apply (rule dvd_multiplicity_int)
  19.757 -  apply auto
  19.758 -done
  19.759 -
  19.760 -lemma multiplicity_dvd_nat: "0 < (x::nat) \<Longrightarrow> 0 < y \<Longrightarrow> 
  19.761 -    ALL p. multiplicity p x <= multiplicity p y \<Longrightarrow>
  19.762 -      x dvd y"
  19.763 -  apply (subst prime_factorization_nat [of x], assumption)
  19.764 -  apply (subst prime_factorization_nat [of y], assumption)
  19.765 -  apply (rule setprod_dvd_setprod_subset2)
  19.766 -  apply force
  19.767 -  apply (subst prime_factors_altdef_nat)+
  19.768 -  apply auto
  19.769 -(* Again, a shame that auto and arith don't get this. *)
  19.770 -  apply (drule_tac x = xa in spec, auto)
  19.771 -  apply (rule le_imp_power_dvd)
  19.772 -  apply blast
  19.773 -done
  19.774 -
  19.775 -lemma multiplicity_dvd_int: "0 < (x::int) \<Longrightarrow> 0 < y \<Longrightarrow> 
  19.776 -    ALL p >= 0. multiplicity p x <= multiplicity p y \<Longrightarrow>
  19.777 -      x dvd y"
  19.778 -  apply (subst prime_factorization_int [of x], assumption)
  19.779 -  apply (subst prime_factorization_int [of y], assumption)
  19.780 -  apply (rule setprod_dvd_setprod_subset2)
  19.781 -  apply force
  19.782 -  apply (subst prime_factors_altdef_int)+
  19.783 -  apply auto
  19.784 -  apply (rule dvd_power_le)
  19.785 -  apply auto
  19.786 -  apply (drule_tac x = xa in spec)
  19.787 -  apply (erule impE)
  19.788 -  apply auto
  19.789 -done
  19.790 -
  19.791 -lemma multiplicity_dvd'_nat: "(0::nat) < x \<Longrightarrow> 
  19.792 -    \<forall>p. prime p \<longrightarrow> multiplicity p x \<le> multiplicity p y \<Longrightarrow> x dvd y"
  19.793 -  apply (cases "y = 0")
  19.794 -  apply auto
  19.795 -  apply (rule multiplicity_dvd_nat, auto)
  19.796 -  apply (case_tac "prime p")
  19.797 -  apply auto
  19.798 -done
  19.799 -
  19.800 -lemma multiplicity_dvd'_int: "(0::int) < x \<Longrightarrow> 0 <= y \<Longrightarrow>
  19.801 -    \<forall>p. prime p \<longrightarrow> multiplicity p x \<le> multiplicity p y \<Longrightarrow> x dvd y"
  19.802 -  apply (cases "y = 0")
  19.803 -  apply auto
  19.804 -  apply (rule multiplicity_dvd_int, auto)
  19.805 -  apply (case_tac "prime p")
  19.806 -  apply auto
  19.807 -done
  19.808 -
  19.809 -lemma dvd_multiplicity_eq_nat: "0 < (x::nat) \<Longrightarrow> 0 < y \<Longrightarrow>
  19.810 -    (x dvd y) = (ALL p. multiplicity p x <= multiplicity p y)"
  19.811 -  by (auto intro: dvd_multiplicity_nat multiplicity_dvd_nat)
  19.812 -
  19.813 -lemma dvd_multiplicity_eq_int: "0 < (x::int) \<Longrightarrow> 0 < y \<Longrightarrow>
  19.814 -    (x dvd y) = (ALL p >= 0. multiplicity p x <= multiplicity p y)"
  19.815 -  by (auto intro: dvd_multiplicity_int multiplicity_dvd_int)
  19.816 -
  19.817 -lemma prime_factors_altdef2_nat: "(n::nat) > 0 \<Longrightarrow> 
  19.818 -    (p : prime_factors n) = (prime p & p dvd n)"
  19.819 -  apply (case_tac "prime p")
  19.820 -  apply auto
  19.821 -  apply (subst prime_factorization_nat [where n = n], assumption)
  19.822 -  apply (rule dvd_trans) 
  19.823 -  apply (rule dvd_power [where x = p and n = "multiplicity p n"])
  19.824 -  apply (subst (asm) prime_factors_altdef_nat, force)
  19.825 -  apply (rule dvd_setprod)
  19.826 -  apply auto  
  19.827 -  apply (subst prime_factors_altdef_nat)
  19.828 -  apply (subst (asm) dvd_multiplicity_eq_nat)
  19.829 -  apply auto
  19.830 -  apply (drule spec [where x = p])
  19.831 -  apply auto
  19.832 -done
  19.833 -
  19.834 -lemma prime_factors_altdef2_int: 
  19.835 -  assumes "(n::int) > 0" 
  19.836 -  shows "(p : prime_factors n) = (prime p & p dvd n)"
  19.837 -
  19.838 -  apply (case_tac "p >= 0")
  19.839 -  apply (rule prime_factors_altdef2_nat [transferred])
  19.840 -  using prems apply auto
  19.841 -  apply (auto simp add: prime_ge_0_int prime_factors_ge_0_int)
  19.842 -done
  19.843 -
  19.844 -lemma multiplicity_eq_nat:
  19.845 -  fixes x and y::nat 
  19.846 -  assumes [arith]: "x > 0" "y > 0" and
  19.847 -    mult_eq [simp]: "!!p. prime p \<Longrightarrow> multiplicity p x = multiplicity p y"
  19.848 -  shows "x = y"
  19.849 -
  19.850 -  apply (rule dvd_anti_sym)
  19.851 -  apply (auto intro: multiplicity_dvd'_nat) 
  19.852 -done
  19.853 -
  19.854 -lemma multiplicity_eq_int:
  19.855 -  fixes x and y::int 
  19.856 -  assumes [arith]: "x > 0" "y > 0" and
  19.857 -    mult_eq [simp]: "!!p. prime p \<Longrightarrow> multiplicity p x = multiplicity p y"
  19.858 -  shows "x = y"
  19.859 -
  19.860 -  apply (rule dvd_anti_sym [transferred])
  19.861 -  apply (auto intro: multiplicity_dvd'_int) 
  19.862 -done
  19.863 -
  19.864 -
  19.865 -subsection {* An application *}
  19.866 -
  19.867 -lemma gcd_eq_nat: 
  19.868 -  assumes pos [arith]: "x > 0" "y > 0"
  19.869 -  shows "gcd (x::nat) y = 
  19.870 -    (PROD p: prime_factors x Un prime_factors y. 
  19.871 -      p ^ (min (multiplicity p x) (multiplicity p y)))"
  19.872 -proof -
  19.873 -  def z == "(PROD p: prime_factors (x::nat) Un prime_factors y. 
  19.874 -      p ^ (min (multiplicity p x) (multiplicity p y)))"
  19.875 -  have [arith]: "z > 0"
  19.876 -    unfolding z_def by (rule setprod_pos_nat, auto)
  19.877 -  have aux: "!!p. prime p \<Longrightarrow> multiplicity p z = 
  19.878 -      min (multiplicity p x) (multiplicity p y)"
  19.879 -    unfolding z_def
  19.880 -    apply (subst multiplicity_prod_prime_powers_nat)
  19.881 -    apply (auto simp add: multiplicity_not_factor_nat)
  19.882 -    done
  19.883 -  have "z dvd x" 
  19.884 -    by (intro multiplicity_dvd'_nat, auto simp add: aux)
  19.885 -  moreover have "z dvd y" 
  19.886 -    by (intro multiplicity_dvd'_nat, auto simp add: aux)
  19.887 -  moreover have "ALL w. w dvd x & w dvd y \<longrightarrow> w dvd z"
  19.888 -    apply auto
  19.889 -    apply (case_tac "w = 0", auto)
  19.890 -    apply (erule multiplicity_dvd'_nat)
  19.891 -    apply (auto intro: dvd_multiplicity_nat simp add: aux)
  19.892 -    done
  19.893 -  ultimately have "z = gcd x y"
  19.894 -    by (subst gcd_unique_nat [symmetric], blast)
  19.895 -  thus ?thesis
  19.896 -    unfolding z_def by auto
  19.897 -qed
  19.898 -
  19.899 -lemma lcm_eq_nat: 
  19.900 -  assumes pos [arith]: "x > 0" "y > 0"
  19.901 -  shows "lcm (x::nat) y = 
  19.902 -    (PROD p: prime_factors x Un prime_factors y. 
  19.903 -      p ^ (max (multiplicity p x) (multiplicity p y)))"
  19.904 -proof -
  19.905 -  def z == "(PROD p: prime_factors (x::nat) Un prime_factors y. 
  19.906 -      p ^ (max (multiplicity p x) (multiplicity p y)))"
  19.907 -  have [arith]: "z > 0"
  19.908 -    unfolding z_def by (rule setprod_pos_nat, auto)
  19.909 -  have aux: "!!p. prime p \<Longrightarrow> multiplicity p z = 
  19.910 -      max (multiplicity p x) (multiplicity p y)"
  19.911 -    unfolding z_def
  19.912 -    apply (subst multiplicity_prod_prime_powers_nat)
  19.913 -    apply (auto simp add: multiplicity_not_factor_nat)
  19.914 -    done
  19.915 -  have "x dvd z" 
  19.916 -    by (intro multiplicity_dvd'_nat, auto simp add: aux)
  19.917 -  moreover have "y dvd z" 
  19.918 -    by (intro multiplicity_dvd'_nat, auto simp add: aux)
  19.919 -  moreover have "ALL w. x dvd w & y dvd w \<longrightarrow> z dvd w"
  19.920 -    apply auto
  19.921 -    apply (case_tac "w = 0", auto)
  19.922 -    apply (rule multiplicity_dvd'_nat)
  19.923 -    apply (auto intro: dvd_multiplicity_nat simp add: aux)
  19.924 -    done
  19.925 -  ultimately have "z = lcm x y"
  19.926 -    by (subst lcm_unique_nat [symmetric], blast)
  19.927 -  thus ?thesis
  19.928 -    unfolding z_def by auto
  19.929 -qed
  19.930 -
  19.931 -lemma multiplicity_gcd_nat: 
  19.932 -  assumes [arith]: "x > 0" "y > 0"
  19.933 -  shows "multiplicity (p::nat) (gcd x y) = 
  19.934 -    min (multiplicity p x) (multiplicity p y)"
  19.935 -
  19.936 -  apply (subst gcd_eq_nat)
  19.937 -  apply auto
  19.938 -  apply (subst multiplicity_prod_prime_powers_nat)
  19.939 -  apply auto
  19.940 -done
  19.941 -
  19.942 -lemma multiplicity_lcm_nat: 
  19.943 -  assumes [arith]: "x > 0" "y > 0"
  19.944 -  shows "multiplicity (p::nat) (lcm x y) = 
  19.945 -    max (multiplicity p x) (multiplicity p y)"
  19.946 -
  19.947 -  apply (subst lcm_eq_nat)
  19.948 -  apply auto
  19.949 -  apply (subst multiplicity_prod_prime_powers_nat)
  19.950 -  apply auto
  19.951 -done
  19.952 -
  19.953 -lemma gcd_lcm_distrib_nat: "gcd (x::nat) (lcm y z) = lcm (gcd x y) (gcd x z)"
  19.954 -  apply (case_tac "x = 0 | y = 0 | z = 0") 
  19.955 -  apply auto
  19.956 -  apply (rule multiplicity_eq_nat)
  19.957 -  apply (auto simp add: multiplicity_gcd_nat multiplicity_lcm_nat 
  19.958 -      lcm_pos_nat)
  19.959 -done
  19.960 -
  19.961 -lemma gcd_lcm_distrib_int: "gcd (x::int) (lcm y z) = lcm (gcd x y) (gcd x z)"
  19.962 -  apply (subst (1 2 3) gcd_abs_int)
  19.963 -  apply (subst lcm_abs_int)
  19.964 -  apply (subst (2) abs_of_nonneg)
  19.965 -  apply force
  19.966 -  apply (rule gcd_lcm_distrib_nat [transferred])
  19.967 -  apply auto
  19.968 -done
  19.969 -
  19.970 -end
    20.1 --- a/src/HOL/NumberTheory/BijectionRel.thy	Tue Sep 01 14:13:34 2009 +0200
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,231 +0,0 @@
    20.4 -(*  Title:      HOL/NumberTheory/BijectionRel.thy
    20.5 -    ID:         $Id$
    20.6 -    Author:     Thomas M. Rasmussen
    20.7 -    Copyright   2000  University of Cambridge
    20.8 -*)
    20.9 -
   20.10 -header {* Bijections between sets *}
   20.11 -
   20.12 -theory BijectionRel imports Main begin
   20.13 -
   20.14 -text {*
   20.15 -  Inductive definitions of bijections between two different sets and
   20.16 -  between the same set.  Theorem for relating the two definitions.
   20.17 -
   20.18 -  \bigskip
   20.19 -*}
   20.20 -
   20.21 -inductive_set
   20.22 -  bijR :: "('a => 'b => bool) => ('a set * 'b set) set"
   20.23 -  for P :: "'a => 'b => bool"
   20.24 -where
   20.25 -  empty [simp]: "({}, {}) \<in> bijR P"
   20.26 -| insert: "P a b ==> a \<notin> A ==> b \<notin> B ==> (A, B) \<in> bijR P
   20.27 -    ==> (insert a A, insert b B) \<in> bijR P"
   20.28 -
   20.29 -text {*
   20.30 -  Add extra condition to @{term insert}: @{term "\<forall>b \<in> B. \<not> P a b"}
   20.31 -  (and similar for @{term A}).
   20.32 -*}
   20.33 -
   20.34 -definition
   20.35 -  bijP :: "('a => 'a => bool) => 'a set => bool" where
   20.36 -  "bijP P F = (\<forall>a b. a \<in> F \<and> P a b --> b \<in> F)"
   20.37 -
   20.38 -definition
   20.39 -  uniqP :: "('a => 'a => bool) => bool" where
   20.40 -  "uniqP P = (\<forall>a b c d. P a b \<and> P c d --> (a = c) = (b = d))"
   20.41 -
   20.42 -definition
   20.43 -  symP :: "('a => 'a => bool) => bool" where
   20.44 -  "symP P = (\<forall>a b. P a b = P b a)"
   20.45 -
   20.46 -inductive_set
   20.47 -  bijER :: "('a => 'a => bool) => 'a set set"
   20.48 -  for P :: "'a => 'a => bool"
   20.49 -where
   20.50 -  empty [simp]: "{} \<in> bijER P"
   20.51 -| insert1: "P a a ==> a \<notin> A ==> A \<in> bijER P ==> insert a A \<in> bijER P"
   20.52 -| insert2: "P a b ==> a \<noteq> b ==> a \<notin> A ==> b \<notin> A ==> A \<in> bijER P
   20.53 -    ==> insert a (insert b A) \<in> bijER P"
   20.54 -
   20.55 -
   20.56 -text {* \medskip @{term bijR} *}
   20.57 -
   20.58 -lemma fin_bijRl: "(A, B) \<in> bijR P ==> finite A"
   20.59 -  apply (erule bijR.induct)
   20.60 -  apply auto
   20.61 -  done
   20.62 -
   20.63 -lemma fin_bijRr: "(A, B) \<in> bijR P ==> finite B"
   20.64 -  apply (erule bijR.induct)
   20.65 -  apply auto
   20.66 -  done
   20.67 -
   20.68 -lemma aux_induct:
   20.69 -  assumes major: "finite F"
   20.70 -    and subs: "F \<subseteq> A"
   20.71 -    and cases: "P {}"
   20.72 -      "!!F a. F \<subseteq> A ==> a \<in> A ==> a \<notin> F ==> P F ==> P (insert a F)"
   20.73 -  shows "P F"
   20.74 -  using major subs
   20.75 -  apply (induct set: finite)
   20.76 -   apply (blast intro: cases)+
   20.77 -  done
   20.78 -
   20.79 -
   20.80 -lemma inj_func_bijR_aux1:
   20.81 -    "A \<subseteq> B ==> a \<notin> A ==> a \<in> B ==> inj_on f B ==> f a \<notin> f ` A"
   20.82 -  apply (unfold inj_on_def)
   20.83 -  apply auto
   20.84 -  done
   20.85 -
   20.86 -lemma inj_func_bijR_aux2:
   20.87 -  "\<forall>a. a \<in> A --> P a (f a) ==> inj_on f A ==> finite A ==> F <= A
   20.88 -    ==> (F, f ` F) \<in> bijR P"
   20.89 -  apply (rule_tac F = F and A = A in aux_induct)
   20.90 -     apply (rule finite_subset)
   20.91 -      apply auto
   20.92 -  apply (rule bijR.insert)
   20.93 -     apply (rule_tac [3] inj_func_bijR_aux1)
   20.94 -        apply auto
   20.95 -  done
   20.96 -
   20.97 -lemma inj_func_bijR:
   20.98 -  "\<forall>a. a \<in> A --> P a (f a) ==> inj_on f A ==> finite A
   20.99 -    ==> (A, f ` A) \<in> bijR P"
  20.100 -  apply (rule inj_func_bijR_aux2)
  20.101 -     apply auto
  20.102 -  done
  20.103 -
  20.104 -
  20.105 -text {* \medskip @{term bijER} *}
  20.106 -
  20.107 -lemma fin_bijER: "A \<in> bijER P ==> finite A"
  20.108 -  apply (erule bijER.induct)
  20.109 -    apply auto
  20.110 -  done
  20.111 -
  20.112 -lemma aux1:
  20.113 -  "a \<notin> A ==> a \<notin> B ==> F \<subseteq> insert a A ==> F \<subseteq> insert a B ==> a \<in> F
  20.114 -    ==> \<exists>C. F = insert a C \<and> a \<notin> C \<and> C <= A \<and> C <= B"
  20.115 -  apply (rule_tac x = "F - {a}" in exI)
  20.116 -  apply auto
  20.117 -  done
  20.118 -
  20.119 -lemma aux2: "a \<noteq> b ==> a \<notin> A ==> b \<notin> B ==> a \<in> F ==> b \<in> F
  20.120 -    ==> F \<subseteq> insert a A ==> F \<subseteq> insert b B
  20.121 -    ==> \<exists>C. F = insert a (insert b C) \<and> a \<notin> C \<and> b \<notin> C \<and> C \<subseteq> A \<and> C \<subseteq> B"
  20.122 -  apply (rule_tac x = "F - {a, b}" in exI)
  20.123 -  apply auto
  20.124 -  done
  20.125 -
  20.126 -lemma aux_uniq: "uniqP P ==> P a b ==> P c d ==> (a = c) = (b = d)"
  20.127 -  apply (unfold uniqP_def)
  20.128 -  apply auto
  20.129 -  done
  20.130 -
  20.131 -lemma aux_sym: "symP P ==> P a b = P b a"
  20.132 -  apply (unfold symP_def)
  20.133 -  apply auto
  20.134 -  done
  20.135 -
  20.136 -lemma aux_in1:
  20.137 -    "uniqP P ==> b \<notin> C ==> P b b ==> bijP P (insert b C) ==> bijP P C"
  20.138 -  apply (unfold bijP_def)
  20.139 -  apply auto
  20.140 -  apply (subgoal_tac "b \<noteq> a")
  20.141 -   prefer 2
  20.142 -   apply clarify
  20.143 -  apply (simp add: aux_uniq)
  20.144 -  apply auto
  20.145 -  done
  20.146 -
  20.147 -lemma aux_in2:
  20.148 -  "symP P ==> uniqP P ==> a \<notin> C ==> b \<notin> C ==> a \<noteq> b ==> P a b
  20.149 -    ==> bijP P (insert a (insert b C)) ==> bijP P C"
  20.150 -  apply (unfold bijP_def)
  20.151 -  apply auto
  20.152 -  apply (subgoal_tac "aa \<noteq> a")
  20.153 -   prefer 2
  20.154 -   apply clarify
  20.155 -  apply (subgoal_tac "aa \<noteq> b")
  20.156 -   prefer 2
  20.157 -   apply clarify
  20.158 -  apply (simp add: aux_uniq)
  20.159 -  apply (subgoal_tac "ba \<noteq> a")
  20.160 -   apply auto
  20.161 -  apply (subgoal_tac "P a aa")
  20.162 -   prefer 2
  20.163 -   apply (simp add: aux_sym)
  20.164 -  apply (subgoal_tac "b = aa")
  20.165 -   apply (rule_tac [2] iffD1)
  20.166 -    apply (rule_tac [2] a = a and c = a and P = P in aux_uniq)
  20.167 -      apply auto
  20.168 -  done
  20.169 -
  20.170 -lemma aux_foo: "\<forall>a b. Q a \<and> P a b --> R b ==> P a b ==> Q a ==> R b"
  20.171 -  apply auto
  20.172 -  done
  20.173 -
  20.174 -lemma aux_bij: "bijP P F ==> symP P ==> P a b ==> (a \<in> F) = (b \<in> F)"
  20.175 -  apply (unfold bijP_def)
  20.176 -  apply (rule iffI)
  20.177 -  apply (erule_tac [!] aux_foo)
  20.178 -      apply simp_all
  20.179 -  apply (rule iffD2)
  20.180 -   apply (rule_tac P = P in aux_sym)
  20.181 -   apply simp_all
  20.182 -  done
  20.183 -
  20.184 -
  20.185 -lemma aux_bijRER:
  20.186 -  "(A, B) \<in> bijR P ==> uniqP P ==> symP P
  20.187 -    ==> \<forall>F. bijP P F \<and> F \<subseteq> A \<and> F \<subseteq> B --> F \<in> bijER P"
  20.188 -  apply (erule bijR.induct)
  20.189 -   apply simp
  20.190 -  apply (case_tac "a = b")
  20.191 -   apply clarify
  20.192 -   apply (case_tac "b \<in> F")
  20.193 -    prefer 2
  20.194 -    apply (simp add: subset_insert)
  20.195 -   apply (cut_tac F = F and a = b and A = A and B = B in aux1)
  20.196 -        prefer 6
  20.197 -        apply clarify
  20.198 -        apply (rule bijER.insert1)
  20.199 -          apply simp_all
  20.200 -   apply (subgoal_tac "bijP P C")
  20.201 -    apply simp
  20.202 -   apply (rule aux_in1)
  20.203 -      apply simp_all
  20.204 -  apply clarify
  20.205 -  apply (case_tac "a \<in> F")
  20.206 -   apply (case_tac [!] "b \<in> F")
  20.207 -     apply (cut_tac F = F and a = a and b = b and A = A and B = B
  20.208 -       in aux2)
  20.209 -            apply (simp_all add: subset_insert)
  20.210 -    apply clarify
  20.211 -    apply (rule bijER.insert2)
  20.212 -        apply simp_all
  20.213 -    apply (subgoal_tac "bijP P C")
  20.214 -     apply simp
  20.215 -    apply (rule aux_in2)
  20.216 -          apply simp_all
  20.217 -   apply (subgoal_tac "b \<in> F")
  20.218 -    apply (rule_tac [2] iffD1)
  20.219 -     apply (rule_tac [2] a = a and F = F and P = P in aux_bij)
  20.220 -       apply (simp_all (no_asm_simp))
  20.221 -   apply (subgoal_tac [2] "a \<in> F")
  20.222 -    apply (rule_tac [3] iffD2)
  20.223 -     apply (rule_tac [3] b = b and F = F and P = P in aux_bij)
  20.224 -       apply auto
  20.225 -  done
  20.226 -
  20.227 -lemma bijR_bijER:
  20.228 -  "(A, A) \<in> bijR P ==>
  20.229 -    bijP P A ==> uniqP P ==> symP P ==> A \<in> bijER P"
  20.230 -  apply (cut_tac A = A and B = A and P = P in aux_bijRER)
  20.231 -     apply auto
  20.232 -  done
  20.233 -
  20.234 -end
    21.1 --- a/src/HOL/NumberTheory/Chinese.thy	Tue Sep 01 14:13:34 2009 +0200
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,259 +0,0 @@
    21.4 -(*  Title:      HOL/NumberTheory/Chinese.thy
    21.5 -    ID:         $Id$
    21.6 -    Author:     Thomas M. Rasmussen
    21.7 -    Copyright   2000  University of Cambridge
    21.8 -*)
    21.9 -
   21.10 -header {* The Chinese Remainder Theorem *}
   21.11 -
   21.12 -theory Chinese 
   21.13 -imports IntPrimes
   21.14 -begin
   21.15 -
   21.16 -text {*
   21.17 -  The Chinese Remainder Theorem for an arbitrary finite number of
   21.18 -  equations.  (The one-equation case is included in theory @{text
   21.19 -  IntPrimes}.  Uses functions for indexing.\footnote{Maybe @{term
   21.20 -