4 Copyright 1992 University of Cambridge |
4 Copyright 1992 University of Cambridge |
5 |
5 |
6 Arithmetic operators and their definitions |
6 Arithmetic operators and their definitions |
7 |
7 |
8 Proofs about elementary arithmetic: addition, multiplication, etc. |
8 Proofs about elementary arithmetic: addition, multiplication, etc. |
9 |
|
10 Could prove def_rec_0, def_rec_succ... |
|
11 *) |
9 *) |
12 |
|
13 open Arith; |
|
14 |
10 |
15 (*"Difference" is subtraction of natural numbers. |
11 (*"Difference" is subtraction of natural numbers. |
16 There are no negative numbers; we have |
12 There are no negative numbers; we have |
17 m #- n = 0 iff m<=n and m #- n = succ(k) iff m>n. |
13 m #- n = 0 iff m<=n and m #- n = succ(k) iff m>n. |
18 Also, rec(m, 0, %z w.z) is pred(m). |
14 Also, rec(m, 0, %z w.z) is pred(m). |
19 *) |
15 *) |
20 |
16 |
21 (** rec -- better than nat_rec; the succ case has no type requirement! **) |
|
22 |
|
23 val rec_trans = rec_def RS def_transrec RS trans; |
|
24 |
|
25 Goal "rec(0,a,b) = a"; |
|
26 by (rtac rec_trans 1); |
|
27 by (rtac nat_case_0 1); |
|
28 qed "rec_0"; |
|
29 |
|
30 Goal "rec(succ(m),a,b) = b(m, rec(m,a,b))"; |
|
31 by (rtac rec_trans 1); |
|
32 by (Simp_tac 1); |
|
33 qed "rec_succ"; |
|
34 |
|
35 Addsimps [rec_0, rec_succ]; |
|
36 |
|
37 val major::prems = Goal |
|
38 "[| n: nat; \ |
|
39 \ a: C(0); \ |
|
40 \ !!m z. [| m: nat; z: C(m) |] ==> b(m,z): C(succ(m)) \ |
|
41 \ |] ==> rec(n,a,b) : C(n)"; |
|
42 by (rtac (major RS nat_induct) 1); |
|
43 by (ALLGOALS |
|
44 (asm_simp_tac (simpset() addsimps prems))); |
|
45 qed "rec_type"; |
|
46 |
|
47 Addsimps [rec_type, nat_0_le, nat_le_refl]; |
17 Addsimps [rec_type, nat_0_le, nat_le_refl]; |
48 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat]; |
18 val nat_typechecks = [rec_type, nat_0I, nat_1I, nat_succI, Ord_nat]; |
49 |
19 |
50 Goal "[| 0<k; k: nat |] ==> EX j: nat. k = succ(j)"; |
20 Goal "[| 0<k; k: nat |] ==> EX j: nat. k = succ(j)"; |
51 by (etac rev_mp 1); |
21 by (etac rev_mp 1); |
52 by (etac nat_induct 1); |
22 by (induct_tac "k" 1); |
53 by (Simp_tac 1); |
23 by (Simp_tac 1); |
54 by (Blast_tac 1); |
24 by (Blast_tac 1); |
55 val lemma = result(); |
25 val lemma = result(); |
56 |
26 |
57 (* [| 0 < k; k: nat; !!j. [| j: nat; k = succ(j) |] ==> Q |] ==> Q *) |
27 (* [| 0 < k; k: nat; !!j. [| j: nat; k = succ(j) |] ==> Q |] ==> Q *) |
58 bind_thm ("zero_lt_natE", lemma RS bexE); |
28 bind_thm ("zero_lt_natE", lemma RS bexE); |
59 |
29 |
60 |
30 |
61 (** Addition **) |
31 (** Addition **) |
62 |
32 |
63 qed_goalw "add_type" Arith.thy [add_def] |
33 Goal "[| m:nat; n:nat |] ==> m #+ n : nat"; |
64 "[| m:nat; n:nat |] ==> m #+ n : nat" |
34 by (induct_tac "m" 1); |
65 (fn prems=> [ (typechk_tac (prems@nat_typechecks@ZF_typechecks)) ]); |
35 by Auto_tac; |
66 |
36 qed "add_type"; |
67 qed_goalw "add_0" Arith.thy [add_def] |
37 Addsimps [add_type]; |
68 "0 #+ n = n" |
|
69 (fn _ => [ (rtac rec_0 1) ]); |
|
70 |
|
71 qed_goalw "add_succ" Arith.thy [add_def] |
|
72 "succ(m) #+ n = succ(m #+ n)" |
|
73 (fn _=> [ (rtac rec_succ 1) ]); |
|
74 |
|
75 Addsimps [add_0, add_succ]; |
|
76 |
38 |
77 (** Multiplication **) |
39 (** Multiplication **) |
78 |
40 |
79 qed_goalw "mult_type" Arith.thy [mult_def] |
41 Goal "[| m:nat; n:nat |] ==> m #* n : nat"; |
80 "[| m:nat; n:nat |] ==> m #* n : nat" |
42 by (induct_tac "m" 1); |
81 (fn prems=> |
43 by Auto_tac; |
82 [ (typechk_tac (prems@[add_type]@nat_typechecks@ZF_typechecks)) ]); |
44 qed "mult_type"; |
83 |
45 Addsimps [mult_type]; |
84 qed_goalw "mult_0" Arith.thy [mult_def] |
46 |
85 "0 #* n = 0" |
|
86 (fn _ => [ (rtac rec_0 1) ]); |
|
87 |
|
88 qed_goalw "mult_succ" Arith.thy [mult_def] |
|
89 "succ(m) #* n = n #+ (m #* n)" |
|
90 (fn _ => [ (rtac rec_succ 1) ]); |
|
91 |
|
92 Addsimps [mult_0, mult_succ]; |
|
93 |
47 |
94 (** Difference **) |
48 (** Difference **) |
95 |
49 |
96 qed_goalw "diff_type" Arith.thy [diff_def] |
50 Goal "[| m:nat; n:nat |] ==> m #- n : nat"; |
97 "[| m:nat; n:nat |] ==> m #- n : nat" |
51 by (induct_tac "n" 1); |
98 (fn prems=> [ (typechk_tac (prems@nat_typechecks@ZF_typechecks)) ]); |
52 by Auto_tac; |
99 |
53 by (fast_tac (claset() addIs [nat_case_type]) 1); |
100 qed_goalw "diff_0" Arith.thy [diff_def] |
54 qed "diff_type"; |
101 "m #- 0 = m" |
55 Addsimps [diff_type]; |
102 (fn _ => [ (rtac rec_0 1) ]); |
56 |
103 |
57 Goal "n:nat ==> 0 #- n = 0"; |
104 qed_goalw "diff_0_eq_0" Arith.thy [diff_def] |
58 by (induct_tac "n" 1); |
105 "n:nat ==> 0 #- n = 0" |
59 by Auto_tac; |
106 (fn [prem]=> |
60 qed "diff_0_eq_0"; |
107 [ (rtac (prem RS nat_induct) 1), |
61 |
108 (ALLGOALS (Asm_simp_tac)) ]); |
62 (*Must simplify BEFORE the induction: else we get a critical pair*) |
109 |
63 Goal "[| m:nat; n:nat |] ==> succ(m) #- succ(n) = m #- n"; |
110 (*Must simplify BEFORE the induction!! (Else we get a critical pair) |
64 by (Asm_simp_tac 1); |
111 succ(m) #- succ(n) rewrites to pred(succ(m) #- n) *) |
65 by (induct_tac "n" 1); |
112 qed_goalw "diff_succ_succ" Arith.thy [diff_def] |
66 by Auto_tac; |
113 "[| m:nat; n:nat |] ==> succ(m) #- succ(n) = m #- n" |
67 qed "diff_succ_succ"; |
114 (fn prems=> |
68 |
115 [ (asm_simp_tac (simpset() addsimps prems) 1), |
69 Addsimps [diff_0_eq_0, diff_succ_succ]; |
116 (nat_ind_tac "n" prems 1), |
70 |
117 (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); |
71 (*This defining property is no longer wanted*) |
118 |
72 Delsimps [diff_SUCC]; |
119 Addsimps [diff_0, diff_0_eq_0, diff_succ_succ]; |
|
120 |
73 |
121 val prems = goal Arith.thy |
74 val prems = goal Arith.thy |
122 "[| m:nat; n:nat |] ==> m #- n le m"; |
75 "[| m:nat; n:nat |] ==> m #- n le m"; |
123 by (rtac (prems MRS diff_induct) 1); |
76 by (rtac (prems MRS diff_induct) 1); |
124 by (etac leE 3); |
77 by (etac leE 3); |
127 qed "diff_le_self"; |
80 qed "diff_le_self"; |
128 |
81 |
129 (*** Simplification over add, mult, diff ***) |
82 (*** Simplification over add, mult, diff ***) |
130 |
83 |
131 val arith_typechecks = [add_type, mult_type, diff_type]; |
84 val arith_typechecks = [add_type, mult_type, diff_type]; |
132 Addsimps arith_typechecks; |
|
133 |
85 |
134 |
86 |
135 (*** Addition ***) |
87 (*** Addition ***) |
136 |
88 |
137 (*Associative law for addition*) |
89 (*Associative law for addition*) |
138 qed_goal "add_assoc" Arith.thy |
90 Goal "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)"; |
139 "m:nat ==> (m #+ n) #+ k = m #+ (n #+ k)" |
91 by (induct_tac "m" 1); |
140 (fn prems=> |
92 by Auto_tac; |
141 [ (nat_ind_tac "m" prems 1), |
93 qed "add_assoc"; |
142 (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); |
|
143 |
94 |
144 (*The following two lemmas are used for add_commute and sometimes |
95 (*The following two lemmas are used for add_commute and sometimes |
145 elsewhere, since they are safe for rewriting.*) |
96 elsewhere, since they are safe for rewriting.*) |
146 qed_goal "add_0_right" Arith.thy |
97 Goal "m:nat ==> m #+ 0 = m"; |
147 "m:nat ==> m #+ 0 = m" |
98 by (induct_tac "m" 1); |
148 (fn prems=> |
99 by Auto_tac; |
149 [ (nat_ind_tac "m" prems 1), |
100 qed "add_0_right"; |
150 (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); |
101 |
151 |
102 Goal "m:nat ==> m #+ succ(n) = succ(m #+ n)"; |
152 qed_goal "add_succ_right" Arith.thy |
103 by (induct_tac "m" 1); |
153 "m:nat ==> m #+ succ(n) = succ(m #+ n)" |
104 by Auto_tac; |
154 (fn prems=> |
105 qed "add_succ_right"; |
155 [ (nat_ind_tac "m" prems 1), |
|
156 (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); |
|
157 |
106 |
158 Addsimps [add_0_right, add_succ_right]; |
107 Addsimps [add_0_right, add_succ_right]; |
159 |
108 |
160 (*Commutative law for addition*) |
109 (*Commutative law for addition*) |
161 qed_goal "add_commute" Arith.thy |
110 Goal "[| m:nat; n:nat |] ==> m #+ n = n #+ m"; |
162 "!!m n. [| m:nat; n:nat |] ==> m #+ n = n #+ m" |
111 by (induct_tac "n" 1); |
163 (fn _ => |
112 by Auto_tac; |
164 [ (nat_ind_tac "n" [] 1), |
113 qed "add_commute"; |
165 (ALLGOALS Asm_simp_tac) ]); |
|
166 |
114 |
167 (*for a/c rewriting*) |
115 (*for a/c rewriting*) |
168 qed_goal "add_left_commute" Arith.thy |
116 Goal "[| m:nat; n:nat |] ==> m#+(n#+k)=n#+(m#+k)"; |
169 "!!m n k. [| m:nat; n:nat |] ==> m#+(n#+k)=n#+(m#+k)" |
117 by (asm_simp_tac (simpset() addsimps [add_assoc RS sym, add_commute]) 1); |
170 (fn _ => [asm_simp_tac(simpset() addsimps [add_assoc RS sym, add_commute]) 1]); |
118 qed "add_left_commute"; |
171 |
119 |
172 (*Addition is an AC-operator*) |
120 (*Addition is an AC-operator*) |
173 val add_ac = [add_assoc, add_commute, add_left_commute]; |
121 val add_ac = [add_assoc, add_commute, add_left_commute]; |
174 |
122 |
175 (*Cancellation law on the left*) |
123 (*Cancellation law on the left*) |
176 val [eqn,knat] = goal Arith.thy |
124 Goal "[| k #+ m = k #+ n; k:nat |] ==> m=n"; |
177 "[| k #+ m = k #+ n; k:nat |] ==> m=n"; |
125 by (etac rev_mp 1); |
178 by (rtac (eqn RS rev_mp) 1); |
126 by (induct_tac "k" 1); |
179 by (nat_ind_tac "k" [knat] 1); |
127 by Auto_tac; |
180 by (ALLGOALS (Simp_tac)); |
|
181 qed "add_left_cancel"; |
128 qed "add_left_cancel"; |
182 |
129 |
183 (*** Multiplication ***) |
130 (*** Multiplication ***) |
184 |
131 |
185 (*right annihilation in product*) |
132 (*right annihilation in product*) |
186 qed_goal "mult_0_right" Arith.thy |
133 Goal "m:nat ==> m #* 0 = 0"; |
187 "!!m. m:nat ==> m #* 0 = 0" |
134 by (induct_tac "m" 1); |
188 (fn _=> |
135 by Auto_tac; |
189 [ (nat_ind_tac "m" [] 1), |
136 qed "mult_0_right"; |
190 (ALLGOALS (Asm_simp_tac)) ]); |
|
191 |
137 |
192 (*right successor law for multiplication*) |
138 (*right successor law for multiplication*) |
193 qed_goal "mult_succ_right" Arith.thy |
139 Goal "[| m:nat; n:nat |] ==> m #* succ(n) = m #+ (m #* n)"; |
194 "!!m n. [| m:nat; n:nat |] ==> m #* succ(n) = m #+ (m #* n)" |
140 by (induct_tac "m" 1); |
195 (fn _ => |
141 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac))); |
196 [ (nat_ind_tac "m" [] 1), |
142 qed "mult_succ_right"; |
197 (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac))) ]); |
|
198 |
143 |
199 Addsimps [mult_0_right, mult_succ_right]; |
144 Addsimps [mult_0_right, mult_succ_right]; |
200 |
145 |
201 Goal "n:nat ==> 1 #* n = n"; |
146 Goal "n:nat ==> 1 #* n = n"; |
202 by (Asm_simp_tac 1); |
147 by (Asm_simp_tac 1); |
204 |
149 |
205 Goal "n:nat ==> n #* 1 = n"; |
150 Goal "n:nat ==> n #* 1 = n"; |
206 by (Asm_simp_tac 1); |
151 by (Asm_simp_tac 1); |
207 qed "mult_1_right"; |
152 qed "mult_1_right"; |
208 |
153 |
|
154 Addsimps [mult_1, mult_1_right]; |
|
155 |
209 (*Commutative law for multiplication*) |
156 (*Commutative law for multiplication*) |
210 qed_goal "mult_commute" Arith.thy |
157 Goal "[| m:nat; n:nat |] ==> m #* n = n #* m"; |
211 "!!m n. [| m:nat; n:nat |] ==> m #* n = n #* m" |
158 by (induct_tac "m" 1); |
212 (fn _=> |
159 by Auto_tac; |
213 [ (nat_ind_tac "m" [] 1), |
160 qed "mult_commute"; |
214 (ALLGOALS Asm_simp_tac) ]); |
|
215 |
161 |
216 (*addition distributes over multiplication*) |
162 (*addition distributes over multiplication*) |
217 qed_goal "add_mult_distrib" Arith.thy |
163 Goal "[| m:nat; k:nat |] ==> (m #+ n) #* k = (m #* k) #+ (n #* k)"; |
218 "!!m n. [| m:nat; k:nat |] ==> (m #+ n) #* k = (m #* k) #+ (n #* k)" |
164 by (induct_tac "m" 1); |
219 (fn _=> |
165 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_assoc RS sym]))); |
220 [ (etac nat_induct 1), |
166 qed "add_mult_distrib"; |
221 (ALLGOALS (asm_simp_tac (simpset() addsimps [add_assoc RS sym]))) ]); |
|
222 |
167 |
223 (*Distributive law on the left; requires an extra typing premise*) |
168 (*Distributive law on the left; requires an extra typing premise*) |
224 qed_goal "add_mult_distrib_left" Arith.thy |
169 Goal "[| m:nat; n:nat; k:nat |] ==> k #* (m #+ n) = (k #* m) #+ (k #* n)"; |
225 "!!m. [| m:nat; n:nat; k:nat |] ==> k #* (m #+ n) = (k #* m) #+ (k #* n)" |
170 by (induct_tac "m" 1); |
226 (fn prems=> |
171 by (ALLGOALS (asm_simp_tac (simpset() addsimps add_ac))); |
227 [ (nat_ind_tac "m" [] 1), |
172 qed "add_mult_distrib_left"; |
228 (Asm_simp_tac 1), |
|
229 (asm_simp_tac (simpset() addsimps add_ac) 1) ]); |
|
230 |
173 |
231 (*Associative law for multiplication*) |
174 (*Associative law for multiplication*) |
232 qed_goal "mult_assoc" Arith.thy |
175 Goal "[| m:nat; n:nat; k:nat |] ==> (m #* n) #* k = m #* (n #* k)"; |
233 "!!m n k. [| m:nat; n:nat; k:nat |] ==> (m #* n) #* k = m #* (n #* k)" |
176 by (induct_tac "m" 1); |
234 (fn _=> |
177 by (ALLGOALS (asm_simp_tac (simpset() addsimps [add_mult_distrib]))); |
235 [ (etac nat_induct 1), |
178 qed "mult_assoc"; |
236 (ALLGOALS (asm_simp_tac (simpset() addsimps [add_mult_distrib]))) ]); |
|
237 |
179 |
238 (*for a/c rewriting*) |
180 (*for a/c rewriting*) |
239 qed_goal "mult_left_commute" Arith.thy |
181 Goal "[| m:nat; n:nat; k:nat |] ==> m #* (n #* k) = n #* (m #* k)"; |
240 "!!m n k. [| m:nat; n:nat; k:nat |] ==> m #* (n #* k) = n #* (m #* k)" |
182 by (rtac (mult_commute RS trans) 1); |
241 (fn _ => [rtac (mult_commute RS trans) 1, |
183 by (rtac (mult_assoc RS trans) 3); |
242 rtac (mult_assoc RS trans) 3, |
184 by (rtac (mult_commute RS subst_context) 6); |
243 rtac (mult_commute RS subst_context) 6, |
185 by (REPEAT (ares_tac [mult_type] 1)); |
244 REPEAT (ares_tac [mult_type] 1)]); |
186 qed "mult_left_commute"; |
245 |
187 |
246 val mult_ac = [mult_assoc,mult_commute,mult_left_commute]; |
188 val mult_ac = [mult_assoc,mult_commute,mult_left_commute]; |
247 |
189 |
248 |
190 |
249 (*** Difference ***) |
191 (*** Difference ***) |
250 |
192 |
251 qed_goal "diff_self_eq_0" Arith.thy |
193 Goal "m:nat ==> m #- m = 0"; |
252 "m:nat ==> m #- m = 0" |
194 by (induct_tac "m" 1); |
253 (fn prems=> |
195 by Auto_tac; |
254 [ (nat_ind_tac "m" prems 1), |
196 qed "diff_self_eq_0"; |
255 (ALLGOALS (asm_simp_tac (simpset() addsimps prems))) ]); |
|
256 |
197 |
257 (*Addition is the inverse of subtraction*) |
198 (*Addition is the inverse of subtraction*) |
258 Goal "[| n le m; m:nat |] ==> n #+ (m#-n) = m"; |
199 Goal "[| n le m; m:nat |] ==> n #+ (m#-n) = m"; |
259 by (forward_tac [lt_nat_in_nat] 1); |
200 by (forward_tac [lt_nat_in_nat] 1); |
260 by (etac nat_succI 1); |
201 by (etac nat_succI 1); |
285 Addsimps [zero_less_diff]; |
226 Addsimps [zero_less_diff]; |
286 |
227 |
287 |
228 |
288 (** Subtraction is the inverse of addition. **) |
229 (** Subtraction is the inverse of addition. **) |
289 |
230 |
290 val [mnat,nnat] = goal Arith.thy |
231 Goal "[| m:nat; n:nat |] ==> (n#+m) #- n = m"; |
291 "[| m:nat; n:nat |] ==> (n#+m) #- n = m"; |
232 by (induct_tac "n" 1); |
292 by (rtac (nnat RS nat_induct) 1); |
233 by Auto_tac; |
293 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat]))); |
|
294 qed "diff_add_inverse"; |
234 qed "diff_add_inverse"; |
295 |
235 |
296 Goal "[| m:nat; n:nat |] ==> (m#+n) #- n = m"; |
236 Goal "[| m:nat; n:nat |] ==> (m#+n) #- n = m"; |
297 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1); |
237 by (res_inst_tac [("m1","m")] (add_commute RS ssubst) 1); |
298 by (REPEAT (ares_tac [diff_add_inverse] 1)); |
238 by (REPEAT (ares_tac [diff_add_inverse] 1)); |
299 qed "diff_add_inverse2"; |
239 qed "diff_add_inverse2"; |
300 |
240 |
301 Goal "[| k:nat; m: nat; n: nat |] ==> (k#+m) #- (k#+n) = m #- n"; |
241 Goal "[| k:nat; m: nat; n: nat |] ==> (k#+m) #- (k#+n) = m #- n"; |
302 by (nat_ind_tac "k" [] 1); |
242 by (induct_tac "k" 1); |
303 by (ALLGOALS Asm_simp_tac); |
243 by (ALLGOALS Asm_simp_tac); |
304 qed "diff_cancel"; |
244 qed "diff_cancel"; |
305 |
245 |
306 Goal "[| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n"; |
246 Goal "[| k:nat; m: nat; n: nat |] ==> (m#+k) #- (n#+k) = m #- n"; |
307 val add_commute_k = read_instantiate [("n","k")] add_commute; |
247 val add_commute_k = read_instantiate [("n","k")] add_commute; |
308 by (asm_simp_tac (simpset() addsimps [add_commute_k, diff_cancel]) 1); |
248 by (asm_simp_tac (simpset() addsimps [add_commute_k, diff_cancel]) 1); |
309 qed "diff_cancel2"; |
249 qed "diff_cancel2"; |
310 |
250 |
311 val [mnat,nnat] = goal Arith.thy |
251 Goal "[| m:nat; n:nat |] ==> n #- (n#+m) = 0"; |
312 "[| m:nat; n:nat |] ==> n #- (n#+m) = 0"; |
252 by (induct_tac "n" 1); |
313 by (rtac (nnat RS nat_induct) 1); |
253 by Auto_tac; |
314 by (ALLGOALS (asm_simp_tac (simpset() addsimps [mnat]))); |
|
315 qed "diff_add_0"; |
254 qed "diff_add_0"; |
316 |
255 |
317 (** Difference distributes over multiplication **) |
256 (** Difference distributes over multiplication **) |
318 |
257 |
319 Goal "[| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)"; |
258 Goal "[| m:nat; n: nat; k:nat |] ==> (m #- n) #* k = (m #* k) #- (n #* k)"; |
332 Goal "[| 0<n; n le m; m:nat |] ==> m #- n < m"; |
271 Goal "[| 0<n; n le m; m:nat |] ==> m #- n < m"; |
333 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1); |
272 by (forward_tac [lt_nat_in_nat] 1 THEN etac nat_succI 1); |
334 by (etac rev_mp 1); |
273 by (etac rev_mp 1); |
335 by (etac rev_mp 1); |
274 by (etac rev_mp 1); |
336 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
275 by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); |
337 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_le_self,diff_succ_succ]))); |
276 by (ALLGOALS (asm_simp_tac (simpset() addsimps [diff_le_self]))); |
338 qed "div_termination"; |
277 qed "div_termination"; |
339 |
278 |
340 val div_rls = (*for mod and div*) |
279 val div_rls = (*for mod and div*) |
341 nat_typechecks @ |
280 nat_typechecks @ |
342 [Ord_transrec_type, apply_type, div_termination RS ltD, if_type, |
281 [Ord_transrec_type, apply_type, div_termination RS ltD, if_type, |
343 nat_into_Ord, not_lt_iff_le RS iffD1]; |
282 nat_into_Ord, not_lt_iff_le RS iffD1]; |
344 |
283 |
345 val div_ss = (simpset()) addsimps [nat_into_Ord, div_termination RS ltD, |
284 val div_ss = simpset() addsimps [nat_into_Ord, div_termination RS ltD, |
346 not_lt_iff_le RS iffD2]; |
285 not_lt_iff_le RS iffD2]; |
347 |
286 |
348 (*Type checking depends upon termination!*) |
287 (*Type checking depends upon termination!*) |
349 Goalw [mod_def] "[| 0<n; m:nat; n:nat |] ==> m mod n : nat"; |
288 Goalw [mod_def] "[| 0<n; m:nat; n:nat |] ==> m mod n : nat"; |
350 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1)); |
289 by (REPEAT (ares_tac div_rls 1 ORELSE etac lt_trans 1)); |
351 qed "mod_type"; |
290 qed "mod_type"; |
440 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2); |
379 by (asm_simp_tac (simpset() addsimps [mod_less_divisor RS ltD]) 2); |
441 by (asm_simp_tac (simpset() addsimps [mod_succ] setloop Step_tac) 1); |
380 by (asm_simp_tac (simpset() addsimps [mod_succ] setloop Step_tac) 1); |
442 qed "mod2_succ_succ"; |
381 qed "mod2_succ_succ"; |
443 |
382 |
444 Goal "m:nat ==> (m#+m) mod 2 = 0"; |
383 Goal "m:nat ==> (m#+m) mod 2 = 0"; |
445 by (etac nat_induct 1); |
384 by (induct_tac "m" 1); |
446 by (simp_tac (simpset() addsimps [mod_less]) 1); |
385 by (simp_tac (simpset() addsimps [mod_less]) 1); |
447 by (asm_simp_tac (simpset() addsimps [mod2_succ_succ, add_succ_right]) 1); |
386 by (asm_simp_tac (simpset() addsimps [mod2_succ_succ, add_succ_right]) 1); |
448 qed "mod2_add_self"; |
387 qed "mod2_add_self"; |
449 |
388 |
450 |
389 |
451 (**** Additional theorems about "le" ****) |
390 (**** Additional theorems about "le" ****) |
452 |
391 |
453 Goal "[| m:nat; n:nat |] ==> m le m #+ n"; |
392 Goal "[| m:nat; n:nat |] ==> m le m #+ n"; |
454 by (etac nat_induct 1); |
393 by (induct_tac "m" 1); |
455 by (ALLGOALS Asm_simp_tac); |
394 by (ALLGOALS Asm_simp_tac); |
456 qed "add_le_self"; |
395 qed "add_le_self"; |
457 |
396 |
458 Goal "[| m:nat; n:nat |] ==> m le n #+ m"; |
397 Goal "[| m:nat; n:nat |] ==> m le n #+ m"; |
459 by (stac add_commute 1); |
398 by (stac add_commute 1); |
569 zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq, |
508 zero_lt_mult_iff, le_refl RS mult_le_mono, mod_geq, |
570 diff_mult_distrib2 RS sym, |
509 diff_mult_distrib2 RS sym, |
571 div_termination RS ltD]) 1); |
510 div_termination RS ltD]) 1); |
572 qed "mult_mod_distrib"; |
511 qed "mult_mod_distrib"; |
573 |
512 |
574 (** Lemma for gcd **) |
513 (*Lemma for gcd*) |
575 |
|
576 val mono_lemma = (nat_into_Ord RS Ord_0_lt) RSN (2,mult_lt_mono2); |
|
577 |
|
578 Goal "[| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0"; |
514 Goal "[| m = m#*n; m: nat; n: nat |] ==> n=1 | m=0"; |
579 by (rtac disjCI 1); |
515 by (rtac disjCI 1); |
580 by (dtac sym 1); |
516 by (dtac sym 1); |
581 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I])); |
517 by (rtac Ord_linear_lt 1 THEN REPEAT_SOME (ares_tac [nat_into_Ord,nat_1I])); |
582 by (fast_tac (claset() addss (simpset())) 1); |
518 by (dtac (nat_into_Ord RS Ord_0_lt RSN (2,mult_lt_mono2)) 2); |
583 by (fast_tac (le_cs addDs [mono_lemma] |
519 by Auto_tac; |
584 addss (simpset() addsimps [mult_1_right])) 1); |
|
585 qed "mult_eq_self_implies_10"; |
520 qed "mult_eq_self_implies_10"; |
586 |
|
587 |
521 |
588 (*Thanks to Sten Agerholm*) |
522 (*Thanks to Sten Agerholm*) |
589 Goal "[|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k"; |
523 Goal "[|m#+n le m#+k; m:nat; n:nat; k:nat|] ==> n le k"; |
590 by (etac rev_mp 1); |
524 by (etac rev_mp 1); |
591 by (eres_inst_tac [("n","n")] nat_induct 1); |
525 by (induct_tac "m" 1); |
592 by (Asm_simp_tac 1); |
526 by (Asm_simp_tac 1); |
593 by Safe_tac; |
527 by Safe_tac; |
594 by (asm_full_simp_tac (simpset() addsimps [not_le_iff_lt,nat_into_Ord]) 1); |
528 by (asm_full_simp_tac (simpset() addsimps [not_le_iff_lt,nat_into_Ord]) 1); |
595 by (etac lt_asym 1); |
|
596 by (assume_tac 1); |
|
597 by (Asm_full_simp_tac 1); |
|
598 by (asm_full_simp_tac (simpset() addsimps [le_iff, nat_into_Ord]) 1); |
|
599 by (Blast_tac 1); |
|
600 qed "add_le_elim1"; |
529 qed "add_le_elim1"; |
601 |
530 |
602 Goal "[| m<n; n: nat |] ==> EX k: nat. n = succ(m#+k)"; |
531 Goal "[| m<n; n: nat |] ==> EX k: nat. n = succ(m#+k)"; |
603 by (forward_tac [lt_nat_in_nat] 1 THEN assume_tac 1); |
532 by (forward_tac [lt_nat_in_nat] 1 THEN assume_tac 1); |
604 be rev_mp 1; |
533 be rev_mp 1; |
605 by (etac nat_induct 1); |
534 by (induct_tac "n" 1); |
606 by (ALLGOALS (simp_tac (simpset() addsimps [le_iff]))); |
535 by (ALLGOALS (simp_tac (simpset() addsimps [le_iff]))); |
607 by (blast_tac (claset() addSEs [leE] |
536 by (blast_tac (claset() addSEs [leE] |
608 addSIs [add_0_right RS sym, add_succ_right RS sym]) 1); |
537 addSIs [add_0_right RS sym, add_succ_right RS sym]) 1); |
609 qed_spec_mp "less_imp_Suc_add"; |
538 qed_spec_mp "less_imp_Suc_add"; |