HOL-NumberTheory: converted to new-style format and proper document setup;
authorwenzelm
Sun Feb 04 19:31:13 2001 +0100 (2001-02-04)
changeset 110497eef34adb852
parent 11048 2f4976370b7a
child 11050 ac5709ac50b9
HOL-NumberTheory: converted to new-style format and proper document setup;
src/HOL/IsaMakefile
src/HOL/NumberTheory/BijectionRel.ML
src/HOL/NumberTheory/BijectionRel.thy
src/HOL/NumberTheory/Chinese.ML
src/HOL/NumberTheory/Chinese.thy
src/HOL/NumberTheory/EulerFermat.thy
src/HOL/NumberTheory/Factorization.ML
src/HOL/NumberTheory/Factorization.thy
src/HOL/NumberTheory/Fib.ML
src/HOL/NumberTheory/Fib.thy
src/HOL/NumberTheory/IntFact.ML
src/HOL/NumberTheory/IntFact.thy
src/HOL/NumberTheory/IntPrimes.ML
src/HOL/NumberTheory/IntPrimes.thy
src/HOL/NumberTheory/Primes.thy
src/HOL/NumberTheory/README
src/HOL/NumberTheory/ROOT.ML
src/HOL/NumberTheory/WilsonBij.ML
src/HOL/NumberTheory/WilsonBij.thy
src/HOL/NumberTheory/WilsonRuss.ML
src/HOL/NumberTheory/WilsonRuss.thy
     1.1 --- a/src/HOL/IsaMakefile	Sat Feb 03 17:43:34 2001 +0100
     1.2 +++ b/src/HOL/IsaMakefile	Sun Feb 04 19:31:13 2001 +0100
     1.3 @@ -180,7 +180,7 @@
     1.4  
     1.5  $(LOG)/HOL-Library.gz: $(OUT)/HOL Library/Accessible_Part.thy \
     1.6    Library/Library.thy Library/List_Prefix.thy Library/Multiset.thy \
     1.7 -  Library/Quotient.thy Library/Ring_and_Field.thy \
     1.8 +  Library/Permutation.thy Library/Quotient.thy Library/Ring_and_Field.thy \
     1.9    Library/Ring_and_Field_Example.thy Library/README.html \
    1.10    Library/Nested_Environment.thy Library/Rational_Numbers.thy Library/ROOT.ML \
    1.11    Library/While_Combinator.thy
    1.12 @@ -205,8 +205,8 @@
    1.13  $(LOG)/HOL-Induct.gz: $(OUT)/HOL \
    1.14    Induct/Com.ML Induct/Com.thy Induct/Comb.ML Induct/Comb.thy \
    1.15    Induct/Exp.ML Induct/Exp.thy Induct/LFilter.ML Induct/LFilter.thy \
    1.16 -  Induct/LList.ML Induct/LList.thy Induct/Mutil.thy Induct/Perm.ML \
    1.17 -  Induct/Perm.thy Induct/PropLog.ML Induct/PropLog.thy Induct/ROOT.ML \
    1.18 +  Induct/LList.ML Induct/LList.thy Induct/Mutil.thy \
    1.19 +  Induct/PropLog.ML Induct/PropLog.thy Induct/ROOT.ML \
    1.20    Induct/Sexp.ML Induct/Sexp.thy Induct/Sigma_Algebra.thy \
    1.21    Induct/SList.ML Induct/SList.thy Induct/ABexp.thy Induct/Term.thy \
    1.22    Induct/Tree.thy Induct/document/root.tex
    1.23 @@ -239,15 +239,11 @@
    1.24  HOL-NumberTheory: HOL $(LOG)/HOL-NumberTheory.gz
    1.25  
    1.26  $(LOG)/HOL-NumberTheory.gz: $(OUT)/HOL \
    1.27 -  NumberTheory/Fib.ML NumberTheory/Fib.thy NumberTheory/Primes.thy \
    1.28 -  NumberTheory/Factorization.ML NumberTheory/Factorization.thy \
    1.29 -  NumberTheory/BijectionRel.ML NumberTheory/BijectionRel.thy \
    1.30 -  NumberTheory/Chinese.ML NumberTheory/Chinese.thy \
    1.31 -  NumberTheory/EulerFermat.ML NumberTheory/EulerFermat.thy \
    1.32 -  NumberTheory/IntFact.ML NumberTheory/IntFact.thy \
    1.33 -  NumberTheory/IntPrimes.ML NumberTheory/IntPrimes.thy \
    1.34 -  NumberTheory/WilsonBij.ML NumberTheory/WilsonBij.thy \
    1.35 -  NumberTheory/WilsonRuss.ML NumberTheory/WilsonRuss.thy \
    1.36 +  Library/Permutation.thy NumberTheory/Fib.thy NumberTheory/Primes.thy \
    1.37 +  NumberTheory/Factorization.thy NumberTheory/BijectionRel.thy \
    1.38 +  NumberTheory/Chinese.thy NumberTheory/EulerFermat.thy \
    1.39 +  NumberTheory/IntFact.thy NumberTheory/IntPrimes.thy \
    1.40 +  NumberTheory/WilsonBij.thy NumberTheory/WilsonRuss.thy \
    1.41    NumberTheory/ROOT.ML
    1.42  	@$(ISATOOL) usedir $(OUT)/HOL NumberTheory
    1.43  
     2.1 --- a/src/HOL/NumberTheory/BijectionRel.ML	Sat Feb 03 17:43:34 2001 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,182 +0,0 @@
     2.4 -(*  Title:	BijectionRel.ML
     2.5 -    ID:         $Id$
     2.6 -    Author:	Thomas M. Rasmussen
     2.7 -    Copyright	2000  University of Cambridge
     2.8 -
     2.9 -Inductive definitions of bijections between two different sets and
    2.10 -	between the same set. 
    2.11 -Theorem for relating the two definitions
    2.12 -*)
    2.13 -
    2.14 -
    2.15 -(***** bijR *****)
    2.16 -
    2.17 -Addsimps [bijR.empty];
    2.18 -
    2.19 -Goal "(A,B) : (bijR P) ==> finite A";
    2.20 -by (etac bijR.induct 1);
    2.21 -by Auto_tac;
    2.22 -qed "fin_bijRl";
    2.23 -
    2.24 -Goal "(A,B) : (bijR P) ==> finite B";
    2.25 -by (etac bijR.induct 1);
    2.26 -by Auto_tac;
    2.27 -qed "fin_bijRr";
    2.28 -
    2.29 -val major::subs::prems = 
    2.30 -Goal "[| finite F;  F <= A; P({}); \
    2.31 -\        !!F a. [| F <= A; a:A; a ~: F;  P(F) |] ==> P(insert a F) |] \
    2.32 -\     ==> P(F)";
    2.33 -by (rtac (subs RS rev_mp) 1);
    2.34 -by (rtac (major RS finite_induct) 1);
    2.35 -by (ALLGOALS (blast_tac (claset() addIs prems)));
    2.36 -val lemma_induct = result();
    2.37 -
    2.38 -Goalw [inj_on_def] 
    2.39 -      "[| A <= B; a ~: A ; a : B; inj_on f B |] ==> (f a) ~: f`A";
    2.40 -by Auto_tac;
    2.41 -val lemma = result();
    2.42 -
    2.43 -Goal "[| ALL a. a:A --> P a (f a); inj_on f A; finite A; F <= A |] \
    2.44 -\    ==> (F,f`F) : bijR P";
    2.45 -by (res_inst_tac [("F","F"),("A","A")] lemma_induct 1);
    2.46 -by (rtac finite_subset 1);
    2.47 -by Auto_tac;
    2.48 -by (rtac bijR.insert 1);
    2.49 -by (rtac lemma 3);
    2.50 -by Auto_tac;
    2.51 -val lemma = result();
    2.52 -
    2.53 -Goal "[| ALL a. a:A --> P a (f a); inj_on f A; finite A |] \
    2.54 -\    ==> (A,f`A) : bijR P";
    2.55 -by (rtac lemma 1);
    2.56 -by Auto_tac;
    2.57 -qed "inj_func_bijR";
    2.58 -
    2.59 -
    2.60 -(***** bijER *****)
    2.61 -
    2.62 -Addsimps [bijER.empty];
    2.63 -
    2.64 -Goal "A : bijER P ==> finite A";
    2.65 -by (etac bijER.induct 1);
    2.66 -by Auto_tac;
    2.67 -qed "fin_bijER";
    2.68 -
    2.69 -Goal "[| a ~: A; a ~: B; F <= insert a A; F <= insert a B; a : F |] \
    2.70 -\    ==> (EX C. F = insert a C & a ~: C & C <= A & C <= B)";
    2.71 -by (res_inst_tac [("x","F-{a}")] exI 1);
    2.72 -by Auto_tac;
    2.73 -val lemma1 = result();
    2.74 -
    2.75 -Goal "[| a ~= b; a ~: A; b ~: B; a : F; b : F; \
    2.76 -\        F <= insert a A; F <= insert b B |] \
    2.77 -\    ==> (EX C. F = insert a (insert b C) & a ~: C & b ~: C & \
    2.78 -\         C <= A & C <= B)";
    2.79 -by (res_inst_tac [("x","F-{a,b}")] exI 1);
    2.80 -by Auto_tac;
    2.81 -val lemma2 = result();
    2.82 -
    2.83 -Goalw [uniqP_def] "[| uniqP P; P a b; P c d |] ==> (a=c) = (b=d)";
    2.84 -by Auto_tac;
    2.85 -val lemma_uniq = result();
    2.86 -
    2.87 -Goalw [symP_def] "symP P ==> (P a b) = (P b a)";
    2.88 -by Auto_tac;
    2.89 -val lemma_sym = result();
    2.90 -
    2.91 -Goalw [bijP_def] 
    2.92 -      "[| uniqP P; b ~: C; P b b; bijP P (insert b C) |] ==> bijP P C";
    2.93 -by Auto_tac;
    2.94 -by (subgoal_tac "b~=a" 1);
    2.95 -by (Clarify_tac 2);
    2.96 -by (asm_full_simp_tac (simpset() addsimps [lemma_uniq]) 1);
    2.97 -by Auto_tac;
    2.98 -val lemma_in1 = result();
    2.99 -
   2.100 -Goalw [bijP_def] 
   2.101 -      "[| symP P; uniqP P; a ~: C; b ~: C; a ~= b; P a b; \
   2.102 -\         bijP P (insert a (insert b C)) |] ==> bijP P C";
   2.103 -by Auto_tac;
   2.104 -by (subgoal_tac "aa~=a" 1);
   2.105 -by (Clarify_tac 2);
   2.106 -by (subgoal_tac "aa~=b" 1);
   2.107 -by (Clarify_tac 2);
   2.108 -by (asm_full_simp_tac (simpset() addsimps [lemma_uniq]) 1);
   2.109 -by (subgoal_tac "ba~=a" 1);
   2.110 -by Auto_tac;
   2.111 -by (subgoal_tac "P a aa" 1);
   2.112 -by (asm_simp_tac (simpset() addsimps [lemma_sym]) 2);
   2.113 -by (subgoal_tac "b=aa" 1);
   2.114 -by (rtac iffD1 2);
   2.115 -by (res_inst_tac [("a","a"),("c","a"),("P","P")] lemma_uniq 2);
   2.116 -by Auto_tac;
   2.117 -val lemma_in2 = result();
   2.118 -
   2.119 -Goal "[| ALL a b. Q a & P a b --> R b; P a b; Q a |] ==> R b";
   2.120 -by Auto_tac;
   2.121 -val lemma = result();
   2.122 -
   2.123 -Goalw [bijP_def] "[| bijP P F; symP P; P a b |] ==> (a:F) = (b:F)";
   2.124 -by (rtac iffI 1);
   2.125 -by (ALLGOALS (etac lemma));
   2.126 -by (ALLGOALS Asm_simp_tac);
   2.127 -by (rtac iffD2 1);
   2.128 -by (res_inst_tac [("P","P")] lemma_sym 1);
   2.129 -by (ALLGOALS Asm_simp_tac);
   2.130 -val lemma_bij = result();
   2.131 -
   2.132 -Goal "[| (A,B) : bijR P; uniqP P; symP P |] \
   2.133 -\     ==> (ALL F. (bijP P F) & F<=A & F<=B --> F : bijER P)";
   2.134 -by (etac bijR.induct 1);
   2.135 -by (Simp_tac 1);
   2.136 -by (case_tac "a=b" 1);
   2.137 -by (Clarify_tac 1);
   2.138 -by (case_tac "b:F" 1);
   2.139 -by (rotate_tac ~1 2);
   2.140 -by (asm_full_simp_tac (simpset() addsimps [subset_insert]) 2);
   2.141 -by (cut_inst_tac [("F","F"),("a","b"),("A","A"),("B","B")] lemma1 1);
   2.142 -by (Clarify_tac 6);
   2.143 -by (rtac bijER.insert1 6);
   2.144 -by (ALLGOALS Asm_full_simp_tac);
   2.145 -by (subgoal_tac "bijP P C" 1);
   2.146 -by (Asm_full_simp_tac 1);
   2.147 -by (rtac lemma_in1 1);
   2.148 -by (ALLGOALS Asm_simp_tac);
   2.149 -by (Clarify_tac 1);
   2.150 -by (case_tac "a:F" 1);
   2.151 -by (ALLGOALS (case_tac "b:F"));
   2.152 -by (rotate_tac ~2 4);
   2.153 -by (asm_full_simp_tac (simpset() addsimps [subset_insert]) 4);
   2.154 -by (rotate_tac ~2 3);
   2.155 -by (asm_full_simp_tac (simpset() addsimps [subset_insert]) 3);
   2.156 -by (rotate_tac ~2 2);
   2.157 -by (asm_full_simp_tac (simpset() addsimps [subset_insert]) 2);
   2.158 -by (cut_inst_tac [("F","F"),("a","a"),("b","b"),("A","A"),("B","B")] 
   2.159 -                 lemma2 1);
   2.160 -by (ALLGOALS Asm_simp_tac);
   2.161 -by (Clarify_tac 1);
   2.162 -by (rtac bijER.insert2 1);
   2.163 -by (ALLGOALS Asm_simp_tac);
   2.164 -by (subgoal_tac "bijP P C" 1);
   2.165 -by (Asm_full_simp_tac 1);
   2.166 -by (rtac lemma_in2 1);
   2.167 -by (ALLGOALS Asm_simp_tac);
   2.168 -by (subgoal_tac "b:F" 1);
   2.169 -by (rtac iffD1 2);
   2.170 -by (res_inst_tac [("a","a"),("F","F"),("P","P")] lemma_bij 2);
   2.171 -by (ALLGOALS Asm_simp_tac);
   2.172 -by (subgoal_tac "a:F" 2);
   2.173 -by (rtac iffD2 3);
   2.174 -by (res_inst_tac [("b","b"),("F","F"),("P","P")] lemma_bij 3);
   2.175 -by Auto_tac;
   2.176 -val lemma_bijRER = result();
   2.177 -
   2.178 -Goal "[| (A,A) : bijR P; (bijP P A); uniqP P; symP P |] ==> A : bijER P";
   2.179 -by (cut_inst_tac [("A","A"),("B","A"),("P","P")] lemma_bijRER 1);
   2.180 -by Auto_tac;
   2.181 -qed "bijR_bijER";
   2.182 -
   2.183 -
   2.184 -
   2.185 -
     3.1 --- a/src/HOL/NumberTheory/BijectionRel.thy	Sat Feb 03 17:43:34 2001 +0100
     3.2 +++ b/src/HOL/NumberTheory/BijectionRel.thy	Sun Feb 04 19:31:13 2001 +0100
     3.3 @@ -1,46 +1,235 @@
     3.4 -(*  Title:	BijectionRel.thy
     3.5 +(*  Title:      HOL/NumberTheory/BijectionRel.thy
     3.6      ID:         $Id$
     3.7 -    Author:	Thomas M. Rasmussen
     3.8 -    Copyright	2000  University of Cambridge
     3.9 +    Author:     Thomas M. Rasmussen
    3.10 +    Copyright   2000  University of Cambridge
    3.11  *)
    3.12  
    3.13 -BijectionRel = Main +
    3.14 +header {* Bijections between sets *}
    3.15 +
    3.16 +theory BijectionRel = Main:
    3.17 +
    3.18 +text {*
    3.19 +  Inductive definitions of bijections between two different sets and
    3.20 +  between the same set.  Theorem for relating the two definitions.
    3.21 +
    3.22 +  \bigskip
    3.23 +*}
    3.24  
    3.25  consts
    3.26 -  bijR :: "(['a, 'b] => bool) => ('a set * 'b set) set"
    3.27 +  bijR :: "('a => 'b => bool) => ('a set * 'b set) set"
    3.28  
    3.29  inductive "bijR P"
    3.30 -intrs
    3.31 -  empty  "({},{}) : bijR P"
    3.32 -  insert "[| P a b; a ~: A; b ~: B; (A,B) : bijR P |] \ 
    3.33 -\        ==> (insert a A, insert b B) : bijR P" 
    3.34 +  intros
    3.35 +  empty [simp]: "({}, {}) \<in> bijR P"
    3.36 +  insert: "P a b ==> a \<notin> A ==> b \<notin> B ==> (A, B) \<in> bijR P
    3.37 +    ==> (insert a A, insert b B) \<in> bijR P"
    3.38 +
    3.39 +text {*
    3.40 +  Add extra condition to @{term insert}: @{term "\<forall>b \<in> B. \<not> P a b"}
    3.41 +  (and similar for @{term A}).
    3.42 +*}
    3.43  
    3.44 -(* Add extra condition to insert: ALL b:B. ~(P a b) (and similar for A) *) 
    3.45 +constdefs
    3.46 +  bijP :: "('a => 'a => bool) => 'a set => bool"
    3.47 +  "bijP P F == \<forall>a b. a \<in> F \<and> P a b --> b \<in> F"
    3.48 +
    3.49 +  uniqP :: "('a => 'a => bool) => bool"
    3.50 +  "uniqP P == \<forall>a b c d. P a b \<and> P c d --> (a = c) = (b = d)"
    3.51 +
    3.52 +  symP :: "('a => 'a => bool) => bool"
    3.53 +  "symP P == \<forall>a b. P a b = P b a"
    3.54  
    3.55  consts
    3.56 -  bijP :: "(['a, 'a] => bool) => 'a set => bool"
    3.57 -
    3.58 -defs
    3.59 -  bijP_def "bijP P F == (ALL a b. a:F & P a b --> b:F)" 
    3.60 -
    3.61 -consts
    3.62 -  uniqP :: "(['a, 'a] => bool) => bool"
    3.63 -  symP :: "(['a, 'a] => bool) => bool"
    3.64 -  
    3.65 -defs
    3.66 -  uniqP_def "uniqP P == (ALL a b c d. P a b & P c d --> (a=c) = (b=d))" 
    3.67 -  symP_def  "symP P  == (ALL a b. (P a b) = (P b a))" 
    3.68 -
    3.69 -consts
    3.70 -  bijER :: "(['a, 'a] => bool) => 'a set set"
    3.71 +  bijER :: "('a => 'a => bool) => 'a set set"
    3.72  
    3.73  inductive "bijER P"
    3.74 -intrs
    3.75 -  empty   "{} : bijER P"
    3.76 -  insert1 "[| P a a; a ~: A; A : bijER P |] \ 
    3.77 -\         ==> (insert a A) : bijER P" 
    3.78 -  insert2 "[| P a b; a ~= b; a ~: A; b ~: A; A : bijER P |] \ 
    3.79 -\         ==> (insert a (insert b A)) : bijER P" 
    3.80 +  intros
    3.81 +  empty [simp]: "{} \<in> bijER P"
    3.82 +  insert1: "P a a ==> a \<notin> A ==> A \<in> bijER P ==> insert a A \<in> bijER P"
    3.83 +  insert2: "P a b ==> a \<noteq> b ==> a \<notin> A ==> b \<notin> A ==> A \<in> bijER P
    3.84 +    ==> insert a (insert b A) \<in> bijER P"
    3.85 +
    3.86 +
    3.87 +text {* \medskip @{term bijR} *}
    3.88 +
    3.89 +lemma fin_bijRl: "(A, B) \<in> bijR P ==> finite A"
    3.90 +  apply (erule bijR.induct)
    3.91 +  apply auto
    3.92 +  done
    3.93 +
    3.94 +lemma fin_bijRr: "(A, B) \<in> bijR P ==> finite B"
    3.95 +  apply (erule bijR.induct)
    3.96 +  apply auto
    3.97 +  done
    3.98 +
    3.99 +lemma aux_induct:
   3.100 +  "finite F ==> F \<subseteq> A ==> P {} ==>
   3.101 +    (!!F a. F \<subseteq> A ==> a \<in> A ==> a \<notin> F ==> P F ==> P (insert a F))
   3.102 +  ==> P F"
   3.103 +proof -
   3.104 +  case antecedent
   3.105 +  assume major: "finite F"
   3.106 +    and subs: "F \<subseteq> A"
   3.107 +  show ?thesis
   3.108 +    apply (rule subs [THEN rev_mp])
   3.109 +    apply (rule major [THEN finite_induct])
   3.110 +     apply (blast intro: antecedent)+
   3.111 +    done
   3.112 +qed
   3.113 +
   3.114 +lemma aux: "A \<subseteq> B ==> a \<notin> A ==> a \<in> B ==> inj_on f B ==> f a \<notin> f ` A"
   3.115 +  apply (unfold inj_on_def)
   3.116 +  apply auto
   3.117 +  done
   3.118 +
   3.119 +lemma aux:
   3.120 +  "\<forall>a. a \<in> A --> P a (f a) ==> inj_on f A ==> finite A ==> F <= A
   3.121 +    ==> (F, f ` F) \<in> bijR P"
   3.122 +  apply (rule_tac F = F and A = A in aux_induct)
   3.123 +     apply (rule finite_subset)
   3.124 +      apply auto
   3.125 +  apply (rule bijR.insert)
   3.126 +     apply (rule_tac [3] aux)
   3.127 +        apply auto
   3.128 +  done
   3.129 +
   3.130 +lemma inj_func_bijR:
   3.131 +  "\<forall>a. a \<in> A --> P a (f a) ==> inj_on f A ==> finite A
   3.132 +    ==> (A, f ` A) \<in> bijR P"
   3.133 +  apply (rule aux)
   3.134 +     apply auto
   3.135 +  done
   3.136 +
   3.137 +
   3.138 +text {* \medskip @{term bijER} *}
   3.139 +
   3.140 +lemma fin_bijER: "A \<in> bijER P ==> finite A"
   3.141 +  apply (erule bijER.induct)
   3.142 +    apply auto
   3.143 +  done
   3.144 +
   3.145 +lemma aux1:
   3.146 +  "a \<notin> A ==> a \<notin> B ==> F \<subseteq> insert a A ==> F \<subseteq> insert a B ==> a \<in> F
   3.147 +    ==> \<exists>C. F = insert a C \<and> a \<notin> C \<and> C <= A \<and> C <= B"
   3.148 +  apply (rule_tac x = "F - {a}" in exI)
   3.149 +  apply auto
   3.150 +  done
   3.151 +
   3.152 +lemma aux2: "a \<noteq> b ==> a \<notin> A ==> b \<notin> B ==> a \<in> F ==> b \<in> F
   3.153 +    ==> F \<subseteq> insert a A ==> F \<subseteq> insert b B
   3.154 +    ==> \<exists>C. F = insert a (insert b C) \<and> a \<notin> C \<and> b \<notin> C \<and> C \<subseteq> A \<and> C \<subseteq> B"
   3.155 +  apply (rule_tac x = "F - {a, b}" in exI)
   3.156 +  apply auto
   3.157 +  done
   3.158 +
   3.159 +lemma aux_uniq: "uniqP P ==> P a b ==> P c d ==> (a = c) = (b = d)"
   3.160 +  apply (unfold uniqP_def)
   3.161 +  apply auto
   3.162 +  done
   3.163 +
   3.164 +lemma aux_sym: "symP P ==> P a b = P b a"
   3.165 +  apply (unfold symP_def)
   3.166 +  apply auto
   3.167 +  done
   3.168 +
   3.169 +lemma aux_in1:
   3.170 +    "uniqP P ==> b \<notin> C ==> P b b ==> bijP P (insert b C) ==> bijP P C"
   3.171 +  apply (unfold bijP_def)
   3.172 +  apply auto
   3.173 +  apply (subgoal_tac "b \<noteq> a")
   3.174 +   prefer 2
   3.175 +   apply clarify
   3.176 +  apply (simp add: aux_uniq)
   3.177 +  apply auto
   3.178 +  done
   3.179 +
   3.180 +lemma aux_in2:
   3.181 +  "symP P ==> uniqP P ==> a \<notin> C ==> b \<notin> C ==> a \<noteq> b ==> P a b
   3.182 +    ==> bijP P (insert a (insert b C)) ==> bijP P C"
   3.183 +  apply (unfold bijP_def)
   3.184 +  apply auto
   3.185 +  apply (subgoal_tac "aa \<noteq> a")
   3.186 +   prefer 2
   3.187 +   apply clarify
   3.188 +  apply (subgoal_tac "aa \<noteq> b")
   3.189 +   prefer 2
   3.190 +   apply clarify
   3.191 +  apply (simp add: aux_uniq)
   3.192 +  apply (subgoal_tac "ba \<noteq> a")
   3.193 +   apply auto
   3.194 +  apply (subgoal_tac "P a aa")
   3.195 +   prefer 2
   3.196 +   apply (simp add: aux_sym)
   3.197 +  apply (subgoal_tac "b = aa")
   3.198 +   apply (rule_tac [2] iffD1)
   3.199 +    apply (rule_tac [2] a = a and c = a and P = P in aux_uniq)
   3.200 +      apply auto
   3.201 +  done
   3.202 +
   3.203 +lemma aux: "\<forall>a b. Q a \<and> P a b --> R b ==> P a b ==> Q a ==> R b"
   3.204 +  apply auto
   3.205 +  done
   3.206 +
   3.207 +lemma aux_bij: "bijP P F ==> symP P ==> P a b ==> (a \<in> F) = (b \<in> F)"
   3.208 +  apply (unfold bijP_def)
   3.209 +  apply (rule iffI)
   3.210 +  apply (erule_tac [!] aux)
   3.211 +      apply simp_all
   3.212 +  apply (rule iffD2)
   3.213 +   apply (rule_tac P = P in aux_sym)
   3.214 +   apply simp_all
   3.215 +  done
   3.216 +
   3.217 +
   3.218 +lemma aux_bijRER:
   3.219 +  "(A, B) \<in> bijR P ==> uniqP P ==> symP P
   3.220 +    ==> \<forall>F. bijP P F \<and> F \<subseteq> A \<and> F \<subseteq> B --> F \<in> bijER P"
   3.221 +  apply (erule bijR.induct)
   3.222 +   apply simp
   3.223 +  apply (case_tac "a = b")
   3.224 +   apply clarify
   3.225 +   apply (case_tac "b \<in> F")
   3.226 +    prefer 2
   3.227 +    apply (rotate_tac -1)
   3.228 +    apply (simp add: subset_insert)
   3.229 +   apply (cut_tac F = F and a = b and A = A and B = B in aux1)
   3.230 +        prefer 6
   3.231 +        apply clarify
   3.232 +        apply (rule bijER.insert1)
   3.233 +          apply simp_all
   3.234 +   apply (subgoal_tac "bijP P C")
   3.235 +    apply simp
   3.236 +   apply (rule aux_in1)
   3.237 +      apply simp_all
   3.238 +  apply clarify
   3.239 +  apply (case_tac "a \<in> F")
   3.240 +   apply (case_tac [!] "b \<in> F")
   3.241 +     apply (rotate_tac [2-4] -2)
   3.242 +     apply (cut_tac F = F and a = a and b = b and A = A and B = B
   3.243 +       in aux2)
   3.244 +            apply (simp_all add: subset_insert)
   3.245 +    apply clarify
   3.246 +    apply (rule bijER.insert2)
   3.247 +        apply simp_all
   3.248 +    apply (subgoal_tac "bijP P C")
   3.249 +     apply simp
   3.250 +    apply (rule aux_in2)
   3.251 +          apply simp_all
   3.252 +   apply (subgoal_tac "b \<in> F")
   3.253 +    apply (rule_tac [2] iffD1)
   3.254 +     apply (rule_tac [2] a = a and F = F and P = P in aux_bij)
   3.255 +       apply (simp_all (no_asm_simp))
   3.256 +   apply (subgoal_tac [2] "a \<in> F")
   3.257 +    apply (rule_tac [3] iffD2)
   3.258 +     apply (rule_tac [3] b = b and F = F and P = P in aux_bij)
   3.259 +       apply auto
   3.260 +  done
   3.261 +
   3.262 +lemma bijR_bijER:
   3.263 +  "(A, A) \<in> bijR P ==>
   3.264 +    bijP P A ==> uniqP P ==> symP P ==> A \<in> bijER P"
   3.265 +  apply (cut_tac A = A and B = A and P = P in aux_bijRER)
   3.266 +     apply auto
   3.267 +  done
   3.268  
   3.269  end
   3.270 -
     4.1 --- a/src/HOL/NumberTheory/Chinese.ML	Sat Feb 03 17:43:34 2001 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,180 +0,0 @@
     4.4 -(*  Title:	Chinese.ML
     4.5 -    ID:         $Id$
     4.6 -    Author:	Thomas M. Rasmussen
     4.7 -    Copyright	2000  University of Cambridge
     4.8 -
     4.9 -The Chinese Remainder Theorem for an arbitrary finite number of equations. 
    4.10 -(The one-equation case is included in 'IntPrimes')
    4.11 -
    4.12 -Uses functions for indexing. Maybe 'funprod' and 'funsum'
    4.13 -should be based on general 'fold' on indices?
    4.14 -*)
    4.15 -
    4.16 -
    4.17 -(*** funprod and funsum ***)
    4.18 -
    4.19 -Goal "(ALL i. i <= n --> #0 < mf i) --> #0 < funprod mf 0 n";
    4.20 -by (induct_tac "n" 1);
    4.21 -by Auto_tac;
    4.22 -by (asm_full_simp_tac (simpset() addsimps [int_0_less_mult_iff]) 1);
    4.23 -qed_spec_mp "funprod_pos";
    4.24 -
    4.25 -Goal "(ALL i. k<=i & i<=(k+l) --> zgcd (mf i, mf m) = #1) --> \
    4.26 -\     zgcd (funprod mf k l, mf m) = #1";
    4.27 -by (induct_tac "l" 1);
    4.28 -by (ALLGOALS Simp_tac);
    4.29 -by (REPEAT (rtac impI 1));
    4.30 -by (stac zgcd_zmult_cancel 1);
    4.31 -by Auto_tac;
    4.32 -qed_spec_mp "funprod_zgcd";
    4.33 -
    4.34 -Goal "k<=i --> i<=(k+l) --> (mf i) dvd (funprod mf k l)";     
    4.35 -by (induct_tac "l" 1);
    4.36 -by Auto_tac;
    4.37 -by (rtac zdvd_zmult2 2);
    4.38 -by (rtac zdvd_zmult 3);
    4.39 -by (subgoal_tac "i=k" 1);
    4.40 -by (subgoal_tac "i=Suc (k + n)" 3);
    4.41 -by (ALLGOALS Asm_simp_tac);
    4.42 -qed_spec_mp "funprod_zdvd";
    4.43 -
    4.44 -Goal "(funsum f k l) mod m = (funsum (%i. (f i) mod m) k l) mod m";
    4.45 -by (induct_tac "l" 1);
    4.46 -by Auto_tac;
    4.47 -by (rtac trans 1);
    4.48 -by (rtac zmod_zadd1_eq 1);
    4.49 -by (Asm_simp_tac 1);
    4.50 -by (rtac (zmod_zadd_right_eq RS sym) 1);
    4.51 -qed "funsum_mod";
    4.52 -
    4.53 -Goal "(ALL i. k<=i & i<=(k+l) --> (f i) = #0) --> (funsum f k l) = #0";
    4.54 -by (induct_tac "l" 1);
    4.55 -by Auto_tac;
    4.56 -qed_spec_mp "funsum_zero";
    4.57 -
    4.58 -Goal "k<=j --> j<=(k+l) --> \
    4.59 -\     (ALL i. k<=i & i<=(k+l) & i~=j --> (f i) = #0) --> \
    4.60 -\     (funsum f k l) = (f j)";
    4.61 -by (induct_tac "l" 1);
    4.62 -by (ALLGOALS Clarify_tac);
    4.63 -by (subgoal_tac "k=j" 1 THEN ALLGOALS Asm_simp_tac);
    4.64 -by (case_tac "Suc (k+n) = j" 1);
    4.65 -by (subgoal_tac "funsum f k n = #0" 1);
    4.66 -by (rtac funsum_zero 2);
    4.67 -by (subgoal_tac "f (Suc (k+n)) = #0" 3);
    4.68 -by (subgoal_tac "j<=k+n" 3);
    4.69 -by (arith_tac 4);
    4.70 -by Auto_tac;
    4.71 -qed_spec_mp "funsum_oneelem";
    4.72 -
    4.73 -
    4.74 -(*** Chinese: Uniqueness ***)
    4.75 -
    4.76 -Goalw [m_cond_def,km_cond_def,lincong_sol_def]
    4.77 -      "[| m_cond n mf; km_cond n kf mf; \
    4.78 -\         lincong_sol n kf bf mf x; lincong_sol n kf bf mf y |] \
    4.79 -\     ==>  [x=y] (mod mf n)";
    4.80 -by (rtac iffD1 1);
    4.81 -by (res_inst_tac [("k","kf n")] zcong_cancel2 1);
    4.82 -by (res_inst_tac [("b","bf n")] zcong_trans 3);
    4.83 -by (stac zcong_sym 4);
    4.84 -by (rtac order_less_imp_le 1);
    4.85 -by (ALLGOALS Asm_simp_tac);
    4.86 -val lemma = result();
    4.87 -
    4.88 -Goal "m_cond n mf --> km_cond n kf mf --> \
    4.89 -\     lincong_sol n kf bf mf x --> lincong_sol n kf bf mf y --> \
    4.90 -\     [x=y] (mod funprod mf 0 n)";
    4.91 -by (induct_tac "n" 1);
    4.92 -by (ALLGOALS Simp_tac);
    4.93 -by (blast_tac (claset() addIs [lemma]) 1);
    4.94 -by (REPEAT (rtac impI 1));
    4.95 -by (rtac zcong_zgcd_zmult_zmod 1);
    4.96 -by (blast_tac (claset() addIs [lemma]) 1);
    4.97 -by (stac zgcd_commute 2);
    4.98 -by (rtac funprod_zgcd 2);
    4.99 -by (auto_tac (claset(), 
   4.100 -              simpset() addsimps [m_cond_def,km_cond_def,lincong_sol_def]));  
   4.101 -qed_spec_mp "zcong_funprod";
   4.102 -
   4.103 -
   4.104 -(* Chinese: Existence *)
   4.105 -
   4.106 -Goal "[| 0<n; i<=n; m_cond n mf; km_cond n kf mf |] \
   4.107 -\     ==> EX! x. #0<=x & x<(mf i) & \
   4.108 -\                [(kf i)*(mhf mf n i)*x = bf i] (mod mf i)";
   4.109 -by (rtac zcong_lineq_unique 1);
   4.110 -by (stac zgcd_zmult_cancel 2);
   4.111 -by (rewrite_goals_tac [m_cond_def,km_cond_def,mhf_def]);
   4.112 -by (ALLGOALS Asm_simp_tac);
   4.113 -by Safe_tac; 
   4.114 -by (stac zgcd_zmult_cancel 3);
   4.115 -by (ALLGOALS (rtac funprod_zgcd));
   4.116 -by Safe_tac;
   4.117 -by (ALLGOALS Asm_full_simp_tac);
   4.118 -by (subgoal_tac "ia<=n" 3);
   4.119 -by (arith_tac 4);
   4.120 -by (subgoal_tac "i<n" 1);
   4.121 -by (arith_tac 2);
   4.122 -by (case_tac "i" 2);
   4.123 -by (ALLGOALS Asm_full_simp_tac);
   4.124 -qed "unique_xi_sol";
   4.125 -
   4.126 -Goalw [mhf_def] "[| 0<n; i<=n; j<=n; j~=i |] ==> (mf j) dvd (mhf mf n i)";
   4.127 -by (case_tac "i=0" 1);
   4.128 -by (case_tac "i=n" 2);
   4.129 -by (ALLGOALS Asm_simp_tac);
   4.130 -by (case_tac "j<i" 3);
   4.131 -by (rtac zdvd_zmult2 3);
   4.132 -by (rtac zdvd_zmult 4);
   4.133 -by (ALLGOALS (rtac funprod_zdvd));
   4.134 -by (ALLGOALS arith_tac);
   4.135 -val lemma = result();
   4.136 -
   4.137 -Goalw [x_sol_def]
   4.138 -     "[| 0<n; i<=n |] \
   4.139 -\     ==> (x_sol n kf bf mf) mod (mf i) = \
   4.140 -\         (xilin_sol i n kf bf mf)*(mhf mf n i) mod (mf i)";
   4.141 -by (stac funsum_mod 1);
   4.142 -by (stac funsum_oneelem 1);
   4.143 -by Auto_tac;
   4.144 -by (stac (zdvd_iff_zmod_eq_0 RS sym) 1);
   4.145 -by (rtac zdvd_zmult 1);
   4.146 -by (rtac lemma 1);
   4.147 -by Auto_tac;
   4.148 -qed "x_sol_lin";
   4.149 -
   4.150 -
   4.151 -(* Chinese *)
   4.152 -
   4.153 -Goal "[| 0<n; m_cond n mf; km_cond n kf mf |] \
   4.154 -\     ==> (EX! x. #0 <= x & x < (funprod mf 0 n) & \
   4.155 -\                 (lincong_sol n kf bf mf x))";
   4.156 -by Safe_tac;
   4.157 -by (res_inst_tac [("m","funprod mf 0 n")] zcong_zless_imp_eq 2);
   4.158 -by (rtac zcong_funprod 6);
   4.159 -by Auto_tac;
   4.160 -by (res_inst_tac [("x","(x_sol n kf bf mf) mod (funprod mf 0 n)")] exI 1);
   4.161 -by (rewtac lincong_sol_def);
   4.162 -by Safe_tac;
   4.163 -by (stac zcong_zmod 3);
   4.164 -by (stac zmod_zmult_distrib 3);
   4.165 -by (stac zmod_zdvd_zmod 3);
   4.166 -by (stac x_sol_lin 5);
   4.167 -by (stac (zmod_zmult_distrib RS sym) 7);
   4.168 -by (stac (zcong_zmod RS sym) 7);
   4.169 -by (subgoal_tac "#0<=(xilin_sol i n kf bf mf) & \
   4.170 -\                (xilin_sol i n kf bf mf)<(mf i) & \
   4.171 -\                [(kf i)*(mhf mf n i)*(xilin_sol i n kf bf mf) = bf i] \
   4.172 -\                  (mod mf i)" 7);
   4.173 -by (asm_full_simp_tac (simpset() addsimps zmult_ac) 7);
   4.174 -by (rewtac xilin_sol_def);
   4.175 -by (Asm_simp_tac 7);
   4.176 -by (rtac (ex1_implies_ex RS someI_ex) 7);
   4.177 -by (rtac unique_xi_sol 7);
   4.178 -by (rtac funprod_zdvd 4);
   4.179 -by (rewtac m_cond_def);
   4.180 -by (rtac (funprod_pos RS pos_mod_sign) 1);
   4.181 -by (rtac (funprod_pos RS pos_mod_bound) 2);
   4.182 -by Auto_tac;
   4.183 -qed "chinese_remainder";
     5.1 --- a/src/HOL/NumberTheory/Chinese.thy	Sat Feb 03 17:43:34 2001 +0100
     5.2 +++ b/src/HOL/NumberTheory/Chinese.thy	Sun Feb 04 19:31:13 2001 +0100
     5.3 @@ -1,55 +1,260 @@
     5.4 -(*  Title:	Chinese.thy
     5.5 +(*  Title:      HOL/NumberTheory/Chinese.thy
     5.6      ID:         $Id$
     5.7 -    Author:	Thomas M. Rasmussen
     5.8 -    Copyright	2000  University of Cambridge
     5.9 +    Author:     Thomas M. Rasmussen
    5.10 +    Copyright   2000  University of Cambridge
    5.11  *)
    5.12  
    5.13 -Chinese = IntPrimes +
    5.14 +header {* The Chinese Remainder Theorem *}
    5.15 +
    5.16 +theory Chinese = IntPrimes:
    5.17 +
    5.18 +text {*
    5.19 +  The Chinese Remainder Theorem for an arbitrary finite number of
    5.20 +  equations.  (The one-equation case is included in theory @{text
    5.21 +  IntPrimes}.  Uses functions for indexing.\footnote{Maybe @{term
    5.22 +  funprod} and @{term funsum} should be based on general @{term fold}
    5.23 +  on indices?}
    5.24 +*}
    5.25 +
    5.26 +
    5.27 +subsection {* Definitions *}
    5.28  
    5.29  consts
    5.30 -  funprod     :: (nat => int) => nat => nat => int
    5.31 -  funsum      :: (nat => int) => nat => nat => int
    5.32 +  funprod :: "(nat => int) => nat => nat => int"
    5.33 +  funsum :: "(nat => int) => nat => nat => int"
    5.34  
    5.35  primrec
    5.36 -  "funprod f i 0        = f i"
    5.37 -  "funprod f i (Suc n)  = (f (Suc (i+n)))*(funprod f i n)" 
    5.38 +  "funprod f i 0 = f i"
    5.39 +  "funprod f i (Suc n) = f (Suc (i + n)) * funprod f i n"
    5.40  
    5.41  primrec
    5.42 -  "funsum f i 0         = f i"
    5.43 -  "funsum f i (Suc n)   = (f (Suc (i+n)))+(funsum f i n)" 
    5.44 -
    5.45 +  "funsum f i 0 = f i"
    5.46 +  "funsum f i (Suc n) = f (Suc (i + n)) + funsum f i n"
    5.47  
    5.48  consts
    5.49 -  m_cond      :: [nat,nat => int] => bool
    5.50 -  km_cond     :: [nat,nat => int,nat => int] => bool
    5.51 -  lincong_sol :: [nat,nat => int,nat => int,nat => int,int] => bool
    5.52 +  m_cond :: "nat => (nat => int) => bool"
    5.53 +  km_cond :: "nat => (nat => int) => (nat => int) => bool"
    5.54 +  lincong_sol ::
    5.55 +    "nat => (nat => int) => (nat => int) => (nat => int) => int => bool"
    5.56  
    5.57 -  mhf         :: (nat => int) => nat => nat => int
    5.58 -  xilin_sol   :: [nat,nat,nat => int,nat => int,nat => int] => int
    5.59 -  x_sol       :: [nat,nat => int,nat => int,nat => int] => int  
    5.60 +  mhf :: "(nat => int) => nat => nat => int"
    5.61 +  xilin_sol ::
    5.62 +    "nat => nat => (nat => int) => (nat => int) => (nat => int) => int"
    5.63 +  x_sol :: "nat => (nat => int) => (nat => int) => (nat => int) => int"
    5.64  
    5.65  defs
    5.66 -  m_cond_def   "m_cond n mf == 
    5.67 -                   (ALL i. i<=n --> #0 < mf i) & 
    5.68 -                   (ALL i j. i<=n & j<=n & i ~= j --> zgcd(mf i,mf j) = #1)"
    5.69 +  m_cond_def:
    5.70 +    "m_cond n mf ==
    5.71 +      (\<forall>i. i \<le> n --> #0 < mf i) \<and>
    5.72 +      (\<forall>i j. i \<le> n \<and> j \<le> n \<and> i \<noteq> j --> zgcd (mf i, mf j) = #1)"
    5.73 +
    5.74 +  km_cond_def:
    5.75 +    "km_cond n kf mf == \<forall>i. i \<le> n --> zgcd (kf i, mf i) = #1"
    5.76 +
    5.77 +  lincong_sol_def:
    5.78 +    "lincong_sol n kf bf mf x == \<forall>i. i \<le> n --> zcong (kf i * x) (bf i) (mf i)"
    5.79 +
    5.80 +  mhf_def:
    5.81 +    "mhf mf n i ==
    5.82 +      if i = 0 then funprod mf 1 (n - 1)
    5.83 +      else if i = n then funprod mf 0 (n - 1)
    5.84 +      else funprod mf 0 (i - 1) * funprod mf (i + 1) (n - 1 - i)"
    5.85 +
    5.86 +  xilin_sol_def:
    5.87 +    "xilin_sol i n kf bf mf ==
    5.88 +      if 0 < n \<and> i \<le> n \<and> m_cond n mf \<and> km_cond n kf mf then
    5.89 +        (SOME x. #0 \<le> x \<and> x < mf i \<and> zcong (kf i * mhf mf n i * x) (bf i) (mf i))
    5.90 +      else #0"
    5.91 +
    5.92 +  x_sol_def:
    5.93 +    "x_sol n kf bf mf == funsum (\<lambda>i. xilin_sol i n kf bf mf * mhf mf n i) 0 n"
    5.94 +
    5.95 +
    5.96 +text {* \medskip @{term funprod} and @{term funsum} *}
    5.97 +
    5.98 +lemma funprod_pos: "(\<forall>i. i \<le> n --> #0 < mf i) ==> #0 < funprod mf 0 n"
    5.99 +  apply (induct n)
   5.100 +   apply auto
   5.101 +  apply (simp add: int_0_less_mult_iff)
   5.102 +  done
   5.103 +
   5.104 +lemma funprod_zgcd [rule_format (no_asm)]:
   5.105 +  "(\<forall>i. k \<le> i \<and> i \<le> k + l --> zgcd (mf i, mf m) = #1) -->
   5.106 +    zgcd (funprod mf k l, mf m) = #1"
   5.107 +  apply (induct l)
   5.108 +   apply simp_all
   5.109 +  apply (rule impI)+
   5.110 +  apply (subst zgcd_zmult_cancel)
   5.111 +  apply auto
   5.112 +  done
   5.113  
   5.114 -  km_cond_def  "km_cond n kf mf == (ALL i. i<=n --> zgcd(kf i,mf i) = #1)"
   5.115 +lemma funprod_zdvd [rule_format]:
   5.116 +    "k \<le> i --> i \<le> k + l --> mf i dvd funprod mf k l"
   5.117 +  apply (induct l)
   5.118 +   apply auto
   5.119 +    apply (rule_tac [2] zdvd_zmult2)
   5.120 +    apply (rule_tac [3] zdvd_zmult)
   5.121 +    apply (subgoal_tac "i = k")
   5.122 +    apply (subgoal_tac [3] "i = Suc (k + n)")
   5.123 +    apply (simp_all (no_asm_simp))
   5.124 +  done
   5.125 +
   5.126 +lemma funsum_mod:
   5.127 +    "funsum f k l mod m = funsum (\<lambda>i. (f i) mod m) k l mod m"
   5.128 +  apply (induct l)
   5.129 +   apply auto
   5.130 +  apply (rule trans)
   5.131 +   apply (rule zmod_zadd1_eq)
   5.132 +  apply simp
   5.133 +  apply (rule zmod_zadd_right_eq [symmetric])
   5.134 +  done
   5.135  
   5.136 -  lincong_sol_def "lincong_sol n kf bf mf x == 
   5.137 -                   (ALL i. i<=n --> zcong ((kf i)*x) (bf i) (mf i))"
   5.138 +lemma funsum_zero [rule_format (no_asm)]:
   5.139 +    "(\<forall>i. k \<le> i \<and> i \<le> k + l --> f i = #0) --> (funsum f k l) = #0"
   5.140 +  apply (induct l)
   5.141 +   apply auto
   5.142 +  done
   5.143 +
   5.144 +lemma funsum_oneelem [rule_format (no_asm)]:
   5.145 +  "k \<le> j --> j \<le> k + l -->
   5.146 +    (\<forall>i. k \<le> i \<and> i \<le> k + l \<and> i \<noteq> j --> f i = #0) -->
   5.147 +    funsum f k l = f j"
   5.148 +  apply (induct l)
   5.149 +   prefer 2
   5.150 +   apply clarify
   5.151 +   defer
   5.152 +   apply clarify
   5.153 +   apply (subgoal_tac "k = j")
   5.154 +    apply (simp_all (no_asm_simp))
   5.155 +  apply (case_tac "Suc (k + n) = j")
   5.156 +   apply (subgoal_tac "funsum f k n = #0")
   5.157 +    apply (rule_tac [2] funsum_zero)
   5.158 +    apply (subgoal_tac [3] "f (Suc (k + n)) = #0")
   5.159 +     apply (subgoal_tac [3] "j \<le> k + n")
   5.160 +      prefer 4
   5.161 +      apply arith
   5.162 +     apply auto
   5.163 +  done
   5.164 +
   5.165 +
   5.166 +subsection {* Chinese: uniqueness *}
   5.167  
   5.168 -  mhf_def  "mhf mf n i == (if i=0 then (funprod mf 1 (n-1)) 
   5.169 -                           else (if i=n then (funprod mf 0 (n-1))
   5.170 -                           else ((funprod mf 0 (i-1)) * 
   5.171 -                                 (funprod mf (i+1) (n-1-i)))))"
   5.172 +lemma aux:
   5.173 +  "m_cond n mf ==> km_cond n kf mf
   5.174 +    ==> lincong_sol n kf bf mf x ==> lincong_sol n kf bf mf y
   5.175 +    ==> [x = y] (mod mf n)"
   5.176 +  apply (unfold m_cond_def km_cond_def lincong_sol_def)
   5.177 +  apply (rule iffD1)
   5.178 +   apply (rule_tac k = "kf n" in zcong_cancel2)
   5.179 +    apply (rule_tac [3] b = "bf n" in zcong_trans)
   5.180 +     prefer 4
   5.181 +     apply (subst zcong_sym)
   5.182 +     defer
   5.183 +     apply (rule order_less_imp_le)
   5.184 +     apply simp_all
   5.185 +  done
   5.186 +
   5.187 +lemma zcong_funprod [rule_format]:
   5.188 +  "m_cond n mf --> km_cond n kf mf -->
   5.189 +    lincong_sol n kf bf mf x --> lincong_sol n kf bf mf y -->
   5.190 +    [x = y] (mod funprod mf 0 n)"
   5.191 +  apply (induct n)
   5.192 +   apply (simp_all (no_asm))
   5.193 +   apply (blast intro: aux)
   5.194 +  apply (rule impI)+
   5.195 +  apply (rule zcong_zgcd_zmult_zmod)
   5.196 +    apply (blast intro: aux)
   5.197 +    prefer 2
   5.198 +    apply (subst zgcd_commute)
   5.199 +    apply (rule funprod_zgcd)
   5.200 +   apply (auto simp add: m_cond_def km_cond_def lincong_sol_def)
   5.201 +  done
   5.202 +
   5.203 +
   5.204 +subsection {* Chinese: existence *}
   5.205 +
   5.206 +lemma unique_xi_sol:
   5.207 +  "0 < n ==> i \<le> n ==> m_cond n mf ==> km_cond n kf mf
   5.208 +    ==> \<exists>!x. #0 \<le> x \<and> x < mf i \<and> [kf i * mhf mf n i * x = bf i] (mod mf i)"
   5.209 +  apply (rule zcong_lineq_unique)
   5.210 +   apply (tactic {* stac (thm "zgcd_zmult_cancel") 2 *})
   5.211 +    apply (unfold m_cond_def km_cond_def mhf_def)
   5.212 +    apply (simp_all (no_asm_simp))
   5.213 +  apply safe
   5.214 +    apply (tactic {* stac (thm "zgcd_zmult_cancel") 3 *})
   5.215 +     apply (rule_tac [!] funprod_zgcd)
   5.216 +     apply safe
   5.217 +     apply simp_all
   5.218 +    apply (subgoal_tac [3] "ia \<le> n")
   5.219 +     prefer 4
   5.220 +     apply arith
   5.221 +     apply (subgoal_tac "i<n")
   5.222 +     prefer 2
   5.223 +     apply arith
   5.224 +    apply (case_tac [2] i)
   5.225 +     apply simp_all
   5.226 +  done
   5.227  
   5.228 -  xilin_sol_def "xilin_sol i n kf bf mf ==
   5.229 -                  (if 0<n & i<=n & m_cond n mf & km_cond n kf mf then
   5.230 -                    (@ x. #0<=x & x<(mf i) & 
   5.231 -                          zcong ((kf i)*(mhf mf n i)*x) (bf i) (mf i))
   5.232 -                    else #0)"
   5.233 +lemma aux:
   5.234 +    "0 < n ==> i \<le> n ==> j \<le> n ==> j \<noteq> i ==> mf j dvd mhf mf n i"
   5.235 +  apply (unfold mhf_def)
   5.236 +  apply (case_tac "i = 0")
   5.237 +   apply (case_tac [2] "i = n")
   5.238 +    apply (simp_all (no_asm_simp))
   5.239 +    apply (case_tac [3] "j < i")
   5.240 +     apply (rule_tac [3] zdvd_zmult2)
   5.241 +     apply (rule_tac [4] zdvd_zmult)
   5.242 +     apply (rule_tac [!] funprod_zdvd)
   5.243 +          apply arith+
   5.244 +  done
   5.245 +
   5.246 +lemma x_sol_lin:
   5.247 +  "0 < n ==> i \<le> n
   5.248 +    ==> x_sol n kf bf mf mod mf i =
   5.249 +      xilin_sol i n kf bf mf * mhf mf n i mod mf i"
   5.250 +  apply (unfold x_sol_def)
   5.251 +  apply (subst funsum_mod)
   5.252 +  apply (subst funsum_oneelem)
   5.253 +     apply auto
   5.254 +  apply (subst zdvd_iff_zmod_eq_0 [symmetric])
   5.255 +  apply (rule zdvd_zmult)
   5.256 +  apply (rule aux)
   5.257 +  apply auto
   5.258 +  done
   5.259 +
   5.260 +
   5.261 +subsection {* Chinese *}
   5.262  
   5.263 -  x_sol_def "x_sol n kf bf mf ==
   5.264 -              (funsum (%i. (xilin_sol i n kf bf mf)*(mhf mf n i)) 0 n)"
   5.265 +lemma chinese_remainder:
   5.266 +  "0 < n ==> m_cond n mf ==> km_cond n kf mf
   5.267 +    ==> \<exists>!x. #0 \<le> x \<and> x < funprod mf 0 n \<and> lincong_sol n kf bf mf x"
   5.268 +  apply safe
   5.269 +   apply (rule_tac [2] m = "funprod mf 0 n" in zcong_zless_imp_eq)
   5.270 +       apply (rule_tac [6] zcong_funprod)
   5.271 +          apply auto
   5.272 +  apply (rule_tac x = "x_sol n kf bf mf mod funprod mf 0 n" in exI)
   5.273 +  apply (unfold lincong_sol_def)
   5.274 +  apply safe
   5.275 +    apply (tactic {* stac (thm "zcong_zmod") 3 *})
   5.276 +    apply (tactic {* stac (thm "zmod_zmult_distrib") 3 *})
   5.277 +    apply (tactic {* stac (thm "zmod_zdvd_zmod") 3 *})
   5.278 +      apply (tactic {* stac (thm "x_sol_lin") 5 *})
   5.279 +        apply (tactic {* stac (thm "zmod_zmult_distrib" RS sym) 7 *})
   5.280 +        apply (tactic {* stac (thm "zcong_zmod" RS sym) 7 *})
   5.281 +        apply (subgoal_tac [7]
   5.282 +          "#0 \<le> xilin_sol i n kf bf mf \<and> xilin_sol i n kf bf mf < mf i
   5.283 +          \<and> [kf i * mhf mf n i * xilin_sol i n kf bf mf = bf i] (mod mf i)")
   5.284 +         prefer 7
   5.285 +         apply (simp add: zmult_ac)
   5.286 +        apply (unfold xilin_sol_def)
   5.287 +        apply (tactic {* Asm_simp_tac 7 *})
   5.288 +        apply (rule_tac [7] ex1_implies_ex [THEN someI_ex])
   5.289 +        apply (rule_tac [7] unique_xi_sol)
   5.290 +           apply (rule_tac [4] funprod_zdvd)
   5.291 +            apply (unfold m_cond_def)
   5.292 +            apply (rule funprod_pos [THEN pos_mod_sign])
   5.293 +            apply (rule_tac [2] funprod_pos [THEN pos_mod_bound])
   5.294 +            apply auto
   5.295 +  done
   5.296  
   5.297  end
     6.1 --- a/src/HOL/NumberTheory/EulerFermat.thy	Sat Feb 03 17:43:34 2001 +0100
     6.2 +++ b/src/HOL/NumberTheory/EulerFermat.thy	Sun Feb 04 19:31:13 2001 +0100
     6.3 @@ -1,46 +1,381 @@
     6.4 -(*  Title:	EulerFermat.thy
     6.5 +(*  Title:      HOL/NumberTheory/EulerFermat.thy
     6.6      ID:         $Id$
     6.7 -    Author:	Thomas M. Rasmussen
     6.8 -    Copyright	2000  University of Cambridge
     6.9 +    Author:     Thomas M. Rasmussen
    6.10 +    Copyright   2000  University of Cambridge
    6.11  *)
    6.12  
    6.13 -EulerFermat = BijectionRel + IntFact +
    6.14 +header {* Fermat's Little Theorem extended to Euler's Totient function *}
    6.15 +
    6.16 +theory EulerFermat = BijectionRel + IntFact:
    6.17 +
    6.18 +text {*
    6.19 +  Fermat's Little Theorem extended to Euler's Totient function. More
    6.20 +  abstract approach than Boyer-Moore (which seems necessary to achieve
    6.21 +  the extended version).
    6.22 +*}
    6.23 +
    6.24 +
    6.25 +subsection {* Definitions and lemmas *}
    6.26  
    6.27  consts
    6.28 -  RsetR        :: "int => int set set"
    6.29 -  BnorRset     :: "int*int=>int set" 
    6.30 -  norRRset     :: int => int set
    6.31 -  noXRRset     :: [int, int] => int set
    6.32 -  phi          :: int => nat
    6.33 -  is_RRset     :: [int set, int] => bool
    6.34 -  RRset2norRR  :: [int set, int, int] => int
    6.35 +  RsetR :: "int => int set set"
    6.36 +  BnorRset :: "int * int => int set"
    6.37 +  norRRset :: "int => int set"
    6.38 +  noXRRset :: "int => int => int set"
    6.39 +  phi :: "int => nat"
    6.40 +  is_RRset :: "int set => int => bool"
    6.41 +  RRset2norRR :: "int set => int => int => int"
    6.42  
    6.43  inductive "RsetR m"
    6.44 -intrs
    6.45 -  empty  "{} : RsetR m"
    6.46 -  insert "[| A : RsetR m; zgcd(a,m) = #1; \
    6.47 -\            ALL a'. a':A --> ~ zcong a a' m |] \
    6.48 -\        ==> insert a A : RsetR m"
    6.49 +  intros
    6.50 +    empty [simp]: "{} \<in> RsetR m"
    6.51 +    insert: "A \<in> RsetR m ==> zgcd (a, m) = #1 ==>
    6.52 +      \<forall>a'. a' \<in> A --> \<not> zcong a a' m ==> insert a A \<in> RsetR m"
    6.53  
    6.54 -recdef BnorRset "measure ((% (a,m).(nat a)) ::int*int=>nat)"
    6.55 -    "BnorRset (a,m) = (if #0<a then let na = BnorRset (a-#1,m) in
    6.56 -                         (if zgcd(a,m) = #1 then insert a na else na) 
    6.57 -                       else {})"
    6.58 +recdef BnorRset
    6.59 +  "measure ((\<lambda>(a, m). nat a) :: int * int => nat)"
    6.60 +  "BnorRset (a, m) =
    6.61 +   (if #0 < a then
    6.62 +    let na = BnorRset (a - #1, m)
    6.63 +    in (if zgcd (a, m) = #1 then insert a na else na)
    6.64 +    else {})"
    6.65  
    6.66  defs
    6.67 -  norRRset_def "norRRset m   == BnorRset (m-#1,m)"
    6.68 +  norRRset_def: "norRRset m == BnorRset (m - #1, m)"
    6.69 +  noXRRset_def: "noXRRset m x == (\<lambda>a. a * x) ` norRRset m"
    6.70 +  phi_def: "phi m == card (norRRset m)"
    6.71 +  is_RRset_def: "is_RRset A m == A \<in> RsetR m \<and> card A = phi m"
    6.72 +  RRset2norRR_def:
    6.73 +    "RRset2norRR A m a ==
    6.74 +     (if #1 < m \<and> is_RRset A m \<and> a \<in> A then
    6.75 +        SOME b. zcong a b m \<and> b \<in> norRRset m
    6.76 +      else #0)"
    6.77 +
    6.78 +constdefs
    6.79 +  zcongm :: "int => int => int => bool"
    6.80 +  "zcongm m == \<lambda>a b. zcong a b m"
    6.81 +
    6.82 +lemma abs_eq_1_iff [iff]: "(abs z = (#1::int)) = (z = #1 \<or> z = #-1)"
    6.83 +  -- {* LCP: not sure why this lemma is needed now *}
    6.84 +  apply (auto simp add: zabs_def)
    6.85 +  done
    6.86 +
    6.87 +
    6.88 +text {* \medskip @{text norRRset} *}
    6.89 +
    6.90 +declare BnorRset.simps [simp del]
    6.91 +
    6.92 +lemma BnorRset_induct:
    6.93 +  "(!!a m. P {} a m) ==>
    6.94 +    (!!a m. #0 < (a::int) ==> P (BnorRset (a - #1, m::int)) (a - #1) m
    6.95 +      ==> P (BnorRset(a,m)) a m)
    6.96 +    ==> P (BnorRset(u,v)) u v"
    6.97 +proof -
    6.98 +  case antecedent
    6.99 +  show ?thesis
   6.100 +    apply (rule BnorRset.induct)
   6.101 +    apply safe
   6.102 +     apply (case_tac [2] "#0 < a")
   6.103 +      apply (rule_tac [2] antecedent)
   6.104 +       apply simp_all
   6.105 +     apply (simp_all add: BnorRset.simps antecedent)
   6.106 +  done
   6.107 +qed
   6.108 +
   6.109 +lemma Bnor_mem_zle [rule_format]: "b \<in> BnorRset (a, m) --> b \<le> a"
   6.110 +  apply (induct a m rule: BnorRset_induct)
   6.111 +   prefer 2
   6.112 +   apply (subst BnorRset.simps)
   6.113 +   apply (unfold Let_def)
   6.114 +   apply auto
   6.115 +  done
   6.116 +
   6.117 +lemma Bnor_mem_zle_swap: "a < b ==> b \<notin> BnorRset (a, m)"
   6.118 +  apply (auto dest: Bnor_mem_zle)
   6.119 +  done
   6.120 +
   6.121 +lemma Bnor_mem_zg [rule_format]: "b \<in> BnorRset (a, m) --> #0 < b"
   6.122 +  apply (induct a m rule: BnorRset_induct)
   6.123 +   prefer 2
   6.124 +   apply (subst BnorRset.simps)
   6.125 +   apply (unfold Let_def)
   6.126 +   apply auto
   6.127 +  done
   6.128 +
   6.129 +lemma Bnor_mem_if [rule_format]:
   6.130 +    "zgcd (b, m) = #1 --> #0 < b --> b \<le> a --> b \<in> BnorRset (a, m)"
   6.131 +  apply (induct a m rule: BnorRset.induct)
   6.132 +  apply auto
   6.133 +   apply (case_tac "a = b")
   6.134 +    prefer 2
   6.135 +    apply (simp add: order_less_le)
   6.136 +   apply (simp (no_asm_simp))
   6.137 +   prefer 2
   6.138 +   apply (subst BnorRset.simps)
   6.139 +   defer
   6.140 +   apply (subst BnorRset.simps)
   6.141 +   apply (unfold Let_def)
   6.142 +   apply auto
   6.143 +  done
   6.144  
   6.145 -  noXRRset_def "noXRRset m x == (%a. a*x)`(norRRset m)"
   6.146 +lemma Bnor_in_RsetR [rule_format]: "a < m --> BnorRset (a, m) \<in> RsetR m"
   6.147 +  apply (induct a m rule: BnorRset_induct)
   6.148 +   apply simp
   6.149 +  apply (subst BnorRset.simps)
   6.150 +  apply (unfold Let_def)
   6.151 +  apply auto
   6.152 +  apply (rule RsetR.insert)
   6.153 +    apply (rule_tac [3] allI)
   6.154 +    apply (rule_tac [3] impI)
   6.155 +    apply (rule_tac [3] zcong_not)
   6.156 +       apply (subgoal_tac [6] "a' \<le> a - #1")
   6.157 +        apply (rule_tac [7] Bnor_mem_zle)
   6.158 +        apply (rule_tac [5] Bnor_mem_zg)
   6.159 +        apply auto
   6.160 +  done
   6.161 +
   6.162 +lemma Bnor_fin: "finite (BnorRset (a, m))"
   6.163 +  apply (induct a m rule: BnorRset_induct)
   6.164 +   prefer 2
   6.165 +   apply (subst BnorRset.simps)
   6.166 +   apply (unfold Let_def)
   6.167 +   apply auto
   6.168 +  done
   6.169 +
   6.170 +lemma aux: "a \<le> b - #1 ==> a < (b::int)"
   6.171 +  apply auto
   6.172 +  done
   6.173  
   6.174 -  phi_def      "phi m == card (norRRset m)"
   6.175 +lemma norR_mem_unique:
   6.176 +  "#1 < m ==>
   6.177 +    zgcd (a, m) = #1 ==> \<exists>!b. [a = b] (mod m) \<and> b \<in> norRRset m"
   6.178 +  apply (unfold norRRset_def)
   6.179 +  apply (cut_tac a = a and m = m in zcong_zless_unique)
   6.180 +   apply auto
   6.181 +   apply (rule_tac [2] m = m in zcong_zless_imp_eq)
   6.182 +       apply (auto intro: Bnor_mem_zle Bnor_mem_zg zcong_trans
   6.183 +	 order_less_imp_le aux simp add: zcong_sym)
   6.184 +  apply (rule_tac "x" = "b" in exI)
   6.185 +  apply safe
   6.186 +  apply (rule Bnor_mem_if)
   6.187 +    apply (case_tac [2] "b = #0")
   6.188 +     apply (auto intro: order_less_le [THEN iffD2])
   6.189 +   prefer 2
   6.190 +   apply (simp only: zcong_def)
   6.191 +   apply (subgoal_tac "zgcd (a, m) = m")
   6.192 +    prefer 2
   6.193 +    apply (subst zdvd_iff_zgcd [symmetric])
   6.194 +     apply (rule_tac [4] zgcd_zcong_zgcd)
   6.195 +       apply (simp_all add: zdvd_zminus_iff zcong_sym)
   6.196 +  done
   6.197 +
   6.198 +
   6.199 +text {* \medskip @{term noXRRset} *}
   6.200 +
   6.201 +lemma RRset_gcd [rule_format]:
   6.202 +    "is_RRset A m ==> a \<in> A --> zgcd (a, m) = #1"
   6.203 +  apply (unfold is_RRset_def)
   6.204 +  apply (rule RsetR.induct)
   6.205 +    apply auto
   6.206 +  done
   6.207 +
   6.208 +lemma RsetR_zmult_mono:
   6.209 +  "A \<in> RsetR m ==>
   6.210 +    #0 < m ==> zgcd (x, m) = #1 ==> (\<lambda>a. a * x) ` A \<in> RsetR m"
   6.211 +  apply (erule RsetR.induct)
   6.212 +   apply simp_all
   6.213 +  apply (rule RsetR.insert)
   6.214 +    apply auto
   6.215 +   apply (blast intro: zgcd_zgcd_zmult)
   6.216 +  apply (simp add: zcong_cancel)
   6.217 +  done
   6.218 +
   6.219 +lemma card_nor_eq_noX:
   6.220 +  "#0 < m ==>
   6.221 +    zgcd (x, m) = #1 ==> card (noXRRset m x) = card (norRRset m)"
   6.222 +  apply (unfold norRRset_def noXRRset_def)
   6.223 +  apply (rule card_image)
   6.224 +   apply (auto simp add: inj_on_def Bnor_fin)
   6.225 +  apply (simp add: BnorRset.simps)
   6.226 +  done
   6.227 +
   6.228 +lemma noX_is_RRset:
   6.229 +    "#0 < m ==> zgcd (x, m) = #1 ==> is_RRset (noXRRset m x) m"
   6.230 +  apply (unfold is_RRset_def phi_def)
   6.231 +  apply (auto simp add: card_nor_eq_noX)
   6.232 +  apply (unfold noXRRset_def norRRset_def)
   6.233 +  apply (rule RsetR_zmult_mono)
   6.234 +    apply (rule Bnor_in_RsetR)
   6.235 +    apply simp_all
   6.236 +  done
   6.237  
   6.238 -  is_RRset_def "is_RRset A m ==  (A : (RsetR m)) & card(A) = (phi m)"
   6.239 +lemma aux_some:
   6.240 +  "#1 < m ==> is_RRset A m ==> a \<in> A
   6.241 +    ==> zcong a (SOME b. [a = b] (mod m) \<and> b \<in> norRRset m) m \<and>
   6.242 +      (SOME b. [a = b] (mod m) \<and> b \<in> norRRset m) \<in> norRRset m"
   6.243 +  apply (rule norR_mem_unique [THEN ex1_implies_ex, THEN someI_ex])
   6.244 +   apply (rule_tac [2] RRset_gcd)
   6.245 +    apply simp_all
   6.246 +  done
   6.247 +
   6.248 +lemma RRset2norRR_correct:
   6.249 +  "#1 < m ==> is_RRset A m ==> a \<in> A ==>
   6.250 +    [a = RRset2norRR A m a] (mod m) \<and> RRset2norRR A m a \<in> norRRset m"
   6.251 +  apply (unfold RRset2norRR_def)
   6.252 +  apply simp
   6.253 +  apply (rule aux_some)
   6.254 +    apply simp_all
   6.255 +  done
   6.256 +
   6.257 +lemmas RRset2norRR_correct1 =
   6.258 +  RRset2norRR_correct [THEN conjunct1, standard]
   6.259 +lemmas RRset2norRR_correct2 =
   6.260 +  RRset2norRR_correct [THEN conjunct2, standard]
   6.261 +
   6.262 +lemma RsetR_fin: "A \<in> RsetR m ==> finite A"
   6.263 +  apply (erule RsetR.induct)
   6.264 +   apply auto
   6.265 +  done
   6.266 +
   6.267 +lemma RRset_zcong_eq [rule_format]:
   6.268 +  "#1 < m ==>
   6.269 +    is_RRset A m ==> [a = b] (mod m) ==> a \<in> A --> b \<in> A --> a = b"
   6.270 +  apply (unfold is_RRset_def)
   6.271 +  apply (rule RsetR.induct)
   6.272 +    apply (auto simp add: zcong_sym)
   6.273 +  done
   6.274 +
   6.275 +lemma aux:
   6.276 +  "P (SOME a. P a) ==> Q (SOME a. Q a) ==>
   6.277 +    (SOME a. P a) = (SOME a. Q a) ==> \<exists>a. P a \<and> Q a"
   6.278 +  apply auto
   6.279 +  done
   6.280 +
   6.281 +lemma RRset2norRR_inj:
   6.282 +    "#1 < m ==> is_RRset A m ==> inj_on (RRset2norRR A m) A"
   6.283 +  apply (unfold RRset2norRR_def inj_on_def)
   6.284 +  apply auto
   6.285 +  apply (subgoal_tac "\<exists>b. ([x = b] (mod m) \<and> b \<in> norRRset m) \<and>
   6.286 +      ([y = b] (mod m) \<and> b \<in> norRRset m)")
   6.287 +   apply (rule_tac [2] aux)
   6.288 +     apply (rule_tac [3] aux_some)
   6.289 +       apply (rule_tac [2] aux_some)
   6.290 +         apply (rule RRset_zcong_eq)
   6.291 +             apply auto
   6.292 +  apply (rule_tac b = b in zcong_trans)
   6.293 +   apply (simp_all add: zcong_sym)
   6.294 +  done
   6.295 +
   6.296 +lemma RRset2norRR_eq_norR:
   6.297 +    "#1 < m ==> is_RRset A m ==> RRset2norRR A m ` A = norRRset m"
   6.298 +  apply (rule card_seteq)
   6.299 +    prefer 3
   6.300 +    apply (subst card_image)
   6.301 +      apply (rule_tac [2] RRset2norRR_inj)
   6.302 +       apply auto
   6.303 +     apply (rule_tac [4] RRset2norRR_correct2)
   6.304 +       apply auto
   6.305 +    apply (unfold is_RRset_def phi_def norRRset_def)
   6.306 +    apply (auto simp add: RsetR_fin Bnor_fin)
   6.307 +  done
   6.308 +
   6.309 +
   6.310 +lemma aux: "a \<notin> A ==> inj f ==> f a \<notin> f ` A"
   6.311 +  apply (unfold inj_on_def)
   6.312 +  apply auto
   6.313 +  done
   6.314  
   6.315 -  RRset2norRR_def "RRset2norRR A m a == 
   6.316 -                     (if #1<m & (is_RRset A m) & a:A 
   6.317 -                      then @b. zcong a b m & b:(norRRset m) else #0)"
   6.318 +lemma Bnor_prod_power [rule_format]:
   6.319 +  "x \<noteq> #0 ==> a < m --> setprod ((\<lambda>a. a * x) ` BnorRset (a, m)) =
   6.320 +      setprod (BnorRset(a, m)) * x^card (BnorRset (a, m))"
   6.321 +  apply (induct a m rule: BnorRset_induct)
   6.322 +   prefer 2
   6.323 +   apply (subst BnorRset.simps)
   6.324 +   apply (unfold Let_def)
   6.325 +   apply auto
   6.326 +  apply (simp add: Bnor_fin Bnor_mem_zle_swap)
   6.327 +  apply (subst setprod_insert)
   6.328 +    apply (rule_tac [2] aux)
   6.329 +     apply (unfold inj_on_def)
   6.330 +     apply (simp_all add: zmult_ac Bnor_fin finite_imageI
   6.331 +       Bnor_mem_zle_swap)
   6.332 +  done
   6.333 +
   6.334 +
   6.335 +subsection {* Fermat *}
   6.336 +
   6.337 +lemma bijzcong_zcong_prod:
   6.338 +    "(A, B) \<in> bijR (zcongm m) ==> [setprod A = setprod B] (mod m)"
   6.339 +  apply (unfold zcongm_def)
   6.340 +  apply (erule bijR.induct)
   6.341 +   apply (subgoal_tac [2] "a \<notin> A \<and> b \<notin> B \<and> finite A \<and> finite B")
   6.342 +    apply (auto intro: fin_bijRl fin_bijRr zcong_zmult)
   6.343 +  done
   6.344 +
   6.345 +lemma Bnor_prod_zgcd [rule_format]:
   6.346 +    "a < m --> zgcd (setprod (BnorRset (a, m)), m) = #1"
   6.347 +  apply (induct a m rule: BnorRset_induct)
   6.348 +   prefer 2
   6.349 +   apply (subst BnorRset.simps)
   6.350 +   apply (unfold Let_def)
   6.351 +   apply auto
   6.352 +  apply (simp add: Bnor_fin Bnor_mem_zle_swap)
   6.353 +  apply (blast intro: zgcd_zgcd_zmult)
   6.354 +  done
   6.355  
   6.356 -consts zcongm :: int => [int, int] => bool
   6.357 -defs zcongm_def "zcongm m == (%a b. zcong a b m)"
   6.358 +theorem Euler_Fermat:
   6.359 +    "#0 < m ==> zgcd (x, m) = #1 ==> [x^(phi m) = #1] (mod m)"
   6.360 +  apply (unfold norRRset_def phi_def)
   6.361 +  apply (case_tac "x = #0")
   6.362 +   apply (case_tac [2] "m = #1")
   6.363 +    apply (rule_tac [3] iffD1)
   6.364 +     apply (rule_tac [3] k = "setprod (BnorRset (m - #1, m))"
   6.365 +       in zcong_cancel2)
   6.366 +      prefer 5
   6.367 +      apply (subst Bnor_prod_power [symmetric])
   6.368 +        apply (rule_tac [7] Bnor_prod_zgcd)
   6.369 +        apply simp_all
   6.370 +  apply (rule bijzcong_zcong_prod)
   6.371 +  apply (fold norRRset_def noXRRset_def)
   6.372 +  apply (subst RRset2norRR_eq_norR [symmetric])
   6.373 +    apply (rule_tac [3] inj_func_bijR)
   6.374 +      apply auto
   6.375 +      apply (unfold zcongm_def)
   6.376 +      apply (rule_tac [3] RRset2norRR_correct1)
   6.377 +        apply (rule_tac [6] RRset2norRR_inj)
   6.378 +         apply (auto intro: order_less_le [THEN iffD2]
   6.379 +	   simp add: noX_is_RRset)
   6.380 +  apply (unfold noXRRset_def norRRset_def)
   6.381 +  apply (rule finite_imageI)
   6.382 +  apply (rule Bnor_fin)
   6.383 +  done
   6.384 +
   6.385 +lemma Bnor_prime [rule_format (no_asm)]:
   6.386 +  "p \<in> zprime ==>
   6.387 +    a < p --> (\<forall>b. #0 < b \<and> b \<le> a --> zgcd (b, p) = #1)
   6.388 +    --> card (BnorRset (a, p)) = nat a"
   6.389 +  apply (unfold zprime_def)
   6.390 +  apply (induct a p rule: BnorRset.induct)
   6.391 +  apply (subst BnorRset.simps)
   6.392 +  apply (unfold Let_def)
   6.393 +  apply auto
   6.394 +  done
   6.395 +
   6.396 +lemma phi_prime: "p \<in> zprime ==> phi p = nat (p - #1)"
   6.397 +  apply (unfold phi_def norRRset_def)
   6.398 +  apply (rule Bnor_prime)
   6.399 +    apply auto
   6.400 +  apply (erule zless_zprime_imp_zrelprime)
   6.401 +   apply simp_all
   6.402 +  done
   6.403 +
   6.404 +theorem Little_Fermat:
   6.405 +    "p \<in> zprime ==> \<not> p dvd x ==> [x^(nat (p - #1)) = #1] (mod p)"
   6.406 +  apply (subst phi_prime [symmetric])
   6.407 +   apply (rule_tac [2] Euler_Fermat)
   6.408 +    apply (erule_tac [3] zprime_imp_zrelprime)
   6.409 +    apply (unfold zprime_def)
   6.410 +    apply auto
   6.411 +  done
   6.412  
   6.413  end
     7.1 --- a/src/HOL/NumberTheory/Factorization.ML	Sat Feb 03 17:43:34 2001 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,310 +0,0 @@
     7.4 -(*  Title:      HOL/ex/Factorization.thy
     7.5 -    ID:         $Id$
     7.6 -    Author:     Thomas Marthedal Rasmussen
     7.7 -    Copyright   2000  University of Cambridge
     7.8 -
     7.9 -Fundamental Theorem of Arithmetic (unique factorization into primes)
    7.10 -*)
    7.11 -
    7.12 -val prime_def = thm "prime_def";
    7.13 -val prime_dvd_mult = thm "prime_dvd_mult";
    7.14 -
    7.15 -
    7.16 -(* --- Arithmetic --- *)
    7.17 -
    7.18 -Goal "!!m::nat. [| m ~= m*k; m ~= 1 |] ==> 1<m";
    7.19 -by (case_tac "m" 1);
    7.20 -by Auto_tac;
    7.21 -qed "one_less_m";
    7.22 -
    7.23 -Goal "!!m::nat. [| m ~= m*k; 1<m*k |] ==> 1<k";
    7.24 -by (case_tac "k" 1);
    7.25 -by Auto_tac;
    7.26 -qed "one_less_k";
    7.27 -
    7.28 -Goal "!!m::nat. [| 0<k; k*n=k*m |] ==> n=m";
    7.29 -by Auto_tac;
    7.30 -qed "mult_left_cancel";
    7.31 -
    7.32 -Goal "!!m::nat. [| 0<m; m*n = m |] ==> n=1";
    7.33 -by (case_tac "n" 1);
    7.34 -by Auto_tac;
    7.35 -qed "mn_eq_m_one";
    7.36 -
    7.37 -Goal "!!m::nat. [| 0<n; 0<k |] ==> 1<m --> m*n = k --> n<k";
    7.38 -by (induct_tac "m" 1);
    7.39 -by Auto_tac;
    7.40 -qed_spec_mp "prod_mn_less_k";
    7.41 -
    7.42 -
    7.43 -(* --- Prime List & Product --- *)
    7.44 -
    7.45 -Goal "prod (xs @ ys) = prod xs * prod ys"; 
    7.46 -by (induct_tac "xs" 1);
    7.47 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [mult_assoc])));
    7.48 -qed "prod_append";
    7.49 -
    7.50 -Goal "prod (x#xs) = prod (y#ys) ==> x*prod xs = y*prod ys";
    7.51 -by Auto_tac;
    7.52 -qed "prod_xy_prod";
    7.53 -
    7.54 -Goalw [primel_def] "primel (xs @ ys) = (primel xs & primel ys)";
    7.55 -by Auto_tac;
    7.56 -qed "primel_append";
    7.57 -
    7.58 -Goalw [primel_def] "n:prime ==> primel [n] & prod [n] = n";
    7.59 -by Auto_tac;
    7.60 -qed "prime_primel";
    7.61 -
    7.62 -Goalw [prime_def,dvd_def] "p:prime ==> ~(p dvd 1)";
    7.63 -by Auto_tac;  
    7.64 -qed "prime_nd_one";
    7.65 -
    7.66 -Goalw [dvd_def] "[| prod (x#xs) = prod ys |] ==> x dvd (prod ys)";
    7.67 -by (rtac exI 1);
    7.68 -by (rtac sym 1);
    7.69 -by (Asm_full_simp_tac 1);
    7.70 -qed "hd_dvd_prod";
    7.71 -
    7.72 -Goalw [primel_def] "primel (x#xs) ==> primel xs";
    7.73 -by Auto_tac;
    7.74 -qed "primel_tl";
    7.75 -
    7.76 -Goalw [primel_def] "(primel (x#xs)) = (x:prime & primel xs)"; 
    7.77 -by Auto_tac;
    7.78 -qed "primel_hd_tl";
    7.79 -
    7.80 -Goalw [prime_def] "[| p:prime; q:prime; p dvd q |] ==> p=q";
    7.81 -by Auto_tac;
    7.82 -qed "primes_eq";
    7.83 -
    7.84 -Goalw [primel_def,prime_def] "[| primel xs; prod xs = 1 |] ==> xs = []";
    7.85 -by (case_tac "xs" 1);
    7.86 -by (ALLGOALS Asm_full_simp_tac);
    7.87 -qed "primel_one_empty";
    7.88 -
    7.89 -Goalw [prime_def] "p:prime ==> 1<p";
    7.90 -by Auto_tac;
    7.91 -qed "prime_g_one";
    7.92 -
    7.93 -Goalw [prime_def] "p:prime ==> 0<p";
    7.94 -by Auto_tac;
    7.95 -qed "prime_g_zero";
    7.96 -
    7.97 -Goalw [primel_def,prime_def] "primel xs --> xs ~= [] --> 1 < prod xs";
    7.98 -by (induct_tac "xs" 1);
    7.99 -by (auto_tac (claset() addEs [one_less_mult], simpset()));
   7.100 -qed_spec_mp "primel_nempty_g_one";
   7.101 -
   7.102 -Goalw [primel_def,prime_def] "primel xs --> 0 < prod xs"; 
   7.103 -by (induct_tac "xs" 1);
   7.104 -by Auto_tac;
   7.105 -qed_spec_mp "primel_prod_gz";
   7.106 -
   7.107 -
   7.108 -(* --- Sorting --- *)
   7.109 -
   7.110 -Goal "nondec xs --> nondec (oinsert x xs)";
   7.111 -by (induct_tac "xs" 1);
   7.112 -by (case_tac "list" 2);
   7.113 -by (ALLGOALS(asm_full_simp_tac (simpset()delcongs[thm"list.weak_case_cong"])));
   7.114 -qed_spec_mp "nondec_oinsert";
   7.115 -
   7.116 -Goal "nondec (sort xs)";
   7.117 -by (induct_tac "xs" 1);
   7.118 -by (ALLGOALS (Asm_full_simp_tac));
   7.119 -by (etac nondec_oinsert 1);
   7.120 -qed "nondec_sort";
   7.121 -
   7.122 -Goal "[| x<=y; l=y#ys |]  ==> x#l = oinsert x l";
   7.123 -by (ALLGOALS Asm_full_simp_tac);
   7.124 -qed "x_less_y_oinsert";
   7.125 -
   7.126 -Goal "nondec xs --> xs = sort xs";
   7.127 -by (induct_tac "xs" 1);
   7.128 -by Safe_tac;
   7.129 -by (ALLGOALS Asm_full_simp_tac);
   7.130 -by (case_tac "list" 1);
   7.131 -by (ALLGOALS Asm_full_simp_tac);
   7.132 -by (case_tac "list" 1);
   7.133 -by (Asm_full_simp_tac 1);
   7.134 -by (res_inst_tac [("y","aa"),("ys","lista")] x_less_y_oinsert 1); 
   7.135 -by (ALLGOALS Asm_full_simp_tac);
   7.136 -qed_spec_mp "nondec_sort_eq";
   7.137 -
   7.138 -Goal "oinsert x (oinsert y l) = oinsert y (oinsert x l)";
   7.139 -by (induct_tac "l" 1);
   7.140 -by Auto_tac;
   7.141 -qed "oinsert_x_y";
   7.142 -
   7.143 -
   7.144 -(* --- Permutation --- *)
   7.145 -
   7.146 -Goalw [primel_def] "xs <~~> ys ==> primel xs --> primel ys";
   7.147 -by (etac perm.induct 1);
   7.148 -by (ALLGOALS Asm_simp_tac);
   7.149 -qed_spec_mp "perm_primel";
   7.150 -
   7.151 -Goal "xs <~~> ys ==> prod xs = prod ys";
   7.152 -by (etac perm.induct 1);
   7.153 -by (ALLGOALS (asm_simp_tac (simpset() addsimps mult_ac)));
   7.154 -qed_spec_mp "perm_prod";
   7.155 -
   7.156 -Goal "xs <~~> ys ==> oinsert a xs <~~> oinsert a ys"; 
   7.157 -by (etac perm.induct 1);
   7.158 -by Auto_tac;
   7.159 -qed "perm_subst_oinsert";
   7.160 -
   7.161 -Goal "x#xs <~~> oinsert x xs";
   7.162 -by (induct_tac "xs" 1);
   7.163 -by Auto_tac;
   7.164 -qed "perm_oinsert";
   7.165 -
   7.166 -Goal "xs <~~> sort xs";
   7.167 -by (induct_tac "xs" 1);
   7.168 -by (auto_tac (claset() addIs [perm_oinsert] 
   7.169 -	               addEs [perm_subst_oinsert],
   7.170 -              simpset()));
   7.171 -qed "perm_sort";
   7.172 -
   7.173 -Goal "xs <~~> ys ==> sort xs = sort ys";
   7.174 -by (etac perm.induct 1);
   7.175 -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [oinsert_x_y])));
   7.176 -qed "perm_sort_eq";
   7.177 -
   7.178 -
   7.179 -(* --- Existence --- *)
   7.180 -
   7.181 -Goal "primel xs ==> EX ys. primel ys & nondec ys & prod ys = prod xs";
   7.182 -by (blast_tac (claset() addIs [nondec_sort, perm_prod,perm_primel,perm_sort,
   7.183 -			       perm_sym]) 1);
   7.184 -qed "ex_nondec_lemma";
   7.185 -
   7.186 -Goalw [prime_def,dvd_def]
   7.187 -     "1<n & n~:prime --> (EX m k.1<m & 1<k & m<n & k<n & n=m*k)";
   7.188 -by (auto_tac (claset() addIs [n_less_m_mult_n, n_less_n_mult_m,
   7.189 -			      one_less_m, one_less_k], 
   7.190 -	      simpset()));
   7.191 -qed_spec_mp "not_prime_ex_mk";
   7.192 -
   7.193 -Goal "[| primel xs; primel ys |] \
   7.194 -\     ==> EX l. primel l & prod l = prod xs * prod ys";
   7.195 -by (rtac exI 1);
   7.196 -by Safe_tac;
   7.197 -by (rtac prod_append 2);
   7.198 -by (asm_simp_tac (simpset() addsimps [primel_append]) 1);
   7.199 -qed "split_primel";
   7.200 -
   7.201 -Goal "1<n --> (EX l. primel l & prod l = n)"; 
   7.202 -by (induct_thm_tac nat_less_induct "n" 1);
   7.203 -by (rtac impI 1);
   7.204 -by (case_tac "n:prime" 1);
   7.205 -by (rtac exI 1);
   7.206 -by (etac prime_primel 1);
   7.207 -by (cut_inst_tac [("n","n")] not_prime_ex_mk 1);
   7.208 -by (auto_tac (claset() addSIs [split_primel], simpset()));
   7.209 -qed_spec_mp "factor_exists";
   7.210 -
   7.211 -Goal "1<n ==> (EX l. primel l & nondec l & prod l = n)"; 
   7.212 -by (etac (factor_exists RS exE) 1);
   7.213 -by (blast_tac (claset() addSIs [ex_nondec_lemma]) 1);
   7.214 -qed "nondec_factor_exists";
   7.215 -
   7.216 -
   7.217 -(* --- Uniqueness --- *)
   7.218 -
   7.219 -Goal "p:prime ==> p dvd (prod xs) --> (EX m. m:set xs & p dvd m)";
   7.220 -by (induct_tac "xs" 1);
   7.221 -by (ALLGOALS Asm_full_simp_tac);
   7.222 -by (etac prime_nd_one 1);
   7.223 -by (rtac impI 1);
   7.224 -by (dtac prime_dvd_mult 1);
   7.225 -by Auto_tac;
   7.226 -qed_spec_mp "prime_dvd_mult_list";
   7.227 -
   7.228 -Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
   7.229 -\     ==> EX m. m :set ys & x dvd m";
   7.230 -by (rtac prime_dvd_mult_list 1);
   7.231 -by (etac hd_dvd_prod 2);
   7.232 -by (asm_full_simp_tac (simpset() addsimps [primel_hd_tl]) 1);
   7.233 -qed "hd_xs_dvd_prod";
   7.234 -
   7.235 -Goal "[| primel (x#xs); primel ys; m:set ys; x dvd m |] ==> x=m";
   7.236 -by (rtac primes_eq 1);
   7.237 -by (auto_tac (claset(), simpset() addsimps [primel_def,primel_hd_tl]));
   7.238 -qed "prime_dvd_eq";
   7.239 -
   7.240 -Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] ==> x:set ys";
   7.241 -by (ftac hd_xs_dvd_prod 1);
   7.242 -by Auto_tac;
   7.243 -by (dtac prime_dvd_eq 1);
   7.244 -by Auto_tac;
   7.245 -qed "hd_xs_eq_prod";
   7.246 -
   7.247 -Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
   7.248 -\     ==> EX l. ys <~~> (x#l)";
   7.249 -by (rtac exI 1);
   7.250 -by (rtac perm_remove 1);
   7.251 -by (etac hd_xs_eq_prod 1);
   7.252 -by (ALLGOALS assume_tac);
   7.253 -qed "perm_primel_ex";
   7.254 -
   7.255 -Goal "[| primel (x#xs); primel ys; prod (x#xs) = prod ys |] \
   7.256 -\     ==> prod xs < prod ys";
   7.257 -by (auto_tac (claset() addIs [prod_mn_less_k,prime_g_one,primel_prod_gz],
   7.258 -              simpset() addsimps [primel_hd_tl]));
   7.259 -qed "primel_prod_less";
   7.260 -
   7.261 -Goal "[| primel xs; p*prod xs = p; p:prime |] ==> xs=[]";
   7.262 -by (auto_tac (claset() addIs [primel_one_empty], 
   7.263 -	      simpset() addsimps [prime_def]));
   7.264 -qed "prod_one_empty";
   7.265 -
   7.266 -Goal "[| ALL m. m < prod ys --> (ALL xs ys. primel xs & primel ys & \
   7.267 -\        prod xs = prod ys & prod xs = m --> xs <~~> ys); primel list; \
   7.268 -\        primel x; prod list = prod x; prod x < prod ys |] ==> x <~~> list";
   7.269 -by (Asm_full_simp_tac 1);
   7.270 -qed "uniq_ex_lemma";
   7.271 -
   7.272 -Goal "ALL xs ys. (primel xs & primel ys & prod xs = prod ys & prod xs = n \
   7.273 -\     --> xs <~~> ys)";
   7.274 -by (induct_thm_tac nat_less_induct "n" 1);
   7.275 -by Safe_tac;
   7.276 -by (case_tac "xs" 1);
   7.277 -by (force_tac (claset() addIs [primel_one_empty], simpset()) 1);
   7.278 -by (rtac (perm_primel_ex RS exE) 1);
   7.279 -by (ALLGOALS Asm_full_simp_tac);
   7.280 -by (rtac (perm.trans RS perm_sym) 1);
   7.281 -by (assume_tac 1);
   7.282 -by (rtac perm.Cons 1);
   7.283 -by (case_tac "x=[]" 1);
   7.284 -by (asm_full_simp_tac (simpset() addsimps [perm_sing_eq,primel_hd_tl]) 1);
   7.285 -by (res_inst_tac [("p","a")] prod_one_empty 1);
   7.286 -by (ALLGOALS Asm_full_simp_tac);
   7.287 -by (etac uniq_ex_lemma 1);
   7.288 -by (auto_tac (claset() addIs [primel_tl,perm_primel],
   7.289 -	      simpset() addsimps [primel_hd_tl]));
   7.290 -by (res_inst_tac [("k","a"),("n","prod list"),("m","prod x")] mult_left_cancel 1);
   7.291 -by (res_inst_tac [("x","a")] primel_prod_less 3);
   7.292 -by (rtac prod_xy_prod 2);
   7.293 -by (res_inst_tac [("s","prod ys")] trans 2);
   7.294 -by (etac perm_prod 3);
   7.295 -by (etac (perm_prod RS sym) 5); 
   7.296 -by (auto_tac (claset() addIs [perm_primel,prime_g_zero], simpset()));
   7.297 -qed_spec_mp "factor_unique";
   7.298 -
   7.299 -Goal "[| xs <~~> ys; nondec xs; nondec ys |] ==> xs = ys"; 
   7.300 -by (rtac trans 1);
   7.301 -by (rtac trans 1);
   7.302 -by (etac nondec_sort_eq 1);
   7.303 -by (etac perm_sort_eq 1);
   7.304 -by (etac (nondec_sort_eq RS sym) 1);
   7.305 -qed "perm_nondec_unique";
   7.306 -
   7.307 -Goal "ALL n. 1<n --> (EX! l. primel l & nondec l & prod l = n)";
   7.308 -by Safe_tac;
   7.309 -by (etac nondec_factor_exists 1);
   7.310 -by (rtac perm_nondec_unique 1);
   7.311 -by (rtac factor_unique 1);
   7.312 -by (ALLGOALS Asm_full_simp_tac);
   7.313 -qed_spec_mp "unique_prime_factorization";
     8.1 --- a/src/HOL/NumberTheory/Factorization.thy	Sat Feb 03 17:43:34 2001 +0100
     8.2 +++ b/src/HOL/NumberTheory/Factorization.thy	Sun Feb 04 19:31:13 2001 +0100
     8.3 @@ -1,38 +1,363 @@
     8.4 -(*  Title:      HOL/ex/Factorization.thy
     8.5 +(*  Title:      HOL/NumberTheory/Factorization.thy
     8.6      ID:         $Id$
     8.7      Author:     Thomas Marthedal Rasmussen
     8.8      Copyright   2000  University of Cambridge
     8.9 +*)
    8.10  
    8.11 -Fundamental Theorem of Arithmetic (unique factorization into primes)
    8.12 -*)
    8.13 +header {* Fundamental Theorem of Arithmetic (unique factorization into primes) *}
    8.14 +
    8.15 +theory Factorization = Primes + Permutation:
    8.16  
    8.17  
    8.18 -Factorization = Primes + Perm +
    8.19 +subsection {* Definitions *}
    8.20  
    8.21  consts
    8.22 -  primel  :: nat list => bool 
    8.23 -  nondec  :: nat list => bool 
    8.24 -  prod    :: nat list => nat
    8.25 -  oinsert :: [nat, nat list] => nat list
    8.26 -  sort    :: nat list => nat list
    8.27 +  primel :: "nat list => bool "
    8.28 +  nondec :: "nat list => bool "
    8.29 +  prod :: "nat list => nat"
    8.30 +  oinsert :: "nat => nat list => nat list"
    8.31 +  sort :: "nat list => nat list"
    8.32  
    8.33  defs
    8.34 -  primel_def "primel xs == set xs <= prime"
    8.35 +  primel_def: "primel xs == set xs \<subseteq> prime"
    8.36 +
    8.37 +primrec
    8.38 +  "nondec [] = True"
    8.39 +  "nondec (x # xs) = (case xs of [] => True | y # ys => x \<le> y \<and> nondec xs)"
    8.40  
    8.41  primrec
    8.42 -  "nondec []     = True"
    8.43 -  "nondec (x#xs) = (case xs of [] => True | y#ys => x<=y & nondec xs)"
    8.44 +  "prod [] = 1"
    8.45 +  "prod (x # xs) = x * prod xs"
    8.46 +
    8.47 +primrec
    8.48 +  "oinsert x [] = [x]"
    8.49 +  "oinsert x (y # ys) = (if x \<le> y then x # y # ys else y # oinsert x ys)"
    8.50  
    8.51  primrec
    8.52 -  "prod []     = 1"
    8.53 -  "prod (x#xs) = x * prod xs"
    8.54 +  "sort [] = []"
    8.55 +  "sort (x # xs) = oinsert x (sort xs)"
    8.56 +
    8.57 +
    8.58 +subsection {* Arithmetic *}
    8.59 +
    8.60 +lemma one_less_m: "(m::nat) \<noteq> m * k ==> m \<noteq> 1 ==> 1 < m"
    8.61 +  apply (case_tac m)
    8.62 +   apply auto
    8.63 +  done
    8.64 +
    8.65 +lemma one_less_k: "(m::nat) \<noteq> m * k ==> 1 < m * k ==> 1 < k"
    8.66 +  apply (case_tac k)
    8.67 +   apply auto
    8.68 +  done
    8.69 +
    8.70 +lemma mult_left_cancel: "(0::nat) < k ==> k * n = k * m ==> n = m"
    8.71 +  apply auto
    8.72 +  done
    8.73 +
    8.74 +lemma mn_eq_m_one: "(0::nat) < m ==> m * n = m ==> n = 1"
    8.75 +  apply (case_tac n)
    8.76 +   apply auto
    8.77 +  done
    8.78 +
    8.79 +lemma prod_mn_less_k:
    8.80 +    "(0::nat) < n ==> 0 < k ==> 1 < m ==> m * n = k ==> n < k"
    8.81 +  apply (induct m)
    8.82 +   apply auto
    8.83 +  done
    8.84 +
    8.85 +
    8.86 +subsection {* Prime list and product *}
    8.87 +
    8.88 +lemma prod_append: "prod (xs @ ys) = prod xs * prod ys"
    8.89 +  apply (induct xs)
    8.90 +   apply (simp_all add: mult_assoc)
    8.91 +  done
    8.92 +
    8.93 +lemma prod_xy_prod:
    8.94 +    "prod (x # xs) = prod (y # ys) ==> x * prod xs = y * prod ys"
    8.95 +  apply auto
    8.96 +  done
    8.97 +
    8.98 +lemma primel_append: "primel (xs @ ys) = (primel xs \<and> primel ys)"
    8.99 +  apply (unfold primel_def)
   8.100 +  apply auto
   8.101 +  done
   8.102 +
   8.103 +lemma prime_primel: "n \<in> prime ==> primel [n] \<and> prod [n] = n"
   8.104 +  apply (unfold primel_def)
   8.105 +  apply auto
   8.106 +  done
   8.107 +
   8.108 +lemma prime_nd_one: "p \<in> prime ==> \<not> p dvd 1"
   8.109 +  apply (unfold prime_def dvd_def)
   8.110 +  apply auto
   8.111 +  done
   8.112 +
   8.113 +lemma hd_dvd_prod: "prod (x # xs) = prod ys ==> x dvd (prod ys)"
   8.114 +  apply (unfold dvd_def)
   8.115 +  apply (rule exI)
   8.116 +  apply (rule sym)
   8.117 +  apply simp
   8.118 +  done
   8.119 +
   8.120 +lemma primel_tl: "primel (x # xs) ==> primel xs"
   8.121 +  apply (unfold primel_def)
   8.122 +  apply auto
   8.123 +  done
   8.124 +
   8.125 +lemma primel_hd_tl: "(primel (x # xs)) = (x \<in> prime \<and> primel xs)"
   8.126 +  apply (unfold primel_def)
   8.127 +  apply auto
   8.128 +  done
   8.129 +
   8.130 +lemma primes_eq: "p \<in> prime ==> q \<in> prime ==> p dvd q ==> p = q"
   8.131 +  apply (unfold prime_def)
   8.132 +  apply auto
   8.133 +  done
   8.134 +
   8.135 +lemma primel_one_empty: "primel xs ==> prod xs = 1 ==> xs = []"
   8.136 +  apply (unfold primel_def prime_def)
   8.137 +  apply (case_tac xs)
   8.138 +   apply simp_all
   8.139 +  done
   8.140 +
   8.141 +lemma prime_g_one: "p \<in> prime ==> 1 < p"
   8.142 +  apply (unfold prime_def)
   8.143 +  apply auto
   8.144 +  done
   8.145 +
   8.146 +lemma prime_g_zero: "p \<in> prime ==> 0 < p"
   8.147 +  apply (unfold prime_def)
   8.148 +  apply auto
   8.149 +  done
   8.150 +
   8.151 +lemma primel_nempty_g_one [rule_format]:
   8.152 +    "primel xs --> xs \<noteq> [] --> 1 < prod xs"
   8.153 +  apply (unfold primel_def prime_def)
   8.154 +  apply (induct xs)
   8.155 +   apply (auto elim: one_less_mult)
   8.156 +  done
   8.157 +
   8.158 +lemma primel_prod_gz: "primel xs ==> 0 < prod xs"
   8.159 +  apply (unfold primel_def prime_def)
   8.160 +  apply (induct xs)
   8.161 +   apply auto
   8.162 +  done
   8.163 +
   8.164 +
   8.165 +subsection {* Sorting *}
   8.166 +
   8.167 +lemma nondec_oinsert [rule_format]: "nondec xs --> nondec (oinsert x xs)"
   8.168 +  apply (induct xs)
   8.169 +   apply (case_tac [2] list)
   8.170 +    apply (simp_all cong del: list.weak_case_cong)
   8.171 +  done
   8.172 +
   8.173 +lemma nondec_sort: "nondec (sort xs)"
   8.174 +  apply (induct xs)
   8.175 +   apply simp_all
   8.176 +  apply (erule nondec_oinsert)
   8.177 +  done
   8.178 +
   8.179 +lemma x_less_y_oinsert: "x \<le> y ==> l = y # ys ==> x # l = oinsert x l"
   8.180 +  apply simp_all
   8.181 +  done
   8.182 +
   8.183 +lemma nondec_sort_eq [rule_format]: "nondec xs --> xs = sort xs"
   8.184 +  apply (induct xs)
   8.185 +   apply safe
   8.186 +    apply simp_all
   8.187 +   apply (case_tac list)
   8.188 +    apply simp_all
   8.189 +  apply (case_tac list)
   8.190 +   apply simp
   8.191 +  apply (rule_tac y = aa and ys = lista in x_less_y_oinsert)
   8.192 +   apply simp_all
   8.193 +  done
   8.194 +
   8.195 +lemma oinsert_x_y: "oinsert x (oinsert y l) = oinsert y (oinsert x l)"
   8.196 +  apply (induct l)
   8.197 +  apply auto
   8.198 +  done
   8.199 +
   8.200 +
   8.201 +subsection {* Permutation *}
   8.202 +
   8.203 +lemma perm_primel [rule_format]: "xs <~~> ys ==> primel xs --> primel ys"
   8.204 +  apply (unfold primel_def)
   8.205 +  apply (erule perm.induct)
   8.206 +     apply simp_all
   8.207 +  done
   8.208 +
   8.209 +lemma perm_prod [rule_format]: "xs <~~> ys ==> prod xs = prod ys"
   8.210 +  apply (erule perm.induct)
   8.211 +     apply (simp_all add: mult_ac)
   8.212 +  done
   8.213  
   8.214 -primrec
   8.215 -  "oinsert x []     = [x]"
   8.216 -  "oinsert x (y#ys) = (if x<=y then x#y#ys else y#oinsert x ys)"
   8.217 +lemma perm_subst_oinsert: "xs <~~> ys ==> oinsert a xs <~~> oinsert a ys"
   8.218 +  apply (erule perm.induct)
   8.219 +     apply auto
   8.220 +  done
   8.221 +
   8.222 +lemma perm_oinsert: "x # xs <~~> oinsert x xs"
   8.223 +  apply (induct xs)
   8.224 +   apply auto
   8.225 +  done
   8.226 +
   8.227 +lemma perm_sort: "xs <~~> sort xs"
   8.228 +  apply (induct xs)
   8.229 +  apply (auto intro: perm_oinsert elim: perm_subst_oinsert)
   8.230 +  done
   8.231 +
   8.232 +lemma perm_sort_eq: "xs <~~> ys ==> sort xs = sort ys"
   8.233 +  apply (erule perm.induct)
   8.234 +     apply (simp_all add: oinsert_x_y)
   8.235 +  done
   8.236 +
   8.237 +
   8.238 +subsection {* Existence *}
   8.239 +
   8.240 +lemma ex_nondec_lemma:
   8.241 +    "primel xs ==> \<exists>ys. primel ys \<and> nondec ys \<and> prod ys = prod xs"
   8.242 +  apply (blast intro: nondec_sort perm_prod perm_primel perm_sort perm_sym)
   8.243 +  done
   8.244 +
   8.245 +lemma not_prime_ex_mk:
   8.246 +  "1 < n \<and> n \<notin> prime ==>
   8.247 +    \<exists>m k. 1 < m \<and> 1 < k \<and> m < n \<and> k < n \<and> n = m * k"
   8.248 +  apply (unfold prime_def dvd_def)
   8.249 +  apply (auto intro: n_less_m_mult_n n_less_n_mult_m one_less_m one_less_k)
   8.250 +  done
   8.251 +
   8.252 +lemma split_primel:
   8.253 +    "primel xs ==> primel ys ==> \<exists>l. primel l \<and> prod l = prod xs * prod ys"
   8.254 +  apply (rule exI)
   8.255 +  apply safe
   8.256 +   apply (rule_tac [2] prod_append)
   8.257 +  apply (simp add: primel_append)
   8.258 +  done
   8.259 +
   8.260 +lemma factor_exists [rule_format]: "1 < n --> (\<exists>l. primel l \<and> prod l = n)"
   8.261 +  apply (induct n rule: nat_less_induct)
   8.262 +  apply (rule impI)
   8.263 +  apply (case_tac "n \<in> prime")
   8.264 +   apply (rule exI)
   8.265 +   apply (erule prime_primel)
   8.266 +  apply (cut_tac n = n in not_prime_ex_mk)
   8.267 +   apply (auto intro!: split_primel)
   8.268 +  done
   8.269 +
   8.270 +lemma nondec_factor_exists: "1 < n ==> \<exists>l. primel l \<and> nondec l \<and> prod l = n"
   8.271 +  apply (erule factor_exists [THEN exE])
   8.272 +  apply (blast intro!: ex_nondec_lemma)
   8.273 +  done
   8.274 +
   8.275 +
   8.276 +subsection {* Uniqueness *}
   8.277 +
   8.278 +lemma prime_dvd_mult_list [rule_format]:
   8.279 +    "p \<in> prime ==> p dvd (prod xs) --> (\<exists>m. m:set xs \<and> p dvd m)"
   8.280 +  apply (induct xs)
   8.281 +   apply simp_all
   8.282 +   apply (erule prime_nd_one)
   8.283 +  apply (rule impI)
   8.284 +  apply (drule prime_dvd_mult)
   8.285 +   apply auto
   8.286 +  done
   8.287 +
   8.288 +lemma hd_xs_dvd_prod:
   8.289 +  "primel (x # xs) ==> primel ys ==> prod (x # xs) = prod ys
   8.290 +    ==> \<exists>m. m \<in> set ys \<and> x dvd m"
   8.291 +  apply (rule prime_dvd_mult_list)
   8.292 +   apply (simp add: primel_hd_tl)
   8.293 +  apply (erule hd_dvd_prod)
   8.294 +  done
   8.295 +
   8.296 +lemma prime_dvd_eq: "primel (x # xs) ==> primel ys ==> m \<in> set ys ==> x dvd m ==> x = m"
   8.297 +  apply (rule primes_eq)
   8.298 +    apply (auto simp add: primel_def primel_hd_tl)
   8.299 +  done
   8.300  
   8.301 -primrec
   8.302 -  "sort []     = []"
   8.303 -  "sort (x#xs) = oinsert x (sort xs)"  
   8.304 +lemma hd_xs_eq_prod:
   8.305 +  "primel (x # xs) ==>
   8.306 +    primel ys ==> prod (x # xs) = prod ys ==> x \<in> set ys"
   8.307 +  apply (frule hd_xs_dvd_prod)
   8.308 +    apply auto
   8.309 +  apply (drule prime_dvd_eq)
   8.310 +     apply auto
   8.311 +  done
   8.312 +
   8.313 +lemma perm_primel_ex:
   8.314 +  "primel (x # xs) ==>
   8.315 +    primel ys ==> prod (x # xs) = prod ys ==> \<exists>l. ys <~~> (x # l)"
   8.316 +  apply (rule exI)
   8.317 +  apply (rule perm_remove)
   8.318 +  apply (erule hd_xs_eq_prod)
   8.319 +   apply simp_all
   8.320 +  done
   8.321 +
   8.322 +lemma primel_prod_less:
   8.323 +  "primel (x # xs) ==>
   8.324 +    primel ys ==> prod (x # xs) = prod ys ==> prod xs < prod ys"
   8.325 +  apply (auto intro: prod_mn_less_k prime_g_one primel_prod_gz simp add: primel_hd_tl)
   8.326 +  done
   8.327 +
   8.328 +lemma prod_one_empty:
   8.329 +    "primel xs ==> p * prod xs = p ==> p \<in> prime ==> xs = []"
   8.330 +  apply (auto intro: primel_one_empty simp add: prime_def)
   8.331 +  done
   8.332 +
   8.333 +lemma uniq_ex_aux:
   8.334 +  "\<forall>m. m < prod ys --> (\<forall>xs ys. primel xs \<and> primel ys \<and>
   8.335 +      prod xs = prod ys \<and> prod xs = m --> xs <~~> ys) ==>
   8.336 +    primel list ==> primel x ==> prod list = prod x ==> prod x < prod ys
   8.337 +    ==> x <~~> list"
   8.338 +  apply simp
   8.339 +  done
   8.340  
   8.341 -end
   8.342 \ No newline at end of file
   8.343 +lemma factor_unique [rule_format]:
   8.344 +  "\<forall>xs ys. primel xs \<and> primel ys \<and> prod xs = prod ys \<and> prod xs = n
   8.345 +    --> xs <~~> ys"
   8.346 +  apply (induct n rule: nat_less_induct)
   8.347 +  apply safe
   8.348 +  apply (case_tac xs)
   8.349 +   apply (force intro: primel_one_empty)
   8.350 +  apply (rule perm_primel_ex [THEN exE])
   8.351 +     apply simp_all
   8.352 +  apply (rule perm.trans [THEN perm_sym])
   8.353 +  apply assumption
   8.354 +  apply (rule perm.Cons)
   8.355 +  apply (case_tac "x = []")
   8.356 +   apply (simp add: perm_sing_eq primel_hd_tl)
   8.357 +   apply (rule_tac p = a in prod_one_empty)
   8.358 +     apply simp_all
   8.359 +  apply (erule uniq_ex_aux)
   8.360 +     apply (auto intro: primel_tl perm_primel simp add: primel_hd_tl)
   8.361 +   apply (rule_tac k = a and n = "prod list" and m = "prod x" in mult_left_cancel)
   8.362 +    apply (rule_tac [3] x = a in primel_prod_less)
   8.363 +      apply (rule_tac [2] prod_xy_prod)
   8.364 +      apply (rule_tac [2] s = "prod ys" in HOL.trans)
   8.365 +       apply (erule_tac [3] perm_prod)
   8.366 +      apply (erule_tac [5] perm_prod [symmetric])
   8.367 +     apply (auto intro: perm_primel prime_g_zero)
   8.368 +  done
   8.369 +
   8.370 +lemma perm_nondec_unique:
   8.371 +    "xs <~~> ys ==> nondec xs ==> nondec ys ==> xs = ys"
   8.372 +  apply (rule HOL.trans)
   8.373 +   apply (rule HOL.trans)
   8.374 +    apply (erule nondec_sort_eq)
   8.375 +   apply (erule perm_sort_eq)
   8.376 +  apply (erule nondec_sort_eq [symmetric])
   8.377 +  done
   8.378 +
   8.379 +lemma unique_prime_factorization [rule_format]:
   8.380 +    "\<forall>n. 1 < n --> (\<exists>!l. primel l \<and> nondec l \<and> prod l = n)"
   8.381 +  apply safe
   8.382 +   apply (erule nondec_factor_exists)
   8.383 +  apply (rule perm_nondec_unique)
   8.384 +    apply (rule factor_unique)
   8.385 +    apply simp_all
   8.386 +  done
   8.387 +
   8.388 +end
     9.1 --- a/src/HOL/NumberTheory/Fib.ML	Sat Feb 03 17:43:34 2001 +0100
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,121 +0,0 @@
     9.4 -(*  Title:      HOL/ex/Fib
     9.5 -    ID:         $Id$
     9.6 -    Author:     Lawrence C Paulson
     9.7 -    Copyright   1997  University of Cambridge
     9.8 -
     9.9 -Fibonacci numbers: proofs of laws taken from
    9.10 -
    9.11 -  R. L. Graham, D. E. Knuth, O. Patashnik.
    9.12 -  Concrete Mathematics.
    9.13 -  (Addison-Wesley, 1989)
    9.14 -*)
    9.15 -
    9.16 -
    9.17 -(** The difficulty in these proofs is to ensure that the induction hypotheses
    9.18 -    are applied before the definition of "fib".  Towards this end, the 
    9.19 -    "fib" equations are not added to the simpset and are applied very 
    9.20 -    selectively at first.
    9.21 -**)
    9.22 -
    9.23 -Delsimps fib.Suc_Suc;
    9.24 -
    9.25 -val [fib_Suc_Suc] = fib.Suc_Suc;
    9.26 -val fib_Suc3 = read_instantiate [("x", "(Suc ?n)")] fib_Suc_Suc;
    9.27 -
    9.28 -(*Concrete Mathematics, page 280*)
    9.29 -Goal "fib (Suc (n + k)) = fib(Suc k) * fib(Suc n) + fib k * fib n";
    9.30 -by (induct_thm_tac fib.induct "n" 1);
    9.31 -(*Simplify the LHS just enough to apply the induction hypotheses*)
    9.32 -by (asm_full_simp_tac
    9.33 -    (simpset() addsimps [inst "x" "Suc(?m+?n)" fib_Suc_Suc]) 3);
    9.34 -by (ALLGOALS 
    9.35 -    (asm_simp_tac (simpset() addsimps 
    9.36 -		   ([fib_Suc_Suc, add_mult_distrib, add_mult_distrib2]))));
    9.37 -qed "fib_add";
    9.38 -
    9.39 -
    9.40 -Goal "fib (Suc n) ~= 0";
    9.41 -by (induct_thm_tac fib.induct "n" 1);
    9.42 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [fib_Suc_Suc])));
    9.43 -qed "fib_Suc_neq_0";
    9.44 -
    9.45 -(* Also add  0 < fib (Suc n) *)
    9.46 -Addsimps [fib_Suc_neq_0, [neq0_conv, fib_Suc_neq_0] MRS iffD1];
    9.47 -
    9.48 -Goal "0<n ==> 0 < fib n";
    9.49 -by (rtac (not0_implies_Suc RS exE) 1);
    9.50 -by Auto_tac;
    9.51 -qed "fib_gr_0";
    9.52 -
    9.53 -(*Concrete Mathematics, page 278: Cassini's identity.
    9.54 -  It is much easier to prove using integers!*)
    9.55 -Goal "int (fib (Suc (Suc n)) * fib n) = \
    9.56 -\     (if n mod #2 = 0 then int (fib(Suc n) * fib(Suc n)) - #1 \
    9.57 -\                      else int (fib(Suc n) * fib(Suc n)) + #1)";
    9.58 -by (induct_thm_tac fib.induct "n" 1);
    9.59 -by (simp_tac (simpset() addsimps [fib_Suc_Suc, mod_Suc]) 2);
    9.60 -by (simp_tac (simpset() addsimps [fib_Suc_Suc]) 1);
    9.61 -by (asm_full_simp_tac
    9.62 -     (simpset() addsimps [fib_Suc_Suc, add_mult_distrib, add_mult_distrib2, 
    9.63 -			  mod_Suc, zmult_int RS sym] @ zmult_ac) 1);
    9.64 -qed "fib_Cassini";
    9.65 -
    9.66 -
    9.67 -
    9.68 -(** Towards Law 6.111 of Concrete Mathematics **)
    9.69 -
    9.70 -val gcd_induct = thm "gcd_induct";
    9.71 -val gcd_commute = thm "gcd_commute";
    9.72 -val gcd_add2 = thm "gcd_add2";
    9.73 -val gcd_non_0 = thm "gcd_non_0";
    9.74 -val gcd_mult_cancel = thm "gcd_mult_cancel";
    9.75 -
    9.76 -
    9.77 -Goal "gcd(fib n, fib (Suc n)) = 1";
    9.78 -by (induct_thm_tac fib.induct "n" 1);
    9.79 -by (asm_simp_tac (simpset() addsimps [gcd_commute, fib_Suc3]) 3);
    9.80 -by (ALLGOALS (simp_tac (simpset() addsimps [fib_Suc_Suc])));
    9.81 -qed "gcd_fib_Suc_eq_1"; 
    9.82 -
    9.83 -val gcd_fib_commute = 
    9.84 -    read_instantiate_sg (sign_of thy) [("m", "fib m")] gcd_commute;
    9.85 -
    9.86 -Goal "gcd(fib m, fib (n+m)) = gcd(fib m, fib n)";
    9.87 -by (simp_tac (simpset() addsimps [gcd_fib_commute]) 1);
    9.88 -by (case_tac "m=0" 1);
    9.89 -by (Asm_simp_tac 1);
    9.90 -by (clarify_tac (claset() addSDs [not0_implies_Suc]) 1);
    9.91 -by (simp_tac (simpset() addsimps [fib_add]) 1);
    9.92 -by (asm_simp_tac (simpset() addsimps [add_commute, gcd_non_0]) 1);
    9.93 -by (asm_simp_tac (simpset() addsimps [gcd_non_0 RS sym]) 1);
    9.94 -by (asm_simp_tac (simpset() addsimps [gcd_fib_Suc_eq_1, gcd_mult_cancel]) 1);
    9.95 -qed "gcd_fib_add";
    9.96 -
    9.97 -Goal "m <= n ==> gcd(fib m, fib (n-m)) = gcd(fib m, fib n)";
    9.98 -by (rtac (gcd_fib_add RS sym RS trans) 1);
    9.99 -by (Asm_simp_tac 1);
   9.100 -qed "gcd_fib_diff";
   9.101 -
   9.102 -Goal "0<m ==> gcd (fib m, fib (n mod m)) = gcd (fib m, fib n)";
   9.103 -by (induct_thm_tac nat_less_induct "n" 1);
   9.104 -by (stac mod_if 1);
   9.105 -by (Asm_simp_tac 1);
   9.106 -by (asm_simp_tac (simpset() addsimps [gcd_fib_diff, mod_geq, 
   9.107 -				      not_less_iff_le, diff_less]) 1);
   9.108 -qed "gcd_fib_mod";
   9.109 -
   9.110 -(*Law 6.111*)
   9.111 -Goal "fib(gcd(m,n)) = gcd(fib m, fib n)";
   9.112 -by (induct_thm_tac gcd_induct "m n" 1);
   9.113 -by (Asm_simp_tac 1);
   9.114 -by (asm_full_simp_tac (simpset() addsimps [gcd_non_0]) 1);
   9.115 -by (asm_full_simp_tac (simpset() addsimps [gcd_commute, gcd_fib_mod]) 1);
   9.116 -qed "fib_gcd";
   9.117 -
   9.118 -Goal "fib (Suc n) * fib n = setsum (%k. fib k * fib k) (atMost n)";
   9.119 -by (induct_thm_tac fib.induct "n" 1);
   9.120 -by (auto_tac (claset(), simpset() addsimps [atMost_Suc, fib_Suc_Suc]));  
   9.121 -by (asm_full_simp_tac
   9.122 -     (simpset() addsimps [add_mult_distrib, add_mult_distrib2]) 1);
   9.123 -qed "fib_mult_eq_setsum";
   9.124 -
    10.1 --- a/src/HOL/NumberTheory/Fib.thy	Sat Feb 03 17:43:34 2001 +0100
    10.2 +++ b/src/HOL/NumberTheory/Fib.thy	Sun Feb 04 19:31:13 2001 +0100
    10.3 @@ -1,17 +1,125 @@
    10.4 -(*  Title:      ex/Fib
    10.5 +(*  Title:      HOL/NumberTheory/Fib.thy
    10.6      ID:         $Id$
    10.7      Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
    10.8      Copyright   1997  University of Cambridge
    10.9 -
   10.10 -The Fibonacci function.  Demonstrates the use of recdef.
   10.11  *)
   10.12  
   10.13 -Fib = Primes +
   10.14 +header {* The Fibonacci function *}
   10.15 +
   10.16 +theory Fib = Primes:
   10.17 +
   10.18 +text {*
   10.19 +  Fibonacci numbers: proofs of laws taken from:
   10.20 +  R. L. Graham, D. E. Knuth, O. Patashnik.  Concrete Mathematics.
   10.21 +  (Addison-Wesley, 1989)
   10.22 +
   10.23 +  \bigskip
   10.24 +*}
   10.25 +
   10.26 +consts fib :: "nat => nat"
   10.27 +recdef fib  less_than
   10.28 +  zero: "fib 0 = 0"
   10.29 +  one:  "fib 1 = 1"
   10.30 +  Suc_Suc: "fib (Suc (Suc x)) = fib x + fib (Suc x)"
   10.31 +
   10.32 +text {*
   10.33 +  \medskip The difficulty in these proofs is to ensure that the
   10.34 +  induction hypotheses are applied before the definition of @{term
   10.35 +  fib}.  Towards this end, the @{term fib} equations are not declared
   10.36 +  to the Simplifier and are applied very selectively at first.
   10.37 +*}
   10.38 +
   10.39 +declare fib.Suc_Suc [simp del]
   10.40 +
   10.41 +lemma fib_Suc3: "fib (Suc (Suc (Suc n))) = fib (Suc n) + fib (Suc (Suc n))"
   10.42 +  apply (rule fib.Suc_Suc)
   10.43 +  done
   10.44 +
   10.45 +
   10.46 +text {* \medskip Concrete Mathematics, page 280 *}
   10.47 +
   10.48 +lemma fib_add: "fib (Suc (n + k)) = fib (Suc k) * fib (Suc n) + fib k * fib n"
   10.49 +  apply (induct n rule: fib.induct)
   10.50 +    prefer 3
   10.51 +    txt {* simplify the LHS just enough to apply the induction hypotheses *}
   10.52 +    apply (simp add: fib.Suc_Suc [of "Suc (m + n)", standard])
   10.53 +    apply (simp_all (no_asm_simp) add: fib.Suc_Suc add_mult_distrib add_mult_distrib2)
   10.54 +    done
   10.55 +
   10.56 +lemma fib_Suc_neq_0 [simp]: "fib (Suc n) \<noteq> 0"
   10.57 +  apply (induct n rule: fib.induct)
   10.58 +    apply (simp_all add: fib.Suc_Suc)
   10.59 +  done
   10.60 +
   10.61 +lemma [simp]: "0 < fib (Suc n)"
   10.62 +  apply (simp add: neq0_conv [symmetric])
   10.63 +  done
   10.64 +
   10.65 +lemma fib_gr_0: "0 < n ==> 0 < fib n"
   10.66 +  apply (rule not0_implies_Suc [THEN exE])
   10.67 +   apply auto
   10.68 +  done
   10.69 +
   10.70  
   10.71 -consts fib  :: "nat => nat"
   10.72 -recdef fib "less_than"
   10.73 -  zero    "fib 0 = 0"
   10.74 -  one     "fib 1 = 1"
   10.75 -  Suc_Suc "fib (Suc (Suc x)) = fib x + fib (Suc x)"
   10.76 +text {*
   10.77 +  \medskip Concrete Mathematics, page 278: Cassini's identity.  It is
   10.78 +  much easier to prove using integers!
   10.79 +*}
   10.80 +
   10.81 +lemma fib_Cassini: "int (fib (Suc (Suc n)) * fib n) =
   10.82 +  (if n mod #2 = 0 then int (fib (Suc n) * fib (Suc n)) - #1
   10.83 +   else int (fib (Suc n) * fib (Suc n)) + #1)"
   10.84 +  apply (induct n rule: fib.induct)
   10.85 +    apply (simp add: fib.Suc_Suc)
   10.86 +   apply (simp add: fib.Suc_Suc mod_Suc)
   10.87 +  apply (simp add: fib.Suc_Suc
   10.88 +    add_mult_distrib add_mult_distrib2 mod_Suc zmult_int [symmetric] zmult_ac)
   10.89 +  done
   10.90 +
   10.91 +
   10.92 +text {* \medskip Towards Law 6.111 of Concrete Mathematics *}
   10.93 +
   10.94 +lemma gcd_fib_Suc_eq_1: "gcd (fib n, fib (Suc n)) = 1"
   10.95 +  apply (induct n rule: fib.induct)
   10.96 +    prefer 3
   10.97 +    apply (simp add: gcd_commute fib_Suc3)
   10.98 +   apply (simp_all add: fib.Suc_Suc)
   10.99 +  done
  10.100 +
  10.101 +lemma gcd_fib_add: "gcd (fib m, fib (n + m)) = gcd (fib m, fib n)"
  10.102 +  apply (simp (no_asm) add: gcd_commute [of "fib m"])
  10.103 +  apply (case_tac "m = 0")
  10.104 +   apply simp
  10.105 +  apply (clarify dest!: not0_implies_Suc)
  10.106 +  apply (simp add: fib_add)
  10.107 +  apply (simp add: add_commute gcd_non_0)
  10.108 +  apply (simp add: gcd_non_0 [symmetric])
  10.109 +  apply (simp add: gcd_fib_Suc_eq_1 gcd_mult_cancel)
  10.110 +  done
  10.111 +
  10.112 +lemma gcd_fib_diff: "m \<le> n ==> gcd (fib m, fib (n - m)) = gcd (fib m, fib n)"
  10.113 +  apply (rule gcd_fib_add [symmetric, THEN trans])
  10.114 +  apply simp
  10.115 +  done
  10.116 +
  10.117 +lemma gcd_fib_mod: "0 < m ==> gcd (fib m, fib (n mod m)) = gcd (fib m, fib n)"
  10.118 +  apply (induct n rule: nat_less_induct)
  10.119 +  apply (subst mod_if)
  10.120 +  apply (simp add: gcd_fib_diff mod_geq not_less_iff_le diff_less)
  10.121 +  done
  10.122 +
  10.123 +lemma fib_gcd: "fib (gcd (m, n)) = gcd (fib m, fib n)"  -- {* Law 6.111 *}
  10.124 +  apply (induct m n rule: gcd_induct)
  10.125 +   apply simp
  10.126 +  apply (simp add: gcd_non_0)
  10.127 +  apply (simp add: gcd_commute gcd_fib_mod)
  10.128 +  done
  10.129 +
  10.130 +lemma fib_mult_eq_setsum:
  10.131 +    "fib (Suc n) * fib n = setsum (\<lambda>k. fib k * fib k) (atMost n)"
  10.132 +  apply (induct n rule: fib.induct)
  10.133 +    apply (auto simp add: atMost_Suc fib.Suc_Suc)
  10.134 +  apply (simp add: add_mult_distrib add_mult_distrib2)
  10.135 +  done
  10.136  
  10.137  end
    11.1 --- a/src/HOL/NumberTheory/IntFact.ML	Sat Feb 03 17:43:34 2001 +0100
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,85 +0,0 @@
    11.4 -(*  Title:	IntPowerFact.ML
    11.5 -    ID:         $Id$
    11.6 -    Author:	Thomas M. Rasmussen
    11.7 -    Copyright	2000  University of Cambridge
    11.8 -
    11.9 -Factorial on integers.
   11.10 -Product of finite set.
   11.11 -Recursively defined set including all Integers from 2 up to a. 
   11.12 -*)
   11.13 -
   11.14 -
   11.15 -(*----  setprod  ----*)
   11.16 -
   11.17 -Goalw [setprod_def] "setprod {} = #1";
   11.18 -by (Simp_tac 1);
   11.19 -qed "setprod_empty";
   11.20 -Addsimps [setprod_empty];
   11.21 -
   11.22 -Goalw [setprod_def] 
   11.23 -      "[| finite A; a ~: A |] ==> setprod (insert a A) = a * setprod A";
   11.24 -by (asm_simp_tac (simpset() addsimps [zmult_left_commute,
   11.25 -                                      export fold_insert]) 1);
   11.26 -qed "setprod_insert";
   11.27 -Addsimps [setprod_insert];
   11.28 -
   11.29 -(*---- IntFact ----*)
   11.30 -
   11.31 -val [d22set_eq] = d22set.simps;
   11.32 -Delsimps d22set.simps;
   11.33 -
   11.34 -val [prem1,prem2] =
   11.35 -Goal "[| !!a. P {} a; \
   11.36 -\        !!a. [| #1<(a::int); P (d22set (a-#1)) (a-#1) |] \
   11.37 -\             ==> P (d22set a) a |] \
   11.38 -\    ==> P (d22set u) u";
   11.39 -by (rtac d22set.induct 1);
   11.40 -by Safe_tac;
   11.41 -by (case_tac "#1<a" 2);
   11.42 -by (rtac prem2 2);
   11.43 -by (ALLGOALS Asm_simp_tac);
   11.44 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [d22set_eq,prem1])));
   11.45 -qed "d22set_induct";
   11.46 -
   11.47 -Goal "b:(d22set a) --> #1<b";
   11.48 -by (induct_thm_tac d22set_induct "a" 1);
   11.49 -by (stac d22set_eq 2);
   11.50 -by Auto_tac;
   11.51 -qed_spec_mp "d22set_g_1";
   11.52 -
   11.53 -Goal "b:(d22set a) --> b<=a";
   11.54 -by (induct_thm_tac d22set_induct "a" 1);
   11.55 -by (stac d22set_eq 2);
   11.56 -by Auto_tac;
   11.57 -qed_spec_mp "d22set_le";
   11.58 -
   11.59 -Goal "a<b ==> b~:(d22set a)";
   11.60 -by (auto_tac (claset() addDs [d22set_le], simpset()));  
   11.61 -qed "d22set_le_swap";
   11.62 -
   11.63 -Goal "#1<b --> b<=a --> b:(d22set a)";
   11.64 -by (induct_thm_tac d22set.induct "a" 1);
   11.65 -by Auto_tac;
   11.66 -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [d22set_eq])));
   11.67 -qed_spec_mp "d22set_mem";
   11.68 -
   11.69 -Goal "finite (d22set a)";
   11.70 -by (induct_thm_tac d22set_induct "a" 1);
   11.71 -by (stac d22set_eq 2);
   11.72 -by Auto_tac;
   11.73 -qed "d22set_fin";
   11.74 -
   11.75 -val [zfact_eq] = zfact.simps;
   11.76 -Delsimps zfact.simps; 
   11.77 -
   11.78 -Goal "setprod(d22set a) = zfact a";
   11.79 -by (induct_thm_tac d22set.induct "a" 1);
   11.80 -by Safe_tac;
   11.81 -by (asm_full_simp_tac (simpset() addsimps [d22set_eq,zfact_eq]) 1);
   11.82 -by (stac d22set_eq 1);
   11.83 -by (stac zfact_eq 1);
   11.84 -by (case_tac "#1<a" 1);
   11.85 -by (asm_full_simp_tac (simpset() addsimps [d22set_eq,zfact_eq]) 2);
   11.86 -by (asm_full_simp_tac (simpset() addsimps [d22set_fin,d22set_le_swap]) 1);
   11.87 -qed "d22set_prod_zfact";
   11.88 -
    12.1 --- a/src/HOL/NumberTheory/IntFact.thy	Sat Feb 03 17:43:34 2001 +0100
    12.2 +++ b/src/HOL/NumberTheory/IntFact.thy	Sun Feb 04 19:31:13 2001 +0100
    12.3 @@ -1,23 +1,118 @@
    12.4 -(*  Title:	IntFact.thy
    12.5 +(*  Title:      HOL/NumberTheory/IntFact.thy
    12.6      ID:         $Id$
    12.7 -    Author:	Thomas M. Rasmussen
    12.8 -    Copyright	2000  University of Cambridge
    12.9 +    Author:     Thomas M. Rasmussen
   12.10 +    Copyright   2000  University of Cambridge
   12.11  *)
   12.12  
   12.13 -IntFact = IntPrimes + 
   12.14 +header {* Factorial on integers *}
   12.15 +
   12.16 +theory IntFact = IntPrimes:
   12.17 +
   12.18 +text {*
   12.19 +  Factorial on integers and recursively defined set including all
   12.20 +  Integers from @{term 2} up to @{term a}.  Plus definition of product
   12.21 +  of finite set.
   12.22 +
   12.23 +  \bigskip
   12.24 +*}
   12.25  
   12.26  consts
   12.27 -  zfact    :: int => int
   12.28 -  setprod  :: int set => int
   12.29 -  d22set   :: int => int set
   12.30 +  zfact :: "int => int"
   12.31 +  setprod :: "int set => int"
   12.32 +  d22set :: "int => int set"
   12.33  
   12.34 -recdef zfact "measure ((% n.(nat n)) ::int=>nat)"
   12.35 -    "zfact n = (if n<=#0 then #1 else n*zfact(n-#1))"
   12.36 +recdef zfact  "measure ((\<lambda>n. nat n) :: int => nat)"
   12.37 +  "zfact n = (if n \<le> #0 then #1 else n * zfact (n - #1))"
   12.38  
   12.39  defs
   12.40 -  setprod_def  "setprod A == (if finite A then fold (op*) #1 A else #1)"
   12.41 +  setprod_def: "setprod A == (if finite A then fold (op *) #1 A else #1)"
   12.42 +
   12.43 +recdef d22set  "measure ((\<lambda>a. nat a) :: int => nat)"
   12.44 +  "d22set a = (if #1 < a then insert a (d22set (a - #1)) else {})"
   12.45 +
   12.46 +
   12.47 +text {* \medskip @{term setprod} --- product of finite set *}
   12.48 +
   12.49 +lemma setprod_empty [simp]: "setprod {} = #1"
   12.50 +  apply (simp add: setprod_def)
   12.51 +  done
   12.52 +
   12.53 +lemma setprod_insert [simp]:
   12.54 +    "finite A ==> a \<notin> A ==> setprod (insert a A) = a * setprod A"
   12.55 +  apply (unfold setprod_def)
   12.56 +  apply (simp add: zmult_left_commute fold_insert [standard])
   12.57 +  done
   12.58 +
   12.59 +
   12.60 +text {*
   12.61 +  \medskip @{term d22set} --- recursively defined set including all
   12.62 +  integers from @{term 2} up to @{term a}
   12.63 +*}
   12.64 +
   12.65 +declare d22set.simps [simp del]
   12.66 +
   12.67 +
   12.68 +lemma d22set_induct:
   12.69 +  "(!!a. P {} a) ==>
   12.70 +    (!!a. #1 < (a::int) ==> P (d22set (a - #1)) (a - #1)
   12.71 +      ==> P (d22set a) a)
   12.72 +    ==> P (d22set u) u"
   12.73 +proof -
   12.74 +  case antecedent
   12.75 +  show ?thesis
   12.76 +    apply (rule d22set.induct)
   12.77 +    apply safe
   12.78 +     apply (case_tac [2] "#1 < a")
   12.79 +      apply (rule_tac [2] antecedent)
   12.80 +       apply (simp_all (no_asm_simp))
   12.81 +     apply (simp_all (no_asm_simp) add: d22set.simps antecedent)
   12.82 +    done
   12.83 +qed
   12.84  
   12.85 -recdef d22set "measure ((%a.(nat a)) ::int=>nat)"
   12.86 -    "d22set a = (if #1<a then insert a (d22set (a-#1)) else {})"
   12.87 +lemma d22set_g_1 [rule_format]: "b \<in> d22set a --> #1 < b"
   12.88 +  apply (induct a rule: d22set_induct)
   12.89 +   prefer 2
   12.90 +   apply (subst d22set.simps)
   12.91 +   apply auto
   12.92 +  done
   12.93 +
   12.94 +lemma d22set_le [rule_format]: "b \<in> d22set a --> b \<le> a"
   12.95 +  apply (induct a rule: d22set_induct)
   12.96 +   prefer 2
   12.97 +   apply (subst d22set.simps)
   12.98 +   apply auto
   12.99 +  done
  12.100 +
  12.101 +lemma d22set_le_swap: "a < b ==> b \<notin> d22set a"
  12.102 +  apply (auto dest: d22set_le)
  12.103 +  done
  12.104 +
  12.105 +lemma d22set_mem [rule_format]: "#1 < b --> b \<le> a --> b \<in> d22set a"
  12.106 +  apply (induct a rule: d22set.induct)
  12.107 +  apply auto
  12.108 +   apply (simp_all add: d22set.simps)
  12.109 +  done
  12.110  
  12.111 -end
  12.112 \ No newline at end of file
  12.113 +lemma d22set_fin: "finite (d22set a)"
  12.114 +  apply (induct a rule: d22set_induct)
  12.115 +   prefer 2
  12.116 +   apply (subst d22set.simps)
  12.117 +   apply auto
  12.118 +  done
  12.119 +
  12.120 +
  12.121 +declare zfact.simps [simp del]
  12.122 +
  12.123 +lemma d22set_prod_zfact: "setprod (d22set a) = zfact a"
  12.124 +  apply (induct a rule: d22set.induct)
  12.125 +  apply safe
  12.126 +   apply (simp add: d22set.simps zfact.simps)
  12.127 +  apply (subst d22set.simps)
  12.128 +  apply (subst zfact.simps)
  12.129 +  apply (case_tac "#1 < a")
  12.130 +   prefer 2
  12.131 +   apply (simp add: d22set.simps zfact.simps)
  12.132 +  apply (simp add: d22set_fin d22set_le_swap)
  12.133 +  done
  12.134 +
  12.135 +end
    13.1 --- a/src/HOL/NumberTheory/IntPrimes.ML	Sat Feb 03 17:43:34 2001 +0100
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,789 +0,0 @@
    13.4 -(*  Title:	IntPrimes.ML
    13.5 -    ID:         $Id$
    13.6 -    Author:	Thomas M. Rasmussen & L C Paulson
    13.7 -    Copyright	2000  University of Cambridge
    13.8 -
    13.9 -dvd relation, GCD, Euclid's extended algorithm, primes, congruences
   13.10 -(all on the Integers)
   13.11 -
   13.12 -Comparable to Primes theory, but dvd is included here as it is not present in
   13.13 -IntDiv.  Also includes extended GCD and congruences -- not present in Primes. 
   13.14 -*)
   13.15 -
   13.16 -eta_contract:=false;
   13.17 -
   13.18 -
   13.19 -Goal "(abs (z::int) = w) = (z=w & #0 <= z | z=-w & z < #0)";
   13.20 -by (auto_tac (claset(), simpset() addsimps [zabs_def]));  
   13.21 -qed "zabs_eq_iff";
   13.22 -
   13.23 -
   13.24 -(** gcd lemmas **)
   13.25 -
   13.26 -val gcd_non_0 = thm "gcd_non_0";
   13.27 -val gcd_add1 = thm "gcd_add1";
   13.28 -val gcd_commute = thm "gcd_commute";
   13.29 -
   13.30 -Goal "gcd (m+k, k) = gcd (m+k, m)";
   13.31 -by (simp_tac (simpset() addsimps [gcd_commute]) 1); 
   13.32 -qed "gcd_add1_eq";
   13.33 -
   13.34 -Goal "m <= n ==> gcd (n, n - m) = gcd (n, m)";
   13.35 -by (subgoal_tac "n = m + (n-m)" 1);
   13.36 -by (etac ssubst 1 THEN rtac gcd_add1_eq 1);
   13.37 -by (Asm_simp_tac 1);
   13.38 -qed "gcd_diff2";
   13.39 -
   13.40 -
   13.41 -(************************************************)
   13.42 -(** Divides relation 'dvd'                     **)
   13.43 -(************************************************)
   13.44 -
   13.45 -Goalw [dvd_def] "(m::int) dvd #0";
   13.46 -by (blast_tac (claset() addIs [zmult_0_right RS sym]) 1);
   13.47 -qed "zdvd_0_right";
   13.48 -AddIffs [zdvd_0_right];
   13.49 -
   13.50 -Goalw [dvd_def] "(#0 dvd (m::int)) = (m = #0)";
   13.51 -by Auto_tac;
   13.52 -qed "zdvd_0_left";
   13.53 -AddIffs [zdvd_0_left];
   13.54 -
   13.55 -Goalw [dvd_def] "#1 dvd (m::int)";
   13.56 -by (Simp_tac 1);
   13.57 -qed "zdvd_1_left";
   13.58 -AddIffs [zdvd_1_left];
   13.59 -
   13.60 -Goalw [dvd_def] "m dvd (m::int)";
   13.61 -by (blast_tac (claset() addIs [zmult_1_right RS sym]) 1);
   13.62 -qed "zdvd_refl";
   13.63 -Addsimps [zdvd_refl];
   13.64 -
   13.65 -Goalw [dvd_def] "[| m dvd n; n dvd k |] ==> m dvd (k::int)";
   13.66 -by (blast_tac (claset() addIs [zmult_assoc] ) 1);
   13.67 -qed "zdvd_trans";
   13.68 -
   13.69 -Goalw [dvd_def] "(m dvd -n) = (m dvd (n::int))";
   13.70 -by Auto_tac;
   13.71 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
   13.72 -by Auto_tac;
   13.73 -qed "zdvd_zminus_iff";  
   13.74 -
   13.75 -Goalw [dvd_def] "(-m dvd n) = (m dvd (n::int))";
   13.76 -by Auto_tac;
   13.77 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
   13.78 -by Auto_tac;
   13.79 -qed "zdvd_zminus2_iff";  
   13.80 -
   13.81 -Goalw [dvd_def] "[| #0<m; #0<n; m dvd n; n dvd m |] ==> m = (n::int)";
   13.82 -by Auto_tac;
   13.83 -by (asm_full_simp_tac
   13.84 -    (simpset() addsimps [zmult_assoc,zmult_eq_self_iff,
   13.85 -                         int_0_less_mult_iff, zmult_eq_1_iff]) 1);
   13.86 -qed "zdvd_anti_sym";
   13.87 -
   13.88 -Goalw [dvd_def] "[| k dvd m; k dvd n |] ==> k dvd (m+n :: int)";
   13.89 -by (blast_tac (claset() addIs [zadd_zmult_distrib2 RS sym]) 1);
   13.90 -qed "zdvd_zadd";
   13.91 -
   13.92 -Goalw [dvd_def] "[| k dvd m; k dvd n |] ==> k dvd (m-n :: int)";
   13.93 -by (blast_tac (claset() addIs [zdiff_zmult_distrib2 RS sym]) 1);
   13.94 -qed "zdvd_zdiff";
   13.95 -
   13.96 -Goal "[| k dvd m-n; k dvd n |] ==> k dvd (m::int)";
   13.97 -by (subgoal_tac "m=n+(m-n)" 1);
   13.98 -by (etac ssubst 1);
   13.99 -by (blast_tac (claset() addIs [zdvd_zadd]) 1);
  13.100 -by (Simp_tac 1);
  13.101 -qed "zdvd_zdiffD";
  13.102 -
  13.103 -Goalw [dvd_def] "k dvd (n::int) ==> k dvd m*n";
  13.104 -by (blast_tac (claset() addIs [zmult_left_commute]) 1);
  13.105 -qed "zdvd_zmult";
  13.106 -
  13.107 -Goal "k dvd (m::int) ==> k dvd m*n";
  13.108 -by (stac zmult_commute 1);
  13.109 -by (etac zdvd_zmult 1);
  13.110 -qed "zdvd_zmult2";
  13.111 -
  13.112 -(* k dvd m*k *)
  13.113 -AddIffs [zdvd_refl RS zdvd_zmult, zdvd_refl RS zdvd_zmult2];
  13.114 -
  13.115 -Goalw [dvd_def] "j*k dvd n ==> j dvd (n::int)";
  13.116 -by (full_simp_tac (simpset() addsimps [zmult_assoc]) 1);
  13.117 -by (Blast_tac 1);
  13.118 -qed "zdvd_zmultD2";
  13.119 -
  13.120 -Goal "j*k dvd n ==> k dvd (n::int)";
  13.121 -by (rtac zdvd_zmultD2 1);
  13.122 -by (stac zmult_commute 1);
  13.123 -by (assume_tac 1);
  13.124 -qed "zdvd_zmultD";
  13.125 -
  13.126 -Goalw [dvd_def] "[| i dvd m; j dvd (n::int) |] ==> i*j dvd m*n";
  13.127 -by (Clarify_tac 1);
  13.128 -by (res_inst_tac [("x","k*ka")] exI 1);
  13.129 -by (asm_simp_tac (simpset() addsimps zmult_ac) 1);
  13.130 -qed "zdvd_zmult_mono";
  13.131 -
  13.132 -Goal "(k dvd n + k*m) = (k dvd (n::int))";
  13.133 -by (rtac iffI 1);
  13.134 -by (etac zdvd_zadd 2);
  13.135 -by (subgoal_tac "n = (n+k*m)-k*m" 1);
  13.136 -by (etac ssubst 1);
  13.137 -by (etac zdvd_zdiff 1);
  13.138 -by (ALLGOALS Simp_tac);
  13.139 -qed "zdvd_reduce";
  13.140 -
  13.141 -Goalw [dvd_def] "[| f dvd m; f dvd (n::int) |] ==> f dvd m mod n";
  13.142 -by (auto_tac (claset(), simpset() addsimps [zmod_zmult_zmult1]));
  13.143 -qed "zdvd_zmod";
  13.144 -
  13.145 -Goal "[| k dvd m mod n;  k dvd n |] ==> k dvd (m::int)";
  13.146 -by (subgoal_tac "k dvd n*(m div n) + m mod n" 1);
  13.147 -by (asm_simp_tac (simpset() addsimps [zdvd_zadd, zdvd_zmult2]) 2);
  13.148 -by (asm_full_simp_tac (simpset() addsimps [zmod_zdiv_equality RS sym]) 1);
  13.149 -qed "zdvd_zmod_imp_zdvd";
  13.150 -
  13.151 -Goalw [dvd_def] "(k dvd n) = (n mod (k::int) = #0)";
  13.152 -by (auto_tac (claset(), simpset() addsimps [zmod_zmult_self2]));  
  13.153 -qed "zdvd_iff_zmod_eq_0";
  13.154 -
  13.155 -Goal "[| ~k<#0; k~=#0 |] ==> #0<(k::int)";
  13.156 -by (arith_tac 1);
  13.157 -val lemma = result();
  13.158 -
  13.159 -Goalw [dvd_def] "[| #0<m; m<n |] ==> ~n dvd (m::int)";
  13.160 -by Auto_tac;
  13.161 -by (subgoal_tac "#0<n" 1);
  13.162 -by (blast_tac (claset() addIs [zless_trans]) 2);
  13.163 -by (asm_full_simp_tac (simpset() addsimps [int_0_less_mult_iff]) 1); 
  13.164 -by (subgoal_tac "n*k < n*#1" 1);
  13.165 -by (dtac (zmult_zless_cancel1 RS iffD1) 1); 
  13.166 -by Auto_tac;  
  13.167 -qed "zdvd_not_zless";
  13.168 -
  13.169 -Goal "(int m dvd z) = (m dvd nat(abs z))";
  13.170 -by (auto_tac (claset(), 
  13.171 -       simpset() addsimps [dvd_def, nat_abs_mult_distrib]));  
  13.172 -by (auto_tac (claset(), simpset() addsimps [nat_eq_iff, zabs_eq_iff]));  
  13.173 -by (res_inst_tac [("x","-(int k)")] exI 2);
  13.174 -by (auto_tac (claset(), simpset() addsimps [zmult_int RS sym]));  
  13.175 -qed "int_dvd_iff";
  13.176 -
  13.177 -Goal "(z dvd int m) = (nat(abs z) dvd m)";
  13.178 -by (auto_tac (claset(), 
  13.179 -       simpset() addsimps [dvd_def, zabs_def, zmult_int RS sym]));  
  13.180 -by (res_inst_tac [("x","nat k")] exI 3); 
  13.181 -by (res_inst_tac [("x","-(int k)")] exI 2);
  13.182 -by (res_inst_tac [("x","nat (-k)")] exI 1);
  13.183 -by (cut_inst_tac [("k","m")] int_less_0_conv 3);
  13.184 -by (cut_inst_tac [("k","m")] int_less_0_conv 1);
  13.185 -by (auto_tac (claset(), 
  13.186 -         simpset() addsimps [int_0_le_mult_iff, zmult_less_0_iff,
  13.187 -                             nat_mult_distrib RS sym, nat_eq_iff2]));  
  13.188 -qed "dvd_int_iff";
  13.189 -
  13.190 -Goal "(nat z dvd m) = (if #0 <= z then (z dvd int m) else m=0)";
  13.191 -by (auto_tac (claset(), simpset() addsimps [dvd_def, zmult_int RS sym]));  
  13.192 -by (res_inst_tac [("x","nat k")] exI 1);
  13.193 -by (cut_inst_tac [("k","m")] int_less_0_conv 1);
  13.194 -by (auto_tac (claset(), 
  13.195 -         simpset() addsimps [int_0_le_mult_iff, zmult_less_0_iff,
  13.196 -                             nat_mult_distrib RS sym, nat_eq_iff2]));  
  13.197 -qed "nat_dvd_iff";
  13.198 -
  13.199 -Goal "(-z dvd w) = (z dvd (w::int))";
  13.200 -by (auto_tac (claset(), simpset() addsimps [dvd_def]));  
  13.201 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
  13.202 -by Auto_tac;  
  13.203 -qed "zminus_dvd_iff";
  13.204 -
  13.205 -Goal "(z dvd -w) = (z dvd (w::int))";
  13.206 -by (auto_tac (claset(), simpset() addsimps [dvd_def]));  
  13.207 -by (dtac (zminus_equation RS iffD1) 1);
  13.208 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
  13.209 -by Auto_tac;  
  13.210 -qed "dvd_zminus_iff";
  13.211 -AddIffs [zminus_dvd_iff, dvd_zminus_iff];
  13.212 -
  13.213 -
  13.214 -(************************************************)
  13.215 -(** Euclid's Algorithm and GCD                 **)
  13.216 -(************************************************)
  13.217 -
  13.218 -Goal "zgcd(m,#0) = abs m";
  13.219 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def]) 1); 
  13.220 -qed "zgcd_0";
  13.221 -Addsimps [zgcd_0];
  13.222 -
  13.223 -Goal"zgcd(#0,m) = abs m";
  13.224 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def]) 1); 
  13.225 -qed "zgcd_0_left";
  13.226 -Addsimps [zgcd_0_left];
  13.227 -
  13.228 -Goal "zgcd(-m,n) = zgcd(m,n)";
  13.229 -by (simp_tac (simpset() addsimps [zgcd_def]) 1); 
  13.230 -qed "zgcd_zminus";
  13.231 -Addsimps [zgcd_zminus];
  13.232 -
  13.233 -Goal "zgcd(m,-n) = zgcd(m,n)";
  13.234 -by (simp_tac (simpset() addsimps [zgcd_def]) 1); 
  13.235 -qed "zgcd_zminus2";
  13.236 -Addsimps [zgcd_zminus2];
  13.237 -
  13.238 -Goal "#0<n ==> zgcd(m,n) = zgcd (n, m mod n)";
  13.239 -by (forw_inst_tac [("b","n"), ("a","m")] pos_mod_sign 1);
  13.240 -by (asm_simp_tac (simpset() addsimps [zgcd_def, zabs_def, nat_mod_distrib]) 1);
  13.241 -by (cut_inst_tac [("a","-m"),("b","n")] zmod_zminus1_eq_if 1);
  13.242 -by (auto_tac (claset(), 
  13.243 -              simpset() addsimps [gcd_non_0, nat_mod_distrib RS sym,
  13.244 -                                  zmod_zminus1_eq_if]));
  13.245 -by (forw_inst_tac [("a","m")] pos_mod_bound 1);
  13.246 -by (asm_simp_tac (simpset() addsimps [nat_diff_distrib]) 1);  
  13.247 -by (rtac gcd_diff2 1);
  13.248 -by (asm_full_simp_tac (simpset() addsimps [nat_le_eq_zle]) 1); 
  13.249 -qed "zgcd_non_0";
  13.250 -
  13.251 -Goal "zgcd(m,n) = zgcd (n, m mod n)";
  13.252 -by (zdiv_undefined_case_tac "n = #0" 1);
  13.253 -by (auto_tac
  13.254 -    (claset(),
  13.255 -     simpset() addsimps [linorder_neq_iff, zgcd_non_0]));
  13.256 -by (cut_inst_tac [("m","-m"),("n","-n")] zgcd_non_0 1);
  13.257 -by Auto_tac;  
  13.258 -qed "zgcd_eq";
  13.259 -
  13.260 -Goal "zgcd(m,#1) = #1";
  13.261 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def]) 1); 
  13.262 -qed "zgcd_1";
  13.263 -Addsimps [zgcd_1];
  13.264 -
  13.265 -Goal "(zgcd(#0,m) = #1) = (abs m = #1)";
  13.266 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def]) 1); 
  13.267 -qed "zgcd_0_1_iff";
  13.268 -Addsimps [zgcd_0_1_iff];
  13.269 -
  13.270 -Goal "zgcd(m,n) dvd m";
  13.271 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def, int_dvd_iff]) 1); 
  13.272 -qed "zgcd_zdvd1";
  13.273 -
  13.274 -Goal "zgcd(m,n) dvd n";
  13.275 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def, int_dvd_iff]) 1); 
  13.276 -qed "zgcd_zdvd2";
  13.277 -AddIffs [zgcd_zdvd1, zgcd_zdvd2];
  13.278 -
  13.279 -Goal "k dvd zgcd(m,n) = (k dvd m & k dvd n)";
  13.280 -by (simp_tac (simpset() addsimps [zgcd_def, zabs_def, int_dvd_iff, 
  13.281 -                                  dvd_int_iff, nat_dvd_iff]) 1); 
  13.282 -qed "zgcd_greatest_iff";
  13.283 -
  13.284 -Goal "zgcd(m,n) = zgcd(n,m)";
  13.285 -by (simp_tac (simpset() addsimps [zgcd_def, thm"gcd_commute"]) 1); 
  13.286 -qed "zgcd_commute";
  13.287 -
  13.288 -Goal "zgcd(#1,m) = #1";
  13.289 -by (simp_tac (simpset() addsimps [zgcd_def, thm"gcd_1_left"]) 1); 
  13.290 -qed "zgcd_1_left";
  13.291 -Addsimps [zgcd_1_left];
  13.292 -
  13.293 -Goal "zgcd(zgcd(k,m),n) = zgcd(k,zgcd(m,n))";
  13.294 -by (simp_tac (simpset() addsimps [zgcd_def, thm"gcd_assoc"]) 1); 
  13.295 -qed "zgcd_assoc";
  13.296 -
  13.297 -Goal "zgcd(k,zgcd(m,n)) = zgcd(m,zgcd(k,n))";
  13.298 -by (rtac (zgcd_commute RS trans) 1);
  13.299 -by (rtac (zgcd_assoc RS trans) 1);
  13.300 -by (rtac (zgcd_commute RS arg_cong) 1);
  13.301 -qed "zgcd_left_commute";
  13.302 -
  13.303 -(*Addition is an AC-operator*)
  13.304 -bind_thms ("zgcd_ac", [zgcd_assoc, zgcd_commute, zgcd_left_commute]);
  13.305 -
  13.306 -val gcd_mult_distrib2 = thm"gcd_mult_distrib2";
  13.307 -
  13.308 -Goal "#0<=k ==> k * zgcd(m,n) = zgcd(k*m, k*n)";
  13.309 -by (asm_simp_tac 
  13.310 -    (simpset() delsimps [zmult_zminus_right] 
  13.311 -	       addsimps [zmult_zminus_right RS sym, 
  13.312 -                         nat_mult_distrib, zgcd_def, zabs_def, 
  13.313 -                         zmult_less_0_iff, gcd_mult_distrib2 RS sym, 
  13.314 -                         zmult_int RS sym]) 1); 
  13.315 -qed "zgcd_zmult_distrib2";
  13.316 -
  13.317 -Goal "zgcd(k*m, k*n) = abs k * zgcd(m,n)";
  13.318 -by (simp_tac (simpset() addsimps [zabs_def, zgcd_zmult_distrib2]) 1);
  13.319 -qed "zgcd_zmult_distrib2_abs";
  13.320 -
  13.321 -
  13.322 -Goal "#0<=m ==> zgcd(m,m) = m";
  13.323 -by (cut_inst_tac [("k","m"),("m","#1"),("n","#1")] zgcd_zmult_distrib2 1);
  13.324 -by (ALLGOALS Asm_full_simp_tac);
  13.325 -qed "zgcd_self";
  13.326 -Addsimps [zgcd_self];
  13.327 -
  13.328 -Goal "#0<=k ==> zgcd(k, k*n) = k";
  13.329 -by (cut_inst_tac [("k","k"),("m","#1"),("n","n")] zgcd_zmult_distrib2 1);
  13.330 -by (ALLGOALS Asm_full_simp_tac);
  13.331 -qed "zgcd_zmult_eq_self";
  13.332 -Addsimps [zgcd_zmult_eq_self];
  13.333 -
  13.334 -Goal "#0<=k ==> zgcd(k*n, k) = k";
  13.335 -by (cut_inst_tac [("k","k"),("m","n"),("n","#1")] zgcd_zmult_distrib2 1);
  13.336 -by (ALLGOALS Asm_full_simp_tac);
  13.337 -qed "zgcd_zmult_eq_self2";
  13.338 -Addsimps [zgcd_zmult_eq_self2];
  13.339 -
  13.340 -Goal "[| zgcd(n,k)=#1; k dvd m*n; #0 <= m |] ==> k dvd m";
  13.341 -by (subgoal_tac "m = zgcd(m*n, m*k)" 1);
  13.342 -by (etac ssubst 1 THEN rtac (zgcd_greatest_iff RS iffD2) 1);
  13.343 -by (ALLGOALS (asm_simp_tac (simpset() 
  13.344 -      addsimps [zgcd_zmult_distrib2 RS sym,int_0_le_mult_iff])));
  13.345 -val lemma = result();
  13.346 -
  13.347 -Goal "[| zgcd(n,k)=#1; k dvd m*n |] ==> k dvd m";
  13.348 -by (case_tac "#0 <= m" 1);
  13.349 -by (blast_tac (claset() addIs [lemma]) 1); 
  13.350 -by (subgoal_tac "k dvd -m" 1);
  13.351 -by (rtac lemma 2);
  13.352 -by Auto_tac;  
  13.353 -qed "zrelprime_zdvd_zmult";
  13.354 -
  13.355 -Goalw [zprime_def] "[| p:zprime; ~p dvd n |] ==> zgcd(n,p) = #1";
  13.356 -by Auto_tac;  
  13.357 -qed "zprime_imp_zrelprime";
  13.358 -
  13.359 -Goal "[| p:zprime; #0<n; n<p |] ==> zgcd(n,p) = #1";
  13.360 -by (etac zprime_imp_zrelprime 1);
  13.361 -by (etac zdvd_not_zless 1);
  13.362 -by (assume_tac 1);
  13.363 -qed "zless_zprime_imp_zrelprime";
  13.364 -
  13.365 -Goal "[| #0<=(m::int); p:zprime; p dvd m*n |] ==> p dvd m | p dvd n";
  13.366 -by Safe_tac;
  13.367 -by (rtac zrelprime_zdvd_zmult 1);
  13.368 -by (rtac zprime_imp_zrelprime 1);
  13.369 -by Auto_tac;
  13.370 -qed "zprime_zdvd_zmult";
  13.371 -
  13.372 -val gcd_add_mult = thm "gcd_add_mult";
  13.373 -
  13.374 -Goal "zgcd(m + n*k, n) = zgcd(m,n)";
  13.375 -by (rtac (zgcd_eq RS trans) 1);
  13.376 -by (simp_tac (simpset() addsimps [zmod_zadd1_eq]) 1);
  13.377 -by (rtac (zgcd_eq RS sym) 1);
  13.378 -qed "zgcd_zadd_zmult";
  13.379 -Addsimps [zgcd_zadd_zmult];
  13.380 -
  13.381 -
  13.382 -Goal "zgcd(m,n) dvd zgcd(k*m,n)";
  13.383 -by (simp_tac (simpset() addsimps [zgcd_greatest_iff]) 1); 
  13.384 -by (blast_tac (claset() addIs [zdvd_trans]) 1); 
  13.385 -qed "zgcd_zdvd_zgcd_zmult";
  13.386 -
  13.387 -Goal "zgcd(k,n) = #1 ==> zgcd(k*m,n) dvd zgcd(m,n)";
  13.388 -by (simp_tac (simpset() addsimps [zgcd_greatest_iff]) 1); 
  13.389 -by (res_inst_tac [("n","k")] zrelprime_zdvd_zmult 1);
  13.390 -by (simp_tac (simpset() addsimps [zmult_commute]) 2); 
  13.391 -by (subgoal_tac "zgcd (k, zgcd (k * m, n)) =  zgcd (k * m, zgcd (k, n))" 1);
  13.392 -by (Asm_full_simp_tac 1); 
  13.393 -by (simp_tac (simpset() addsimps zgcd_ac) 1); 
  13.394 -qed "zgcd_zmult_zdvd_zgcd";
  13.395 -
  13.396 -val gcd_mult_cancel = thm "gcd_mult_cancel";
  13.397 -
  13.398 -Goal "zgcd(k,n) = #1 ==> zgcd(k*m, n) = zgcd(m,n)";
  13.399 -by (asm_full_simp_tac (simpset() addsimps [zgcd_def, 
  13.400 -                           nat_abs_mult_distrib, gcd_mult_cancel]) 1); 
  13.401 -qed "zgcd_zmult_cancel";
  13.402 -
  13.403 -Goal "[| zgcd(k,m) = #1; zgcd(n,m) = #1 |] ==> zgcd(k*n,m) = #1";
  13.404 -by (asm_simp_tac (simpset() addsimps [zgcd_zmult_cancel]) 1);
  13.405 -qed "zgcd_zgcd_zmult";
  13.406 -
  13.407 -Goal "#0<m ==> (m dvd n) = (zgcd(n,m) = m)";
  13.408 -by Safe_tac;
  13.409 -by (res_inst_tac [("n","zgcd(n,m)")] zdvd_trans 2);
  13.410 -by (rtac zgcd_zdvd1 3);
  13.411 -by (ALLGOALS Asm_simp_tac);
  13.412 -by (rewtac dvd_def);
  13.413 -by Auto_tac;
  13.414 -qed "zdvd_iff_zgcd";
  13.415 -
  13.416 -
  13.417 -(************************************************)
  13.418 -(** Congruences                                **)
  13.419 -(************************************************)
  13.420 -
  13.421 -Goalw [zcong_def] "[a=b](mod #1)";
  13.422 -by Auto_tac;
  13.423 -qed "zcong_1";
  13.424 -Addsimps [zcong_1];
  13.425 -
  13.426 -Goalw [zcong_def] "[k = k] (mod m)";
  13.427 -by Auto_tac;
  13.428 -qed "zcong_refl";
  13.429 -Addsimps [zcong_refl];
  13.430 -
  13.431 -Goalw [zcong_def,dvd_def] "[a = b](mod m) = [b = a](mod m)";
  13.432 -by Auto_tac;
  13.433 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
  13.434 -by Auto_tac;
  13.435 -qed "zcong_sym";
  13.436 -
  13.437 -Goalw [zcong_def]
  13.438 -     "[| [a = b] (mod m); [c = d] (mod m) |] ==> [a+c = b+d](mod m)";
  13.439 -by (res_inst_tac [("s","(a-b)+(c-d)")] subst 1);
  13.440 -by (rtac zdvd_zadd 2);
  13.441 -by Auto_tac;
  13.442 -qed "zcong_zadd";
  13.443 -
  13.444 -Goalw [zcong_def]
  13.445 -     "[| [a = b] (mod m); [c = d] (mod m) |] ==> [a-c = b-d](mod m)";
  13.446 -by (res_inst_tac [("s","(a-b)-(c-d)")] subst 1);
  13.447 -by (rtac zdvd_zdiff 2);
  13.448 -by Auto_tac;
  13.449 -qed "zcong_zdiff";
  13.450 -
  13.451 -Goalw [zcong_def,dvd_def]
  13.452 -     "[| [a = b](mod m); [b = c](mod m) |] ==> [a = c](mod m)";
  13.453 -by Auto_tac;
  13.454 -by (res_inst_tac [("x","k+ka")] exI 1);
  13.455 -by (asm_full_simp_tac (simpset() addsimps zadd_ac@[zadd_zmult_distrib2]) 1);
  13.456 -qed "zcong_trans";
  13.457 - 
  13.458 -Goal "[| [a = b] (mod m); [c = d] (mod m) |] ==> [a*c = b*d](mod m)";
  13.459 -by (res_inst_tac [("b","b*c")] zcong_trans 1);
  13.460 -by (rewtac zcong_def);
  13.461 -by (res_inst_tac [("s","c*(a-b)")] subst 1);
  13.462 -by (res_inst_tac [("s","b*(c-d)")] subst 3);
  13.463 -by (blast_tac (claset() addIs [zdvd_zmult]) 4);
  13.464 -by (blast_tac (claset() addIs [zdvd_zmult]) 2);
  13.465 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [zdiff_zmult_distrib2,
  13.466 -                                                zmult_commute])));
  13.467 -qed "zcong_zmult";
  13.468 -
  13.469 -Goal "[a = b] (mod m) ==> [a*k = b*k](mod m)";
  13.470 -by (rtac zcong_zmult 1);
  13.471 -by (ALLGOALS Asm_simp_tac);
  13.472 -qed "zcong_scalar";
  13.473 -
  13.474 -Goal "[a = b] (mod m) ==> [k*a = k*b](mod m)";
  13.475 -by (rtac zcong_zmult 1);
  13.476 -by (ALLGOALS Asm_simp_tac);
  13.477 -qed "zcong_scalar2";
  13.478 -
  13.479 -Goalw [zcong_def] "[a*m = b*m](mod m)";
  13.480 -by (rtac zdvd_zdiff 1);
  13.481 -by (ALLGOALS Simp_tac);
  13.482 -qed "zcong_zmult_self";
  13.483 -
  13.484 -Goalw [zcong_def]
  13.485 -      "[| p:zprime; #0<a; [a*a = #1](mod p) |] \
  13.486 -\     ==> [a=#1](mod p) | [a = p-#1](mod p)";
  13.487 -by (rtac zprime_zdvd_zmult 1);
  13.488 -by (res_inst_tac [("s","a*a - #1 + p*(#1-a)")] subst 3);
  13.489 -by (simp_tac (simpset() addsimps [zdvd_reduce]) 4);
  13.490 -by (ALLGOALS (asm_simp_tac (simpset() 
  13.491 -      addsimps [zdiff_zmult_distrib,zmult_commute,zdiff_zmult_distrib2])));
  13.492 -qed "zcong_square";
  13.493 -
  13.494 -Goal "[| #0<=m; zgcd(k,m) = #1 |] ==> [a*k = b*k](mod m) = [a = b](mod m)";
  13.495 -by Safe_tac;
  13.496 -by (blast_tac (claset() addIs [zcong_scalar]) 2);
  13.497 -by (case_tac "b<a" 1);
  13.498 -by (stac zcong_sym 2);
  13.499 -by (rewrite_goals_tac [zcong_def]);
  13.500 -by (ALLGOALS (rtac zrelprime_zdvd_zmult));
  13.501 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [zdiff_zmult_distrib])));
  13.502 -by (subgoal_tac "m dvd (-(a*k - b*k))" 1);
  13.503 -by (asm_full_simp_tac (simpset() addsimps [zminus_zdiff_eq]) 1);
  13.504 -by (stac zdvd_zminus_iff 1);
  13.505 -by (assume_tac 1);
  13.506 -qed "zcong_cancel";
  13.507 -
  13.508 -Goal "[| #0<=m; zgcd(k,m) = #1 |] ==> [k*a = k*b](mod m) = [a = b](mod m)";
  13.509 -by (asm_simp_tac (simpset() addsimps [zmult_commute,zcong_cancel]) 1);
  13.510 -qed "zcong_cancel2";
  13.511 -
  13.512 -Goalw [zcong_def,dvd_def]
  13.513 -      "[| [a = b] (mod m);  [a = b] (mod n);  zgcd(m,n) = #1 |] \
  13.514 -\     ==> [a=b](mod m*n)";
  13.515 -by Auto_tac;
  13.516 -by (subgoal_tac "m dvd n*ka" 1);
  13.517 -by (subgoal_tac "m dvd ka" 1);
  13.518 -by (case_tac "#0<=ka" 2);
  13.519 -by (stac (zdvd_zminus_iff RS sym) 3);
  13.520 -by (res_inst_tac [("n","n")] zrelprime_zdvd_zmult 3);
  13.521 -by (asm_simp_tac (simpset() addsimps [zgcd_commute]) 3);
  13.522 -by (asm_full_simp_tac (simpset() addsimps [zmult_commute,zdvd_zminus_iff]) 3);
  13.523 -by (res_inst_tac [("n","n")] zrelprime_zdvd_zmult 2);
  13.524 -by (asm_simp_tac (simpset() addsimps [zgcd_commute]) 2);
  13.525 -by (asm_full_simp_tac (simpset() addsimps [zmult_commute]) 2);
  13.526 -by (auto_tac (claset(), simpset() addsimps [dvd_def]));  
  13.527 -by (blast_tac (claset() addIs [sym]) 1); 
  13.528 -qed "zcong_zgcd_zmult_zmod";
  13.529 -
  13.530 -Goalw [zcong_def,dvd_def] 
  13.531 -      "[| #0<=a; a<m; #0<=b; b<m; [a = b] (mod m) |] ==> a = b";
  13.532 -by Auto_tac;  
  13.533 -by (dres_inst_tac [("f", "%z. z mod m")] arg_cong 1);  
  13.534 -by (cut_inst_tac [("z","a"),("w","b")] zless_linear 1);
  13.535 -by Auto_tac;  
  13.536 -by (subgoal_tac "(a - b) mod m = a-b" 2);
  13.537 -by (rtac mod_pos_pos_trivial 3); 
  13.538 -by Auto_tac;
  13.539 -by (subgoal_tac "(m + (a - b)) mod m = m + (a - b)" 1);
  13.540 -by (rtac mod_pos_pos_trivial 2); 
  13.541 -by Auto_tac;  
  13.542 -qed "zcong_zless_imp_eq";
  13.543 -
  13.544 -Goal "[| p:zprime; #0<a; a<p; [a*a = #1](mod p) |] ==> a = #1 | a = p-#1";
  13.545 -by (cut_inst_tac [("p","p"),("a","a")] zcong_square 1);
  13.546 -by (full_simp_tac (simpset() addsimps [zprime_def]) 1); 
  13.547 -by (auto_tac (claset() addIs [zcong_zless_imp_eq], simpset())); 
  13.548 -qed "zcong_square_zless";
  13.549 -
  13.550 -Goalw [zcong_def] "[| #0<a; a<m; #0<b; b<a |] ==> ~[a = b] (mod m) ";
  13.551 -by (rtac zdvd_not_zless 1);
  13.552 -by Auto_tac;
  13.553 -qed "zcong_not";
  13.554 -
  13.555 -Goalw [zcong_def,dvd_def] "[| #0<=a; a<m; [a=#0](mod m) |] ==> a = #0";
  13.556 -by Auto_tac;
  13.557 -by (subgoal_tac "#0<m" 1);
  13.558 -by (rotate_tac ~1 1);
  13.559 -by (asm_full_simp_tac (simpset() addsimps [int_0_le_mult_iff]) 1);
  13.560 -by (subgoal_tac "m*k<m*#1" 1);
  13.561 -by (dtac (zmult_zless_cancel1 RS iffD1) 1);
  13.562 -by (auto_tac (claset(), simpset() addsimps [linorder_neq_iff]));
  13.563 -qed "zcong_zless_0";
  13.564 -
  13.565 -Goal "#0<m ==> (EX! b. #0<=b & b<m & [a = b] (mod m))";
  13.566 -by Auto_tac;
  13.567 -by (subgoal_tac "[b = y] (mod m)" 2);
  13.568 -by (case_tac "b=#0" 2);
  13.569 -by (case_tac "y=#0" 3);
  13.570 -by (auto_tac (claset() addIs [zcong_trans,zcong_zless_0,
  13.571 -                              zcong_zless_imp_eq,order_less_le],
  13.572 -              simpset() addsimps [zcong_sym]));
  13.573 -by (rewrite_goals_tac [zcong_def,dvd_def]);
  13.574 -by (res_inst_tac [("x","a mod m")] exI 1);
  13.575 -by (auto_tac (claset(),simpset() addsimps [pos_mod_sign,pos_mod_bound]));
  13.576 -by (res_inst_tac [("x","-(a div m)")] exI 1);
  13.577 -by (cut_inst_tac [("a","a"),("b","m")] zmod_zdiv_equality 1);
  13.578 -by Auto_tac;
  13.579 -qed "zcong_zless_unique";
  13.580 -
  13.581 -Goalw [zcong_def,dvd_def] "([a = b] (mod m)) = (EX k. b = a + m*k)"; 
  13.582 -by Auto_tac;
  13.583 -by (ALLGOALS (res_inst_tac [("x","-k")] exI));
  13.584 -by Auto_tac;
  13.585 -qed "zcong_iff_lin";
  13.586 -
  13.587 -Goal "[| #0<m; zgcd(a,m) = #1; [a = b] (mod m) |] ==> zgcd(b,m) = #1";
  13.588 -by (auto_tac (claset(),simpset() addsimps [zcong_iff_lin]));
  13.589 -qed "zgcd_zcong_zgcd";
  13.590 -
  13.591 -Goal "[| a=c; b=d |] ==> a-b = c-(d::int)";
  13.592 -by Auto_tac;
  13.593 -val lemma = result();
  13.594 -
  13.595 -Goal "a - b = (m::int) * (a div m - b div m) + (a mod m - b mod m)";
  13.596 -by (res_inst_tac [("s","(m * (a div m) + a mod m) - \
  13.597 -\                 (m * (b div m) + b mod m)")] trans 1);
  13.598 -by (simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 2);
  13.599 -by (rtac lemma 1);
  13.600 -by (ALLGOALS (rtac zmod_zdiv_equality));
  13.601 -val lemma = result();
  13.602 -
  13.603 -Goalw [zcong_def] "[a = b] (mod m) = [a mod m = b mod m](mod m)";
  13.604 -by (res_inst_tac [("t","a-b")] ssubst 1);
  13.605 -by (res_inst_tac [("m","m")] lemma 1);
  13.606 -by (rtac trans 1);
  13.607 -by (res_inst_tac [("k","m"),("m","a div m - b div m")] zdvd_reduce 2);
  13.608 -by (simp_tac (simpset() addsimps [zadd_commute]) 1);
  13.609 -qed "zcong_zmod";
  13.610 -
  13.611 -Goal "#0<m ==> [a = b] (mod m) = (a mod m = b mod m)";
  13.612 -by Auto_tac;
  13.613 -by (res_inst_tac [("m","m")] zcong_zless_imp_eq 1);
  13.614 -by (stac (zcong_zmod RS sym) 5);
  13.615 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_bound,pos_mod_sign])));
  13.616 -by (rewrite_goals_tac [zcong_def,dvd_def]);
  13.617 -by (res_inst_tac [("x","a div m - b div m")] exI 1);
  13.618 -by (res_inst_tac [("m1","m")] (lemma RS trans) 1);
  13.619 -by Auto_tac;
  13.620 -qed "zcong_zmod_eq";
  13.621 -
  13.622 -Goal "[a = b] (mod -m) = [a = b] (mod m)";
  13.623 -by (auto_tac (claset(), simpset() addsimps [zcong_def]));  
  13.624 -qed "zcong_zminus";
  13.625 -AddIffs [zcong_zminus];
  13.626 -
  13.627 -Goal "[a = b] (mod #0) = (a = b)";
  13.628 -by (auto_tac (claset(), simpset() addsimps [zcong_def]));  
  13.629 -qed "zcong_zero";
  13.630 -AddIffs [zcong_zero];
  13.631 -
  13.632 -Goal "[a = b] (mod m) = (a mod m = b mod m)";
  13.633 -by (zdiv_undefined_case_tac "m = #0" 1);
  13.634 -by (case_tac "#0<m" 1);
  13.635 -by (asm_simp_tac (simpset() addsimps [zcong_zmod_eq]) 1); 
  13.636 -by (res_inst_tac [("t","m")] (zminus_zminus RS subst) 1); 
  13.637 -by (stac zcong_zminus 1);
  13.638 -by (stac zcong_zmod_eq 1);
  13.639 -by (arith_tac 1); 
  13.640 -(*FIXME: finish this proof?*)
  13.641 -
  13.642 -(************************************************)
  13.643 -(** Modulo                                     **)
  13.644 -(************************************************)
  13.645 -
  13.646 -Goalw [dvd_def] "[| #0<(m::int); m dvd b |] ==> (a mod b mod m) = (a mod m)";
  13.647 -by Auto_tac;
  13.648 -by (stac (zcong_zmod_eq RS sym) 1);
  13.649 -by (stac zcong_iff_lin 2);
  13.650 -by (res_inst_tac [("x","k*(a div (m*k))")] exI 2);
  13.651 -by (stac zadd_commute 2);
  13.652 -by (stac (zmult_assoc RS sym) 2);
  13.653 -by (rtac zmod_zdiv_equality 2);
  13.654 -by (assume_tac 1);
  13.655 -qed "zmod_zdvd_zmod";
  13.656 -
  13.657 -
  13.658 -(************************************************)
  13.659 -(** Extended GCD                               **)
  13.660 -(************************************************)
  13.661 -
  13.662 -val [xzgcda_eq] = xzgcda.simps;
  13.663 -Delsimps xzgcda.simps;
  13.664 -
  13.665 -Goal "zgcd(r',r) = k --> #0 < r --> \
  13.666 -\     (EX sn tn. xzgcda (m,n,r',r,s',s,t',t) = (k,sn,tn))";
  13.667 -by (res_inst_tac [("u","m"),("v","n"),("w","r'"),("x","r"),
  13.668 -                  ("y","s'"),("z","s"),("aa","t'"),("ab","t")] 
  13.669 -                  xzgcda.induct 1);
  13.670 -by (stac zgcd_eq 1);
  13.671 -by (stac xzgcda_eq 1);
  13.672 -by Auto_tac;
  13.673 -by (case_tac "r' mod r = #0" 1);
  13.674 -by (forw_inst_tac [("a","r'")] pos_mod_sign 2);
  13.675 -by Auto_tac;  
  13.676 -by (arith_tac 2);
  13.677 -by (rtac exI 1);
  13.678 -by (rtac exI 1);
  13.679 -by (stac xzgcda_eq 1);
  13.680 -by Auto_tac;  
  13.681 -by (asm_full_simp_tac (simpset() addsimps [zabs_def]) 1); 
  13.682 -val lemma1 = result();
  13.683 -
  13.684 -Goal "(EX sn tn. xzgcda (m,n,r',r,s',s,t',t) = (k,sn,tn)) --> #0 < r --> \
  13.685 -\     zgcd(r',r) = k";
  13.686 -by (res_inst_tac [("u","m"),("v","n"),("w","r'"),("x","r"),
  13.687 -                  ("y","s'"),("z","s"),("aa","t'"),("ab","t")] 
  13.688 -                  xzgcda.induct 1);
  13.689 -by (stac zgcd_eq 1);
  13.690 -by (stac xzgcda_eq 1);
  13.691 -by (auto_tac (claset(), simpset() addsimps [linorder_not_le]));  
  13.692 -by (case_tac "r' mod r = #0" 1);
  13.693 -by (forw_inst_tac [("a","r'")] pos_mod_sign 2);
  13.694 -by Auto_tac;  
  13.695 -by (arith_tac 2);
  13.696 -by (eres_inst_tac [("P","xzgcda ?u = ?v")] rev_mp 1); 
  13.697 -by (stac xzgcda_eq 1);
  13.698 -by Auto_tac;  
  13.699 -by (asm_full_simp_tac (simpset() addsimps [zabs_def]) 1); 
  13.700 -val lemma2 = result();
  13.701 -
  13.702 -Goalw [xzgcd_def] "#0 < n ==> (zgcd(m,n) = k) = (EX s t. xzgcd m n = (k,s,t))"; 
  13.703 -by (rtac iffI 1);
  13.704 -by (rtac (lemma2 RS mp RS mp) 2);
  13.705 -by (rtac (lemma1 RS mp RS mp) 1);
  13.706 -by Auto_tac;
  13.707 -qed "xzgcd_correct";
  13.708 -
  13.709 -(* xzgcd linear *)
  13.710 -
  13.711 -Goal "(a-r*b)*m + (c-r*d)*(n::int) = (a*m + c*n) - r*(b*m + d*n)";
  13.712 -by (simp_tac (simpset() addsimps [zdiff_zmult_distrib,zadd_zmult_distrib2,
  13.713 -                                  zmult_assoc]) 1);
  13.714 -val lemma = result();
  13.715 -
  13.716 -Goal "[| r' = s'*m + t'*n; r = s*m + t*n |] \
  13.717 -\    ==> (r' mod r) = (s' - (r' div r)*s)*m + (t' - (r' div r)*t)*(n::int)"; 
  13.718 -by (rtac trans 1);
  13.719 -by (rtac (lemma RS sym) 2);
  13.720 -by (Asm_simp_tac 1);
  13.721 -by (stac eq_zdiff_eq 1);
  13.722 -by (rtac (trans RS sym) 1);
  13.723 -by (res_inst_tac [("b","s*m + t*n")] zmod_zdiv_equality 1);
  13.724 -by (simp_tac (simpset() addsimps [zmult_commute]) 1);
  13.725 -val lemma = result();
  13.726 -
  13.727 -bind_thm ("order_le_neq_implies_less", [order_less_le, conjI] MRS iffD2);
  13.728 -
  13.729 -Goal "#0<r --> xzgcda(m,n,r',r,s',s,t',t) = (rn,sn,tn) \
  13.730 -\          --> r' = s'*m + t'*n -->  r = s*m + t*n --> rn = sn*m + tn*n";
  13.731 -by (res_inst_tac [("u","m"),("v","n"),("w","r'"),("x","r"),
  13.732 -                  ("y","s'"),("z","s"),("aa","t'"),("ab","t")] 
  13.733 -                  xzgcda.induct 1);
  13.734 -by (stac xzgcda_eq 1);
  13.735 -by (Simp_tac 1);
  13.736 -by (REPEAT (rtac impI 1));
  13.737 -by (case_tac "r' mod r = #0" 1);
  13.738 -by (asm_full_simp_tac (simpset() addsimps [xzgcda_eq]) 1);
  13.739 -by (SELECT_GOAL Safe_tac 1);
  13.740 -by (subgoal_tac "#0 < r' mod r" 1);
  13.741 -by (rtac order_le_neq_implies_less 2);
  13.742 -by (rtac pos_mod_sign 2);
  13.743 -by (cut_inst_tac [("m","m"),("n","n"),("r'","r'"),("r","r"),
  13.744 -                  ("s'","s'"),("s","s"),("t'","t'"),("t","t")] 
  13.745 -                 lemma 1);
  13.746 -by Auto_tac;
  13.747 -qed_spec_mp "xzgcda_linear";
  13.748 -
  13.749 -Goalw [xzgcd_def] "[| #0<n; xzgcd m n = (r,s,t) |] ==> r = s*m + t*n";
  13.750 -by (etac xzgcda_linear 1);
  13.751 -by (assume_tac 1);
  13.752 -by Auto_tac;
  13.753 -qed "xzgcd_linear";
  13.754 -
  13.755 -Goal "[| #0<n; zgcd(m,n) = k |] ==> (EX s t. k = s*m + t*n)";
  13.756 -by (asm_full_simp_tac (simpset() addsimps [xzgcd_correct]) 1);
  13.757 -by Safe_tac;
  13.758 -by (REPEAT (rtac exI 1));
  13.759 -by (etac xzgcd_linear 1);
  13.760 -by Auto_tac;
  13.761 -qed "zgcd_ex_linear";
  13.762 -
  13.763 -Goal "[| #0<n; zgcd(a,n) = #1 |] ==> EX x. [a*x = #1](mod n)";
  13.764 -by (cut_inst_tac [("m","a"),("n","n"),("k","#1")] zgcd_ex_linear 1);
  13.765 -by Safe_tac;
  13.766 -by (res_inst_tac [("x","s")] exI 1);
  13.767 -by (res_inst_tac [("b","s*a+t*n")] zcong_trans 1);
  13.768 -by (Asm_simp_tac 2);
  13.769 -by (rewtac zcong_def);
  13.770 -by (simp_tac (simpset() addsimps [zmult_commute,zdvd_zminus_iff]) 1);
  13.771 -qed "zcong_lineq_ex";
  13.772 -
  13.773 -Goal "[| #0<n; zgcd(a,n) = #1 |] ==> EX! x. #0<=x & x<n & [a*x = b](mod n)";
  13.774 -by Auto_tac;
  13.775 -by (rtac zcong_zless_imp_eq 2);
  13.776 -by (stac (zcong_cancel2 RS sym) 6);
  13.777 -by (rtac zcong_trans 8);
  13.778 -by (ALLGOALS Asm_simp_tac);
  13.779 -by (asm_full_simp_tac (simpset() addsimps [zcong_sym]) 2);
  13.780 -by (cut_inst_tac [("a","a"),("n","n")] zcong_lineq_ex 1);
  13.781 -by Auto_tac;
  13.782 -by (res_inst_tac [("x","x*b mod n")] exI 1);
  13.783 -by Safe_tac;
  13.784 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_bound,pos_mod_sign])));
  13.785 -by (stac zcong_zmod 1);
  13.786 -by (stac (zmod_zmult1_eq RS sym) 1);
  13.787 -by (stac (zcong_zmod RS sym) 1);
  13.788 -by (subgoal_tac "[a*x*b = #1*b](mod n)" 1);
  13.789 -by (rtac zcong_zmult 2);
  13.790 -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [zmult_assoc])));
  13.791 -qed "zcong_lineq_unique";
  13.792 -
    14.1 --- a/src/HOL/NumberTheory/IntPrimes.thy	Sat Feb 03 17:43:34 2001 +0100
    14.2 +++ b/src/HOL/NumberTheory/IntPrimes.thy	Sun Feb 04 19:31:13 2001 +0100
    14.3 @@ -1,34 +1,841 @@
    14.4 -(*  Title:	IntPrimes.thy
    14.5 +(*  Title:      HOL/NumberTheory/IntPrimes.thy
    14.6      ID:         $Id$
    14.7 -    Author:	Thomas M. Rasmussen
    14.8 -    Copyright	2000  University of Cambridge
    14.9 +    Author:     Thomas M. Rasmussen
   14.10 +    Copyright   2000  University of Cambridge
   14.11  *)
   14.12  
   14.13 -IntPrimes = Primes +
   14.14 +header {* Divisibility and prime numbers (on integers) *}
   14.15 +
   14.16 +theory IntPrimes = Primes:
   14.17 +
   14.18 +text {*
   14.19 +  The @{text dvd} relation, GCD, Euclid's extended algorithm, primes,
   14.20 +  congruences (all on the Integers).  Comparable to theory @{text
   14.21 +  Primes}, but @{text dvd} is included here as it is not present in
   14.22 +  main HOL.  Also includes extended GCD and congruences not present in
   14.23 +  @{text Primes}.
   14.24 +*}
   14.25 +
   14.26 +
   14.27 +subsection {* Definitions *}
   14.28  
   14.29  consts
   14.30 -  xzgcda   :: "int*int*int*int*int*int*int*int => int*int*int"
   14.31 -  xzgcd    :: "[int,int] => int*int*int" 
   14.32 -  zprime   :: int set
   14.33 -  zcong    :: [int,int,int] => bool     ("(1[_ = _] '(mod _'))")
   14.34 -  
   14.35 -recdef xzgcda 
   14.36 -       "measure ((%(m,n,r',r,s',s,t',t).(nat r))
   14.37 -                 ::int*int*int*int*int*int*int*int=>nat)"
   14.38 -        simpset "simpset() addsimps [pos_mod_bound]"
   14.39 -       "xzgcda (m,n,r',r,s',s,t',t) = 
   14.40 -          (if r<=#0 then (r',s',t') else  
   14.41 -           xzgcda(m,n,r,r' mod r,s,s'-(r' div r)*s,t,t'-(r' div r)*t))"
   14.42 +  xzgcda :: "int * int * int * int * int * int * int * int => int * int * int"
   14.43 +  xzgcd :: "int => int => int * int * int"
   14.44 +  zprime :: "int set"
   14.45 +  zcong :: "int => int => int => bool"    ("(1[_ = _] '(mod _'))")
   14.46 +
   14.47 +recdef xzgcda
   14.48 +  "measure ((\<lambda>(m, n, r', r, s', s, t', t). nat r)
   14.49 +    :: int * int * int * int *int * int * int * int => nat)"
   14.50 +  "xzgcda (m, n, r', r, s', s, t', t) =
   14.51 +    (if r \<le> #0 then (r', s', t')
   14.52 +     else xzgcda (m, n, r, r' mod r, s, s' - (r' div r) * s, t, t' - (r' div r) * t))"
   14.53 +  (hints simp: pos_mod_bound)
   14.54  
   14.55  constdefs
   14.56 -  zgcd     :: "int*int => int"              
   14.57 -      "zgcd == %(x,y). int (gcd(nat (abs x), nat (abs y)))"
   14.58 +  zgcd :: "int * int => int"
   14.59 +  "zgcd == \<lambda>(x,y). int (gcd (nat (abs x), nat (abs y)))"
   14.60  
   14.61  defs
   14.62 -  xzgcd_def    "xzgcd m n == xzgcda (m,n,m,n,#1,#0,#0,#1)"
   14.63 +  xzgcd_def: "xzgcd m n == xzgcda (m, n, m, n, #1, #0, #0, #1)"
   14.64 +  zprime_def: "zprime == {p. #1 < p \<and> (\<forall>m. m dvd p --> m = #1 \<or> m = p)}"
   14.65 +  zcong_def: "[a = b] (mod m) == m dvd (a - b)"
   14.66 +
   14.67 +
   14.68 +lemma zabs_eq_iff:
   14.69 +    "(abs (z::int) = w) = (z = w \<and> #0 <= z \<or> z = -w \<and> z < #0)"
   14.70 +  apply (auto simp add: zabs_def)
   14.71 +  done
   14.72 +
   14.73 +
   14.74 +text {* \medskip @{term gcd} lemmas *}
   14.75 +
   14.76 +lemma gcd_add1_eq: "gcd (m + k, k) = gcd (m + k, m)"
   14.77 +  apply (simp add: gcd_commute)
   14.78 +  done
   14.79 +
   14.80 +lemma gcd_diff2: "m \<le> n ==> gcd (n, n - m) = gcd (n, m)"
   14.81 +  apply (subgoal_tac "n = m + (n - m)")
   14.82 +   apply (erule ssubst, rule gcd_add1_eq)
   14.83 +  apply simp
   14.84 +  done
   14.85 +
   14.86 +
   14.87 +subsection {* Divides relation *}
   14.88 +
   14.89 +lemma zdvd_0_right [iff]: "(m::int) dvd #0"
   14.90 +  apply (unfold dvd_def)
   14.91 +  apply (blast intro: zmult_0_right [symmetric])
   14.92 +  done
   14.93 +
   14.94 +lemma zdvd_0_left [iff]: "(#0 dvd (m::int)) = (m = #0)"
   14.95 +  apply (unfold dvd_def)
   14.96 +  apply auto
   14.97 +  done
   14.98 +
   14.99 +lemma zdvd_1_left [iff]: "#1 dvd (m::int)"
  14.100 +  apply (unfold dvd_def)
  14.101 +  apply simp
  14.102 +  done
  14.103 +
  14.104 +lemma zdvd_refl [simp]: "m dvd (m::int)"
  14.105 +  apply (unfold dvd_def)
  14.106 +  apply (blast intro: zmult_1_right [symmetric])
  14.107 +  done
  14.108 +
  14.109 +lemma zdvd_trans: "m dvd n ==> n dvd k ==> m dvd (k::int)"
  14.110 +  apply (unfold dvd_def)
  14.111 +  apply (blast intro: zmult_assoc)
  14.112 +  done
  14.113 +
  14.114 +lemma zdvd_zminus_iff: "(m dvd -n) = (m dvd (n::int))"
  14.115 +  apply (unfold dvd_def)
  14.116 +  apply auto
  14.117 +   apply (rule_tac [!] x = "-k" in exI)
  14.118 +  apply auto
  14.119 +  done
  14.120 +
  14.121 +lemma zdvd_zminus2_iff: "(-m dvd n) = (m dvd (n::int))"
  14.122 +  apply (unfold dvd_def)
  14.123 +  apply auto
  14.124 +   apply (rule_tac [!] x = "-k" in exI)
  14.125 +  apply auto
  14.126 +  done
  14.127 +
  14.128 +lemma zdvd_anti_sym:
  14.129 +    "#0 < m ==> #0 < n ==> m dvd n ==> n dvd m ==> m = (n::int)"
  14.130 +  apply (unfold dvd_def)
  14.131 +  apply auto
  14.132 +  apply (simp add: zmult_assoc zmult_eq_self_iff int_0_less_mult_iff zmult_eq_1_iff)
  14.133 +  done
  14.134 +
  14.135 +lemma zdvd_zadd: "k dvd m ==> k dvd n ==> k dvd (m + n :: int)"
  14.136 +  apply (unfold dvd_def)
  14.137 +  apply (blast intro: zadd_zmult_distrib2 [symmetric])
  14.138 +  done
  14.139 +
  14.140 +lemma zdvd_zdiff: "k dvd m ==> k dvd n ==> k dvd (m - n :: int)"
  14.141 +  apply (unfold dvd_def)
  14.142 +  apply (blast intro: zdiff_zmult_distrib2 [symmetric])
  14.143 +  done
  14.144 +
  14.145 +lemma zdvd_zdiffD: "k dvd m - n ==> k dvd n ==> k dvd (m::int)"
  14.146 +  apply (subgoal_tac "m = n + (m - n)")
  14.147 +   apply (erule ssubst)
  14.148 +   apply (blast intro: zdvd_zadd)
  14.149 +  apply simp
  14.150 +  done
  14.151 +
  14.152 +lemma zdvd_zmult: "k dvd (n::int) ==> k dvd m * n"
  14.153 +  apply (unfold dvd_def)
  14.154 +  apply (blast intro: zmult_left_commute)
  14.155 +  done
  14.156 +
  14.157 +lemma zdvd_zmult2: "k dvd (m::int) ==> k dvd m * n"
  14.158 +  apply (subst zmult_commute)
  14.159 +  apply (erule zdvd_zmult)
  14.160 +  done
  14.161 +
  14.162 +lemma [iff]: "(k::int) dvd m * k"
  14.163 +  apply (rule zdvd_zmult)
  14.164 +  apply (rule zdvd_refl)
  14.165 +  done
  14.166 +
  14.167 +lemma [iff]: "(k::int) dvd k * m"
  14.168 +  apply (rule zdvd_zmult2)
  14.169 +  apply (rule zdvd_refl)
  14.170 +  done
  14.171 +
  14.172 +lemma zdvd_zmultD2: "j * k dvd n ==> j dvd (n::int)"
  14.173 +  apply (unfold dvd_def)
  14.174 +  apply (simp add: zmult_assoc)
  14.175 +  apply blast
  14.176 +  done
  14.177 +
  14.178 +lemma zdvd_zmultD: "j * k dvd n ==> k dvd (n::int)"
  14.179 +  apply (rule zdvd_zmultD2)
  14.180 +  apply (subst zmult_commute)
  14.181 +  apply assumption
  14.182 +  done
  14.183 +
  14.184 +lemma zdvd_zmult_mono: "i dvd m ==> j dvd (n::int) ==> i * j dvd m * n"
  14.185 +  apply (unfold dvd_def)
  14.186 +  apply clarify
  14.187 +  apply (rule_tac x = "k * ka" in exI)
  14.188 +  apply (simp add: zmult_ac)
  14.189 +  done
  14.190 +
  14.191 +lemma zdvd_reduce: "(k dvd n + k * m) = (k dvd (n::int))"
  14.192 +  apply (rule iffI)
  14.193 +   apply (erule_tac [2] zdvd_zadd)
  14.194 +   apply (subgoal_tac "n = (n + k * m) - k * m")
  14.195 +    apply (erule ssubst)
  14.196 +    apply (erule zdvd_zdiff)
  14.197 +    apply simp_all
  14.198 +  done
  14.199 +
  14.200 +lemma zdvd_zmod: "f dvd m ==> f dvd (n::int) ==> f dvd m mod n"
  14.201 +  apply (unfold dvd_def)
  14.202 +  apply (auto simp add: zmod_zmult_zmult1)
  14.203 +  done
  14.204 +
  14.205 +lemma zdvd_zmod_imp_zdvd: "k dvd m mod n ==> k dvd n ==> k dvd (m::int)"
  14.206 +  apply (subgoal_tac "k dvd n * (m div n) + m mod n")
  14.207 +   apply (simp add: zmod_zdiv_equality [symmetric])
  14.208 +  apply (simp add: zdvd_zadd zdvd_zmult2)
  14.209 +  done
  14.210 +
  14.211 +lemma zdvd_iff_zmod_eq_0: "(k dvd n) = (n mod (k::int) = #0)"
  14.212 +  apply (unfold dvd_def)
  14.213 +  apply auto
  14.214 +  done
  14.215 +
  14.216 +lemma zdvd_not_zless: "#0 < m ==> m < n ==> \<not> n dvd (m::int)"
  14.217 +  apply (unfold dvd_def)
  14.218 +  apply auto
  14.219 +  apply (subgoal_tac "#0 < n")
  14.220 +   prefer 2
  14.221 +   apply (blast intro: zless_trans)
  14.222 +  apply (simp add: int_0_less_mult_iff)
  14.223 +  apply (subgoal_tac "n * k < n * #1")
  14.224 +   apply (drule zmult_zless_cancel1 [THEN iffD1])
  14.225 +   apply auto
  14.226 +  done
  14.227 +
  14.228 +lemma int_dvd_iff: "(int m dvd z) = (m dvd nat (abs z))"
  14.229 +  apply (auto simp add: dvd_def nat_abs_mult_distrib)
  14.230 +  apply (auto simp add: nat_eq_iff zabs_eq_iff)
  14.231 +   apply (rule_tac [2] x = "-(int k)" in exI)
  14.232 +  apply (auto simp add: zmult_int [symmetric])
  14.233 +  done
  14.234 +
  14.235 +lemma dvd_int_iff: "(z dvd int m) = (nat (abs z) dvd m)"
  14.236 +  apply (auto simp add: dvd_def zabs_def zmult_int [symmetric])
  14.237 +    apply (rule_tac [3] x = "nat k" in exI)
  14.238 +    apply (rule_tac [2] x = "-(int k)" in exI)
  14.239 +    apply (rule_tac x = "nat (-k)" in exI)
  14.240 +    apply (cut_tac [3] k = m in int_less_0_conv)
  14.241 +    apply (cut_tac k = m in int_less_0_conv)
  14.242 +    apply (auto simp add: int_0_le_mult_iff zmult_less_0_iff
  14.243 +      nat_mult_distrib [symmetric] nat_eq_iff2)
  14.244 +  done
  14.245 +
  14.246 +lemma nat_dvd_iff: "(nat z dvd m) = (if #0 \<le> z then (z dvd int m) else m = 0)"
  14.247 +  apply (auto simp add: dvd_def zmult_int [symmetric])
  14.248 +  apply (rule_tac x = "nat k" in exI)
  14.249 +  apply (cut_tac k = m in int_less_0_conv)
  14.250 +  apply (auto simp add: int_0_le_mult_iff zmult_less_0_iff
  14.251 +    nat_mult_distrib [symmetric] nat_eq_iff2)
  14.252 +  done
  14.253 +
  14.254 +lemma zminus_dvd_iff [iff]: "(-z dvd w) = (z dvd (w::int))"
  14.255 +  apply (auto simp add: dvd_def)
  14.256 +   apply (rule_tac [!] x = "-k" in exI)
  14.257 +   apply auto
  14.258 +  done
  14.259 +
  14.260 +lemma dvd_zminus_iff [iff]: "(z dvd -w) = (z dvd (w::int))"
  14.261 +  apply (auto simp add: dvd_def)
  14.262 +   apply (drule zminus_equation [THEN iffD1])
  14.263 +   apply (rule_tac [!] x = "-k" in exI)
  14.264 +   apply auto
  14.265 +  done
  14.266 +
  14.267 +
  14.268 +subsection {* Euclid's Algorithm and GCD *}
  14.269 +
  14.270 +lemma zgcd_0 [simp]: "zgcd (m, #0) = abs m"
  14.271 +  apply (simp add: zgcd_def zabs_def)
  14.272 +  done
  14.273 +
  14.274 +lemma zgcd_0_left [simp]: "zgcd (#0, m) = abs m"
  14.275 +  apply (simp add: zgcd_def zabs_def)
  14.276 +  done
  14.277 +
  14.278 +lemma zgcd_zminus [simp]: "zgcd (-m, n) = zgcd (m, n)"
  14.279 +  apply (simp add: zgcd_def)
  14.280 +  done
  14.281 +
  14.282 +lemma zgcd_zminus2 [simp]: "zgcd (m, -n) = zgcd (m, n)"
  14.283 +  apply (simp add: zgcd_def)
  14.284 +  done
  14.285 +
  14.286 +lemma zgcd_non_0: "#0 < n ==> zgcd (m, n) = zgcd (n, m mod n)"
  14.287 +  apply (frule_tac b = n and a = m in pos_mod_sign)
  14.288 +  apply (simp add: zgcd_def zabs_def nat_mod_distrib)
  14.289 +  apply (cut_tac a = "-m" and b = n in zmod_zminus1_eq_if)
  14.290 +  apply (auto simp add: gcd_non_0 nat_mod_distrib [symmetric] zmod_zminus1_eq_if)
  14.291 +  apply (frule_tac a = m in pos_mod_bound)
  14.292 +  apply (simp add: nat_diff_distrib)
  14.293 +  apply (rule gcd_diff2)
  14.294 +  apply (simp add: nat_le_eq_zle)
  14.295 +  done
  14.296 +
  14.297 +lemma zgcd_eq: "zgcd (m, n) = zgcd (n, m mod n)"
  14.298 +  apply (tactic {* zdiv_undefined_case_tac "n = #0" 1 *})
  14.299 +  apply (auto simp add: linorder_neq_iff zgcd_non_0)
  14.300 +  apply (cut_tac m = "-m" and n = "-n" in zgcd_non_0)
  14.301 +   apply auto
  14.302 +  done
  14.303 +
  14.304 +lemma zgcd_1 [simp]: "zgcd (m, #1) = #1"
  14.305 +  apply (simp add: zgcd_def zabs_def)
  14.306 +  done
  14.307 +
  14.308 +lemma zgcd_0_1_iff [simp]: "(zgcd (#0, m) = #1) = (abs m = #1)"
  14.309 +  apply (simp add: zgcd_def zabs_def)
  14.310 +  done
  14.311 +
  14.312 +lemma zgcd_zdvd1 [iff]: "zgcd (m, n) dvd m"
  14.313 +  apply (simp add: zgcd_def zabs_def int_dvd_iff)
  14.314 +  done
  14.315 +
  14.316 +lemma zgcd_zdvd2 [iff]: "zgcd (m, n) dvd n"
  14.317 +  apply (simp add: zgcd_def zabs_def int_dvd_iff)
  14.318 +  done
  14.319 +
  14.320 +lemma zgcd_greatest_iff: "k dvd zgcd (m, n) = (k dvd m \<and> k dvd n)"
  14.321 +  apply (simp add: zgcd_def zabs_def int_dvd_iff dvd_int_iff nat_dvd_iff)
  14.322 +  done
  14.323 +
  14.324 +lemma zgcd_commute: "zgcd (m, n) = zgcd (n, m)"
  14.325 +  apply (simp add: zgcd_def gcd_commute)
  14.326 +  done
  14.327 +
  14.328 +lemma zgcd_1_left [simp]: "zgcd (#1, m) = #1"
  14.329 +  apply (simp add: zgcd_def gcd_1_left)
  14.330 +  done
  14.331 +
  14.332 +lemma zgcd_assoc: "zgcd (zgcd (k, m), n) = zgcd (k, zgcd (m, n))"
  14.333 +  apply (simp add: zgcd_def gcd_assoc)
  14.334 +  done
  14.335 +
  14.336 +lemma zgcd_left_commute: "zgcd (k, zgcd (m, n)) = zgcd (m, zgcd (k, n))"
  14.337 +  apply (rule zgcd_commute [THEN trans])
  14.338 +  apply (rule zgcd_assoc [THEN trans])
  14.339 +  apply (rule zgcd_commute [THEN arg_cong])
  14.340 +  done
  14.341 +
  14.342 +lemmas zgcd_ac = zgcd_assoc zgcd_commute zgcd_left_commute
  14.343 +  -- {* addition is an AC-operator *}
  14.344 +
  14.345 +lemma zgcd_zmult_distrib2: "#0 \<le> k ==> k * zgcd (m, n) = zgcd (k * m, k * n)"
  14.346 +  apply (simp del: zmult_zminus_right
  14.347 +    add: zmult_zminus_right [symmetric] nat_mult_distrib zgcd_def zabs_def
  14.348 +    zmult_less_0_iff gcd_mult_distrib2 [symmetric] zmult_int [symmetric])
  14.349 +  done
  14.350 +
  14.351 +lemma zgcd_zmult_distrib2_abs: "zgcd (k * m, k * n) = abs k * zgcd (m, n)"
  14.352 +  apply (simp add: zabs_def zgcd_zmult_distrib2)
  14.353 +  done
  14.354 +
  14.355 +lemma zgcd_self [simp]: "#0 \<le> m ==> zgcd (m, m) = m"
  14.356 +  apply (cut_tac k = m and m = "#1" and n = "#1" in zgcd_zmult_distrib2)
  14.357 +   apply simp_all
  14.358 +  done
  14.359 +
  14.360 +lemma zgcd_zmult_eq_self [simp]: "#0 \<le> k ==> zgcd (k, k * n) = k"
  14.361 +  apply (cut_tac k = k and m = "#1" and n = n in zgcd_zmult_distrib2)
  14.362 +   apply simp_all
  14.363 +  done
  14.364 +
  14.365 +lemma zgcd_zmult_eq_self2 [simp]: "#0 \<le> k ==> zgcd (k * n, k) = k"
  14.366 +  apply (cut_tac k = k and m = n and n = "#1" in zgcd_zmult_distrib2)
  14.367 +   apply simp_all
  14.368 +  done
  14.369 +
  14.370 +lemma aux: "zgcd (n, k) = #1 ==> k dvd m * n ==> #0 \<le> m ==> k dvd m"
  14.371 +  apply (subgoal_tac "m = zgcd (m * n, m * k)")
  14.372 +   apply (erule ssubst, rule zgcd_greatest_iff [THEN iffD2])
  14.373 +   apply (simp_all add: zgcd_zmult_distrib2 [symmetric] int_0_le_mult_iff)
  14.374 +  done
  14.375 +
  14.376 +lemma zrelprime_zdvd_zmult: "zgcd (n, k) = #1 ==> k dvd m * n ==> k dvd m"
  14.377 +  apply (case_tac "#0 \<le> m")
  14.378 +   apply (blast intro: aux)
  14.379 +  apply (subgoal_tac "k dvd -m")
  14.380 +   apply (rule_tac [2] aux)
  14.381 +     apply auto
  14.382 +  done
  14.383 +
  14.384 +lemma zprime_imp_zrelprime:
  14.385 +    "p \<in> zprime ==> \<not> p dvd n ==> zgcd (n, p) = #1"
  14.386 +  apply (unfold zprime_def)
  14.387 +  apply auto
  14.388 +  done
  14.389 +
  14.390 +lemma zless_zprime_imp_zrelprime:
  14.391 +    "p \<in> zprime ==> #0 < n ==> n < p ==> zgcd (n, p) = #1"
  14.392 +  apply (erule zprime_imp_zrelprime)
  14.393 +  apply (erule zdvd_not_zless)
  14.394 +  apply assumption
  14.395 +  done
  14.396 +
  14.397 +lemma zprime_zdvd_zmult:
  14.398 +    "#0 \<le> (m::int) ==> p \<in> zprime ==> p dvd m * n ==> p dvd m \<or> p dvd n"
  14.399 +  apply safe
  14.400 +  apply (rule zrelprime_zdvd_zmult)
  14.401 +   apply (rule zprime_imp_zrelprime)
  14.402 +    apply auto
  14.403 +  done
  14.404 +
  14.405 +lemma zgcd_zadd_zmult [simp]: "zgcd (m + n * k, n) = zgcd (m, n)"
  14.406 +  apply (rule zgcd_eq [THEN trans])
  14.407 +  apply (simp add: zmod_zadd1_eq)
  14.408 +  apply (rule zgcd_eq [symmetric])
  14.409 +  done
  14.410 +
  14.411 +lemma zgcd_zdvd_zgcd_zmult: "zgcd (m, n) dvd zgcd (k * m, n)"
  14.412 +  apply (simp add: zgcd_greatest_iff)
  14.413 +  apply (blast intro: zdvd_trans)
  14.414 +  done
  14.415 +
  14.416 +lemma zgcd_zmult_zdvd_zgcd:
  14.417 +    "zgcd (k, n) = #1 ==> zgcd (k * m, n) dvd zgcd (m, n)"
  14.418 +  apply (simp add: zgcd_greatest_iff)
  14.419 +  apply (rule_tac n = k in zrelprime_zdvd_zmult)
  14.420 +   prefer 2
  14.421 +   apply (simp add: zmult_commute)
  14.422 +  apply (subgoal_tac "zgcd (k, zgcd (k * m, n)) = zgcd (k * m, zgcd (k, n))")
  14.423 +   apply simp
  14.424 +  apply (simp (no_asm) add: zgcd_ac)
  14.425 +  done
  14.426 +
  14.427 +lemma zgcd_zmult_cancel: "zgcd (k, n) = #1 ==> zgcd (k * m, n) = zgcd (m, n)"
  14.428 +  apply (simp add: zgcd_def nat_abs_mult_distrib gcd_mult_cancel)
  14.429 +  done
  14.430 +
  14.431 +lemma zgcd_zgcd_zmult:
  14.432 +    "zgcd (k, m) = #1 ==> zgcd (n, m) = #1 ==> zgcd (k * n, m) = #1"
  14.433 +  apply (simp (no_asm_simp) add: zgcd_zmult_cancel)
  14.434 +  done
  14.435 +
  14.436 +lemma zdvd_iff_zgcd: "#0 < m ==> (m dvd n) = (zgcd (n, m) = m)"
  14.437 +  apply safe
  14.438 +   apply (rule_tac [2] n = "zgcd (n, m)" in zdvd_trans)
  14.439 +    apply (rule_tac [3] zgcd_zdvd1)
  14.440 +   apply simp_all
  14.441 +  apply (unfold dvd_def)
  14.442 +  apply auto
  14.443 +  done
  14.444 +
  14.445 +
  14.446 +subsection {* Congruences *}
  14.447 +
  14.448 +lemma zcong_1 [simp]: "[a = b] (mod #1)"
  14.449 +  apply (unfold zcong_def)
  14.450 +  apply auto
  14.451 +  done
  14.452 +
  14.453 +lemma zcong_refl [simp]: "[k = k] (mod m)"
  14.454 +  apply (unfold zcong_def)
  14.455 +  apply auto
  14.456 +  done
  14.457  
  14.458 -  zprime_def   "zprime == {p. #1<p & (ALL m. m dvd p --> m=#1 | m=p)}"
  14.459 +lemma zcong_sym: "[a = b] (mod m) = [b = a] (mod m)"
  14.460 +  apply (unfold zcong_def dvd_def)
  14.461 +  apply auto
  14.462 +   apply (rule_tac [!] x = "-k" in exI)
  14.463 +   apply auto
  14.464 +  done
  14.465 +
  14.466 +lemma zcong_zadd:
  14.467 +    "[a = b] (mod m) ==> [c = d] (mod m) ==> [a + c = b + d] (mod m)"
  14.468 +  apply (unfold zcong_def)
  14.469 +  apply (rule_tac s = "(a - b) + (c - d)" in subst)
  14.470 +   apply (rule_tac [2] zdvd_zadd)
  14.471 +    apply auto
  14.472 +  done
  14.473 +
  14.474 +lemma zcong_zdiff:
  14.475 +    "[a = b] (mod m) ==> [c = d] (mod m) ==> [a - c = b - d] (mod m)"
  14.476 +  apply (unfold zcong_def)
  14.477 +  apply (rule_tac s = "(a - b) - (c - d)" in subst)
  14.478 +   apply (rule_tac [2] zdvd_zdiff)
  14.479 +    apply auto
  14.480 +  done
  14.481 +
  14.482 +lemma zcong_trans:
  14.483 +    "[a = b] (mod m) ==> [b = c] (mod m) ==> [a = c] (mod m)"
  14.484 +  apply (unfold zcong_def dvd_def)
  14.485 +  apply auto
  14.486 +  apply (rule_tac x = "k + ka" in exI)
  14.487 +  apply (simp add: zadd_ac zadd_zmult_distrib2)
  14.488 +  done
  14.489 +
  14.490 +lemma zcong_zmult:
  14.491 +    "[a = b] (mod m) ==> [c = d] (mod m) ==> [a * c = b * d] (mod m)"
  14.492 +  apply (rule_tac b = "b * c" in zcong_trans)
  14.493 +   apply (unfold zcong_def)
  14.494 +   apply (rule_tac s = "c * (a - b)" in subst)
  14.495 +    apply (rule_tac [3] s = "b * (c - d)" in subst)
  14.496 +     prefer 4
  14.497 +     apply (blast intro: zdvd_zmult)
  14.498 +    prefer 2
  14.499 +    apply (blast intro: zdvd_zmult)
  14.500 +   apply (simp_all add: zdiff_zmult_distrib2 zmult_commute)
  14.501 +  done
  14.502 +
  14.503 +lemma zcong_scalar: "[a = b] (mod m) ==> [a * k = b * k] (mod m)"
  14.504 +  apply (rule zcong_zmult)
  14.505 +  apply simp_all
  14.506 +  done
  14.507 +
  14.508 +lemma zcong_scalar2: "[a = b] (mod m) ==> [k * a = k * b] (mod m)"
  14.509 +  apply (rule zcong_zmult)
  14.510 +  apply simp_all
  14.511 +  done
  14.512 +
  14.513 +lemma zcong_zmult_self: "[a * m = b * m] (mod m)"
  14.514 +  apply (unfold zcong_def)
  14.515 +  apply (rule zdvd_zdiff)
  14.516 +   apply simp_all
  14.517 +  done
  14.518 +
  14.519 +lemma zcong_square:
  14.520 +  "p \<in> zprime ==> #0 < a ==> [a * a = #1] (mod p)
  14.521 +    ==> [a = #1] (mod p) \<or> [a = p - #1] (mod p)"
  14.522 +  apply (unfold zcong_def)
  14.523 +  apply (rule zprime_zdvd_zmult)
  14.524 +    apply (rule_tac [3] s = "a * a - #1 + p * (#1 - a)" in subst)
  14.525 +     prefer 4
  14.526 +     apply (simp add: zdvd_reduce)
  14.527 +    apply (simp_all add: zdiff_zmult_distrib zmult_commute zdiff_zmult_distrib2)
  14.528 +  done
  14.529 +
  14.530 +lemma zcong_cancel:
  14.531 +  "#0 \<le> m ==>
  14.532 +    zgcd (k, m) = #1 ==> [a * k = b * k] (mod m) = [a = b] (mod m)"
  14.533 +  apply safe
  14.534 +   prefer 2
  14.535 +   apply (blast intro: zcong_scalar)
  14.536 +  apply (case_tac "b < a")
  14.537 +   prefer 2
  14.538 +   apply (subst zcong_sym)
  14.539 +   apply (unfold zcong_def)
  14.540 +   apply (rule_tac [!] zrelprime_zdvd_zmult)
  14.541 +     apply (simp_all add: zdiff_zmult_distrib)
  14.542 +  apply (subgoal_tac "m dvd (-(a * k - b * k))")
  14.543 +   apply (simp add: zminus_zdiff_eq)
  14.544 +  apply (subst zdvd_zminus_iff)
  14.545 +  apply assumption
  14.546 +  done
  14.547 +
  14.548 +lemma zcong_cancel2:
  14.549 +  "#0 \<le> m ==>
  14.550 +    zgcd (k, m) = #1 ==> [k * a = k * b] (mod m) = [a = b] (mod m)"
  14.551 +  apply (simp add: zmult_commute zcong_cancel)
  14.552 +  done
  14.553 +
  14.554 +lemma zcong_zgcd_zmult_zmod:
  14.555 +  "[a = b] (mod m) ==> [a = b] (mod n) ==> zgcd (m, n) = #1
  14.556 +    ==> [a = b] (mod m * n)"
  14.557 +  apply (unfold zcong_def dvd_def)
  14.558 +  apply auto
  14.559 +  apply (subgoal_tac "m dvd n * ka")
  14.560 +   apply (subgoal_tac "m dvd ka")
  14.561 +    apply (case_tac [2] "#0 \<le> ka")
  14.562 +     prefer 3
  14.563 +     apply (subst zdvd_zminus_iff [symmetric])
  14.564 +     apply (rule_tac n = n in zrelprime_zdvd_zmult)
  14.565 +      apply (simp add: zgcd_commute)
  14.566 +     apply (simp add: zmult_commute zdvd_zminus_iff)
  14.567 +    prefer 2
  14.568 +    apply (rule_tac n = n in zrelprime_zdvd_zmult)
  14.569 +     apply (simp add: zgcd_commute)
  14.570 +    apply (simp add: zmult_commute)
  14.571 +   apply (auto simp add: dvd_def)
  14.572 +  apply (blast intro: sym)
  14.573 +  done
  14.574 +
  14.575 +lemma zcong_zless_imp_eq:
  14.576 +  "#0 \<le> a ==>
  14.577 +    a < m ==> #0 \<le> b ==> b < m ==> [a = b] (mod m) ==> a = b"
  14.578 +  apply (unfold zcong_def dvd_def)
  14.579 +  apply auto
  14.580 +  apply (drule_tac f = "\<lambda>z. z mod m" in arg_cong)
  14.581 +  apply (cut_tac z = a and w = b in zless_linear)
  14.582 +  apply auto
  14.583 +   apply (subgoal_tac [2] "(a - b) mod m = a - b")
  14.584 +    apply (rule_tac [3] mod_pos_pos_trivial)
  14.585 +     apply auto
  14.586 +  apply (subgoal_tac "(m + (a - b)) mod m = m + (a - b)")
  14.587 +   apply (rule_tac [2] mod_pos_pos_trivial)
  14.588 +    apply auto
  14.589 +  done
  14.590 +
  14.591 +lemma zcong_square_zless:
  14.592 +  "p \<in> zprime ==> #0 < a ==> a < p ==>
  14.593 +    [a * a = #1] (mod p) ==> a = #1 \<or> a = p - #1"
  14.594 +  apply (cut_tac p = p and a = a in zcong_square)
  14.595 +     apply (simp add: zprime_def)
  14.596 +    apply (auto intro: zcong_zless_imp_eq)
  14.597 +  done
  14.598 +
  14.599 +lemma zcong_not:
  14.600 +    "#0 < a ==> a < m ==> #0 < b ==> b < a ==> \<not> [a = b] (mod m)"
  14.601 +  apply (unfold zcong_def)
  14.602 +  apply (rule zdvd_not_zless)
  14.603 +   apply auto
  14.604 +  done
  14.605 +
  14.606 +lemma zcong_zless_0:
  14.607 +    "#0 \<le> a ==> a < m ==> [a = #0] (mod m) ==> a = #0"
  14.608 +  apply (unfold zcong_def dvd_def)
  14.609 +  apply auto
  14.610 +  apply (subgoal_tac "#0 < m")
  14.611 +   apply (rotate_tac -1)
  14.612 +   apply (simp add: int_0_le_mult_iff)
  14.613 +   apply (subgoal_tac "m * k < m * #1")
  14.614 +    apply (drule zmult_zless_cancel1 [THEN iffD1])
  14.615 +    apply (auto simp add: linorder_neq_iff)
  14.616 +  done
  14.617 +
  14.618 +lemma zcong_zless_unique:
  14.619 +    "#0 < m ==> (\<exists>!b. #0 \<le> b \<and> b < m \<and> [a = b] (mod m))"
  14.620 +  apply auto
  14.621 +   apply (subgoal_tac [2] "[b = y] (mod m)")
  14.622 +    apply (case_tac [2] "b = #0")
  14.623 +     apply (case_tac [3] "y = #0")
  14.624 +      apply (auto intro: zcong_trans zcong_zless_0 zcong_zless_imp_eq order_less_le
  14.625 +        simp add: zcong_sym)
  14.626 +  apply (unfold zcong_def dvd_def)
  14.627 +  apply (rule_tac x = "a mod m" in exI)
  14.628 +  apply (auto simp add: pos_mod_sign pos_mod_bound)
  14.629 +  apply (rule_tac x = "-(a div m)" in exI)
  14.630 +  apply (cut_tac a = a and b = m in zmod_zdiv_equality)
  14.631 +  apply auto
  14.632 +  done
  14.633 +
  14.634 +lemma zcong_iff_lin: "([a = b] (mod m)) = (\<exists>k. b = a + m * k)"
  14.635 +  apply (unfold zcong_def dvd_def)
  14.636 +  apply auto
  14.637 +   apply (rule_tac [!] x = "-k" in exI)
  14.638 +   apply auto
  14.639 +  done
  14.640 +
  14.641 +lemma zgcd_zcong_zgcd:
  14.642 +  "#0 < m ==>
  14.643 +    zgcd (a, m) = #1 ==> [a = b] (mod m) ==> zgcd (b, m) = #1"
  14.644 +  apply (auto simp add: zcong_iff_lin)
  14.645 +  done
  14.646 +
  14.647 +lemma aux: "a = c ==> b = d ==> a - b = c - (d::int)"
  14.648 +  apply auto
  14.649 +  done
  14.650 +
  14.651 +lemma aux: "a - b = (m::int) * (a div m - b div m) + (a mod m - b mod m)"
  14.652 +  apply (rule_tac "s" = "(m * (a div m) + a mod m) - (m * (b div m) + b mod m)"
  14.653 +    in trans)
  14.654 +   prefer 2
  14.655 +   apply (simp add: zdiff_zmult_distrib2)
  14.656 +  apply (rule aux)
  14.657 +   apply (rule_tac [!] zmod_zdiv_equality)
  14.658 +  done
  14.659  
  14.660 -  zcong_def    "[a=b] (mod m) == m dvd (a-b)"
  14.661 +lemma zcong_zmod: "[a = b] (mod m) = [a mod m = b mod m] (mod m)"
  14.662 +  apply (unfold zcong_def)
  14.663 +  apply (rule_tac t = "a - b" in ssubst)
  14.664 +  apply (rule_tac "m" = "m" in aux)
  14.665 +  apply (rule trans)
  14.666 +   apply (rule_tac [2] k = m and m = "a div m - b div m" in zdvd_reduce)
  14.667 +  apply (simp add: zadd_commute)
  14.668 +  done
  14.669 +
  14.670 +lemma zcong_zmod_eq: "#0 < m ==> [a = b] (mod m) = (a mod m = b mod m)"
  14.671 +  apply auto
  14.672 +   apply (rule_tac m = m in zcong_zless_imp_eq)
  14.673 +       prefer 5
  14.674 +       apply (subst zcong_zmod [symmetric])
  14.675 +       apply (simp_all add: pos_mod_bound pos_mod_sign)
  14.676 +  apply (unfold zcong_def dvd_def)
  14.677 +  apply (rule_tac x = "a div m - b div m" in exI)
  14.678 +  apply (rule_tac m1 = m in aux [THEN trans])
  14.679 +  apply auto
  14.680 +  done
  14.681 +
  14.682 +lemma zcong_zminus [iff]: "[a = b] (mod -m) = [a = b] (mod m)"
  14.683 +  apply (auto simp add: zcong_def)
  14.684 +  done
  14.685 +
  14.686 +lemma zcong_zero [iff]: "[a = b] (mod #0) = (a = b)"
  14.687 +  apply (auto simp add: zcong_def)
  14.688 +  done
  14.689 +
  14.690 +lemma "[a = b] (mod m) = (a mod m = b mod m)"
  14.691 +  apply (tactic {* zdiv_undefined_case_tac "m = #0" 1 *})
  14.692 +  apply (case_tac "#0 < m")
  14.693 +   apply (simp add: zcong_zmod_eq)
  14.694 +  apply (rule_tac t = m in zminus_zminus [THEN subst])
  14.695 +  apply (subst zcong_zminus)
  14.696 +  apply (subst zcong_zmod_eq)
  14.697 +   apply arith
  14.698 +  oops  -- {* FIXME: finish this proof? *}
  14.699 +
  14.700 +
  14.701 +subsection {* Modulo *}
  14.702 +
  14.703 +lemma zmod_zdvd_zmod:
  14.704 +    "#0 < (m::int) ==> m dvd b ==> (a mod b mod m) = (a mod m)"
  14.705 +  apply (unfold dvd_def)
  14.706 +  apply auto
  14.707 +  apply (subst zcong_zmod_eq [symmetric])
  14.708 +   prefer 2
  14.709 +   apply (subst zcong_iff_lin)
  14.710 +   apply (rule_tac x = "k * (a div (m * k))" in exI)
  14.711 +   apply (subst zadd_commute)
  14.712 +   apply (subst zmult_assoc [symmetric])
  14.713 +   apply (rule_tac zmod_zdiv_equality)
  14.714 +  apply assumption
  14.715 +  done
  14.716 +
  14.717 +
  14.718 +subsection {* Extended GCD *}
  14.719 +
  14.720 +declare xzgcda.simps [simp del]
  14.721 +
  14.722 +lemma aux1:
  14.723 +  "zgcd (r', r) = k --> #0 < r -->
  14.724 +    (\<exists>sn tn. xzgcda (m, n, r', r, s', s, t', t) = (k, sn, tn))"
  14.725 +  apply (rule_tac u = m and v = n and w = r' and x = r and y = s' and
  14.726 +    z = s and aa = t' and ab = t in xzgcda.induct)
  14.727 +  apply (subst zgcd_eq)
  14.728 +  apply (subst xzgcda.simps)
  14.729 +  apply auto
  14.730 +  apply (case_tac "r' mod r = #0")
  14.731 +   prefer 2
  14.732 +   apply (frule_tac a = "r'" in pos_mod_sign)
  14.733 +   apply auto
  14.734 +   apply arith
  14.735 +  apply (rule exI)
  14.736 +  apply (rule exI)
  14.737 +  apply (subst xzgcda.simps)
  14.738 +  apply auto
  14.739 +  apply (simp add: zabs_def)
  14.740 +  done
  14.741 +
  14.742 +lemma aux2:
  14.743 +  "(\<exists>sn tn. xzgcda (m, n, r', r, s', s, t', t) = (k, sn, tn)) --> #0 < r -->
  14.744 +    zgcd (r', r) = k"
  14.745 +  apply (rule_tac u = m and v = n and w = r' and x = r and y = s' and
  14.746 +    z = s and aa = t' and ab = t in xzgcda.induct)
  14.747 +  apply (subst zgcd_eq)
  14.748 +  apply (subst xzgcda.simps)
  14.749 +  apply (auto simp add: linorder_not_le)
  14.750 +  apply (case_tac "r' mod r = #0")
  14.751 +   prefer 2
  14.752 +   apply (frule_tac a = "r'" in pos_mod_sign)
  14.753 +   apply auto
  14.754 +   apply arith
  14.755 +  apply (erule_tac P = "xzgcda ?u = ?v" in rev_mp)
  14.756 +  apply (subst xzgcda.simps)
  14.757 +  apply auto
  14.758 +  apply (simp add: zabs_def)
  14.759 +  done
  14.760 +
  14.761 +lemma xzgcd_correct:
  14.762 +    "#0 < n ==> (zgcd (m, n) = k) = (\<exists>s t. xzgcd m n = (k, s, t))"
  14.763 +  apply (unfold xzgcd_def)
  14.764 +  apply (rule iffI)
  14.765 +   apply (rule_tac [2] aux2 [THEN mp, THEN mp])
  14.766 +    apply (rule aux1 [THEN mp, THEN mp])
  14.767 +     apply auto
  14.768 +  done
  14.769 +
  14.770 +
  14.771 +text {* \medskip @{term xzgcd} linear *}
  14.772 +
  14.773 +lemma aux:
  14.774 +  "(a - r * b) * m + (c - r * d) * (n::int) =
  14.775 +    (a * m + c * n) - r * (b * m + d * n)"
  14.776 +  apply (simp add: zdiff_zmult_distrib zadd_zmult_distrib2 zmult_assoc)
  14.777 +  done
  14.778 +
  14.779 +lemma aux:
  14.780 +  "r' = s' * m + t' * n ==> r = s * m + t * n
  14.781 +    ==> (r' mod r) = (s' - (r' div r) * s) * m + (t' - (r' div r) * t) * (n::int)"
  14.782 +  apply (rule trans)
  14.783 +   apply (rule_tac [2] aux [symmetric])
  14.784 +  apply simp
  14.785 +  apply (subst eq_zdiff_eq)
  14.786 +  apply (rule trans [symmetric])
  14.787 +  apply (rule_tac b = "s * m + t * n" in zmod_zdiv_equality)
  14.788 +  apply (simp add: zmult_commute)
  14.789 +  done
  14.790 +
  14.791 +lemma order_le_neq_implies_less: "(x::'a::order) \<le> y ==> x \<noteq> y ==> x < y"
  14.792 +  by (rule iffD2 [OF order_less_le conjI])
  14.793 +
  14.794 +lemma xzgcda_linear [rule_format]:
  14.795 +  "#0 < r --> xzgcda (m, n, r', r, s', s, t', t) = (rn, sn, tn) -->
  14.796 +    r' = s' * m + t' * n -->  r = s * m + t * n --> rn = sn * m + tn * n"
  14.797 +  apply (rule_tac u = m and v = n and w = r' and x = r and y = s' and
  14.798 +    z = s and aa = t' and ab = t in xzgcda.induct)
  14.799 +  apply (subst xzgcda.simps)
  14.800 +  apply (simp (no_asm))
  14.801 +  apply (rule impI)+
  14.802 +  apply (case_tac "r' mod r = #0")
  14.803 +   apply (simp add: xzgcda.simps)
  14.804 +   apply clarify
  14.805 +  apply (subgoal_tac "#0 < r' mod r")
  14.806 +   apply (rule_tac [2] order_le_neq_implies_less)
  14.807 +   apply (rule_tac [2] pos_mod_sign)
  14.808 +    apply (cut_tac m = m and n = n and r' = r' and r = r and s' = s' and
  14.809 +      s = s and t' = t' and t = t in aux)
  14.810 +      apply auto
  14.811 +  done
  14.812 +
  14.813 +lemma xzgcd_linear:
  14.814 +    "#0 < n ==> xzgcd m n = (r, s, t) ==> r = s * m + t * n"
  14.815 +  apply (unfold xzgcd_def)
  14.816 +  apply (erule xzgcda_linear)
  14.817 +    apply assumption
  14.818 +   apply auto
  14.819 +  done
  14.820 +
  14.821 +lemma zgcd_ex_linear:
  14.822 +    "#0 < n ==> zgcd (m, n) = k ==> (\<exists>s t. k = s * m + t * n)"
  14.823 +  apply (simp add: xzgcd_correct)
  14.824 +  apply safe
  14.825 +  apply (rule exI)+
  14.826 +  apply (erule xzgcd_linear)
  14.827 +  apply auto
  14.828 +  done
  14.829 +
  14.830 +lemma zcong_lineq_ex:
  14.831 +    "#0 < n ==> zgcd (a, n) = #1 ==> \<exists>x. [a * x = #1] (mod n)"
  14.832 +  apply (cut_tac m = a and n = n and k = "#1" in zgcd_ex_linear)
  14.833 +    apply safe
  14.834 +  apply (rule_tac x = s in exI)
  14.835 +  apply (rule_tac b = "s * a + t * n" in zcong_trans)
  14.836 +   prefer 2
  14.837 +   apply simp
  14.838 +  apply (unfold zcong_def)
  14.839 +  apply (simp (no_asm) add: zmult_commute zdvd_zminus_iff)
  14.840 +  done
  14.841 +
  14.842 +lemma zcong_lineq_unique:
  14.843 +  "#0 < n ==>
  14.844 +    zgcd (a, n) = #1 ==> \<exists>!x. #0 \<le> x \<and> x < n \<and> [a * x = b] (mod n)"
  14.845 +  apply auto
  14.846 +   apply (rule_tac [2] zcong_zless_imp_eq)
  14.847 +       apply (tactic {* stac (thm "zcong_cancel2" RS sym) 6 *})
  14.848 +         apply (rule_tac [8] zcong_trans)
  14.849 +          apply (simp_all (no_asm_simp))
  14.850 +   prefer 2
  14.851 +   apply (simp add: zcong_sym)
  14.852 +  apply (cut_tac a = a and n = n in zcong_lineq_ex)
  14.853 +    apply auto
  14.854 +  apply (rule_tac x = "x * b mod n" in exI)
  14.855 +  apply safe
  14.856 +    apply (simp_all (no_asm_simp) add: pos_mod_bound pos_mod_sign)
  14.857 +  apply (subst zcong_zmod)
  14.858 +  apply (subst zmod_zmult1_eq [symmetric])
  14.859 +  apply (subst zcong_zmod [symmetric])
  14.860 +  apply (subgoal_tac "[a * x * b = #1 * b] (mod n)")
  14.861 +   apply (rule_tac [2] zcong_zmult)
  14.862 +    apply (simp_all add: zmult_assoc)
  14.863 +  done
  14.864  
  14.865  end
    15.1 --- a/src/HOL/NumberTheory/Primes.thy	Sat Feb 03 17:43:34 2001 +0100
    15.2 +++ b/src/HOL/NumberTheory/Primes.thy	Sun Feb 04 19:31:13 2001 +0100
    15.3 @@ -2,207 +2,229 @@
    15.4      ID:         $Id$
    15.5      Author:     Christophe Tabacznyj and Lawrence C Paulson
    15.6      Copyright   1996  University of Cambridge
    15.7 -
    15.8 -The Greatest Common Divisor and Euclid's algorithm
    15.9 -
   15.10 -See H. Davenport, "The Higher Arithmetic".  6th edition.  (CUP, 1992)
   15.11  *)
   15.12  
   15.13 +header {* The Greatest Common Divisor and Euclid's algorithm *}
   15.14 +
   15.15  theory Primes = Main:
   15.16 +
   15.17 +text {*
   15.18 +  (See H. Davenport, "The Higher Arithmetic".  6th edition.  (CUP, 1992))
   15.19 +
   15.20 +  \bigskip
   15.21 +*}
   15.22 +
   15.23  consts
   15.24 -  gcd     :: "nat*nat=>nat"               (*Euclid's algorithm *)
   15.25 +  gcd  :: "nat * nat => nat"  -- {* Euclid's algorithm *}
   15.26  
   15.27 -recdef gcd "measure ((%(m,n).n) ::nat*nat=>nat)"
   15.28 -    "gcd (m, n) = (if n=0 then m else gcd(n, m mod n))"
   15.29 +recdef gcd  "measure ((\<lambda>(m, n). n) :: nat * nat => nat)"
   15.30 +  "gcd (m, n) = (if n = 0 then m else gcd (n, m mod n))"
   15.31  
   15.32  constdefs
   15.33 -  is_gcd  :: "[nat,nat,nat]=>bool"        (*gcd as a relation*)
   15.34 -    "is_gcd p m n == p dvd m  &  p dvd n  &
   15.35 -                     (ALL d. d dvd m & d dvd n --> d dvd p)"
   15.36 -
   15.37 -  coprime :: "[nat,nat]=>bool"
   15.38 -    "coprime m n == gcd(m,n) = 1"
   15.39 +  is_gcd :: "nat => nat => nat => bool"  -- {* @{term gcd} as a relation *}
   15.40 +  "is_gcd p m n == p dvd m \<and> p dvd n \<and>
   15.41 +    (\<forall>d. d dvd m \<and> d dvd n --> d dvd p)"
   15.42  
   15.43 -  prime   :: "nat set"
   15.44 -    "prime == {p. 1<p & (ALL m. m dvd p --> m=1 | m=p)}"
   15.45 -
   15.46 +  coprime :: "nat => nat => bool"
   15.47 +  "coprime m n == gcd (m, n) = 1"
   15.48  
   15.49 -(************************************************)
   15.50 -(** Greatest Common Divisor                    **)
   15.51 -(************************************************)
   15.52 -
   15.53 -(*** Euclid's Algorithm ***)
   15.54 +  prime :: "nat set"
   15.55 +  "prime == {p. 1 < p \<and> (\<forall>m. m dvd p --> m = 1 \<or> m = p)}"
   15.56  
   15.57  
   15.58  lemma gcd_induct:
   15.59 -     "[| !!m. P m 0;     
   15.60 -         !!m n. [| 0<n;  P n (m mod n) |] ==> P m n  
   15.61 -      |] ==> P (m::nat) (n::nat)"
   15.62 -  apply (induct_tac m n rule: gcd.induct)
   15.63 -  apply (case_tac "n=0")
   15.64 -  apply (simp_all)
   15.65 +  "(!!m. P m 0) ==>
   15.66 +    (!!m n. 0 < n ==> P n (m mod n) ==> P m n)
   15.67 +  ==> P (m::nat) (n::nat)"
   15.68 +  apply (induct m n rule: gcd.induct)
   15.69 +  apply (case_tac "n = 0")
   15.70 +   apply simp_all
   15.71    done
   15.72  
   15.73  
   15.74 -lemma gcd_0 [simp]: "gcd(m,0) = m"
   15.75 -  apply (simp);
   15.76 +lemma gcd_0 [simp]: "gcd (m, 0) = m"
   15.77 +  apply simp
   15.78    done
   15.79  
   15.80 -lemma gcd_non_0: "0<n ==> gcd(m,n) = gcd (n, m mod n)"
   15.81 -  apply (simp)
   15.82 -  done;
   15.83 +lemma gcd_non_0: "0 < n ==> gcd (m, n) = gcd (n, m mod n)"
   15.84 +  apply simp
   15.85 +  done
   15.86  
   15.87 -declare gcd.simps [simp del];
   15.88 +declare gcd.simps [simp del]
   15.89  
   15.90 -lemma gcd_1 [simp]: "gcd(m,1) = 1"
   15.91 +lemma gcd_1 [simp]: "gcd (m, 1) = 1"
   15.92    apply (simp add: gcd_non_0)
   15.93    done
   15.94  
   15.95 -(*gcd(m,n) divides m and n.  The conjunctions don't seem provable separately*)
   15.96 -lemma gcd_dvd_both: "gcd(m,n) dvd m & gcd(m,n) dvd n"
   15.97 -  apply (induct_tac m n rule: gcd_induct)
   15.98 -  apply (simp_all add: gcd_non_0)
   15.99 +text {*
  15.100 +  \medskip @{term "gcd (m, n)"} divides @{text m} and @{text n}.  The
  15.101 +  conjunctions don't seem provable separately.
  15.102 +*}
  15.103 +
  15.104 +lemma gcd_dvd_both: "gcd (m, n) dvd m \<and> gcd (m, n) dvd n"
  15.105 +  apply (induct m n rule: gcd_induct)
  15.106 +   apply (simp_all add: gcd_non_0)
  15.107    apply (blast dest: dvd_mod_imp_dvd)
  15.108    done
  15.109  
  15.110 -lemmas gcd_dvd1 [iff] = gcd_dvd_both [THEN conjunct1]
  15.111 -lemmas gcd_dvd2 [iff] = gcd_dvd_both [THEN conjunct2];
  15.112 +lemmas gcd_dvd1 [iff] = gcd_dvd_both [THEN conjunct1, standard]
  15.113 +lemmas gcd_dvd2 [iff] = gcd_dvd_both [THEN conjunct2, standard]
  15.114  
  15.115  
  15.116 -(*Maximality: for all m,n,k naturals, 
  15.117 -                if k divides m and k divides n then k divides gcd(m,n)*)
  15.118 -lemma gcd_greatest [rule_format]: "k dvd m --> k dvd n --> k dvd gcd(m,n)"
  15.119 -  apply (induct_tac m n rule: gcd_induct)
  15.120 -  apply (simp_all add: gcd_non_0 dvd_mod);
  15.121 -  done;
  15.122 +text {*
  15.123 +  \medskip Maximality: for all @{term m}, @{term n}, @{term k}
  15.124 +  naturals, if @{term k} divides @{term m} and @{term k} divides
  15.125 +  @{term n} then @{term k} divides @{term "gcd (m, n)"}.
  15.126 +*}
  15.127 +
  15.128 +lemma gcd_greatest: "k dvd m ==> k dvd n ==> k dvd gcd (m, n)"
  15.129 +  apply (induct m n rule: gcd_induct)
  15.130 +   apply (simp_all add: gcd_non_0 dvd_mod)
  15.131 +  done
  15.132  
  15.133 -lemma gcd_greatest_iff [iff]: "(k dvd gcd(m,n)) = (k dvd m & k dvd n)"
  15.134 -  apply (blast intro!: gcd_greatest intro: dvd_trans);
  15.135 -  done;
  15.136 +lemma gcd_greatest_iff [iff]: "(k dvd gcd (m, n)) = (k dvd m \<and> k dvd n)"
  15.137 +  apply (blast intro!: gcd_greatest intro: dvd_trans)
  15.138 +  done
  15.139 +
  15.140  
  15.141 -(*Function gcd yields the Greatest Common Divisor*)
  15.142 -lemma is_gcd: "is_gcd (gcd(m,n)) m n"
  15.143 +text {*
  15.144 +  \medskip Function gcd yields the Greatest Common Divisor.
  15.145 +*}
  15.146 +
  15.147 +lemma is_gcd: "is_gcd (gcd (m, n)) m n"
  15.148    apply (simp add: is_gcd_def gcd_greatest)
  15.149    done
  15.150  
  15.151 -(*uniqueness of GCDs*)
  15.152 -lemma is_gcd_unique: "[| is_gcd m a b; is_gcd n a b |] ==> m=n"
  15.153 -  apply (simp add: is_gcd_def);
  15.154 +text {*
  15.155 +  \medskip Uniqueness of GCDs.
  15.156 +*}
  15.157 +
  15.158 +lemma is_gcd_unique: "is_gcd m a b ==> is_gcd n a b ==> m = n"
  15.159 +  apply (simp add: is_gcd_def)
  15.160    apply (blast intro: dvd_anti_sym)
  15.161    done
  15.162  
  15.163 -lemma is_gcd_dvd: "[| is_gcd m a b; k dvd a; k dvd b |] ==> k dvd m"
  15.164 -  apply (auto simp add: is_gcd_def);
  15.165 +lemma is_gcd_dvd: "is_gcd m a b ==> k dvd a ==> k dvd b ==> k dvd m"
  15.166 +  apply (auto simp add: is_gcd_def)
  15.167    done
  15.168  
  15.169 -(** Commutativity **)
  15.170 +
  15.171 +text {*
  15.172 +  \medskip Commutativity
  15.173 +*}
  15.174  
  15.175  lemma is_gcd_commute: "is_gcd k m n = is_gcd k n m"
  15.176 -  apply (auto simp add: is_gcd_def);
  15.177 +  apply (auto simp add: is_gcd_def)
  15.178    done
  15.179  
  15.180 -lemma gcd_commute: "gcd(m,n) = gcd(n,m)"
  15.181 +lemma gcd_commute: "gcd (m, n) = gcd (n, m)"
  15.182    apply (rule is_gcd_unique)
  15.183 -  apply (rule is_gcd)
  15.184 +   apply (rule is_gcd)
  15.185    apply (subst is_gcd_commute)
  15.186    apply (simp add: is_gcd)
  15.187    done
  15.188  
  15.189 -lemma gcd_assoc: "gcd(gcd(k,m),n) = gcd(k,gcd(m,n))"
  15.190 +lemma gcd_assoc: "gcd (gcd (k, m), n) = gcd (k, gcd (m, n))"
  15.191    apply (rule is_gcd_unique)
  15.192 -  apply (rule is_gcd)
  15.193 -  apply (simp add: is_gcd_def);
  15.194 -  apply (blast intro: dvd_trans);
  15.195 -  done 
  15.196 +   apply (rule is_gcd)
  15.197 +  apply (simp add: is_gcd_def)
  15.198 +  apply (blast intro: dvd_trans)
  15.199 +  done
  15.200  
  15.201 -lemma gcd_0_left [simp]: "gcd(0,m) = m"
  15.202 +lemma gcd_0_left [simp]: "gcd (0, m) = m"
  15.203    apply (simp add: gcd_commute [of 0])
  15.204    done
  15.205  
  15.206 -lemma gcd_1_left [simp]: "gcd(1,m) = 1"
  15.207 +lemma gcd_1_left [simp]: "gcd (1, m) = 1"
  15.208    apply (simp add: gcd_commute [of 1])
  15.209    done
  15.210  
  15.211  
  15.212 -(** Multiplication laws **)
  15.213 +text {*
  15.214 +  \medskip Multiplication laws
  15.215 +*}
  15.216  
  15.217 -(*Davenport, page 27*)
  15.218 -lemma gcd_mult_distrib2: "k * gcd(m,n) = gcd(k*m, k*n)"
  15.219 -  apply (induct_tac m n rule: gcd_induct)
  15.220 -  apply (simp)
  15.221 -  apply (case_tac "k=0")
  15.222 -  apply (simp_all add: mod_geq gcd_non_0 mod_mult_distrib2)
  15.223 +lemma gcd_mult_distrib2: "k * gcd (m, n) = gcd (k * m, k * n)"
  15.224 +    -- {* Davenport, page 27 *}
  15.225 +  apply (induct m n rule: gcd_induct)
  15.226 +   apply simp
  15.227 +  apply (case_tac "k = 0")
  15.228 +   apply (simp_all add: mod_geq gcd_non_0 mod_mult_distrib2)
  15.229    done
  15.230  
  15.231 -lemma gcd_mult [simp]: "gcd(k, k*n) = k"
  15.232 -  apply (rule gcd_mult_distrib2 [of k 1 n, simplified, THEN sym])
  15.233 +lemma gcd_mult [simp]: "gcd (k, k * n) = k"
  15.234 +  apply (rule gcd_mult_distrib2 [of k 1 n, simplified, symmetric])
  15.235    done
  15.236  
  15.237 -lemma gcd_self [simp]: "gcd(k,k) = k"
  15.238 +lemma gcd_self [simp]: "gcd (k, k) = k"
  15.239    apply (rule gcd_mult [of k 1, simplified])
  15.240    done
  15.241  
  15.242 -lemma relprime_dvd_mult: "[| gcd(k,n)=1; k dvd m*n |] ==> k dvd m";
  15.243 +lemma relprime_dvd_mult: "gcd (k, n) = 1 ==> k dvd m * n ==> k dvd m"
  15.244    apply (insert gcd_mult_distrib2 [of m k n])
  15.245 -  apply (simp)
  15.246 -  apply (erule_tac t="m" in ssubst);
  15.247 -  apply (simp)
  15.248 +  apply simp
  15.249 +  apply (erule_tac t = m in ssubst)
  15.250 +  apply simp
  15.251    done
  15.252  
  15.253 -lemma relprime_dvd_mult_iff: "gcd(k,n)=1 ==> (k dvd m*n) = (k dvd m)";
  15.254 +lemma relprime_dvd_mult_iff: "gcd (k, n) = 1 ==> (k dvd m * n) = (k dvd m)"
  15.255    apply (blast intro: relprime_dvd_mult dvd_trans)
  15.256    done
  15.257  
  15.258 -lemma prime_imp_relprime: "[| p: prime;  ~ p dvd n |] ==> gcd (p, n) = 1"
  15.259 +lemma prime_imp_relprime: "p \<in> prime ==> \<not> p dvd n ==> gcd (p, n) = 1"
  15.260    apply (auto simp add: prime_def)
  15.261 -  apply (drule_tac x="gcd(p,n)" in spec)
  15.262 +  apply (drule_tac x = "gcd (p, n)" in spec)
  15.263    apply auto
  15.264    apply (insert gcd_dvd2 [of p n])
  15.265 -  apply (simp)
  15.266 +  apply simp
  15.267    done
  15.268  
  15.269 -(*This theorem leads immediately to a proof of the uniqueness of factorization.
  15.270 -  If p divides a product of primes then it is one of those primes.*)
  15.271 -lemma prime_dvd_mult: "[| p: prime; p dvd m*n |] ==> p dvd m | p dvd n"
  15.272 +text {*
  15.273 +  This theorem leads immediately to a proof of the uniqueness of
  15.274 +  factorization.  If @{term p} divides a product of primes then it is
  15.275 +  one of those primes.
  15.276 +*}
  15.277 +
  15.278 +lemma prime_dvd_mult: "p \<in> prime ==> p dvd m * n ==> p dvd m \<or> p dvd n"
  15.279    apply (blast intro: relprime_dvd_mult prime_imp_relprime)
  15.280    done
  15.281  
  15.282  
  15.283 -(** Addition laws **)
  15.284 +text {* \medskip Addition laws *}
  15.285  
  15.286 -lemma gcd_add1 [simp]: "gcd(m+n, n) = gcd(m,n)"
  15.287 -  apply (case_tac "n=0")
  15.288 -  apply (simp_all add: gcd_non_0)
  15.289 +lemma gcd_add1 [simp]: "gcd (m + n, n) = gcd (m, n)"
  15.290 +  apply (case_tac "n = 0")
  15.291 +   apply (simp_all add: gcd_non_0)
  15.292    done
  15.293  
  15.294 -lemma gcd_add2 [simp]: "gcd(m, m+n) = gcd(m,n)"
  15.295 +lemma gcd_add2 [simp]: "gcd (m, m + n) = gcd (m, n)"
  15.296    apply (rule gcd_commute [THEN trans])
  15.297    apply (subst add_commute)
  15.298    apply (simp add: gcd_add1)
  15.299    apply (rule gcd_commute)
  15.300    done
  15.301  
  15.302 -lemma gcd_add2' [simp]: "gcd(m, n+m) = gcd(m,n)"
  15.303 +lemma gcd_add2' [simp]: "gcd (m, n + m) = gcd (m, n)"
  15.304    apply (subst add_commute)
  15.305    apply (rule gcd_add2)
  15.306    done
  15.307  
  15.308 -lemma gcd_add_mult: "gcd(m, k*m+n) = gcd(m,n)"
  15.309 -  apply (induct_tac "k")
  15.310 -  apply (simp_all add: gcd_add2 add_assoc)
  15.311 +lemma gcd_add_mult: "gcd (m, k * m + n) = gcd (m, n)"
  15.312 +  apply (induct k)
  15.313 +   apply (simp_all add: gcd_add2 add_assoc)
  15.314    done
  15.315  
  15.316  
  15.317 -(** More multiplication laws **)
  15.318 +text {* \medskip More multiplication laws *}
  15.319  
  15.320 -lemma gcd_mult_cancel: "gcd(k,n) = 1 ==> gcd(k*m, n) = gcd(m,n)"
  15.321 +lemma gcd_mult_cancel: "gcd (k, n) = 1 ==> gcd (k * m, n) = gcd (m, n)"
  15.322    apply (rule dvd_anti_sym)
  15.323     apply (rule gcd_greatest)
  15.324 -    apply (rule_tac n="k" in relprime_dvd_mult)
  15.325 +    apply (rule_tac n = k in relprime_dvd_mult)
  15.326       apply (simp add: gcd_assoc)
  15.327       apply (simp add: gcd_commute)
  15.328      apply (simp_all add: mult_commute gcd_dvd1 gcd_dvd2)
  15.329 -  apply (blast intro: gcd_dvd1 dvd_trans);
  15.330 +  apply (blast intro: gcd_dvd1 dvd_trans)
  15.331    done
  15.332  
  15.333  end
    16.1 --- a/src/HOL/NumberTheory/README	Sat Feb 03 17:43:34 2001 +0100
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,30 +0,0 @@
    16.4 -IntPrimes	dvd relation, GCD, Euclid's extended algorithm, primes,
    16.5 -                congruences (all on the Integers)
    16.6 -                Comparable to 'Primes' theory but dvd is included here
    16.7 -                as it is not present in 'IntDiv'.  Also includes extended
    16.8 -                GCD and congruences not present in 'Primes'. 
    16.9 -
   16.10 -Chinese		The Chinese Remainder Theorem for an arbitrary finite
   16.11 -                number of equations.  (The one-equation case is included
   16.12 -                in 'IntPrimes')  Uses functions for indexing. 
   16.13 -
   16.14 -IntFact         Factorial on integers and recursively defined set
   16.15 -                including all Integers from 2 up to a.  Plus definition 
   16.16 -		of product of finite set. 
   16.17 -
   16.18 -BijectionRel    Inductive definitions of bijections between two different
   16.19 -                sets and between the same set.  Theorem for relating
   16.20 -                the two definitions
   16.21 -
   16.22 -EulerFermat     Fermat's Little Theorem extended to Euler's Totient function. 
   16.23 -                More abstract approach than Boyer-Moore (which seems necessary
   16.24 -                to achieve the extended version)
   16.25 -
   16.26 -WilsonRuss      Wilson's Theorem following quite closely Russinoff's approach
   16.27 -		using Boyer-Moore (using finite sets instead of lists, though)
   16.28 -
   16.29 -WilsonBij	Wilson's Theorem using a more "abstract" approach based on
   16.30 -		bijections between sets.  Does not use Fermat's Little Theorem
   16.31 -                (unlike Russinoff)
   16.32 - 
   16.33 -  
   16.34 \ No newline at end of file
    17.1 --- a/src/HOL/NumberTheory/ROOT.ML	Sat Feb 03 17:43:34 2001 +0100
    17.2 +++ b/src/HOL/NumberTheory/ROOT.ML	Sun Feb 04 19:31:13 2001 +0100
    17.3 @@ -1,15 +1,10 @@
    17.4 -(*  Title:      HOL/NumberTheory/ROOT
    17.5 -    ID:         $Id$
    17.6 -    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
    17.7 -    Copyright   2000  University of Cambridge
    17.8  
    17.9 -Number theory developments by Thomas M Rasmussen
   17.10 -*)
   17.11 +no_document use_thy "Permutation";
   17.12  
   17.13 -time_use_thy "Primes";
   17.14 -time_use_thy "Fib";
   17.15 -with_path "../Induct" time_use_thy "Factorization";
   17.16 -time_use_thy "Chinese";
   17.17 -time_use_thy "EulerFermat";
   17.18 -time_use_thy "WilsonRuss";
   17.19 -time_use_thy "WilsonBij";
   17.20 +use_thy "Primes";
   17.21 +use_thy "Fib";
   17.22 +use_thy "Factorization";
   17.23 +use_thy "Chinese";
   17.24 +use_thy "EulerFermat";
   17.25 +use_thy "WilsonRuss";
   17.26 +use_thy "WilsonBij";
    18.1 --- a/src/HOL/NumberTheory/WilsonBij.ML	Sat Feb 03 17:43:34 2001 +0100
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,223 +0,0 @@
    18.4 -(*  Title:	WilsonBij.ML
    18.5 -    ID:         $Id$
    18.6 -    Author:	Thomas M. Rasmussen
    18.7 -    Copyright	2000  University of Cambridge
    18.8 -
    18.9 -Wilson's Theorem using a more "abstract" approach based on
   18.10 -bijections between sets.  Does not use Fermat's Little Theorem
   18.11 -(unlike Russinoff)
   18.12 - *)
   18.13 -
   18.14 -
   18.15 -(************  Inverse  **************)
   18.16 -
   18.17 -Goalw [inv_def] 
   18.18 -      "[| p:zprime; #0<a; a<p |] \ 
   18.19 -\     ==> #0 <= (inv p a) & (inv p a)<p & [a*(inv p a) = #1](mod p)";
   18.20 -by (Asm_simp_tac 1);
   18.21 -by (rtac (zcong_lineq_unique RS ex1_implies_ex RS someI_ex) 1);
   18.22 -by (etac zless_zprime_imp_zrelprime 2);
   18.23 -by (rewtac zprime_def);
   18.24 -by Auto_tac;
   18.25 -qed "inv_correct";
   18.26 -
   18.27 -bind_thm ("inv_ge",inv_correct RS conjunct1);
   18.28 -bind_thm ("inv_less",(inv_correct RS conjunct2) RS conjunct1);
   18.29 -bind_thm ("inv_is_inv",(inv_correct RS conjunct2) RS conjunct2);
   18.30 -
   18.31 -(* Same as WilsonRuss *)
   18.32 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= #0";
   18.33 -by Safe_tac;
   18.34 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   18.35 -by (rewtac zcong_def);
   18.36 -by Auto_tac;
   18.37 -by (subgoal_tac "~p dvd #1" 1);
   18.38 -by (rtac zdvd_not_zless 2);
   18.39 -by (subgoal_tac "p dvd #1" 1);
   18.40 -by (stac (zdvd_zminus_iff RS sym) 2);
   18.41 -by Auto_tac;
   18.42 -qed "inv_not_0";
   18.43 -
   18.44 -(* Same as WilsonRuss *)
   18.45 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= #1";
   18.46 -by Safe_tac;
   18.47 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   18.48 -by (Asm_full_simp_tac 4);
   18.49 -by (subgoal_tac "a = #1" 4);
   18.50 -by (rtac zcong_zless_imp_eq 5);
   18.51 -by Auto_tac;
   18.52 -qed "inv_not_1";
   18.53 -
   18.54 -(* Same as WilsonRuss *)
   18.55 -Goalw [zcong_def] "[a*(p-#1) = #1](mod p) = [a = p-#1](mod p)"; 
   18.56 -by (simp_tac (simpset() addsimps [zdiff_zdiff_eq,zdiff_zdiff_eq2,
   18.57 -                                  zdiff_zmult_distrib2]) 1);
   18.58 -by (res_inst_tac [("s","p dvd -((a+#1)+(p*(-a)))")] trans 1);
   18.59 -by (simp_tac (simpset() addsimps [zmult_commute,zminus_zdiff_eq]) 1);
   18.60 -by (stac zdvd_zminus_iff 1);
   18.61 -by (stac zdvd_reduce 1);
   18.62 -by (res_inst_tac [("s","p dvd (a+#1)+(p*(-#1))")] trans 1);
   18.63 -by (stac zdvd_reduce 1);
   18.64 -by Auto_tac;
   18.65 -val lemma = result();
   18.66 -
   18.67 -(* Same as WilsonRuss *)
   18.68 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= p-#1";
   18.69 -by Safe_tac;
   18.70 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   18.71 -by Auto_tac;
   18.72 -by (asm_full_simp_tac (simpset() addsimps [lemma]) 1);
   18.73 -by (subgoal_tac "a = p-#1" 1);
   18.74 -by (rtac zcong_zless_imp_eq 2);
   18.75 -by Auto_tac;
   18.76 -qed "inv_not_p_minus_1";
   18.77 -
   18.78 -(* Below is slightly different as we don't expand 
   18.79 -   inv but use 'correct'-theos *)
   18.80 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> #1<(inv p a)";
   18.81 -by (subgoal_tac "(inv p a) ~= #1" 1);
   18.82 -by (subgoal_tac "(inv p a) ~= #0" 1);
   18.83 -by (stac order_less_le 1);
   18.84 -by (stac (zle_add1_eq_le RS sym) 1);
   18.85 -by (stac order_less_le 1);
   18.86 -by (rtac inv_not_0 2);
   18.87 -by (rtac inv_not_1 5);
   18.88 -by Auto_tac;
   18.89 -by (rtac inv_ge 1);
   18.90 -by Auto_tac;
   18.91 -qed "inv_g_1";
   18.92 -
   18.93 -(* ditto *)
   18.94 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a)<p-#1";
   18.95 -by (stac order_less_le 1);
   18.96 -by (asm_full_simp_tac (simpset() addsimps [inv_not_p_minus_1, inv_less]) 1); 
   18.97 -qed "inv_less_p_minus_1";
   18.98 -
   18.99 -(*************  Bijection  *******************)
  18.100 -
  18.101 -Goal "#1<x ==> #0<=(x::int)";
  18.102 -by Auto_tac;
  18.103 -val l1 = result();
  18.104 -
  18.105 -Goal "#1<x ==> #0<(x::int)";
  18.106 -by Auto_tac;
  18.107 -val l2 = result();
  18.108 -
  18.109 -Goal "x<=p-#2 ==> x<(p::int)";
  18.110 -by Auto_tac;
  18.111 -val l3 = result();
  18.112 -
  18.113 -Goal "x<=p-#2 ==> x<(p::int)-#1";
  18.114 -by Auto_tac;
  18.115 -val l4 = result();
  18.116 -
  18.117 -Goalw [inj_on_def] "p : zprime ==> inj_on (inv p) (d22set (p-#2))";
  18.118 -by Auto_tac;
  18.119 -by (rtac zcong_zless_imp_eq 1);
  18.120 -by (stac (zcong_cancel RS sym) 5);
  18.121 -by (rtac zcong_trans 7);
  18.122 -by (stac zcong_sym 8);
  18.123 -by (etac inv_is_inv 7);
  18.124 -by (Asm_simp_tac 9);
  18.125 -by (etac inv_is_inv 9);
  18.126 -by (rtac zless_zprime_imp_zrelprime 6);
  18.127 -by (rtac inv_less 8);
  18.128 -by (rtac (inv_g_1 RS l2) 7);
  18.129 -by (rewtac zprime_def);
  18.130 -by (auto_tac (claset() addIs [d22set_g_1,d22set_le,l1,l2,l3,l4],simpset()));
  18.131 -qed "inv_inj";
  18.132 -
  18.133 -Goal "p : zprime ==> (inv p)`(d22set (p-#2)) = (d22set (p-#2))";
  18.134 -by (rtac endo_inj_surj 1);
  18.135 -by (rtac d22set_fin 1);
  18.136 -by (etac inv_inj 2);
  18.137 -by Auto_tac;
  18.138 -by (rtac d22set_mem 1);
  18.139 -by (etac inv_g_1 1);
  18.140 -by (subgoal_tac "inv p xa < p - #1" 3);
  18.141 -by (etac inv_less_p_minus_1 4);
  18.142 -by (auto_tac (claset() addIs [d22set_g_1,d22set_le,l4],simpset()));
  18.143 -qed "inv_d22set_d22set";
  18.144 -
  18.145 -Goalw [reciR_def] "p:zprime \
  18.146 -\    ==> (d22set(p-#2),d22set(p-#2)) : (bijR (reciR p))";
  18.147 -by (res_inst_tac [("s","(d22set(p-#2),(inv p)`(d22set(p-#2)))")] subst 1);
  18.148 -by (asm_simp_tac (simpset() addsimps [inv_d22set_d22set]) 1);
  18.149 -by (rtac inj_func_bijR 1);
  18.150 -by (rtac d22set_fin 3);
  18.151 -by (etac inv_inj 2);
  18.152 -by Auto_tac;
  18.153 -by (etac inv_is_inv 1);
  18.154 -by (etac inv_g_1 5);
  18.155 -by (etac inv_less_p_minus_1 7);
  18.156 -by (auto_tac (claset() addIs [d22set_g_1,d22set_le,l2,l3,l4],simpset()));
  18.157 -qed "d22set_d22set_bij";
  18.158 -
  18.159 -Goalw [reciR_def,bijP_def] 
  18.160 -      "p:zprime ==>  bijP (reciR p) (d22set(p-#2))";
  18.161 -by Auto_tac;
  18.162 -by (rtac d22set_mem 1);
  18.163 -by Auto_tac;
  18.164 -qed "reciP_bijP";
  18.165 -
  18.166 -Goalw [reciR_def,uniqP_def] 
  18.167 -      "p:zprime ==> uniqP (reciR p)";
  18.168 -by Auto_tac;
  18.169 -by (rtac zcong_zless_imp_eq 1);
  18.170 -by (stac (zcong_cancel2 RS sym) 5);
  18.171 -by (rtac zcong_trans 7);
  18.172 -by (stac zcong_sym 8);
  18.173 -by (rtac zless_zprime_imp_zrelprime 6);
  18.174 -by Auto_tac;
  18.175 -by (rtac zcong_zless_imp_eq 1);
  18.176 -by (stac (zcong_cancel RS sym) 5);
  18.177 -by (rtac zcong_trans 7);
  18.178 -by (stac zcong_sym 8);
  18.179 -by (rtac zless_zprime_imp_zrelprime 6);
  18.180 -by Auto_tac;
  18.181 -qed "reciP_uniq";
  18.182 -
  18.183 -Goalw [reciR_def,symP_def] 
  18.184 -      "p:zprime ==> symP (reciR p)";
  18.185 -by (simp_tac (simpset() addsimps [zmult_commute]) 1);
  18.186 -by Auto_tac;
  18.187 -qed "reciP_sym";
  18.188 -
  18.189 -Goal "p:zprime ==> d22set(p-#2) : (bijER (reciR p))";
  18.190 -by (rtac bijR_bijER 1);
  18.191 -by (etac d22set_d22set_bij 1);
  18.192 -by (etac reciP_bijP 1);
  18.193 -by (etac reciP_uniq 1);
  18.194 -by (etac reciP_sym 1);
  18.195 -qed "bijER_d22set";
  18.196 -
  18.197 -(***********  Wilson  **************)
  18.198 -
  18.199 -Goalw [reciR_def] 
  18.200 -      "[| p:zprime; A : bijER (reciR p) |] ==> [setprod A = #1](mod p)";
  18.201 -by (etac bijER.induct 1);
  18.202 -by (subgoal_tac "a=#1 | a=p-#1" 2);
  18.203 -by (rtac zcong_square_zless 3);
  18.204 -by Auto_tac;
  18.205 -by (stac setprod_insert 1);
  18.206 -by (stac setprod_insert 3);
  18.207 -by (auto_tac (claset(),simpset() addsimps [fin_bijER]));
  18.208 -by (subgoal_tac "zcong ((a * b) * setprod A) (#1*#1) p" 1);
  18.209 -by (asm_full_simp_tac (simpset() addsimps [zmult_assoc]) 1);
  18.210 -by (rtac zcong_zmult 1); 
  18.211 -by Auto_tac;
  18.212 -qed "bijER_zcong_prod_1";
  18.213 -
  18.214 -Goal "p:zprime ==> [zfact(p-#1) = #-1](mod p)";
  18.215 -by (subgoal_tac "zcong ((p-#1)*zfact(p-#2)) (#-1*#1) p" 1);
  18.216 -by (rtac zcong_zmult 2);
  18.217 -by (full_simp_tac (simpset() addsimps [zprime_def]) 1); 
  18.218 -by (stac zfact_eq 1);
  18.219 -by (res_inst_tac [("t","p-#1-#1"),("s","p-#2")] subst 1);
  18.220 -by Auto_tac;
  18.221 -by (asm_simp_tac (simpset() addsimps [zcong_def]) 1); 
  18.222 -by (stac (d22set_prod_zfact RS sym) 1);
  18.223 -by (rtac bijER_zcong_prod_1 1);
  18.224 -by (rtac bijER_d22set 2);
  18.225 -by Auto_tac;
  18.226 -qed "WilsonBij";
    19.1 --- a/src/HOL/NumberTheory/WilsonBij.thy	Sat Feb 03 17:43:34 2001 +0100
    19.2 +++ b/src/HOL/NumberTheory/WilsonBij.thy	Sun Feb 04 19:31:13 2001 +0100
    19.3 @@ -1,20 +1,262 @@
    19.4 -(*  Title:	WilsonBij.thy
    19.5 +(*  Title:      HOL/NumberTheory/WilsonBij.thy
    19.6      ID:         $Id$
    19.7 -    Author:	Thomas M. Rasmussen
    19.8 -    Copyright	2000  University of Cambridge
    19.9 +    Author:     Thomas M. Rasmussen
   19.10 +    Copyright   2000  University of Cambridge
   19.11  *)
   19.12  
   19.13 -WilsonBij = BijectionRel + IntFact +
   19.14 +header {* Wilson's Theorem using a more abstract approach *}
   19.15 +
   19.16 +theory WilsonBij = BijectionRel + IntFact:
   19.17 +
   19.18 +text {*
   19.19 +  Wilson's Theorem using a more ``abstract'' approach based on
   19.20 +  bijections between sets.  Does not use Fermat's Little Theorem
   19.21 +  (unlike Russinoff).
   19.22 +*}
   19.23 +
   19.24 +
   19.25 +subsection {* Definitions and lemmas *}
   19.26 +
   19.27 +constdefs
   19.28 +  reciR :: "int => int => int => bool"
   19.29 +  "reciR p ==
   19.30 +    \<lambda>a b. zcong (a * b) #1 p \<and> #1 < a \<and> a < p - #1 \<and> #1 < b \<and> b < p - #1"
   19.31 +  inv :: "int => int => int"
   19.32 +  "inv p a ==
   19.33 +    if p \<in> zprime \<and> #0 < a \<and> a < p then
   19.34 +      (SOME x. #0 \<le> x \<and> x < p \<and> zcong (a * x) #1 p)
   19.35 +    else #0"
   19.36 +
   19.37 +
   19.38 +text {* \medskip Inverse *}
   19.39 +
   19.40 +lemma inv_correct:
   19.41 +  "p \<in> zprime ==> #0 < a ==> a < p
   19.42 +    ==> #0 \<le> inv p a \<and> inv p a < p \<and> [a * inv p a = #1] (mod p)"
   19.43 +  apply (unfold inv_def)
   19.44 +  apply (simp (no_asm_simp))
   19.45 +  apply (rule zcong_lineq_unique [THEN ex1_implies_ex, THEN someI_ex])
   19.46 +   apply (erule_tac [2] zless_zprime_imp_zrelprime)
   19.47 +    apply (unfold zprime_def)
   19.48 +    apply auto
   19.49 +  done
   19.50 +
   19.51 +lemmas inv_ge = inv_correct [THEN conjunct1, standard]
   19.52 +lemmas inv_less = inv_correct [THEN conjunct2, THEN conjunct1, standard]
   19.53 +lemmas inv_is_inv = inv_correct [THEN conjunct2, THEN conjunct2, standard]
   19.54 +
   19.55 +lemma inv_not_0:
   19.56 +  "p \<in> zprime ==> #1 < a ==> a < p - #1 ==> inv p a \<noteq> #0"
   19.57 +  -- {* same as @{text WilsonRuss} *}
   19.58 +  apply safe
   19.59 +  apply (cut_tac a = a and p = p in inv_is_inv)
   19.60 +     apply (unfold zcong_def)
   19.61 +     apply auto
   19.62 +  apply (subgoal_tac "\<not> p dvd #1")
   19.63 +   apply (rule_tac [2] zdvd_not_zless)
   19.64 +    apply (subgoal_tac "p dvd #1")
   19.65 +     prefer 2
   19.66 +     apply (subst zdvd_zminus_iff [symmetric])
   19.67 +     apply auto
   19.68 +  done
   19.69  
   19.70 -consts
   19.71 -  reciR  :: "int => [int,int] => bool"
   19.72 -  inv    :: "[int,int] => int"
   19.73 +lemma inv_not_1:
   19.74 +  "p \<in> zprime ==> #1 < a ==> a < p - #1 ==> inv p a \<noteq> #1"
   19.75 +  -- {* same as @{text WilsonRuss} *}
   19.76 +  apply safe
   19.77 +  apply (cut_tac a = a and p = p in inv_is_inv)
   19.78 +     prefer 4
   19.79 +     apply simp
   19.80 +     apply (subgoal_tac "a = #1")
   19.81 +      apply (rule_tac [2] zcong_zless_imp_eq)
   19.82 +          apply auto
   19.83 +  done
   19.84 +
   19.85 +lemma aux: "[a * (p - #1) = #1] (mod p) = [a = p - #1] (mod p)"
   19.86 +  -- {* same as @{text WilsonRuss} *}
   19.87 +  apply (unfold zcong_def)
   19.88 +  apply (simp add: zdiff_zdiff_eq zdiff_zdiff_eq2 zdiff_zmult_distrib2)
   19.89 +  apply (rule_tac s = "p dvd -((a + #1) + (p * -a))" in trans)
   19.90 +   apply (simp add: zmult_commute zminus_zdiff_eq)
   19.91 +  apply (subst zdvd_zminus_iff)
   19.92 +  apply (subst zdvd_reduce)
   19.93 +  apply (rule_tac s = "p dvd (a + #1) + (p * -#1)" in trans)
   19.94 +   apply (subst zdvd_reduce)
   19.95 +   apply auto
   19.96 +  done
   19.97 +
   19.98 +lemma inv_not_p_minus_1:
   19.99 +  "p \<in> zprime ==> #1 < a ==> a < p - #1 ==> inv p a \<noteq> p - #1"
  19.100 +  -- {* same as @{text WilsonRuss} *}
  19.101 +  apply safe
  19.102 +  apply (cut_tac a = a and p = p in inv_is_inv)
  19.103 +     apply auto
  19.104 +  apply (simp add: aux)
  19.105 +  apply (subgoal_tac "a = p - #1")
  19.106 +   apply (rule_tac [2] zcong_zless_imp_eq)
  19.107 +       apply auto
  19.108 +  done
  19.109 +
  19.110 +text {*
  19.111 +  Below is slightly different as we don't expand @{term [source] inv}
  19.112 +  but use ``@{text correct}'' theorems.
  19.113 +*}
  19.114 +
  19.115 +lemma inv_g_1: "p \<in> zprime ==> #1 < a ==> a < p - #1 ==> #1 < inv p a"
  19.116 +  apply (subgoal_tac "inv p a \<noteq> #1")
  19.117 +   apply (subgoal_tac "inv p a \<noteq> #0")
  19.118 +    apply (subst order_less_le)
  19.119 +    apply (subst zle_add1_eq_le [symmetric])
  19.120 +    apply (subst order_less_le)
  19.121 +    apply (rule_tac [2] inv_not_0)
  19.122 +      apply (rule_tac [5] inv_not_1)
  19.123 +        apply auto
  19.124 +  apply (rule inv_ge)
  19.125 +    apply auto
  19.126 +  done
  19.127 +
  19.128 +lemma inv_less_p_minus_1:
  19.129 +  "p \<in> zprime ==> #1 < a ==> a < p - #1 ==> inv p a < p - #1"
  19.130 +  -- {* ditto *}
  19.131 +  apply (subst order_less_le)
  19.132 +  apply (simp add: inv_not_p_minus_1 inv_less)
  19.133 +  done
  19.134 +
  19.135 +
  19.136 +text {* \medskip Bijection *}
  19.137 +
  19.138 +lemma aux1: "#1 < x ==> #0 \<le> (x::int)"
  19.139 +  apply auto
  19.140 +  done
  19.141  
  19.142 -defs
  19.143 -  reciR_def "reciR p == (%a b. zcong (a*b) #1 p & 
  19.144 -                               #1<a & a<p-#1 & #1<b & b<p-#1)"
  19.145 -  inv_def   "inv p a == (if p:zprime & #0<a & a<p then
  19.146 -                           (@x. #0<=x & x<p & zcong (a*x) #1 p)
  19.147 -                         else #0)"
  19.148 +lemma aux2: "#1 < x ==> #0 < (x::int)"
  19.149 +  apply auto
  19.150 +  done
  19.151 +
  19.152 +lemma aux3: "x \<le> p - #2 ==> x < (p::int)"
  19.153 +  apply auto
  19.154 +  done
  19.155 +
  19.156 +lemma aux4: "x \<le> p - #2 ==> x < (p::int)-#1"
  19.157 +  apply auto
  19.158 +  done
  19.159 +
  19.160 +lemma inv_inj: "p \<in> zprime ==> inj_on (inv p) (d22set (p - #2))"
  19.161 +  apply (unfold inj_on_def)
  19.162 +  apply auto
  19.163 +  apply (rule zcong_zless_imp_eq)
  19.164 +      apply (tactic {* stac (thm "zcong_cancel" RS sym) 5 *})
  19.165 +        apply (rule_tac [7] zcong_trans)
  19.166 +         apply (tactic {* stac (thm "zcong_sym") 8 *})
  19.167 +         apply (erule_tac [7] inv_is_inv)
  19.168 +          apply (tactic "Asm_simp_tac 9")
  19.169 +          apply (erule_tac [9] inv_is_inv)
  19.170 +           apply (rule_tac [6] zless_zprime_imp_zrelprime)
  19.171 +             apply (rule_tac [8] inv_less)
  19.172 +               apply (rule_tac [7] inv_g_1 [THEN aux2])
  19.173 +                 apply (unfold zprime_def)
  19.174 +                 apply (auto intro: d22set_g_1 d22set_le
  19.175 +		   aux1 aux2 aux3 aux4)
  19.176 +  done
  19.177 +
  19.178 +lemma inv_d22set_d22set:
  19.179 +    "p \<in> zprime ==> inv p ` d22set (p - #2) = d22set (p - #2)"
  19.180 +  apply (rule endo_inj_surj)
  19.181 +    apply (rule d22set_fin)
  19.182 +   apply (erule_tac [2] inv_inj)
  19.183 +  apply auto
  19.184 +  apply (rule d22set_mem)
  19.185 +   apply (erule inv_g_1)
  19.186 +    apply (subgoal_tac [3] "inv p xa < p - #1")
  19.187 +     apply (erule_tac [4] inv_less_p_minus_1)
  19.188 +      apply (auto intro: d22set_g_1 d22set_le aux4)
  19.189 +  done
  19.190 +
  19.191 +lemma d22set_d22set_bij:
  19.192 +    "p \<in> zprime ==> (d22set (p - #2), d22set (p - #2)) \<in> bijR (reciR p)"
  19.193 +  apply (unfold reciR_def)
  19.194 +  apply (rule_tac s = "(d22set (p - #2), inv p ` d22set (p - #2))" in subst)
  19.195 +   apply (simp add: inv_d22set_d22set)
  19.196 +  apply (rule inj_func_bijR)
  19.197 +    apply (rule_tac [3] d22set_fin)
  19.198 +   apply (erule_tac [2] inv_inj)
  19.199 +  apply auto
  19.200 +      apply (erule inv_is_inv)
  19.201 +       apply (erule_tac [5] inv_g_1)
  19.202 +        apply (erule_tac [7] inv_less_p_minus_1)
  19.203 +         apply (auto intro: d22set_g_1 d22set_le aux2 aux3 aux4)
  19.204 +  done
  19.205 +
  19.206 +lemma reciP_bijP: "p \<in> zprime ==> bijP (reciR p) (d22set (p - #2))"
  19.207 +  apply (unfold reciR_def bijP_def)
  19.208 +  apply auto
  19.209 +  apply (rule d22set_mem)
  19.210 +   apply auto
  19.211 +  done
  19.212 +
  19.213 +lemma reciP_uniq: "p \<in> zprime ==> uniqP (reciR p)"
  19.214 +  apply (unfold reciR_def uniqP_def)
  19.215 +  apply auto
  19.216 +   apply (rule zcong_zless_imp_eq)
  19.217 +       apply (tactic {* stac (thm "zcong_cancel2" RS sym) 5 *})
  19.218 +         apply (rule_tac [7] zcong_trans)
  19.219 +          apply (tactic {* stac (thm "zcong_sym") 8 *})
  19.220 +          apply (rule_tac [6] zless_zprime_imp_zrelprime)
  19.221 +            apply auto
  19.222 +  apply (rule zcong_zless_imp_eq)
  19.223 +      apply (tactic {* stac (thm "zcong_cancel" RS sym) 5 *})
  19.224 +        apply (rule_tac [7] zcong_trans)
  19.225 +         apply (tactic {* stac (thm "zcong_sym") 8 *})
  19.226 +         apply (rule_tac [6] zless_zprime_imp_zrelprime)
  19.227 +           apply auto
  19.228 +  done
  19.229 +
  19.230 +lemma reciP_sym: "p \<in> zprime ==> symP (reciR p)"
  19.231 +  apply (unfold reciR_def symP_def)
  19.232 +  apply (simp add: zmult_commute)
  19.233 +  apply auto
  19.234 +  done
  19.235 +
  19.236 +lemma bijER_d22set: "p \<in> zprime ==> d22set (p - #2) \<in> bijER (reciR p)"
  19.237 +  apply (rule bijR_bijER)
  19.238 +     apply (erule d22set_d22set_bij)
  19.239 +    apply (erule reciP_bijP)
  19.240 +   apply (erule reciP_uniq)
  19.241 +  apply (erule reciP_sym)
  19.242 +  done
  19.243 +
  19.244 +
  19.245 +subsection {* Wilson *}
  19.246 +
  19.247 +lemma bijER_zcong_prod_1:
  19.248 +    "p \<in> zprime ==> A \<in> bijER (reciR p) ==> [setprod A = #1] (mod p)"
  19.249 +  apply (unfold reciR_def)
  19.250 +  apply (erule bijER.induct)
  19.251 +    apply (subgoal_tac [2] "a = #1 \<or> a = p - #1")
  19.252 +     apply (rule_tac [3] zcong_square_zless)
  19.253 +        apply auto
  19.254 +  apply (subst setprod_insert)
  19.255 +    prefer 3
  19.256 +    apply (subst setprod_insert)
  19.257 +      apply (auto simp add: fin_bijER)
  19.258 +  apply (subgoal_tac "zcong ((a * b) * setprod A) (#1 * #1) p")
  19.259 +   apply (simp add: zmult_assoc)
  19.260 +  apply (rule zcong_zmult)
  19.261 +   apply auto
  19.262 +  done
  19.263 +
  19.264 +theorem Wilson_Bij: "p \<in> zprime ==> [zfact (p - #1) = #-1] (mod p)"
  19.265 +  apply (subgoal_tac "zcong ((p - #1) * zfact (p - #2)) (#-1 * #1) p")
  19.266 +   apply (rule_tac [2] zcong_zmult)
  19.267 +    apply (simp add: zprime_def)
  19.268 +    apply (subst zfact.simps)
  19.269 +    apply (rule_tac t = "p - #1 - #1" and s = "p - #2" in subst)
  19.270 +     apply auto
  19.271 +   apply (simp add: zcong_def)
  19.272 +  apply (subst d22set_prod_zfact [symmetric])
  19.273 +  apply (rule bijER_zcong_prod_1)
  19.274 +   apply (rule_tac [2] bijER_d22set)
  19.275 +   apply auto
  19.276 +  done
  19.277  
  19.278  end
    20.1 --- a/src/HOL/NumberTheory/WilsonRuss.ML	Sat Feb 03 17:43:34 2001 +0100
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,310 +0,0 @@
    20.4 -(*  Title:	WilsonRuss.ML
    20.5 -    ID:         $Id$
    20.6 -    Author:	Thomas M. Rasmussen
    20.7 -    Copyright	2000  University of Cambridge
    20.8 -*)
    20.9 -
   20.10 -
   20.11 -(************  Inverse  **************)
   20.12 -
   20.13 -Goal "#1<m ==> Suc(nat(m-#2)) = nat(m-#1)";
   20.14 -by (stac (int_int_eq RS sym) 1);
   20.15 -by Auto_tac;
   20.16 -val lemma = result();
   20.17 -
   20.18 -Goalw [inv_def]
   20.19 -      "[| p:zprime; #0<a; a<p |] ==> [a*(inv p a) = #1] (mod p)";
   20.20 -by (stac zcong_zmod 1);
   20.21 -by (stac (zmod_zmult1_eq RS sym) 1);
   20.22 -by (stac (zcong_zmod RS sym) 1);
   20.23 -by (stac (power_Suc RS sym) 1);
   20.24 -by (stac lemma 1);
   20.25 -by (etac Little_Fermat 2);
   20.26 -by (etac zdvd_not_zless 2);
   20.27 -by (rewtac zprime_def);
   20.28 -by Auto_tac;
   20.29 -qed "inv_is_inv";
   20.30 -
   20.31 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> a ~= (inv p a)";
   20.32 -by Safe_tac;
   20.33 -by (cut_inst_tac [("a","a"),("p","p")] zcong_square 1);
   20.34 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 3);
   20.35 -by Auto_tac;
   20.36 -by (subgoal_tac "a=#1" 1);
   20.37 -by (res_inst_tac [("m","p")] zcong_zless_imp_eq 2);
   20.38 -by (subgoal_tac "a=p-#1" 7);
   20.39 -by (res_inst_tac [("m","p")] zcong_zless_imp_eq 8);
   20.40 -by Auto_tac;
   20.41 -qed "inv_distinct";
   20.42 -
   20.43 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= #0";
   20.44 -by Safe_tac;
   20.45 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   20.46 -by (rewtac zcong_def);
   20.47 -by Auto_tac;
   20.48 -by (subgoal_tac "~p dvd #1" 1);
   20.49 -by (rtac zdvd_not_zless 2);
   20.50 -by (subgoal_tac "p dvd #1" 1);
   20.51 -by (stac (zdvd_zminus_iff RS sym) 2);
   20.52 -by Auto_tac;
   20.53 -qed "inv_not_0";
   20.54 -
   20.55 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= #1";
   20.56 -by Safe_tac;
   20.57 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   20.58 -by (Asm_full_simp_tac 4);
   20.59 -by (subgoal_tac "a = #1" 4);
   20.60 -by (rtac zcong_zless_imp_eq 5);
   20.61 -by Auto_tac;
   20.62 -qed "inv_not_1";
   20.63 -
   20.64 -Goalw [zcong_def] "[a*(p-#1) = #1](mod p) = [a = p-#1](mod p)"; 
   20.65 -by (simp_tac (simpset() addsimps [zdiff_zdiff_eq,zdiff_zdiff_eq2,
   20.66 -                                  zdiff_zmult_distrib2]) 1);
   20.67 -by (res_inst_tac [("s","p dvd -((a+#1)+(p*(-a)))")] trans 1);
   20.68 -by (simp_tac (simpset() addsimps [zmult_commute,zminus_zdiff_eq]) 1);
   20.69 -by (stac zdvd_zminus_iff 1);
   20.70 -by (stac zdvd_reduce 1);
   20.71 -by (res_inst_tac [("s","p dvd (a+#1)+(p*(-#1))")] trans 1);
   20.72 -by (stac zdvd_reduce 1);
   20.73 -by Auto_tac;
   20.74 -val lemma = result();
   20.75 -
   20.76 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a) ~= p-#1";
   20.77 -by Safe_tac;
   20.78 -by (cut_inst_tac [("a","a"),("p","p")] inv_is_inv 1);
   20.79 -by Auto_tac;
   20.80 -by (asm_full_simp_tac (simpset() addsimps [lemma]) 1);
   20.81 -by (subgoal_tac "a = p-#1" 1);
   20.82 -by (rtac zcong_zless_imp_eq 2);
   20.83 -by Auto_tac;
   20.84 -qed "inv_not_p_minus_1";
   20.85 -
   20.86 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> #1<(inv p a)";
   20.87 -by (case_tac "#0<=(inv p a)" 1);
   20.88 -by (subgoal_tac "(inv p a) ~= #1" 1);
   20.89 -by (subgoal_tac "(inv p a) ~= #0" 1);
   20.90 -by (stac order_less_le 1);
   20.91 -by (stac (zle_add1_eq_le RS sym) 1);
   20.92 -by (stac order_less_le 1);
   20.93 -by (rtac inv_not_0 2);
   20.94 -by (rtac inv_not_1 5);
   20.95 -by Auto_tac;
   20.96 -by (rewrite_goals_tac [inv_def,zprime_def]);
   20.97 -by (asm_full_simp_tac (simpset() addsimps [pos_mod_sign]) 1);
   20.98 -qed "inv_g_1";
   20.99 -
  20.100 -Goal "[| p:zprime; #1<a; a<p-#1 |] ==> (inv p a)<p-#1";
  20.101 -by (case_tac "(inv p a)<p" 1);
  20.102 -by (stac order_less_le 1);
  20.103 -by (asm_full_simp_tac (simpset() addsimps [inv_not_p_minus_1]) 1); 
  20.104 -by Auto_tac;
  20.105 -by (rewrite_goals_tac [inv_def,zprime_def]);
  20.106 -by (asm_full_simp_tac (simpset() addsimps [pos_mod_bound]) 1);
  20.107 -qed "inv_less_p_minus_1";
  20.108 -
  20.109 -Goal "#5<=p ==> nat(p-#2)*nat(p-#2) = Suc(nat(p-#1)*nat(p-#3))";
  20.110 -by (stac (int_int_eq RS sym) 1);
  20.111 -by (asm_simp_tac (simpset() addsimps [zmult_int RS sym]) 1);
  20.112 -by (simp_tac (simpset() addsimps [zdiff_zmult_distrib,
  20.113 -                                  zdiff_zmult_distrib2]) 1);
  20.114 -val lemma = result();
  20.115 -
  20.116 -Goal "[x^y = #1](mod p) --> [x^(y*z) = #1](mod p)";
  20.117 -by (induct_tac "z" 1);
  20.118 -by (auto_tac (claset(),simpset() addsimps [zpower_zadd_distrib]));
  20.119 -by (subgoal_tac "zcong (x^y * x^(y*n)) (#1*#1) p" 1);
  20.120 -by (rtac zcong_zmult 2);
  20.121 -by (ALLGOALS Asm_full_simp_tac);
  20.122 -qed_spec_mp "zcong_zpower_zmult";
  20.123 -
  20.124 -Goalw [inv_def] "[| p:zprime; #5<=p; #0<a; a<p |] ==> (inv p (inv p a)) = a";
  20.125 -by (stac zpower_zmod 1);
  20.126 -by (stac zpower_zpower 1);
  20.127 -by (rtac zcong_zless_imp_eq 1);
  20.128 -by (stac zcong_zmod 5); 
  20.129 -by (stac mod_mod_trivial 5);
  20.130 -by (stac (zcong_zmod RS sym) 5); 
  20.131 -by (stac lemma 5);
  20.132 -by (subgoal_tac "zcong (a * a^(nat (p - #1) * nat (p - #3))) (a*#1) p" 6);
  20.133 -by (rtac zcong_zmult 7);
  20.134 -by (rtac zcong_zpower_zmult 8);
  20.135 -by (etac Little_Fermat 8);
  20.136 -by (rtac zdvd_not_zless 8);
  20.137 -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [pos_mod_bound,
  20.138 -                                                     pos_mod_sign])));
  20.139 -qed "inv_inv";
  20.140 -
  20.141 -
  20.142 -(*************  wset  *************)
  20.143 -
  20.144 -val [wset_eq] = wset.simps;
  20.145 -Delsimps wset.simps;
  20.146 -
  20.147 -val [prem1,prem2] =
  20.148 -Goal "[| !!a p. P {} a p; \
  20.149 -\        !!a p. [| #1<(a::int); P (wset (a-#1,p)) (a-#1) p |] \
  20.150 -\               ==> P (wset (a,p)) a p|] \
  20.151 -\    ==> P (wset (u,v)) u v";
  20.152 -by (rtac wset.induct 1);
  20.153 -by Safe_tac;
  20.154 -by (case_tac "#1<a" 2);
  20.155 -by (rtac prem2 2);
  20.156 -by (ALLGOALS Asm_simp_tac);
  20.157 -by (ALLGOALS (asm_simp_tac (simpset() addsimps [wset_eq,prem1])));
  20.158 -qed "wset_induct";
  20.159 -
  20.160 -Goal "[| #1<a; b~:(wset (a-#1,p)) |] \
  20.161 -\     ==> b:(wset (a,p)) --> b=a | b = inv p a";
  20.162 -by (stac wset_eq 1);
  20.163 -by (rewtac Let_def);
  20.164 -by (Asm_simp_tac 1);
  20.165 -qed_spec_mp "wset_mem_imp_or";
  20.166 -
  20.167 -Goal "#1<a ==> a:(wset(a,p))";
  20.168 -by (stac wset_eq 1);
  20.169 -by (rewtac Let_def);
  20.170 -by (Asm_simp_tac 1);
  20.171 -qed "wset_mem_mem";
  20.172 -Addsimps [wset_mem_mem];
  20.173 -
  20.174 -Goal "[| #1<a; b:wset(a-#1,p) |] ==> b:wset(a,p)";
  20.175 -by (stac wset_eq 1);
  20.176 -by (rewtac Let_def);
  20.177 -by Auto_tac;
  20.178 -qed "wset_subset";
  20.179 -
  20.180 -Goal "p:zprime --> a<p-#1 --> b:(wset(a,p)) --> #1<b";
  20.181 -by (induct_thm_tac wset_induct "a p" 1);
  20.182 -by Auto_tac;
  20.183 -by (case_tac "b=a" 1);
  20.184 -by (case_tac "b=inv p a" 2);
  20.185 -by (subgoal_tac "b=a | b = inv p a" 3);
  20.186 -by (rtac wset_mem_imp_or 4);
  20.187 -by (Asm_simp_tac 2);
  20.188 -by (rtac inv_g_1 2);
  20.189 -by Auto_tac;
  20.190 -qed_spec_mp "wset_g_1";
  20.191 -
  20.192 -Goal "p:zprime --> a<p-#1 --> b:(wset(a,p)) --> b<p-#1";
  20.193 -by (induct_thm_tac wset_induct "a p" 1);
  20.194 -by Auto_tac;
  20.195 -by (case_tac "b=a" 1);
  20.196 -by (case_tac "b=inv p a" 2);
  20.197 -by (subgoal_tac "b=a | b = inv p a" 3);
  20.198 -by (rtac wset_mem_imp_or 4);
  20.199 -by (Asm_simp_tac 2);
  20.200 -by (rtac inv_less_p_minus_1 2);
  20.201 -by Auto_tac;
  20.202 -qed_spec_mp "wset_less";
  20.203 -
  20.204 -Goal "p:zprime --> a<p-#1 --> #1<b --> b<=a --> b:(wset(a,p))"; 
  20.205 -by (induct_thm_tac wset.induct "a p" 1);
  20.206 -by Auto_tac;
  20.207 -by (subgoal_tac "b=a" 1);
  20.208 -by (rtac zle_anti_sym 2);
  20.209 -by (rtac wset_subset 4);
  20.210 -by (Asm_simp_tac 1);
  20.211 -by Auto_tac;
  20.212 -qed_spec_mp "wset_mem";
  20.213 -
  20.214 -Goal "p:zprime --> #5<=p --> a<p-#1 --> b:(wset (a,p)) \
  20.215 -\     --> (inv p b):(wset (a,p))";
  20.216 -by (induct_thm_tac wset_induct "a p" 1);
  20.217 -by Auto_tac;
  20.218 -by (case_tac "b=a" 1);
  20.219 -by (stac wset_eq 1);
  20.220 -by (rewtac Let_def);
  20.221 -by (rtac wset_subset 3);
  20.222 -by Auto_tac;
  20.223 -by (case_tac "b = inv p a" 1);
  20.224 -by (Asm_simp_tac 1);
  20.225 -by (stac inv_inv 1);
  20.226 -by (subgoal_tac "b=a | b = inv p a" 6);
  20.227 -by (rtac wset_mem_imp_or 7);
  20.228 -by Auto_tac;
  20.229 -qed_spec_mp "wset_mem_inv_mem";
  20.230 -
  20.231 -Goal "[| p:zprime; #5<=p; a<p-#1; #1<b; b<p-#1; (inv p b):(wset (a,p)) |] \
  20.232 -\    ==> b:(wset (a,p))";
  20.233 -by (res_inst_tac [("s","inv p (inv p b)"),("t","b")] subst 1);
  20.234 -by (rtac wset_mem_inv_mem 2);
  20.235 -by (rtac inv_inv 1);
  20.236 -by (ALLGOALS (Asm_simp_tac));
  20.237 -qed "wset_inv_mem_mem";
  20.238 -
  20.239 -Goal "finite (wset (a,p))";
  20.240 -by (induct_thm_tac wset_induct "a p" 1);
  20.241 -by (stac wset_eq 2);
  20.242 -by (rewtac Let_def);
  20.243 -by Auto_tac;
  20.244 -qed "wset_fin";
  20.245 -
  20.246 -Goal "p:zprime --> #5<=p --> a<p-#1 --> [setprod (wset (a,p)) = #1](mod p)";
  20.247 -by (induct_thm_tac wset_induct "a p" 1);
  20.248 -by (stac wset_eq 2);
  20.249 -by (rewtac Let_def);
  20.250 -by Auto_tac;
  20.251 -by (stac setprod_insert 1);
  20.252 -by (stac setprod_insert 3);
  20.253 -by (subgoal_tac "zcong (a * (inv p a) * setprod(wset(a-#1,p))) (#1*#1) p" 5);
  20.254 -by (asm_full_simp_tac (simpset() addsimps [zmult_assoc]) 5);
  20.255 -by (rtac zcong_zmult 5);
  20.256 -by (rtac inv_is_inv 5);
  20.257 -by (Clarify_tac 4);
  20.258 -by (subgoal_tac "a:wset(a-#1,p)" 4);
  20.259 -by (rtac wset_inv_mem_mem 5);
  20.260 -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [wset_fin])));
  20.261 -by (rtac inv_distinct 1);
  20.262 -by Auto_tac;
  20.263 -qed_spec_mp "wset_zcong_prod_1";
  20.264 -
  20.265 -Goal "p:zprime ==> d22set(p-#2) = wset(p-#2,p)";
  20.266 -by Safe_tac;
  20.267 -by (etac wset_mem 1); 
  20.268 -by (rtac d22set_g_1 2);
  20.269 -by (rtac d22set_le 3);
  20.270 -by (rtac d22set_mem 4);
  20.271 -by (etac wset_g_1 4);
  20.272 -by (stac (zle_add1_eq_le RS sym) 6); 
  20.273 -by (subgoal_tac "p-#2+#1 = p-#1" 6);
  20.274 -by (Asm_simp_tac 6);
  20.275 -by (etac wset_less 6);
  20.276 -by Auto_tac;
  20.277 -qed "d22set_eq_wset";
  20.278 -
  20.279 -(**********  Wilson  *************)
  20.280 -
  20.281 -Goalw [zprime_def,dvd_def] "[| p : zprime; p ~= #2; p ~= #3 |] ==> #5<=p";
  20.282 -by (case_tac "p=#4" 1);
  20.283 -by Auto_tac;
  20.284 -by (rtac notE 1);
  20.285 -by (assume_tac 2);
  20.286 -by (Simp_tac 1);
  20.287 -by (res_inst_tac [("x","#2")] exI 1);
  20.288 -by Safe_tac;
  20.289 -by (res_inst_tac [("x","#2")] exI 1);
  20.290 -by Auto_tac;
  20.291 -by (arith_tac 1);
  20.292 -qed "prime_g_5";
  20.293 -
  20.294 -Goal "p:zprime ==> [zfact(p-#1) = #-1] (mod p)";
  20.295 -by (subgoal_tac "[(p-#1)*zfact(p-#2) = #-1*#1] (mod p)" 1);
  20.296 -by (rtac zcong_zmult 2);
  20.297 -by (SELECT_GOAL (rewtac zprime_def) 1);
  20.298 -by (stac zfact_eq 1);
  20.299 -by (res_inst_tac [("t","p-#1-#1"),("s","p-#2")] subst 1);
  20.300 -by Auto_tac;
  20.301 -by (SELECT_GOAL (rewtac zcong_def) 1);
  20.302 -by (Asm_simp_tac 1);
  20.303 -by (case_tac "p=#2" 1);
  20.304 -by (asm_full_simp_tac (simpset() addsimps [zfact_eq]) 1);
  20.305 -by (case_tac "p=#3" 1);
  20.306 -by (asm_full_simp_tac (simpset() addsimps [zfact_eq]) 1);
  20.307 -by (subgoal_tac "#5<=p" 1);
  20.308 -by (etac prime_g_5 2);
  20.309 -by (stac (d22set_prod_zfact RS sym) 1);
  20.310 -by (stac d22set_eq_wset 1);
  20.311 -by (rtac wset_zcong_prod_1 2);
  20.312 -by Auto_tac;
  20.313 -qed "WilsonRuss";
    21.1 --- a/src/HOL/NumberTheory/WilsonRuss.thy	Sat Feb 03 17:43:34 2001 +0100
    21.2 +++ b/src/HOL/NumberTheory/WilsonRuss.thy	Sun Feb 04 19:31:13 2001 +0100
    21.3 @@ -1,21 +1,372 @@
    21.4 -(*  Title:	WilsonRuss.thy
    21.5 +(*  Title:      HOL/NumberTheory/WilsonRuss.thy
    21.6      ID:         $Id$
    21.7 -    Author:	Thomas M. Rasmussen
    21.8 -    Copyright	2000  University of Cambridge
    21.9 +    Author:     Thomas M. Rasmussen
   21.10 +    Copyright   2000  University of Cambridge
   21.11  *)
   21.12  
   21.13 -WilsonRuss = EulerFermat +
   21.14 +header {* Wilson's Theorem according to Russinoff *}
   21.15 +
   21.16 +theory WilsonRuss = EulerFermat:
   21.17 +
   21.18 +text {*
   21.19 +  Wilson's Theorem following quite closely Russinoff's approach
   21.20 +  using Boyer-Moore (using finite sets instead of lists, though).
   21.21 +*}
   21.22 +
   21.23 +subsection {* Definitions and lemmas *}
   21.24  
   21.25  consts
   21.26 -  inv    :: "[int,int] => int" 
   21.27 -  wset   :: "int*int=>int set"
   21.28 +  inv :: "int => int => int"
   21.29 +  wset :: "int * int => int set"
   21.30  
   21.31  defs
   21.32 -  inv_def   "inv p a == (a ^ (nat (p - #2))) mod p"
   21.33 +  inv_def: "inv p a == (a^(nat (p - #2))) mod p"
   21.34 +
   21.35 +recdef wset
   21.36 +  "measure ((\<lambda>(a, p). nat a) :: int * int => nat)"
   21.37 +  "wset (a, p) =
   21.38 +    (if #1 < a then
   21.39 +      let ws = wset (a - #1, p)
   21.40 +      in (if a \<in> ws then ws else insert a (insert (inv p a) ws)) else {})"
   21.41 +
   21.42 +
   21.43 +text {* \medskip @{term [source] inv} *}
   21.44 +
   21.45 +lemma aux: "#1 < m ==> Suc (nat (m - #2)) = nat (m - #1)"
   21.46 +  apply (subst int_int_eq [symmetric])
   21.47 +  apply auto
   21.48 +  done
   21.49 +
   21.50 +lemma inv_is_inv:
   21.51 +    "p \<in> zprime \<Longrightarrow> #0 < a \<Longrightarrow> a < p ==> [a * inv p a = #1] (mod p)"
   21.52 +  apply (unfold inv_def)
   21.53 +  apply (subst zcong_zmod)
   21.54 +  apply (subst zmod_zmult1_eq [symmetric])
   21.55 +  apply (subst zcong_zmod [symmetric])
   21.56 +  apply (subst power_Suc [symmetric])
   21.57 +  apply (subst aux)
   21.58 +   apply (erule_tac [2] Little_Fermat)
   21.59 +   apply (erule_tac [2] zdvd_not_zless)
   21.60 +   apply (unfold zprime_def)
   21.61 +   apply auto
   21.62 +  done
   21.63 +
   21.64 +lemma inv_distinct:
   21.65 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> a \<noteq> inv p a"
   21.66 +  apply safe
   21.67 +  apply (cut_tac a = a and p = p in zcong_square)
   21.68 +     apply (cut_tac [3] a = a and p = p in inv_is_inv)
   21.69 +        apply auto
   21.70 +   apply (subgoal_tac "a = #1")
   21.71 +    apply (rule_tac [2] m = p in zcong_zless_imp_eq)
   21.72 +        apply (subgoal_tac [7] "a = p - #1")
   21.73 +         apply (rule_tac [8] m = p in zcong_zless_imp_eq)
   21.74 +             apply auto
   21.75 +  done
   21.76 +
   21.77 +lemma inv_not_0:
   21.78 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> inv p a \<noteq> #0"
   21.79 +  apply safe
   21.80 +  apply (cut_tac a = a and p = p in inv_is_inv)
   21.81 +     apply (unfold zcong_def)
   21.82 +     apply auto
   21.83 +  apply (subgoal_tac "\<not> p dvd #1")
   21.84 +   apply (rule_tac [2] zdvd_not_zless)
   21.85 +    apply (subgoal_tac "p dvd #1")
   21.86 +     prefer 2
   21.87 +     apply (subst zdvd_zminus_iff [symmetric])
   21.88 +     apply auto
   21.89 +  done
   21.90 +
   21.91 +lemma inv_not_1:
   21.92 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> inv p a \<noteq> #1"
   21.93 +  apply safe
   21.94 +  apply (cut_tac a = a and p = p in inv_is_inv)
   21.95 +     prefer 4
   21.96 +     apply simp
   21.97 +     apply (subgoal_tac "a = #1")
   21.98 +      apply (rule_tac [2] zcong_zless_imp_eq)
   21.99 +          apply auto
  21.100 +  done
  21.101 +
  21.102 +lemma aux: "[a * (p - #1) = #1] (mod p) = [a = p - #1] (mod p)"
  21.103 +  apply (unfold zcong_def)
  21.104 +  apply (simp add: zdiff_zdiff_eq zdiff_zdiff_eq2 zdiff_zmult_distrib2)
  21.105 +  apply (rule_tac s = "p dvd -((a + #1) + (p * -a))" in trans)
  21.106 +   apply (simp add: zmult_commute zminus_zdiff_eq)
  21.107 +  apply (subst zdvd_zminus_iff)
  21.108 +  apply (subst zdvd_reduce)
  21.109 +  apply (rule_tac s = "p dvd (a + #1) + (p * -#1)" in trans)
  21.110 +   apply (subst zdvd_reduce)
  21.111 +   apply auto
  21.112 +  done
  21.113 +
  21.114 +lemma inv_not_p_minus_1:
  21.115 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> inv p a \<noteq> p - #1"
  21.116 +  apply safe
  21.117 +  apply (cut_tac a = a and p = p in inv_is_inv)
  21.118 +     apply auto
  21.119 +  apply (simp add: aux)
  21.120 +  apply (subgoal_tac "a = p - #1")
  21.121 +   apply (rule_tac [2] zcong_zless_imp_eq)
  21.122 +       apply auto
  21.123 +  done
  21.124 +
  21.125 +lemma inv_g_1:
  21.126 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> #1 < inv p a"
  21.127 +  apply (case_tac "#0\<le> inv p a")
  21.128 +   apply (subgoal_tac "inv p a \<noteq> #1")
  21.129 +    apply (subgoal_tac "inv p a \<noteq> #0")
  21.130 +     apply (subst order_less_le)
  21.131 +     apply (subst zle_add1_eq_le [symmetric])
  21.132 +     apply (subst order_less_le)
  21.133 +     apply (rule_tac [2] inv_not_0)
  21.134 +       apply (rule_tac [5] inv_not_1)
  21.135 +         apply auto
  21.136 +  apply (unfold inv_def zprime_def)
  21.137 +  apply (simp add: pos_mod_sign)
  21.138 +  done
  21.139 +
  21.140 +lemma inv_less_p_minus_1:
  21.141 +    "p \<in> zprime \<Longrightarrow> #1 < a \<Longrightarrow> a < p - #1 ==> inv p a < p - #1"
  21.142 +  apply (case_tac "inv p a < p")
  21.143 +   apply (subst order_less_le)
  21.144 +   apply (simp add: inv_not_p_minus_1)
  21.145 +  apply auto
  21.146 +  apply (unfold inv_def zprime_def)
  21.147 +  apply (simp add: pos_mod_bound)
  21.148 +  done
  21.149 +
  21.150 +lemma aux: "#5 \<le> p ==>
  21.151 +    nat (p - #2) * nat (p - #2) = Suc (nat (p - #1) * nat (p - #3))"
  21.152 +  apply (subst int_int_eq [symmetric])
  21.153 +  apply (simp add: zmult_int [symmetric])
  21.154 +  apply (simp add: zdiff_zmult_distrib zdiff_zmult_distrib2)
  21.155 +  done
  21.156 +
  21.157 +lemma zcong_zpower_zmult:
  21.158 +    "[x^y = #1] (mod p) \<Longrightarrow> [x^(y * z) = #1] (mod p)"
  21.159 +  apply (induct z)
  21.160 +   apply (auto simp add: zpower_zadd_distrib)
  21.161 +  apply (subgoal_tac "zcong (x^y * x^(y * n)) (#1 * #1) p")
  21.162 +   apply (rule_tac [2] zcong_zmult)
  21.163 +    apply simp_all
  21.164 +  done
  21.165 +
  21.166 +lemma inv_inv: "p \<in> zprime \<Longrightarrow>
  21.167 +    #5 \<le> p \<Longrightarrow> #0 < a \<Longrightarrow> a < p ==> inv p (inv p a) = a"
  21.168 +  apply (unfold inv_def)
  21.169 +  apply (subst zpower_zmod)
  21.170 +  apply (subst zpower_zpower)
  21.171 +  apply (rule zcong_zless_imp_eq)
  21.172 +      prefer 5
  21.173 +      apply (subst zcong_zmod)
  21.174 +      apply (subst mod_mod_trivial)
  21.175 +      apply (subst zcong_zmod [symmetric])
  21.176 +      apply (subst aux)
  21.177 +       apply (subgoal_tac [2]
  21.178 +	 "zcong (a * a^(nat (p - #1) * nat (p - #3))) (a * #1) p")
  21.179 +        apply (rule_tac [3] zcong_zmult)
  21.180 +         apply (rule_tac [4] zcong_zpower_zmult)
  21.181 +         apply (erule_tac [4] Little_Fermat)
  21.182 +         apply (rule_tac [4] zdvd_not_zless)
  21.183 +          apply (simp_all add: pos_mod_bound pos_mod_sign)
  21.184 +  done
  21.185 +
  21.186 +
  21.187 +text {* \medskip @{term wset} *}
  21.188 +
  21.189 +declare wset.simps [simp del]
  21.190  
  21.191 -recdef wset "measure ((%(a,p).(nat a)) ::int*int=>nat)"
  21.192 -    "wset (a,p) = (if #1<a then let ws = wset (a-#1,p) in
  21.193 -                     (if a:ws then ws else insert a (insert (inv p a) ws))
  21.194 -                   else {})"
  21.195 +lemma wset_induct:
  21.196 +  "(!!a p. P {} a p) \<Longrightarrow>
  21.197 +    (!!a p. #1 < (a::int) \<Longrightarrow> P (wset (a - #1, p)) (a - #1) p
  21.198 +      ==> P (wset (a, p)) a p)
  21.199 +    ==> P (wset (u, v)) u v"
  21.200 +proof -
  21.201 +  case antecedent
  21.202 +  show ?thesis
  21.203 +    apply (rule wset.induct)
  21.204 +    apply safe
  21.205 +     apply (case_tac [2] "#1 < a")
  21.206 +      apply (rule_tac [2] antecedent)
  21.207 +        apply simp_all
  21.208 +      apply (simp_all add: wset.simps antecedent)
  21.209 +    done
  21.210 +qed
  21.211 +
  21.212 +lemma wset_mem_imp_or [rule_format]:
  21.213 +  "#1 < a \<Longrightarrow> b \<notin> wset (a - #1, p)
  21.214 +    ==> b \<in> wset (a, p) --> b = a \<or> b = inv p a"
  21.215 +  apply (subst wset.simps)
  21.216 +  apply (unfold Let_def)
  21.217 +  apply simp
  21.218 +  done
  21.219 +
  21.220 +lemma wset_mem_mem [simp]: "#1 < a ==> a \<in> wset (a, p)"
  21.221 +  apply (subst wset.simps)
  21.222 +  apply (unfold Let_def)
  21.223 +  apply simp
  21.224 +  done
  21.225 +
  21.226 +lemma wset_subset: "#1 < a \<Longrightarrow> b \<in> wset (a - #1, p) ==> b \<in> wset (a, p)"
  21.227 +  apply (subst wset.simps)
  21.228 +  apply (unfold Let_def)
  21.229 +  apply auto
  21.230 +  done
  21.231 +
  21.232 +lemma wset_g_1 [rule_format]:
  21.233 +    "p \<in> zprime --> a < p - #1 --> b \<in> wset (a, p) --> #1 < b"
  21.234 +  apply (induct a p rule: wset_induct)
  21.235 +   apply auto
  21.236 +  apply (case_tac "b = a")
  21.237 +   apply (case_tac [2] "b = inv p a")
  21.238 +    apply (subgoal_tac [3] "b = a \<or> b = inv p a")
  21.239 +     apply (rule_tac [4] wset_mem_imp_or)
  21.240 +       prefer 2
  21.241 +       apply simp
  21.242 +       apply (rule inv_g_1)
  21.243 +         apply auto
  21.244 +  done
  21.245 +
  21.246 +lemma wset_less [rule_format]:
  21.247 +    "p \<in> zprime --> a < p - #1 --> b \<in> wset (a, p) --> b < p - #1"
  21.248 +  apply (induct a p rule: wset_induct)
  21.249 +   apply auto
  21.250 +  apply (case_tac "b = a")
  21.251 +   apply (case_tac [2] "b = inv p a")
  21.252 +    apply (subgoal_tac [3] "b = a \<or> b = inv p a")
  21.253 +     apply (rule_tac [4] wset_mem_imp_or)
  21.254 +       prefer 2
  21.255 +       apply simp
  21.256 +       apply (rule inv_less_p_minus_1)
  21.257 +         apply auto
  21.258 +  done
  21.259 +
  21.260 +lemma wset_mem [rule_format]:
  21.261 +  "p \<in> zprime -->
  21.262 +    a < p - #1 --> #1 < b --> b \<le> a --> b \<in> wset (a, p)"
  21.263 +  apply (induct a p rule: wset.induct)
  21.264 +  apply auto
  21.265 +   apply (subgoal_tac "b = a")
  21.266 +    apply (rule_tac [2] zle_anti_sym)
  21.267 +     apply (rule_tac [4] wset_subset)
  21.268 +      apply (simp (no_asm_simp))
  21.269 +     apply auto
  21.270 +  done
  21.271 +
  21.272 +lemma wset_mem_inv_mem [rule_format]:
  21.273 +  "p \<in> zprime --> #5 \<le> p --> a < p - #1 --> b \<in> wset (a, p)
  21.274 +    --> inv p b \<in> wset (a, p)"
  21.275 +  apply (induct a p rule: wset_induct)
  21.276 +   apply auto
  21.277 +   apply (case_tac "b = a")
  21.278 +    apply (subst wset.simps)
  21.279 +    apply (unfold Let_def)
  21.280 +    apply (rule_tac [3] wset_subset)
  21.281 +     apply auto
  21.282 +  apply (case_tac "b = inv p a")
  21.283 +   apply (simp (no_asm_simp))
  21.284 +   apply (subst inv_inv)
  21.285 +       apply (subgoal_tac [6] "b = a \<or> b = inv p a")
  21.286 +        apply (rule_tac [7] wset_mem_imp_or)
  21.287 +          apply auto
  21.288 +  done
  21.289 +
  21.290 +lemma wset_inv_mem_mem:
  21.291 +  "p \<in> zprime \<Longrightarrow> #5 \<le> p \<Longrightarrow> a < p - #1 \<Longrightarrow> #1 < b \<Longrightarrow> b < p - #1
  21.292 +    \<Longrightarrow> inv p b \<in> wset (a, p) \<Longrightarrow> b \<in> wset (a, p)"
  21.293 +  apply (rule_tac s = "inv p (inv p b)" and t = b in subst)
  21.294 +   apply (rule_tac [2] wset_mem_inv_mem)
  21.295 +      apply (rule inv_inv)
  21.296 +         apply simp_all
  21.297 +  done
  21.298 +
  21.299 +lemma wset_fin: "finite (wset (a, p))"
  21.300 +  apply (induct a p rule: wset_induct)
  21.301 +   prefer 2
  21.302 +   apply (subst wset.simps)
  21.303 +   apply (unfold Let_def)
  21.304 +   apply auto
  21.305 +  done
  21.306 +
  21.307 +lemma wset_zcong_prod_1 [rule_format]:
  21.308 +  "p \<in> zprime -->
  21.309 +    #5 \<le> p --> a < p - #1 --> [setprod (wset (a, p)) = #1] (mod p)"
  21.310 +  apply (induct a p rule: wset_induct)
  21.311 +   prefer 2
  21.312 +   apply (subst wset.simps)
  21.313 +   apply (unfold Let_def)
  21.314 +   apply auto
  21.315 +  apply (subst setprod_insert)
  21.316 +    apply (tactic {* stac (thm "setprod_insert") 3 *})
  21.317 +      apply (subgoal_tac [5]
  21.318 +	"zcong (a * inv p a * setprod (wset (a - #1, p))) (#1 * #1) p")
  21.319 +       prefer 5
  21.320 +       apply (simp add: zmult_assoc)
  21.321 +      apply (rule_tac [5] zcong_zmult)
  21.322 +       apply (rule_tac [5] inv_is_inv)
  21.323 +         apply (tactic "Clarify_tac 4")
  21.324 +         apply (subgoal_tac [4] "a \<in> wset (a - #1, p)")
  21.325 +          apply (rule_tac [5] wset_inv_mem_mem)
  21.326 +               apply (simp_all add: wset_fin)
  21.327 +  apply (rule inv_distinct)
  21.328 +    apply auto
  21.329 +  done
  21.330 +
  21.331 +lemma d22set_eq_wset: "p \<in> zprime ==> d22set (p - #2) = wset (p - #2, p)"
  21.332 +  apply safe
  21.333 +   apply (erule wset_mem)
  21.334 +     apply (rule_tac [2] d22set_g_1)
  21.335 +     apply (rule_tac [3] d22set_le)
  21.336 +     apply (rule_tac [4] d22set_mem)
  21.337 +      apply (erule_tac [4] wset_g_1)
  21.338 +       prefer 6
  21.339 +       apply (subst zle_add1_eq_le [symmetric])
  21.340 +       apply (subgoal_tac "p - #2 + #1 = p - #1")
  21.341 +        apply (simp (no_asm_simp))
  21.342 +        apply (erule wset_less)
  21.343 +         apply auto
  21.344 +  done
  21.345 +
  21.346 +
  21.347 +subsection {* Wilson *}
  21.348 +
  21.349 +lemma prime_g_5: "p \<in> zprime \<Longrightarrow> p \<noteq> #2 \<Longrightarrow> p \<noteq> #3 ==> #5 \<le> p"
  21.350 +  apply (unfold zprime_def dvd_def)
  21.351 +  apply (case_tac "p = #4")
  21.352 +   apply auto
  21.353 +   apply (rule notE)
  21.354 +    prefer 2
  21.355 +    apply assumption
  21.356 +   apply (simp (no_asm))
  21.357 +   apply (rule_tac x = "#2" in exI)
  21.358 +   apply safe
  21.359 +     apply (rule_tac x = "#2" in exI)
  21.360 +     apply auto
  21.361 +  apply arith
  21.362 +  done
  21.363 +
  21.364 +theorem Wilson_Russ:
  21.365 +    "p \<in> zprime ==> [zfact (p - #1) = #-1] (mod p)"
  21.366 +  apply (subgoal_tac "[(p - #1) * zfact (p - #2) = #-1 * #1] (mod p)")
  21.367 +   apply (rule_tac [2] zcong_zmult)
  21.368 +    apply (simp only: zprime_def)
  21.369 +    apply (subst zfact.simps)
  21.370 +    apply (rule_tac t = "p - #1 - #1" and s = "p - #2" in subst)
  21.371 +     apply auto
  21.372 +   apply (simp only: zcong_def)
  21.373 +   apply (simp (no_asm_simp))
  21.374 +  apply (case_tac "p = #2")
  21.375 +   apply (simp add: zfact.simps)
  21.376 +  apply (case_tac "p = #3")
  21.377 +   apply (simp add: zfact.simps)
  21.378 +  apply (subgoal_tac "#5 \<le> p")
  21.379 +   apply (erule_tac [2] prime_g_5)
  21.380 +    apply (subst d22set_prod_zfact [symmetric])
  21.381 +    apply (subst d22set_eq_wset)
  21.382 +     apply (rule_tac [2] wset_zcong_prod_1)
  21.383 +       apply auto
  21.384 +  done
  21.385  
  21.386  end