24 |
24 |
25 |
25 |
26 (** Aribtrary definitions for division by zero. Useful to simplify |
26 (** Aribtrary definitions for division by zero. Useful to simplify |
27 certain equations **) |
27 certain equations **) |
28 |
28 |
29 Goal "a div 0 = 0"; |
29 Goal "a div 0 = (0::nat)"; |
30 by (rtac (div_eq RS wf_less_trans) 1); |
30 by (rtac (div_eq RS wf_less_trans) 1); |
31 by (Asm_simp_tac 1); |
31 by (Asm_simp_tac 1); |
32 qed "DIVISION_BY_ZERO_DIV"; (*NOT for adding to default simpset*) |
32 qed "DIVISION_BY_ZERO_DIV"; (*NOT for adding to default simpset*) |
33 |
33 |
34 Goal "a mod 0 = a"; |
34 Goal "a mod 0 = (a::nat)"; |
35 by (rtac (mod_eq RS wf_less_trans) 1); |
35 by (rtac (mod_eq RS wf_less_trans) 1); |
36 by (Asm_simp_tac 1); |
36 by (Asm_simp_tac 1); |
37 qed "DIVISION_BY_ZERO_MOD"; (*NOT for adding to default simpset*) |
37 qed "DIVISION_BY_ZERO_MOD"; (*NOT for adding to default simpset*) |
38 |
38 |
39 fun div_undefined_case_tac s i = |
39 fun div_undefined_case_tac s i = |
63 |
63 |
64 Goal "m mod (n::nat) = (if m<n then m else (m-n) mod n)"; |
64 Goal "m mod (n::nat) = (if m<n then m else (m-n) mod n)"; |
65 by (asm_simp_tac (simpset() addsimps [mod_geq]) 1); |
65 by (asm_simp_tac (simpset() addsimps [mod_geq]) 1); |
66 qed "mod_if"; |
66 qed "mod_if"; |
67 |
67 |
68 Goal "m mod 1 = 0"; |
68 Goal "m mod 1 = (0::nat)"; |
69 by (induct_tac "m" 1); |
69 by (induct_tac "m" 1); |
70 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mod_geq]))); |
70 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mod_geq]))); |
71 qed "mod_1"; |
71 qed "mod_1"; |
72 Addsimps [mod_1]; |
72 Addsimps [mod_1]; |
73 |
73 |
74 Goal "n mod n = 0"; |
74 Goal "n mod n = (0::nat)"; |
75 by (div_undefined_case_tac "n=0" 1); |
75 by (div_undefined_case_tac "n=0" 1); |
76 by (asm_simp_tac (simpset() addsimps [mod_geq]) 1); |
76 by (asm_simp_tac (simpset() addsimps [mod_geq]) 1); |
77 qed "mod_self"; |
77 qed "mod_self"; |
78 |
78 |
79 Goal "(m+n) mod n = m mod (n::nat)"; |
79 Goal "(m+n) mod n = m mod (n::nat)"; |
115 by (asm_simp_tac |
115 by (asm_simp_tac |
116 (simpset() addsimps [read_instantiate [("m","k")] mult_commute, |
116 (simpset() addsimps [read_instantiate [("m","k")] mult_commute, |
117 mod_mult_distrib]) 1); |
117 mod_mult_distrib]) 1); |
118 qed "mod_mult_distrib2"; |
118 qed "mod_mult_distrib2"; |
119 |
119 |
120 Goal "(m*n) mod n = 0"; |
120 Goal "(m*n) mod n = (0::nat)"; |
121 by (div_undefined_case_tac "n=0" 1); |
121 by (div_undefined_case_tac "n=0" 1); |
122 by (induct_tac "m" 1); |
122 by (induct_tac "m" 1); |
123 by (Asm_simp_tac 1); |
123 by (Asm_simp_tac 1); |
124 by (rename_tac "k" 1); |
124 by (rename_tac "k" 1); |
125 by (cut_inst_tac [("m","k*n"),("n","n")] mod_add_self2 1); |
125 by (cut_inst_tac [("m","k*n"),("n","n")] mod_add_self2 1); |
126 by (asm_full_simp_tac (simpset() addsimps [add_commute]) 1); |
126 by (asm_full_simp_tac (simpset() addsimps [add_commute]) 1); |
127 qed "mod_mult_self_is_0"; |
127 qed "mod_mult_self_is_0"; |
128 |
128 |
129 Goal "(n*m) mod n = 0"; |
129 Goal "(n*m) mod n = (0::nat)"; |
130 by (simp_tac (simpset() addsimps [mult_commute, mod_mult_self_is_0]) 1); |
130 by (simp_tac (simpset() addsimps [mult_commute, mod_mult_self_is_0]) 1); |
131 qed "mod_mult_self1_is_0"; |
131 qed "mod_mult_self1_is_0"; |
132 Addsimps [mod_mult_self_is_0, mod_mult_self1_is_0]; |
132 Addsimps [mod_mult_self_is_0, mod_mult_self1_is_0]; |
133 |
133 |
134 |
134 |
135 (*** Quotient ***) |
135 (*** Quotient ***) |
136 |
136 |
137 Goal "m<n ==> m div n = 0"; |
137 Goal "m<n ==> m div n = (0::nat)"; |
138 by (rtac (div_eq RS wf_less_trans) 1); |
138 by (rtac (div_eq RS wf_less_trans) 1); |
139 by (Asm_simp_tac 1); |
139 by (Asm_simp_tac 1); |
140 qed "div_less"; |
140 qed "div_less"; |
141 Addsimps [div_less]; |
141 Addsimps [div_less]; |
142 |
142 |
176 by (induct_tac "m" 1); |
176 by (induct_tac "m" 1); |
177 by (ALLGOALS (asm_simp_tac (simpset() addsimps [div_geq]))); |
177 by (ALLGOALS (asm_simp_tac (simpset() addsimps [div_geq]))); |
178 qed "div_1"; |
178 qed "div_1"; |
179 Addsimps [div_1]; |
179 Addsimps [div_1]; |
180 |
180 |
181 Goal "0<n ==> n div n = 1"; |
181 Goal "0<n ==> n div n = (1::nat)"; |
182 by (asm_simp_tac (simpset() addsimps [div_geq]) 1); |
182 by (asm_simp_tac (simpset() addsimps [div_geq]) 1); |
183 qed "div_self"; |
183 qed "div_self"; |
184 |
184 |
185 |
185 |
186 Goal "0<n ==> (m+n) div n = Suc (m div n)"; |
186 Goal "0<n ==> (m+n) div n = Suc (m div n)"; |
191 |
191 |
192 Goal "0<n ==> (n+m) div n = Suc (m div n)"; |
192 Goal "0<n ==> (n+m) div n = Suc (m div n)"; |
193 by (asm_simp_tac (simpset() addsimps [add_commute, div_add_self2]) 1); |
193 by (asm_simp_tac (simpset() addsimps [add_commute, div_add_self2]) 1); |
194 qed "div_add_self1"; |
194 qed "div_add_self1"; |
195 |
195 |
196 Goal "!!n. 0<n ==> (m + k*n) div n = k + m div n"; |
196 Goal "!!n::nat. 0<n ==> (m + k*n) div n = k + m div n"; |
197 by (induct_tac "k" 1); |
197 by (induct_tac "k" 1); |
198 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac @ [div_add_self1]))); |
198 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac @ [div_add_self1]))); |
199 qed "div_mult_self1"; |
199 qed "div_mult_self1"; |
200 |
200 |
201 Goal "0<n ==> (m + n*k) div n = k + m div n"; |
201 Goal "0<n ==> (m + n*k) div n = k + m div (n::nat)"; |
202 by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self1]) 1); |
202 by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self1]) 1); |
203 qed "div_mult_self2"; |
203 qed "div_mult_self2"; |
204 |
204 |
205 Addsimps [div_mult_self1, div_mult_self2]; |
205 Addsimps [div_mult_self1, div_mult_self2]; |
206 |
206 |
207 (** A dividend of zero **) |
207 (** A dividend of zero **) |
208 |
208 |
209 Goal "0 div m = 0"; |
209 Goal "0 div m = (0::nat)"; |
210 by (div_undefined_case_tac "m=0" 1); |
210 by (div_undefined_case_tac "m=0" 1); |
211 by (Asm_simp_tac 1); |
211 by (Asm_simp_tac 1); |
212 qed "div_0"; |
212 qed "div_0"; |
213 |
213 |
214 Goal "0 mod m = 0"; |
214 Goal "0 mod m = (0::nat)"; |
215 by (div_undefined_case_tac "m=0" 1); |
215 by (div_undefined_case_tac "m=0" 1); |
216 by (Asm_simp_tac 1); |
216 by (Asm_simp_tac 1); |
217 qed "mod_0"; |
217 qed "mod_0"; |
218 Addsimps [div_0, mod_0]; |
218 Addsimps [div_0, mod_0]; |
219 |
219 |
232 (* 2.2 case m>=k *) |
232 (* 2.2 case m>=k *) |
233 by (asm_simp_tac (simpset() addsimps [div_geq, diff_less, diff_le_mono]) 1); |
233 by (asm_simp_tac (simpset() addsimps [div_geq, diff_less, diff_le_mono]) 1); |
234 qed_spec_mp "div_le_mono"; |
234 qed_spec_mp "div_le_mono"; |
235 |
235 |
236 (* Antimonotonicity of div in second argument *) |
236 (* Antimonotonicity of div in second argument *) |
237 Goal "[| 0<m; m<=n |] ==> (k div n) <= (k div m)"; |
237 Goal "!!m::nat. [| 0<m; m<=n |] ==> (k div n) <= (k div m)"; |
238 by (subgoal_tac "0<n" 1); |
238 by (subgoal_tac "0<n" 1); |
239 by (Asm_simp_tac 2); |
239 by (Asm_simp_tac 2); |
240 by (res_inst_tac [("n","k")] less_induct 1); |
240 by (res_inst_tac [("n","k")] less_induct 1); |
241 by (rename_tac "k" 1); |
241 by (rename_tac "k" 1); |
242 by (case_tac "k<n" 1); |
242 by (case_tac "k<n" 1); |
259 by (ALLGOALS Asm_simp_tac); |
259 by (ALLGOALS Asm_simp_tac); |
260 qed "div_le_dividend"; |
260 qed "div_le_dividend"; |
261 Addsimps [div_le_dividend]; |
261 Addsimps [div_le_dividend]; |
262 |
262 |
263 (* Similar for "less than" *) |
263 (* Similar for "less than" *) |
264 Goal "1<n ==> (0 < m) --> (m div n < m)"; |
264 Goal "!!n::nat. 1<n ==> (0 < m) --> (m div n < m)"; |
265 by (res_inst_tac [("n","m")] less_induct 1); |
265 by (res_inst_tac [("n","m")] less_induct 1); |
266 by (rename_tac "m" 1); |
266 by (rename_tac "m" 1); |
267 by (case_tac "m<n" 1); |
267 by (case_tac "m<n" 1); |
268 by (Asm_full_simp_tac 1); |
268 by (Asm_full_simp_tac 1); |
269 by (subgoal_tac "0<n" 1); |
269 by (subgoal_tac "0<n" 1); |
294 mod_geq]) 1); |
294 mod_geq]) 1); |
295 by (auto_tac (claset(), |
295 by (auto_tac (claset(), |
296 simpset() addsimps [Suc_diff_le, diff_less, le_mod_geq])); |
296 simpset() addsimps [Suc_diff_le, diff_less, le_mod_geq])); |
297 qed "mod_Suc"; |
297 qed "mod_Suc"; |
298 |
298 |
299 Goal "0<n ==> m mod n < n"; |
299 Goal "0<n ==> m mod n < (n::nat)"; |
300 by (res_inst_tac [("n","m")] less_induct 1); |
300 by (res_inst_tac [("n","m")] less_induct 1); |
301 by (case_tac "na<n" 1); |
301 by (case_tac "na<n" 1); |
302 (*case n le na*) |
302 (*case n le na*) |
303 by (asm_full_simp_tac (simpset() addsimps [mod_geq, diff_less]) 2); |
303 by (asm_full_simp_tac (simpset() addsimps [mod_geq, diff_less]) 2); |
304 (*case na<n*) |
304 (*case na<n*) |
306 qed "mod_less_divisor"; |
306 qed "mod_less_divisor"; |
307 Addsimps [mod_less_divisor]; |
307 Addsimps [mod_less_divisor]; |
308 |
308 |
309 (*** More division laws ***) |
309 (*** More division laws ***) |
310 |
310 |
311 Goal "0<n ==> (m*n) div n = m"; |
311 Goal "0<n ==> (m*n) div n = (m::nat)"; |
312 by (cut_inst_tac [("m", "m*n"),("n","n")] mod_div_equality 1); |
312 by (cut_inst_tac [("m", "m*n"),("n","n")] mod_div_equality 1); |
313 by (asm_full_simp_tac (simpset() addsimps [mod_mult_self_is_0]) 1); |
313 by (asm_full_simp_tac (simpset() addsimps [mod_mult_self_is_0]) 1); |
314 qed "div_mult_self_is_m"; |
314 qed "div_mult_self_is_m"; |
315 |
315 |
316 Goal "0<n ==> (n*m) div n = m"; |
316 Goal "0<n ==> (n*m) div n = (m::nat)"; |
317 by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self_is_m]) 1); |
317 by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self_is_m]) 1); |
318 qed "div_mult_self1_is_m"; |
318 qed "div_mult_self1_is_m"; |
319 Addsimps [div_mult_self_is_m, div_mult_self1_is_m]; |
319 Addsimps [div_mult_self_is_m, div_mult_self1_is_m]; |
320 |
320 |
321 (*Cancellation law for division*) |
321 (*Cancellation law for division*) |
322 Goal "0<k ==> (k*m) div (k*n) = m div n"; |
322 Goal "0<k ==> (k*m) div (k*n) = m div (n::nat)"; |
323 by (div_undefined_case_tac "n=0" 1); |
323 by (div_undefined_case_tac "n=0" 1); |
324 by (res_inst_tac [("n","m")] less_induct 1); |
324 by (res_inst_tac [("n","m")] less_induct 1); |
325 by (case_tac "na<n" 1); |
325 by (case_tac "na<n" 1); |
326 by (asm_simp_tac (simpset() addsimps [zero_less_mult_iff, mult_less_mono2]) 1); |
326 by (asm_simp_tac (simpset() addsimps [zero_less_mult_iff, mult_less_mono2]) 1); |
327 by (subgoal_tac "~ k*na < k*n" 1); |
327 by (subgoal_tac "~ k*na < k*n" 1); |
338 |
338 |
339 (************************************************) |
339 (************************************************) |
340 (** Divides Relation **) |
340 (** Divides Relation **) |
341 (************************************************) |
341 (************************************************) |
342 |
342 |
343 Goalw [dvd_def] "m dvd 0"; |
343 Goalw [dvd_def] "m dvd (0::nat)"; |
344 by (blast_tac (claset() addIs [mult_0_right RS sym]) 1); |
344 by (blast_tac (claset() addIs [mult_0_right RS sym]) 1); |
345 qed "dvd_0_right"; |
345 qed "dvd_0_right"; |
346 AddIffs [dvd_0_right]; |
346 AddIffs [dvd_0_right]; |
347 |
347 |
348 Goalw [dvd_def] "0 dvd m ==> m = 0"; |
348 Goalw [dvd_def] "0 dvd m ==> m = (0::nat)"; |
349 by Auto_tac; |
349 by Auto_tac; |
350 qed "dvd_0_left"; |
350 qed "dvd_0_left"; |
351 |
351 |
352 Goalw [dvd_def] "1 dvd k"; |
352 Goalw [dvd_def] "1 dvd (k::nat)"; |
353 by (Simp_tac 1); |
353 by (Simp_tac 1); |
354 qed "dvd_1_left"; |
354 qed "dvd_1_left"; |
355 AddIffs [dvd_1_left]; |
355 AddIffs [dvd_1_left]; |
356 |
356 |
357 Goalw [dvd_def] "m dvd (m::nat)"; |
357 Goalw [dvd_def] "m dvd (m::nat)"; |
402 by (etac ssubst 1); |
402 by (etac ssubst 1); |
403 by (etac dvd_diff 1); |
403 by (etac dvd_diff 1); |
404 by (rtac dvd_refl 1); |
404 by (rtac dvd_refl 1); |
405 qed "dvd_reduce"; |
405 qed "dvd_reduce"; |
406 |
406 |
407 Goalw [dvd_def] "[| f dvd m; f dvd n; 0<n |] ==> f dvd (m mod n)"; |
407 Goalw [dvd_def] "!!n::nat. [| f dvd m; f dvd n; 0<n |] ==> f dvd (m mod n)"; |
408 by (Clarify_tac 1); |
408 by (Clarify_tac 1); |
409 by (Full_simp_tac 1); |
409 by (Full_simp_tac 1); |
410 by (res_inst_tac |
410 by (res_inst_tac |
411 [("x", "(((k div ka)*ka + k mod ka) - ((f*k) div (f*ka)) * ka)")] |
411 [("x", "(((k div ka)*ka + k mod ka) - ((f*k) div (f*ka)) * ka)")] |
412 exI 1); |
412 exI 1); |
436 Goalw [dvd_def] "(i*j :: nat) dvd k ==> i dvd k"; |
436 Goalw [dvd_def] "(i*j :: nat) dvd k ==> i dvd k"; |
437 by (full_simp_tac (simpset() addsimps [mult_assoc]) 1); |
437 by (full_simp_tac (simpset() addsimps [mult_assoc]) 1); |
438 by (Blast_tac 1); |
438 by (Blast_tac 1); |
439 qed "dvd_mult_left"; |
439 qed "dvd_mult_left"; |
440 |
440 |
441 Goalw [dvd_def] "[| k dvd n; 0 < n |] ==> k <= n"; |
441 Goalw [dvd_def] "[| k dvd n; 0 < n |] ==> k <= (n::nat)"; |
442 by (Clarify_tac 1); |
442 by (Clarify_tac 1); |
443 by (ALLGOALS (full_simp_tac (simpset() addsimps [zero_less_mult_iff]))); |
443 by (ALLGOALS (full_simp_tac (simpset() addsimps [zero_less_mult_iff]))); |
444 by (etac conjE 1); |
444 by (etac conjE 1); |
445 by (rtac le_trans 1); |
445 by (rtac le_trans 1); |
446 by (rtac (le_refl RS mult_le_mono) 2); |
446 by (rtac (le_refl RS mult_le_mono) 2); |
447 by (etac Suc_leI 2); |
447 by (etac Suc_leI 2); |
448 by (Simp_tac 1); |
448 by (Simp_tac 1); |
449 qed "dvd_imp_le"; |
449 qed "dvd_imp_le"; |
450 |
450 |
451 Goalw [dvd_def] "(k dvd n) = (n mod k = 0)"; |
451 Goalw [dvd_def] "!!k::nat. (k dvd n) = (n mod k = 0)"; |
452 by (div_undefined_case_tac "k=0" 1); |
452 by (div_undefined_case_tac "k=0" 1); |
453 by Safe_tac; |
453 by Safe_tac; |
454 by (asm_simp_tac (simpset() addsimps [mult_commute]) 1); |
454 by (asm_simp_tac (simpset() addsimps [mult_commute]) 1); |
455 by (res_inst_tac [("t","n"),("n1","k")] (mod_div_equality RS subst) 1); |
455 by (res_inst_tac [("t","n"),("n1","k")] (mod_div_equality RS subst) 1); |
456 by (stac mult_commute 1); |
456 by (stac mult_commute 1); |