src/HOL/GroupTheory/Exponent.ML
author wenzelm
Fri, 05 Oct 2001 21:52:39 +0200
changeset 11701 3d51fbf81c17
parent 11506 244a02a2968b
child 11704 3c50a2cd6f00
permissions -rw-r--r--
sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
"num" syntax (still with "#"), Numeral0, Numeral1;
     1 (*  Title:      HOL/GroupTheory/Exponent
     2     ID:         $Id$
     3     Author:     Florian Kammueller, with new proofs by L C Paulson
     4     Copyright   2001  University of Cambridge
     5 *)
     6 
     7 (*** prime theorems ***)
     8 
     9 val prime_def = thm "prime_def";
    10 
    11 Goalw [prime_def] "p\\<in>prime ==> Suc 0 < p";
    12 by (force_tac (claset(), simpset() addsimps []) 1); 
    13 qed "prime_imp_one_less";
    14 
    15 Goal "(p\\<in>prime) = (Suc 0 < p & (\\<forall>a b. p dvd a*b --> (p dvd a) | (p dvd b)))";
    16 by (auto_tac (claset(), simpset() addsimps [prime_imp_one_less]));  
    17 by (blast_tac (claset() addSDs [thm "prime_dvd_mult"]) 1);
    18 by (auto_tac (claset(), simpset() addsimps [prime_def]));  
    19 by (etac dvdE 1); 
    20 by (case_tac "k=0" 1);
    21 by (Asm_full_simp_tac 1); 
    22 by (dres_inst_tac [("x","m")] spec 1); 
    23 by (dres_inst_tac [("x","k")] spec 1);
    24 by (asm_full_simp_tac
    25     (simpset() addsimps [dvd_mult_cancel1, dvd_mult_cancel2]) 1);  
    26 by Auto_tac; 
    27 qed "prime_iff";
    28 
    29 Goal "p\\<in>prime ==> 0 < p^a";
    30 by (rtac zero_less_power 1);
    31 by (force_tac (claset(), simpset() addsimps [prime_iff]) 1);
    32 qed "zero_less_prime_power";
    33 
    34 
    35 (*First some things about HOL and sets *)
    36 val [p1] = goal (the_context()) "(P x y) ==> ( (x, y)\\<in>{(a,b). P a b})";
    37 by (rtac CollectI 1);
    38 by (rewrite_goals_tac [split RS eq_reflection]);
    39 by (rtac p1 1);
    40 qed "CollectI_prod";
    41 
    42 val [p1] = goal (the_context()) "( (x, y)\\<in>{(a,b). P a b}) ==> (P x y)";
    43 by (res_inst_tac [("c1","P")] (split RS subst) 1);
    44 by (res_inst_tac [("a","(x,y)")] CollectD 1);
    45 by (rtac p1 1);
    46 qed "CollectD_prod";
    47 
    48 val [p1] = goal (the_context()) "(P x y z v) ==> ( (x, y, z, v)\\<in>{(a,b,c,d). P a b c d})";
    49 by (rtac CollectI_prod 1);
    50 by (rewrite_goals_tac [split RS eq_reflection]);
    51 by (rtac p1 1);
    52 qed "CollectI_prod4";
    53 
    54 Goal "( (x, y, z, v)\\<in>{(a,b,c,d). P a b c d}) ==> (P x y z v)";
    55 by Auto_tac; 
    56 qed "CollectD_prod4";
    57 
    58 
    59 
    60 val [p1] = goal (the_context()) "x\\<in>{y. P(y) & Q(y)} ==> P(x)";
    61 by (res_inst_tac [("Q","Q x"),("P", "P x")] conjE 1);
    62 by (assume_tac 2);
    63 by (res_inst_tac [("a", "x")] CollectD 1);
    64 by (rtac p1 1);
    65 qed "subset_lemma1";
    66 
    67 val [p1,p2] = goal (the_context()) "[|P == Q; P|] ==> Q";
    68 by (fold_goals_tac [p1]);
    69 by (rtac p2 1);
    70 qed "apply_def";
    71 
    72 Goal "S \\<noteq> {} ==> \\<exists>x. x\\<in>S";
    73 by Auto_tac;  
    74 qed "NotEmpty_ExEl";
    75 
    76 Goal "\\<exists>x. x: S ==> S \\<noteq> {}";
    77 by Auto_tac;  
    78 qed "ExEl_NotEmpty";
    79 
    80 
    81 (* The following lemmas are needed for existsM1inM *)
    82 
    83 Goal "[| {} \\<notin> A; M\\<in>A |] ==> M \\<noteq> {}";
    84 by Auto_tac;  
    85 qed "MnotEqempty";
    86 
    87 val [p1] = goal (the_context()) "\\<exists>g \\<in> A. x = P(g) ==> \\<exists>g \\<in> A. P(g) = x";
    88 by (rtac bexE 1);
    89 by (rtac p1 1);
    90 by (rtac bexI 1);
    91 by (rtac sym 1);
    92 by (assume_tac 1);
    93 by (assume_tac 1);
    94 qed "bex_sym";
    95 
    96 Goalw [equiv_def,quotient_def,sym_def,trans_def]
    97      "[| equiv A r; C\\<in>A // r |] ==> \\<forall>x \\<in> C. \\<forall>y \\<in> C. (x,y)\\<in>r";
    98 by (Blast_tac 1); 
    99 qed "ElemClassEquiv";
   100 
   101 Goalw [equiv_def,quotient_def,sym_def,trans_def]
   102      "[|equiv A r; M\\<in>A // r; M1\\<in>M; (M1, M2)\\<in>r |] ==> M2\\<in>M";
   103 by (Blast_tac 1); 
   104 qed "EquivElemClass";
   105 
   106 Goal "[| 0 < c; a <= b |] ==> a <= b * (c::nat)";
   107 by (res_inst_tac [("P","%x. x <= b * c")] subst 1);
   108 by (rtac mult_1_right 1);
   109 by (rtac mult_le_mono 1);
   110 by Auto_tac; 
   111 qed "le_extend_mult";
   112 
   113 
   114 Goal "0 < card(S) ==> S \\<noteq> {}";
   115 by (force_tac (claset(), simpset() addsimps [card_empty]) 1); 
   116 qed "card_nonempty";
   117 
   118 Goal "[| x \\<notin> F; \
   119 \        \\<forall>c1\\<in>insert x F. \\<forall>c2 \\<in> insert x F. c1 \\<noteq> c2 --> c1 \\<inter> c2 = {}|]\
   120 \     ==> x \\<inter> \\<Union> F = {}";
   121 by Auto_tac;  
   122 qed "insert_partition";
   123 
   124 (* main cardinality theorem *)
   125 Goal "finite C ==> \
   126 \       finite (\\<Union> C) --> \
   127 \       (\\<forall>c\\<in>C. card c = k) -->  \
   128 \       (\\<forall>c1 \\<in> C. \\<forall>c2 \\<in> C. c1 \\<noteq> c2 --> c1 \\<inter> c2 = {}) --> \
   129 \       k * card(C) = card (\\<Union> C)";
   130 by (etac finite_induct 1);
   131 by (Asm_full_simp_tac 1); 
   132 by (asm_full_simp_tac 
   133     (simpset() addsimps [card_insert_disjoint, card_Un_disjoint, 
   134             insert_partition, inst "B" "\\<Union>(insert x F)" finite_subset]) 1);
   135 qed_spec_mp "card_partition";
   136 
   137 Goal "[| finite S; S \\<noteq> {} |] ==> 0 < card(S)";
   138 by (swap_res_tac [card_0_eq RS iffD1] 1);
   139 by Auto_tac;  
   140 qed "zero_less_card_empty";
   141 
   142 
   143 Goal "[| p*k dvd m*n;  p\\<in>prime |] \
   144 \     ==> (\\<exists>x. k dvd x*n & m = p*x) | (\\<exists>y. k dvd m*y & n = p*y)";
   145 by (asm_full_simp_tac (simpset() addsimps [prime_iff]) 1);
   146 by (ftac dvd_mult_left 1);
   147 by (subgoal_tac "p dvd m | p dvd n" 1);
   148 by (Blast_tac 2);
   149 by (etac disjE 1);
   150 by (rtac disjI1 1); 
   151 by (rtac disjI2 2);
   152 by (eres_inst_tac [("n","m")] dvdE 1);
   153 by (eres_inst_tac [("n","n")] dvdE 2);
   154 by Auto_tac;
   155 by (res_inst_tac [("k","p")] dvd_mult_cancel 2); 
   156 by (res_inst_tac [("k","p")] dvd_mult_cancel 1); 
   157 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps mult_ac))); 
   158 qed "prime_dvd_cases";
   159 
   160 
   161 Goal "p\\<in>prime \
   162 \     ==> \\<forall>m n. p^c dvd m*n --> \
   163 \         (\\<forall>a b. a+b = Suc c --> p^a dvd m | p^b dvd n)";
   164 by (induct_tac "c" 1);
   165  by (Clarify_tac 1);
   166  by (case_tac "a" 1); 
   167   by (Asm_full_simp_tac 1); 
   168  by (Asm_full_simp_tac 1);
   169 (*inductive step*)
   170 by (Asm_full_simp_tac 1);  
   171 by (Clarify_tac 1); 
   172 by (etac (prime_dvd_cases RS disjE) 1); 
   173 by (assume_tac 1); 
   174 by Auto_tac;  
   175 (*case 1: p dvd m*)
   176  by (case_tac "a" 1);
   177   by (Asm_full_simp_tac 1); 
   178  by (Clarify_tac 1); 
   179  by (dtac spec 1 THEN dtac spec 1 THEN  mp_tac 1);
   180  by (dres_inst_tac [("x","nat")] spec 1);
   181  by (dres_inst_tac [("x","b")] spec 1); 
   182  by (Asm_full_simp_tac 1);
   183  by (blast_tac (claset() addIs [dvd_refl, mult_dvd_mono]) 1);
   184 (*case 2: p dvd n*)
   185 by (case_tac "b" 1);
   186  by (Asm_full_simp_tac 1); 
   187 by (Clarify_tac 1); 
   188 by (dtac spec 1 THEN dtac spec 1 THEN  mp_tac 1);
   189 by (dres_inst_tac [("x","a")] spec 1); 
   190 by (dres_inst_tac [("x","nat")] spec 1);
   191 by (Asm_full_simp_tac 1);
   192 by (blast_tac (claset() addIs [dvd_refl, mult_dvd_mono]) 1);
   193 qed_spec_mp "prime_power_dvd_cases";
   194 
   195 (*needed in this form in Sylow.ML*)
   196 Goal "[| p \\<in> prime; ~ (p ^ (Suc r) dvd n);  p^(a+r) dvd n*k |] \
   197 \     ==> p ^ a dvd k";
   198 by (dres_inst_tac [("a","Suc r"), ("b","a")] prime_power_dvd_cases 1);
   199 by (assume_tac 1);  
   200 by Auto_tac;  
   201 qed "div_combine";
   202 
   203 (*Lemma for power_dvd_bound*)
   204 Goal "Suc 0 < p ==> Suc n <= p^n";
   205 by (induct_tac "n" 1);
   206 by (Asm_simp_tac 1); 
   207 by (Asm_full_simp_tac 1); 
   208 by (subgoal_tac "# 2 * n + # 2 <= p * p^n" 1);
   209 by (Asm_full_simp_tac 1); 
   210 by (subgoal_tac "# 2 * p^n <= p * p^n" 1);
   211 (*?arith_tac should handle all of this!*)
   212 by (rtac order_trans 1); 
   213 by (assume_tac 2); 
   214 by (dres_inst_tac [("k","# 2")] mult_le_mono2 1); 
   215 by (Asm_full_simp_tac 1); 
   216 by (rtac mult_le_mono1 1); 
   217 by (Asm_full_simp_tac 1); 
   218 qed "Suc_le_power";
   219 
   220 (*An upper bound for the n such that p^n dvd a: needed for GREATEST to exist*)
   221 Goal "[|p^n dvd a;  Suc 0 < p;  0 < a|] ==> n < a";
   222 by (dtac dvd_imp_le 1); 
   223 by (dres_inst_tac [("n","n")] Suc_le_power 2); 
   224 by Auto_tac;  
   225 qed "power_dvd_bound";
   226 
   227 
   228 (*** exponent theorems ***)
   229 
   230 Goal "[|p^k dvd n;  p\\<in>prime;  0<n|] ==> k <= exponent p n";
   231 by (asm_full_simp_tac (simpset() addsimps [exponent_def]) 1); 
   232 by (etac (thm "Greatest_le") 1);
   233 by (blast_tac (claset() addDs [prime_imp_one_less, power_dvd_bound]) 1);  
   234 qed_spec_mp "exponent_ge";
   235 
   236 Goal "0<s ==> (p ^ exponent p s) dvd s";
   237 by (simp_tac (simpset() addsimps [exponent_def]) 1); 
   238 by (Clarify_tac 1); 
   239 by (res_inst_tac [("k","0")] (thm "GreatestI") 1);
   240 by (blast_tac (claset() addDs [prime_imp_one_less, power_dvd_bound]) 2);  
   241 by (Asm_full_simp_tac 1); 
   242 qed "power_exponent_dvd";
   243 
   244 Goal "[|(p * p ^ exponent p s) dvd s;  p\\<in>prime |] ==> s=0";
   245 by (subgoal_tac "p ^ Suc(exponent p s) dvd s" 1);
   246 by (Asm_full_simp_tac 2);
   247 by (rtac ccontr 1); 
   248 by (dtac exponent_ge 1); 
   249 by Auto_tac;  
   250 qed "power_Suc_exponent_Not_dvd";
   251 
   252 Goal "p\\<in>prime ==> exponent p (p^a) = a";
   253 by (asm_simp_tac (simpset() addsimps [exponent_def]) 1);
   254 by (rtac (thm "Greatest_equality") 1); 
   255 by (Asm_full_simp_tac 1);
   256 by (asm_simp_tac (simpset() addsimps [prime_imp_one_less, power_dvd_imp_le]) 1); 
   257 qed "exponent_power_eq";
   258 Addsimps [exponent_power_eq];
   259 
   260 Goal "!r::nat. (p^r dvd a) = (p^r dvd b) ==> exponent p a = exponent p b";
   261 by (asm_simp_tac (simpset() addsimps [exponent_def]) 1); 
   262 qed "exponent_equalityI";
   263 
   264 Goal "p \\<notin> prime ==> exponent p s = 0";
   265 by (asm_simp_tac (simpset() addsimps [exponent_def]) 1); 
   266 qed "exponent_eq_0";
   267 Addsimps [exponent_eq_0];
   268 
   269 
   270 (* exponent_mult_add, easy inclusion.  Could weaken p\\<in>prime to Suc 0 < p *)
   271 Goal "[| 0 < a; 0 < b |]  \
   272 \     ==> (exponent p a) + (exponent p b) <= exponent p (a * b)";
   273 by (case_tac "p \\<in> prime" 1);
   274 by (rtac exponent_ge 1);
   275 by (auto_tac (claset(), simpset() addsimps [power_add]));   
   276 by (blast_tac (claset() addIs [prime_imp_one_less, power_exponent_dvd, 
   277                                mult_dvd_mono]) 1); 
   278 qed "exponent_mult_add1";
   279 
   280 (* exponent_mult_add, opposite inclusion *)
   281 Goal "[| 0 < a; 0 < b |] \
   282 \     ==> exponent p (a * b) <= (exponent p a) + (exponent p b)";
   283 by (case_tac "p\\<in>prime" 1);
   284 by (rtac leI 1); 
   285 by (Clarify_tac 1); 
   286 by (cut_inst_tac [("p","p"),("s","a*b")] power_exponent_dvd 1);
   287 by Auto_tac;  
   288 by (subgoal_tac "p ^ (Suc (exponent p a + exponent p b)) dvd a * b" 1);
   289 by (rtac (le_imp_power_dvd RS dvd_trans) 2);
   290   by (assume_tac 3);
   291  by (Asm_full_simp_tac 2);
   292 by (forw_inst_tac [("a","Suc (exponent p a)"), ("b","Suc (exponent p b)")] 
   293     prime_power_dvd_cases 1);
   294  by (assume_tac 1 THEN Force_tac 1);
   295 by (Asm_full_simp_tac 1); 
   296 by (blast_tac (claset() addDs [power_Suc_exponent_Not_dvd]) 1); 
   297 qed "exponent_mult_add2";
   298 
   299 Goal "[| 0 < a; 0 < b |] \
   300 \     ==> exponent p (a * b) = (exponent p a) + (exponent p b)";
   301 by (blast_tac (claset() addIs [exponent_mult_add1, exponent_mult_add2, 
   302                                order_antisym]) 1); 
   303 qed "exponent_mult_add";
   304 
   305 
   306 Goal "~ (p dvd n) ==> exponent p n = 0";
   307 by (case_tac "exponent p n" 1);
   308 by (Asm_full_simp_tac 1); 
   309 by (case_tac "n" 1);
   310 by (Asm_full_simp_tac 1);
   311 by (cut_inst_tac [("s","n"),("p","p")] power_exponent_dvd 1);
   312 by (auto_tac (claset() addDs [dvd_mult_left], simpset()));  
   313 qed "not_divides_exponent_0";
   314 
   315 Goal "exponent p (Suc 0) = 0";
   316 by (case_tac "p \\<in> prime" 1);
   317 by (auto_tac (claset(), 
   318               simpset() addsimps [prime_iff, not_divides_exponent_0]));
   319 qed "exponent_1_eq_0";
   320 Addsimps [exponent_1_eq_0];
   321 
   322 
   323 (*** Lemmas for the main combinatorial argument ***)
   324 
   325 Goal "[| 0 < (m::nat); 0<k; k < p^a; (p^r) dvd (p^a)* m - k |] ==> r <= a";
   326 by (rtac notnotD 1);
   327 by (rtac notI 1);
   328 by (dtac (leI RSN (2, contrapos_nn) RS notnotD) 1);
   329 by (assume_tac 1);
   330 by (dres_inst_tac [("m","a")] less_imp_le 1);
   331 by (dtac le_imp_power_dvd 1);
   332 by (dres_inst_tac [("n","p ^ r")] dvd_trans 1);
   333 by (assume_tac 1);
   334 by (forw_inst_tac [("m","k")] less_imp_le 1);
   335 by (dres_inst_tac [("c","m")] le_extend_mult 1);
   336 by (assume_tac 1);
   337 by (dres_inst_tac [("k","p ^ a"),("m","(p ^ a) * m")] dvd_diffD1 1);
   338 by (assume_tac 2);
   339 by (rtac (dvd_refl RS dvd_mult2) 1);
   340 by (dres_inst_tac [("n","k")] dvd_imp_le 1);
   341 by Auto_tac;
   342 qed "p_fac_forw_lemma";
   343 
   344 Goal "[| 0 < (m::nat); 0<k; k < p^a; (p^r) dvd (p^a)* m - k |] \
   345 \     ==> (p^r) dvd (p^a) - k";
   346 by (forw_inst_tac [("k1","k"),("i","p")]
   347      (p_fac_forw_lemma RS le_imp_power_dvd) 1);
   348 by Auto_tac;
   349 by (subgoal_tac "p^r dvd p^a*m" 1);
   350  by (blast_tac (claset() addIs [dvd_mult2]) 2);
   351 by (dtac dvd_diffD1 1);
   352   by (assume_tac 1);
   353  by (blast_tac (claset() addIs [dvd_diff]) 2);
   354 by (dtac less_imp_Suc_add 1);
   355 by Auto_tac;
   356 qed "p_fac_forw";
   357 
   358 
   359 Goal "[| 0 < (k::nat); k < p^a; 0 < p; (p^r) dvd (p^a) - k |] ==> r <= a";
   360 by (res_inst_tac [("m","Suc 0")] p_fac_forw_lemma 1);
   361 by Auto_tac;
   362 qed "r_le_a_forw";
   363 
   364 Goal "[| 0<m; 0<k; 0 < (p::nat);  k < p^a;  (p^r) dvd p^a - k |] \
   365 \     ==> (p^r) dvd (p^a)*m - k";
   366 by (forw_inst_tac [("k1","k"),("i","p")] (r_le_a_forw RS le_imp_power_dvd) 1);
   367 by Auto_tac;
   368 by (subgoal_tac "p^r dvd p^a*m" 1);
   369  by (blast_tac (claset() addIs [dvd_mult2]) 2);
   370 by (dtac dvd_diffD1 1);
   371   by (assume_tac 1);
   372  by (blast_tac (claset() addIs [dvd_diff]) 2);
   373 by (dtac less_imp_Suc_add 1);
   374 by Auto_tac;
   375 qed "p_fac_backw";
   376 
   377 Goal "[| 0<m; 0<k; 0 < (p::nat);  k < p^a |] \
   378 \     ==> exponent p (p^a * m - k) = exponent p (p^a - k)";
   379 by (blast_tac (claset() addIs [exponent_equalityI, p_fac_forw, 
   380                                p_fac_backw]) 1);
   381 qed "exponent_p_a_m_k_equation";
   382 
   383 (*Suc rules that we have to delete from the simpset*)
   384 val bad_Sucs = [binomial_Suc_Suc, mult_Suc, mult_Suc_right];
   385 
   386 (*The bound K is needed; otherwise it's too weak to be used.*)
   387 Goal "[| \\<forall>i. Suc i < K --> exponent p (Suc i) = exponent p (Suc(j+i))|] \
   388 \     ==> k<K --> exponent p ((j+k) choose k) = 0";
   389 by (case_tac "p \\<in> prime" 1);
   390 by (Asm_simp_tac 2);
   391 by (induct_tac "k" 1);
   392 by (Simp_tac 1);
   393 (*induction step*)
   394 by (subgoal_tac "0 < (Suc(j+n) choose Suc n)" 1);
   395  by (simp_tac (simpset() addsimps [zero_less_binomial_iff]) 2);
   396 by (Clarify_tac 1);
   397 by (subgoal_tac
   398      "exponent p ((Suc(j+n) choose Suc n) * Suc n) = exponent p (Suc n)" 1);
   399 (*First, use the assumed equation.  We simplify the LHS to
   400   exponent p (Suc (j + n) choose Suc n) + exponent p (Suc n);
   401   the common terms cancel, proving the conclusion.*)
   402  by (asm_full_simp_tac (simpset() delsimps bad_Sucs
   403 				  addsimps [exponent_mult_add]) 1);
   404 (*Establishing the equation requires first applying Suc_times_binomial_eq...*)
   405 by (asm_full_simp_tac (simpset() delsimps bad_Sucs
   406 				 addsimps [Suc_times_binomial_eq RS sym]) 1);
   407 (*...then exponent_mult_add and the quantified premise.*)
   408 by (asm_full_simp_tac (simpset() delsimps bad_Sucs
   409           	 addsimps [zero_less_binomial_iff, exponent_mult_add]) 1);
   410 qed_spec_mp "p_not_div_choose_lemma";
   411 
   412 (*The lemma above, with two changes of variables*)
   413 Goal "[| k<K;  k<=n;  \
   414 \      \\<forall>j. 0<j & j<K --> exponent p (n - k + (K - j)) = exponent p (K - j)|] \
   415 \     ==> exponent p (n choose k) = 0";
   416 by (cut_inst_tac [("j","n-k"),("k","k"),("p","p")] p_not_div_choose_lemma 1);
   417 by (assume_tac 2);
   418 by (Asm_full_simp_tac 2);
   419 by (Clarify_tac 1); 
   420 by (dres_inst_tac [("x","K - Suc i")] spec 1);
   421 by (asm_full_simp_tac (simpset() addsimps [Suc_diff_le]) 1);
   422 qed "p_not_div_choose";
   423 
   424 
   425 Goal "0 < m ==> exponent p ((p^a * m - Suc 0) choose (p^a - Suc 0)) = 0";
   426 by (case_tac "p \\<in> prime" 1);
   427 by (Asm_simp_tac 2);
   428 by (forw_inst_tac [("a","a")] zero_less_prime_power 1);
   429 by (res_inst_tac [("K","p^a")] p_not_div_choose 1);
   430    by (Asm_full_simp_tac 1);
   431   by (Asm_full_simp_tac 1);
   432  by (case_tac "m" 1);
   433   by (case_tac "p^a" 2);
   434    by Auto_tac;
   435 (*now the hard case, simplified to
   436     exponent p (Suc (p ^ a * m + i - p ^ a)) = exponent p (Suc i) *)
   437 by (subgoal_tac "0<p" 1);
   438  by (force_tac (claset() addSDs [prime_imp_one_less], simpset()) 2);
   439 by (stac exponent_p_a_m_k_equation 1);
   440 by Auto_tac;
   441 qed "const_p_fac_right";
   442 
   443 Goal "0 < m ==> exponent p (((p^a) * m) choose p^a) = exponent p m";
   444 by (case_tac "p \\<in> prime" 1);
   445 by (Asm_simp_tac 2);
   446 by (forw_inst_tac [("a","a")] zero_less_prime_power 1);
   447 by (subgoal_tac "0 < p^a * m & p^a <= p^a * m" 1);
   448 by (Asm_full_simp_tac 2);
   449 (*A similar trick to the one used in p_not_div_choose_lemma:
   450   insert an equation; use exponent_mult_add on the LHS; on the RHS, first
   451   transform the binomial coefficient, then use exponent_mult_add.*)
   452 by (subgoal_tac
   453     "exponent p ((((p^a) * m) choose p^a) * p^a) = a + exponent p m" 1);
   454 by (asm_full_simp_tac (simpset() delsimps bad_Sucs
   455 	 addsimps [zero_less_binomial_iff, exponent_mult_add, prime_iff]) 1);
   456 (*one subgoal left!*)
   457 by (stac times_binomial_minus1_eq 1);
   458 by (Asm_full_simp_tac 1);
   459 by (Asm_full_simp_tac 1);
   460 by (stac exponent_mult_add 1);
   461 by (Asm_full_simp_tac 1);
   462 by (asm_simp_tac (simpset() addsimps [zero_less_binomial_iff]) 1);
   463 by (arith_tac 1);
   464 by (asm_simp_tac (simpset() delsimps bad_Sucs
   465                          addsimps [exponent_mult_add, const_p_fac_right]) 1);
   466 qed "const_p_fac";