1 (* Title: HOL/GroupTheory/Exponent
3 Author: Florian Kammueller, with new proofs by L C Paulson
4 Copyright 2001 University of Cambridge
7 (*** prime theorems ***)
9 val prime_def = thm "prime_def";
11 Goalw [prime_def] "p\\<in>prime ==> Suc 0 < p";
12 by (force_tac (claset(), simpset() addsimps []) 1);
13 qed "prime_imp_one_less";
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]));
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);
25 (simpset() addsimps [dvd_mult_cancel1, dvd_mult_cancel2]) 1);
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";
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})";
38 by (rewrite_goals_tac [split RS eq_reflection]);
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);
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]);
54 Goal "( (x, y, z, v)\\<in>{(a,b,c,d). P a b c d}) ==> (P x y z v)";
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);
63 by (res_inst_tac [("a", "x")] CollectD 1);
67 val [p1,p2] = goal (the_context()) "[|P == Q; P|] ==> Q";
68 by (fold_goals_tac [p1]);
72 Goal "S \\<noteq> {} ==> \\<exists>x. x\\<in>S";
76 Goal "\\<exists>x. x: S ==> S \\<noteq> {}";
81 (* The following lemmas are needed for existsM1inM *)
83 Goal "[| {} \\<notin> A; M\\<in>A |] ==> M \\<noteq> {}";
87 val [p1] = goal (the_context()) "\\<exists>g \\<in> A. x = P(g) ==> \\<exists>g \\<in> A. P(g) = x";
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";
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";
104 qed "EquivElemClass";
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);
111 qed "le_extend_mult";
114 Goal "0 < card(S) ==> S \\<noteq> {}";
115 by (force_tac (claset(), simpset() addsimps [card_empty]) 1);
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 = {}";
122 qed "insert_partition";
124 (* main cardinality theorem *)
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";
137 Goal "[| finite S; S \\<noteq> {} |] ==> 0 < card(S)";
138 by (swap_res_tac [card_0_eq RS iffD1] 1);
140 qed "zero_less_card_empty";
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);
152 by (eres_inst_tac [("n","m")] dvdE 1);
153 by (eres_inst_tac [("n","n")] dvdE 2);
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";
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);
167 by (Asm_full_simp_tac 1);
168 by (Asm_full_simp_tac 1);
170 by (Asm_full_simp_tac 1);
172 by (etac (prime_dvd_cases RS disjE) 1);
177 by (Asm_full_simp_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);
186 by (Asm_full_simp_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";
195 (*needed in this form in Sylow.ML*)
196 Goal "[| p \\<in> prime; ~ (p ^ (Suc r) dvd n); p^(a+r) dvd n*k |] \
198 by (dres_inst_tac [("a","Suc r"), ("b","a")] prime_power_dvd_cases 1);
203 (*Lemma for power_dvd_bound*)
204 Goal "Suc 0 < p ==> Suc n <= p^n";
205 by (induct_tac "n" 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);
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);
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);
225 qed "power_dvd_bound";
228 (*** exponent theorems ***)
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";
236 Goal "0<s ==> (p ^ exponent p s) dvd s";
237 by (simp_tac (simpset() addsimps [exponent_def]) 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";
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);
248 by (dtac exponent_ge 1);
250 qed "power_Suc_exponent_Not_dvd";
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];
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";
264 Goal "p \\<notin> prime ==> exponent p s = 0";
265 by (asm_simp_tac (simpset() addsimps [exponent_def]) 1);
267 Addsimps [exponent_eq_0];
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,
278 qed "exponent_mult_add1";
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);
286 by (cut_inst_tac [("p","p"),("s","a*b")] power_exponent_dvd 1);
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);
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";
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,
303 qed "exponent_mult_add";
306 Goal "~ (p dvd n) ==> exponent p n = 0";
307 by (case_tac "exponent p n" 1);
308 by (Asm_full_simp_tac 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";
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];
323 (*** Lemmas for the main combinatorial argument ***)
325 Goal "[| 0 < (m::nat); 0<k; k < p^a; (p^r) dvd (p^a)* m - k |] ==> r <= a";
328 by (dtac (leI RSN (2, contrapos_nn) RS notnotD) 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);
334 by (forw_inst_tac [("m","k")] less_imp_le 1);
335 by (dres_inst_tac [("c","m")] le_extend_mult 1);
337 by (dres_inst_tac [("k","p ^ a"),("m","(p ^ a) * m")] dvd_diffD1 1);
339 by (rtac (dvd_refl RS dvd_mult2) 1);
340 by (dres_inst_tac [("n","k")] dvd_imp_le 1);
342 qed "p_fac_forw_lemma";
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);
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);
353 by (blast_tac (claset() addIs [dvd_diff]) 2);
354 by (dtac less_imp_Suc_add 1);
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);
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);
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);
372 by (blast_tac (claset() addIs [dvd_diff]) 2);
373 by (dtac less_imp_Suc_add 1);
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,
381 qed "exponent_p_a_m_k_equation";
383 (*Suc rules that we have to delete from the simpset*)
384 val bad_Sucs = [binomial_Suc_Suc, mult_Suc, mult_Suc_right];
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);
391 by (induct_tac "k" 1);
394 by (subgoal_tac "0 < (Suc(j+n) choose Suc n)" 1);
395 by (simp_tac (simpset() addsimps [zero_less_binomial_iff]) 2);
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";
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);
418 by (Asm_full_simp_tac 2);
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";
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);
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);
433 by (case_tac "p^a" 2);
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);
441 qed "const_p_fac_right";
443 Goal "0 < m ==> exponent p (((p^a) * m) choose p^a) = exponent p m";
444 by (case_tac "p \\<in> prime" 1);
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.*)
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);
464 by (asm_simp_tac (simpset() delsimps bad_Sucs
465 addsimps [exponent_mult_add, const_p_fac_right]) 1);