103 Addsimps [add_left_cancel, add_right_cancel, |
103 Addsimps [add_left_cancel, add_right_cancel, |
104 add_left_cancel_le, add_left_cancel_less]; |
104 add_left_cancel_le, add_left_cancel_less]; |
105 |
105 |
106 (** Reasoning about m+0=0, etc. **) |
106 (** Reasoning about m+0=0, etc. **) |
107 |
107 |
108 Goal "(m+n = 0) = (m=0 & n=0)"; |
108 Goal "!!m::nat. (m+n = 0) = (m=0 & n=0)"; |
109 by (case_tac "m" 1); |
109 by (case_tac "m" 1); |
110 by (Auto_tac); |
110 by (Auto_tac); |
111 qed "add_is_0"; |
111 qed "add_is_0"; |
112 AddIffs [add_is_0]; |
112 AddIffs [add_is_0]; |
113 |
113 |
114 Goal "(0 = m+n) = (m=0 & n=0)"; |
114 Goal "!!m::nat. (0 = m+n) = (m=0 & n=0)"; |
115 by (case_tac "m" 1); |
115 by (case_tac "m" 1); |
116 by (Auto_tac); |
116 by (Auto_tac); |
117 qed "zero_is_add"; |
117 qed "zero_is_add"; |
118 AddIffs [zero_is_add]; |
118 AddIffs [zero_is_add]; |
119 |
119 |
120 Goal "(m+n=1) = (m=1 & n=0 | m=0 & n=1)"; |
120 Goal "!!m::nat. (m+n=1) = (m=1 & n=0 | m=0 & n=1)"; |
121 by (case_tac "m" 1); |
121 by (case_tac "m" 1); |
122 by (Auto_tac); |
122 by (Auto_tac); |
123 qed "add_is_1"; |
123 qed "add_is_1"; |
124 |
124 |
125 Goal "(1=m+n) = (m=1 & n=0 | m=0 & n=1)"; |
125 Goal "!!m::nat. (1=m+n) = (m=1 & n=0 | m=0 & n=1)"; |
126 by (case_tac "m" 1); |
126 by (case_tac "m" 1); |
127 by (Auto_tac); |
127 by (Auto_tac); |
128 qed "one_is_add"; |
128 qed "one_is_add"; |
129 |
129 |
130 Goal "(0<m+n) = (0<m | 0<n)"; |
130 Goal "!!m::nat. (0<m+n) = (0<m | 0<n)"; |
131 by (simp_tac (simpset() delsimps [neq0_conv] addsimps [neq0_conv RS sym]) 1); |
131 by (simp_tac (simpset() delsimps [neq0_conv] addsimps [neq0_conv RS sym]) 1); |
132 qed "add_gr_0"; |
132 qed "add_gr_0"; |
133 AddIffs [add_gr_0]; |
133 AddIffs [add_gr_0]; |
134 |
134 |
135 (* Could be generalized, eg to "k<n ==> m+(n-(Suc k)) = (m+n)-(Suc k)" *) |
135 (* Could be generalized, eg to "k<n ==> m+(n-(Suc k)) = (m+n)-(Suc k)" *) |
136 Goal "0<n ==> m + (n-1) = (m+n)-1"; |
136 Goal "!!m::nat. 0<n ==> m + (n-1) = (m+n)-1"; |
137 by (case_tac "m" 1); |
137 by (case_tac "m" 1); |
138 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_Suc, Suc_n_not_n] |
138 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_Suc, Suc_n_not_n] |
139 addsplits [nat.split]))); |
139 addsplits [nat.split]))); |
140 qed "add_pred"; |
140 qed "add_pred"; |
141 Addsimps [add_pred]; |
141 Addsimps [add_pred]; |
142 |
142 |
143 Goal "m + n = m ==> n = 0"; |
143 Goal "!!m::nat. m + n = m ==> n = 0"; |
144 by (dtac (add_0_right RS ssubst) 1); |
144 by (dtac (add_0_right RS ssubst) 1); |
145 by (asm_full_simp_tac (simpset() addsimps [add_assoc] |
145 by (asm_full_simp_tac (simpset() addsimps [add_assoc] |
146 delsimps [add_0_right]) 1); |
146 delsimps [add_0_right]) 1); |
147 qed "add_eq_self_zero"; |
147 qed "add_eq_self_zero"; |
148 |
148 |
268 |
268 |
269 |
269 |
270 (*** Multiplication ***) |
270 (*** Multiplication ***) |
271 |
271 |
272 (*right annihilation in product*) |
272 (*right annihilation in product*) |
273 Goal "m * 0 = 0"; |
273 Goal "!!m::nat. m * 0 = 0"; |
274 by (induct_tac "m" 1); |
274 by (induct_tac "m" 1); |
275 by (ALLGOALS Asm_simp_tac); |
275 by (ALLGOALS Asm_simp_tac); |
276 qed "mult_0_right"; |
276 qed "mult_0_right"; |
277 |
277 |
278 (*right successor law for multiplication*) |
278 (*right successor law for multiplication*) |
322 by (rtac (mult_commute RS arg_cong) 1); |
322 by (rtac (mult_commute RS arg_cong) 1); |
323 qed "mult_left_commute"; |
323 qed "mult_left_commute"; |
324 |
324 |
325 bind_thms ("mult_ac", [mult_assoc,mult_commute,mult_left_commute]); |
325 bind_thms ("mult_ac", [mult_assoc,mult_commute,mult_left_commute]); |
326 |
326 |
327 Goal "(m*n = 0) = (m=0 | n=0)"; |
327 Goal "!!m::nat. (m*n = 0) = (m=0 | n=0)"; |
328 by (induct_tac "m" 1); |
328 by (induct_tac "m" 1); |
329 by (induct_tac "n" 2); |
329 by (induct_tac "n" 2); |
330 by (ALLGOALS Asm_simp_tac); |
330 by (ALLGOALS Asm_simp_tac); |
331 qed "mult_is_0"; |
331 qed "mult_is_0"; |
332 |
332 |
333 Goal "(0 = m*n) = (0=m | 0=n)"; |
333 Goal "!!m::nat. (0 = m*n) = (0=m | 0=n)"; |
334 by (cut_facts_tac [mult_is_0] 1); |
334 by (stac eq_commute 1 THEN stac mult_is_0 1); |
335 by (full_simp_tac (simpset() addsimps [eq_commute]) 1); |
335 by Auto_tac; |
336 qed "zero_is_mult"; |
336 qed "zero_is_mult"; |
337 |
337 |
338 Addsimps [mult_is_0, zero_is_mult]; |
338 Addsimps [mult_is_0, zero_is_mult]; |
339 |
339 |
340 |
340 |
341 (*** Difference ***) |
341 (*** Difference ***) |
342 |
342 |
343 Goal "m - m = 0"; |
343 Goal "!!m::nat. m - m = 0"; |
344 by (induct_tac "m" 1); |
344 by (induct_tac "m" 1); |
345 by (ALLGOALS Asm_simp_tac); |
345 by (ALLGOALS Asm_simp_tac); |
346 qed "diff_self_eq_0"; |
346 qed "diff_self_eq_0"; |
347 |
347 |
348 Addsimps [diff_self_eq_0]; |
348 Addsimps [diff_self_eq_0]; |
430 Goal "i <= (j::nat) ==> (j-i=k) = (j=k+i)"; |
430 Goal "i <= (j::nat) ==> (j-i=k) = (j=k+i)"; |
431 by Safe_tac; |
431 by Safe_tac; |
432 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_add_inverse2]))); |
432 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_add_inverse2]))); |
433 qed "le_imp_diff_is_add"; |
433 qed "le_imp_diff_is_add"; |
434 |
434 |
435 Goal "(m-n = 0) = (m <= n)"; |
435 Goal "!!m::nat. (m-n = 0) = (m <= n)"; |
436 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
436 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
437 by (ALLGOALS Asm_simp_tac); |
437 by (ALLGOALS Asm_simp_tac); |
438 qed "diff_is_0_eq"; |
438 qed "diff_is_0_eq"; |
439 |
439 |
440 Goal "(0 = m-n) = (m <= n)"; |
440 Goal "!!m::nat. (0 = m-n) = (m <= n)"; |
441 by (stac (diff_is_0_eq RS sym) 1); |
441 by (stac (diff_is_0_eq RS sym) 1); |
442 by (rtac eq_sym_conv 1); |
442 by (rtac eq_sym_conv 1); |
443 qed "zero_is_diff_eq"; |
443 qed "zero_is_diff_eq"; |
444 Addsimps [diff_is_0_eq, zero_is_diff_eq]; |
444 Addsimps [diff_is_0_eq, zero_is_diff_eq]; |
445 |
445 |
446 Goal "(0<n-m) = (m<n)"; |
446 Goal "!!m::nat. (0<n-m) = (m<n)"; |
447 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
447 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
448 by (ALLGOALS Asm_simp_tac); |
448 by (ALLGOALS Asm_simp_tac); |
449 qed "zero_less_diff"; |
449 qed "zero_less_diff"; |
450 Addsimps [zero_less_diff]; |
450 Addsimps [zero_less_diff]; |
451 |
451 |
452 Goal "i < j ==> ? k. 0<k & i+k = j"; |
452 Goal "i < j ==> ? k::nat. 0<k & i+k = j"; |
453 by (res_inst_tac [("x","j - i")] exI 1); |
453 by (res_inst_tac [("x","j - i")] exI 1); |
454 by (asm_simp_tac (simpset() addsimps [add_diff_inverse, less_not_sym]) 1); |
454 by (asm_simp_tac (simpset() addsimps [add_diff_inverse, less_not_sym]) 1); |
455 qed "less_imp_add_positive"; |
455 qed "less_imp_add_positive"; |
456 |
456 |
457 Goal "P(k) --> (!n. P(Suc(n))--> P(n)) --> P(k-i)"; |
457 Goal "P(k) --> (!n. P(Suc(n))--> P(n)) --> P(k-i)"; |
473 Goal "(m+k) - (n+k) = m - (n::nat)"; |
473 Goal "(m+k) - (n+k) = m - (n::nat)"; |
474 by (asm_simp_tac |
474 by (asm_simp_tac |
475 (simpset() addsimps [diff_cancel, inst "n" "k" add_commute]) 1); |
475 (simpset() addsimps [diff_cancel, inst "n" "k" add_commute]) 1); |
476 qed "diff_cancel2"; |
476 qed "diff_cancel2"; |
477 |
477 |
478 Goal "n - (n+m) = 0"; |
478 Goal "n - (n+m) = (0::nat)"; |
479 by (induct_tac "n" 1); |
479 by (induct_tac "n" 1); |
480 by (ALLGOALS Asm_simp_tac); |
480 by (ALLGOALS Asm_simp_tac); |
481 qed "diff_add_0"; |
481 qed "diff_add_0"; |
482 |
482 |
483 |
483 |
512 by (etac (mult_le_mono1 RS le_trans) 1); |
512 by (etac (mult_le_mono1 RS le_trans) 1); |
513 by (etac mult_le_mono2 1); |
513 by (etac mult_le_mono2 1); |
514 qed "mult_le_mono"; |
514 qed "mult_le_mono"; |
515 |
515 |
516 (*strict, in 1st argument; proof is by induction on k>0*) |
516 (*strict, in 1st argument; proof is by induction on k>0*) |
517 Goal "[| i<j; 0<k |] ==> k*i < k*j"; |
517 Goal "!!i::nat. [| i<j; 0<k |] ==> k*i < k*j"; |
518 by (eres_inst_tac [("m1","0")] (less_eq_Suc_add RS exE) 1); |
518 by (eres_inst_tac [("m1","0")] (less_eq_Suc_add RS exE) 1); |
519 by (Asm_simp_tac 1); |
519 by (Asm_simp_tac 1); |
520 by (induct_tac "x" 1); |
520 by (induct_tac "x" 1); |
521 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_less_mono]))); |
521 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_less_mono]))); |
522 qed "mult_less_mono2"; |
522 qed "mult_less_mono2"; |
523 |
523 |
524 Goal "[| i<j; 0<k |] ==> i*k < j*k"; |
524 Goal "!!i::nat. [| i<j; 0<k |] ==> i*k < j*k"; |
525 by (dtac mult_less_mono2 1); |
525 by (dtac mult_less_mono2 1); |
526 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [mult_commute]))); |
526 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [mult_commute]))); |
527 qed "mult_less_mono1"; |
527 qed "mult_less_mono1"; |
528 |
528 |
529 Goal "(0 < m*n) = (0<m & 0<n)"; |
529 Goal "!!m::nat. (0 < m*n) = (0<m & 0<n)"; |
530 by (induct_tac "m" 1); |
530 by (induct_tac "m" 1); |
531 by (case_tac "n" 2); |
531 by (case_tac "n" 2); |
532 by (ALLGOALS Asm_simp_tac); |
532 by (ALLGOALS Asm_simp_tac); |
533 qed "zero_less_mult_iff"; |
533 qed "zero_less_mult_iff"; |
534 Addsimps [zero_less_mult_iff]; |
534 Addsimps [zero_less_mult_iff]; |
547 by (Simp_tac 1); |
547 by (Simp_tac 1); |
548 by (fast_tac (claset() addss simpset()) 1); |
548 by (fast_tac (claset() addss simpset()) 1); |
549 qed "mult_eq_1_iff"; |
549 qed "mult_eq_1_iff"; |
550 Addsimps [mult_eq_1_iff]; |
550 Addsimps [mult_eq_1_iff]; |
551 |
551 |
552 Goal "0<k ==> (m*k < n*k) = (m<n)"; |
552 Goal "!!m::nat. 0<k ==> (m*k < n*k) = (m<n)"; |
553 by (safe_tac (claset() addSIs [mult_less_mono1])); |
553 by (safe_tac (claset() addSIs [mult_less_mono1])); |
554 by (cut_facts_tac [less_linear] 1); |
554 by (cut_facts_tac [less_linear] 1); |
555 by (blast_tac (claset() addIs [mult_less_mono1] addEs [less_asym]) 1); |
555 by (blast_tac (claset() addIs [mult_less_mono1] addEs [less_asym]) 1); |
556 qed "mult_less_cancel2"; |
556 qed "mult_less_cancel2"; |
557 |
557 |
558 Goal "0<k ==> (k*m < k*n) = (m<n)"; |
558 Goal "!!m::nat. 0<k ==> (k*m < k*n) = (m<n)"; |
559 by (dtac mult_less_cancel2 1); |
559 by (dtac mult_less_cancel2 1); |
560 by (asm_full_simp_tac (simpset() addsimps [mult_commute]) 1); |
560 by (etac subst 1); |
|
561 by (simp_tac (simpset() addsimps [mult_commute]) 1); |
561 qed "mult_less_cancel1"; |
562 qed "mult_less_cancel1"; |
562 Addsimps [mult_less_cancel1, mult_less_cancel2]; |
563 Addsimps [mult_less_cancel1, mult_less_cancel2]; |
563 |
564 |
564 Goal "0<k ==> (m*k <= n*k) = (m<=n)"; |
565 Goal "!!m::nat. 0<k ==> (m*k <= n*k) = (m<=n)"; |
565 by (asm_full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1); |
566 by (asm_full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1); |
566 qed "mult_le_cancel2"; |
567 qed "mult_le_cancel2"; |
567 |
568 |
568 Goal "0<k ==> (k*m <= k*n) = (m<=n)"; |
569 Goal "!!m::nat. 0<k ==> (k*m <= k*n) = (m<=n)"; |
569 by (asm_full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1); |
570 by (asm_full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1); |
570 qed "mult_le_cancel1"; |
571 qed "mult_le_cancel1"; |
571 Addsimps [mult_le_cancel1, mult_le_cancel2]; |
572 Addsimps [mult_le_cancel1, mult_le_cancel2]; |
572 |
573 |
573 Goal "(Suc k * m < Suc k * n) = (m < n)"; |
574 Goal "(Suc k * m < Suc k * n) = (m < n)"; |
578 Goalw [le_def] "(Suc k * m <= Suc k * n) = (m <= n)"; |
579 Goalw [le_def] "(Suc k * m <= Suc k * n) = (m <= n)"; |
579 by (simp_tac (simpset_of HOL.thy) 1); |
580 by (simp_tac (simpset_of HOL.thy) 1); |
580 by (rtac Suc_mult_less_cancel1 1); |
581 by (rtac Suc_mult_less_cancel1 1); |
581 qed "Suc_mult_le_cancel1"; |
582 qed "Suc_mult_le_cancel1"; |
582 |
583 |
583 Goal "0<k ==> (m*k = n*k) = (m=n)"; |
584 Goal "0 < (k::nat) ==> (m*k = n*k) = (m=n)"; |
584 by (cut_facts_tac [less_linear] 1); |
585 by (cut_facts_tac [less_linear] 1); |
585 by Safe_tac; |
586 by Safe_tac; |
586 by (assume_tac 2); |
587 by (assume_tac 2); |
587 by (ALLGOALS (dtac mult_less_mono1 THEN' assume_tac)); |
588 by (ALLGOALS (dtac mult_less_mono1 THEN' assume_tac)); |
588 by (ALLGOALS Asm_full_simp_tac); |
589 by (ALLGOALS Asm_full_simp_tac); |
589 qed "mult_cancel2"; |
590 qed "mult_cancel2"; |
590 |
591 |
591 Goal "0<k ==> (k*m = k*n) = (m=n)"; |
592 Goal "0 < (k::nat) ==> (k*m = k*n) = (m=n)"; |
592 by (dtac mult_cancel2 1); |
593 by (dtac mult_cancel2 1); |
593 by (asm_full_simp_tac (simpset() addsimps [mult_commute]) 1); |
594 by (asm_full_simp_tac (simpset() addsimps [mult_commute]) 1); |
594 qed "mult_cancel1"; |
595 qed "mult_cancel1"; |
595 Addsimps [mult_cancel1, mult_cancel2]; |
596 Addsimps [mult_cancel1, mult_cancel2]; |
596 |
597 |
599 by (Simp_tac 1); |
600 by (Simp_tac 1); |
600 qed "Suc_mult_cancel1"; |
601 qed "Suc_mult_cancel1"; |
601 |
602 |
602 |
603 |
603 (*Lemma for gcd*) |
604 (*Lemma for gcd*) |
604 Goal "m = m*n ==> n=1 | m=0"; |
605 Goal "!!m::nat. m = m*n ==> n=1 | m=0"; |
605 by (dtac sym 1); |
606 by (dtac sym 1); |
606 by (rtac disjCI 1); |
607 by (rtac disjCI 1); |
607 by (rtac nat_less_cases 1 THEN assume_tac 2); |
608 by (rtac nat_less_cases 1 THEN assume_tac 2); |
608 by (fast_tac (claset() addSEs [less_SucE] addss simpset()) 1); |
609 by (fast_tac (claset() addSEs [less_SucE] addss simpset()) 1); |
609 by (best_tac (claset() addDs [mult_less_mono2] addss simpset()) 1); |
610 by (best_tac (claset() addDs [mult_less_mono2] addss simpset()) 1); |
1086 Goal "n - Suc i <= n - i"; |
1087 Goal "n - Suc i <= n - i"; |
1087 by (arith_tac 1); |
1088 by (arith_tac 1); |
1088 qed "diff_Suc_le_diff"; |
1089 qed "diff_Suc_le_diff"; |
1089 AddIffs [diff_Suc_le_diff]; |
1090 AddIffs [diff_Suc_le_diff]; |
1090 |
1091 |
1091 Goal "0 < n ==> (m <= n-1) = (m<n)"; |
1092 Goal "!!m::nat. 0 < n ==> (m <= n-1) = (m<n)"; |
1092 by (arith_tac 1); |
1093 by (arith_tac 1); |
1093 qed "le_pred_eq"; |
1094 qed "le_pred_eq"; |
1094 |
1095 |
1095 Goal "0 < n ==> (m-1 < n) = (m<=n)"; |
1096 Goal "!!m::nat. 0 < n ==> (m-1 < n) = (m<=n)"; |
1096 by (arith_tac 1); |
1097 by (arith_tac 1); |
1097 qed "less_pred_eq"; |
1098 qed "less_pred_eq"; |
1098 |
1099 |
1099 (*Replaces the previous diff_less and le_diff_less, which had the stronger |
1100 (*Replaces the previous diff_less and le_diff_less, which had the stronger |
1100 second premise n<=m*) |
1101 second premise n<=m*) |
1101 Goal "[| 0<n; 0<m |] ==> m - n < m"; |
1102 Goal "!!m::nat. [| 0<n; 0<m |] ==> m - n < m"; |
1102 by (arith_tac 1); |
1103 by (arith_tac 1); |
1103 qed "diff_less"; |
1104 qed "diff_less"; |
1104 |
1105 |
1105 Goal "j <= (k::nat) ==> (j+i)-k = i-(k-j)"; |
1106 Goal "j <= (k::nat) ==> (j+i)-k = i-(k-j)"; |
1106 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1107 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1157 |
1158 |
1158 Goal "[| m < (n::nat); m<l |] ==> (l-n) < (l-m)"; |
1159 Goal "[| m < (n::nat); m<l |] ==> (l-n) < (l-m)"; |
1159 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1160 by (asm_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1160 qed "diff_less_mono2"; |
1161 qed "diff_less_mono2"; |
1161 |
1162 |
1162 Goal "[| m-n = 0; n-m = 0 |] ==> m=n"; |
1163 Goal "!!m::nat. [| m-n = 0; n-m = 0 |] ==> m=n"; |
1163 by (asm_full_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1164 by (asm_full_simp_tac (simpset() addsplits [nat_diff_split]) 1); |
1164 qed "diffs0_imp_equal"; |
1165 qed "diffs0_imp_equal"; |
1165 |
1166 |
1166 (** Lemmas for ex/Factorization **) |
1167 (** Lemmas for ex/Factorization **) |
1167 |
1168 |
1168 Goal "[| 1<n; 1<m |] ==> 1<m*n"; |
1169 Goal "!!m::nat. [| 1<n; 1<m |] ==> 1<m*n"; |
1169 by (case_tac "m" 1); |
1170 by (case_tac "m" 1); |
1170 by Auto_tac; |
1171 by Auto_tac; |
1171 qed "one_less_mult"; |
1172 qed "one_less_mult"; |
1172 |
1173 |
1173 Goal "[| 1<n; 1<m |] ==> n<m*n"; |
1174 Goal "!!m::nat. [| 1<n; 1<m |] ==> n<m*n"; |
1174 by (case_tac "m" 1); |
1175 by (case_tac "m" 1); |
1175 by Auto_tac; |
1176 by Auto_tac; |
1176 qed "n_less_m_mult_n"; |
1177 qed "n_less_m_mult_n"; |
1177 |
1178 |
1178 Goal "[| 1<n; 1<m |] ==> n<n*m"; |
1179 Goal "!!m::nat. [| 1<n; 1<m |] ==> n<n*m"; |
1179 by (case_tac "m" 1); |
1180 by (case_tac "m" 1); |
1180 by Auto_tac; |
1181 by Auto_tac; |
1181 qed "n_less_n_mult_m"; |
1182 qed "n_less_n_mult_m"; |
1182 |
1183 |
1183 |
1184 |