1 (* Title: ZF/intr-elim.ML |
1 (* Title: ZF/intr-elim.ML |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
4 Copyright 1993 University of Cambridge |
4 Copyright 1994 University of Cambridge |
5 |
5 |
6 Introduction/elimination rule module -- for Inductive/Coinductive Definitions |
6 Introduction/elimination rule module -- for Inductive/Coinductive Definitions |
7 |
|
8 Features: |
|
9 * least or greatest fixedpoints |
|
10 * user-specified product and sum constructions |
|
11 * mutually recursive definitions |
|
12 * definitions involving arbitrary monotone operators |
|
13 * automatically proves introduction and elimination rules |
|
14 |
|
15 The recursive sets must *already* be declared as constants in parent theory! |
|
16 |
|
17 Introduction rules have the form |
|
18 [| ti:M(Sj), ..., P(x), ... |] ==> t: Sk |] |
|
19 where M is some monotone operator (usually the identity) |
|
20 P(x) is any (non-conjunctive) side condition on the free variables |
|
21 ti, t are any terms |
|
22 Sj, Sk are two of the sets being defined in mutual recursion |
|
23 |
|
24 Sums are used only for mutual recursion; |
|
25 Products are used only to derive "streamlined" induction rules for relations |
|
26 *) |
7 *) |
27 |
8 |
28 signature FP = (** Description of a fixed point operator **) |
9 signature INDUCTIVE_ARG = (** Description of a (co)inductive def **) |
29 sig |
10 sig |
30 val oper : term (*fixed point operator*) |
11 val thy : theory (*new theory with inductive defs*) |
31 val bnd_mono : term (*monotonicity predicate*) |
|
32 val bnd_monoI : thm (*intro rule for bnd_mono*) |
|
33 val subs : thm (*subset theorem for fp*) |
|
34 val Tarski : thm (*Tarski's fixed point theorem*) |
|
35 val induct : thm (*induction/coinduction rule*) |
|
36 end; |
|
37 |
|
38 signature PR = (** Description of a Cartesian product **) |
|
39 sig |
|
40 val sigma : term (*Cartesian product operator*) |
|
41 val pair : term (*pairing operator*) |
|
42 val split_const : term (*splitting operator*) |
|
43 val fsplit_const : term (*splitting operator for formulae*) |
|
44 val pair_iff : thm (*injectivity of pairing, using <->*) |
|
45 val split_eq : thm (*equality rule for split*) |
|
46 val fsplitI : thm (*intro rule for fsplit*) |
|
47 val fsplitD : thm (*destruct rule for fsplit*) |
|
48 val fsplitE : thm (*elim rule for fsplit*) |
|
49 end; |
|
50 |
|
51 signature SU = (** Description of a disjoint sum **) |
|
52 sig |
|
53 val sum : term (*disjoint sum operator*) |
|
54 val inl : term (*left injection*) |
|
55 val inr : term (*right injection*) |
|
56 val elim : term (*case operator*) |
|
57 val case_inl : thm (*inl equality rule for case*) |
|
58 val case_inr : thm (*inr equality rule for case*) |
|
59 val inl_iff : thm (*injectivity of inl, using <->*) |
|
60 val inr_iff : thm (*injectivity of inr, using <->*) |
|
61 val distinct : thm (*distinctness of inl, inr using <->*) |
|
62 val distinct' : thm (*distinctness of inr, inl using <->*) |
|
63 end; |
|
64 |
|
65 signature INDUCTIVE = (** Description of a (co)inductive defn **) |
|
66 sig |
|
67 val thy : theory (*parent theory*) |
|
68 val thy_name : string (*name of generated theory*) |
|
69 val rec_doms : (string*string) list (*recursion ops and their domains*) |
|
70 val sintrs : string list (*desired introduction rules*) |
|
71 val monos : thm list (*monotonicity of each M operator*) |
12 val monos : thm list (*monotonicity of each M operator*) |
72 val con_defs : thm list (*definitions of the constructors*) |
13 val con_defs : thm list (*definitions of the constructors*) |
73 val type_intrs : thm list (*type-checking intro rules*) |
14 val type_intrs : thm list (*type-checking intro rules*) |
74 val type_elims : thm list (*type-checking elim rules*) |
15 val type_elims : thm list (*type-checking elim rules*) |
75 end; |
16 end; |
76 |
17 |
|
18 (*internal items*) |
|
19 signature INDUCTIVE_I = |
|
20 sig |
|
21 val rec_tms : term list (*the recursive sets*) |
|
22 val domts : term list (*their domains*) |
|
23 val intr_tms : term list (*terms for the introduction rules*) |
|
24 end; |
|
25 |
77 signature INTR_ELIM = |
26 signature INTR_ELIM = |
78 sig |
27 sig |
79 val thy : theory (*new theory*) |
28 val thy : theory (*copy of input theory*) |
80 val thy_name : string (*name of generated theory*) |
|
81 val defs : thm list (*definitions made in thy*) |
29 val defs : thm list (*definitions made in thy*) |
82 val bnd_mono : thm (*monotonicity for the lfp definition*) |
30 val bnd_mono : thm (*monotonicity for the lfp definition*) |
83 val unfold : thm (*fixed-point equation*) |
31 val unfold : thm (*fixed-point equation*) |
84 val dom_subset : thm (*inclusion of recursive set in dom*) |
32 val dom_subset : thm (*inclusion of recursive set in dom*) |
85 val intrs : thm list (*introduction rules*) |
33 val intrs : thm list (*introduction rules*) |
86 val elim : thm (*case analysis theorem*) |
34 val elim : thm (*case analysis theorem*) |
87 val raw_induct : thm (*raw induction rule from Fp.induct*) |
35 val raw_induct : thm (*raw induction rule from Fp.induct*) |
88 val mk_cases : thm list -> string -> thm (*generates case theorems*) |
36 val mk_cases : thm list -> string -> thm (*generates case theorems*) |
89 (*internal items...*) |
37 val rec_names : string list (*names of recursive sets*) |
90 val big_rec_tm : term (*the lhs of the fixedpoint defn*) |
|
91 val rec_tms : term list (*the mutually recursive sets*) |
|
92 val domts : term list (*domains of the recursive sets*) |
|
93 val intr_tms : term list (*terms for the introduction rules*) |
|
94 val rec_params : term list (*parameters of the recursion*) |
|
95 val sumprod_free_SEs : thm list (*destruct rules for Su and Pr*) |
38 val sumprod_free_SEs : thm list (*destruct rules for Su and Pr*) |
96 end; |
39 end; |
97 |
40 |
|
41 (*prove intr/elim rules for a fixedpoint definition*) |
|
42 functor Intr_elim_Fun |
|
43 (structure Inductive: sig include INDUCTIVE_ARG INDUCTIVE_I end |
|
44 and Fp: FP and Pr : PR and Su : SU) : INTR_ELIM = |
|
45 struct |
|
46 open Logic Inductive Ind_Syntax; |
98 |
47 |
99 functor Intr_elim_Fun (structure Ind: INDUCTIVE and |
48 val rec_names = map (#1 o dest_Const o head_of) rec_tms; |
100 Fp: FP and Pr : PR and Su : SU) : INTR_ELIM = |
|
101 struct |
|
102 open Logic Ind; |
|
103 |
|
104 (*** Extract basic information from arguments ***) |
|
105 |
|
106 val sign = sign_of Ind.thy; |
|
107 |
|
108 fun rd T a = |
|
109 read_cterm sign (a,T) |
|
110 handle ERROR => error ("The error above occurred for " ^ a); |
|
111 |
|
112 val rec_names = map #1 rec_doms |
|
113 and domts = map (term_of o rd iT o #2) rec_doms; |
|
114 |
|
115 val dummy = assert_all Syntax.is_identifier rec_names |
|
116 (fn a => "Name of recursive set not an identifier: " ^ a); |
|
117 |
|
118 val dummy = assert_all (is_some o lookup_const sign) rec_names |
|
119 (fn a => "Name of recursive set not declared as constant: " ^ a); |
|
120 |
|
121 val intr_tms = map (term_of o rd propT) sintrs; |
|
122 |
|
123 local (*Checking the introduction rules*) |
|
124 val intr_sets = map (#2 o rule_concl_msg sign) intr_tms; |
|
125 |
|
126 fun intr_ok set = |
|
127 case head_of set of Const(a,recT) => a mem rec_names | _ => false; |
|
128 |
|
129 val dummy = assert_all intr_ok intr_sets |
|
130 (fn t => "Conclusion of rule does not name a recursive set: " ^ |
|
131 Sign.string_of_term sign t); |
|
132 in |
|
133 val (Const(_,recT),rec_params) = strip_comb (hd intr_sets) |
|
134 end; |
|
135 |
|
136 val rec_hds = map (fn a=> Const(a,recT)) rec_names; |
|
137 val rec_tms = map (fn rec_hd=> list_comb(rec_hd,rec_params)) rec_hds; |
|
138 |
|
139 val dummy = assert_all is_Free rec_params |
|
140 (fn t => "Param in recursion term not a free variable: " ^ |
|
141 Sign.string_of_term sign t); |
|
142 |
|
143 (*** Construct the lfp definition ***) |
|
144 |
|
145 val mk_variant = variant (foldr add_term_names (intr_tms,[])); |
|
146 |
|
147 val z' = mk_variant"z" |
|
148 and X' = mk_variant"X" |
|
149 and w' = mk_variant"w"; |
|
150 |
|
151 (*simple error-checking in the premises*) |
|
152 fun chk_prem rec_hd (Const("op &",_) $ _ $ _) = |
|
153 error"Premises may not be conjuctive" |
|
154 | chk_prem rec_hd (Const("op :",_) $ t $ X) = |
|
155 deny (rec_hd occs t) "Recursion term on left of member symbol" |
|
156 | chk_prem rec_hd t = |
|
157 deny (rec_hd occs t) "Recursion term in side formula"; |
|
158 |
|
159 fun dest_tprop (Const("Trueprop",_) $ P) = P |
|
160 | dest_tprop Q = error ("Ill-formed premise of introduction rule: " ^ |
|
161 Sign.string_of_term sign Q); |
|
162 |
|
163 (*Makes a disjunct from an introduction rule*) |
|
164 fun lfp_part intr = (*quantify over rule's free vars except parameters*) |
|
165 let val prems = map dest_tprop (strip_imp_prems intr) |
|
166 val dummy = seq (fn rec_hd => seq (chk_prem rec_hd) prems) rec_hds |
|
167 val exfrees = term_frees intr \\ rec_params |
|
168 val zeq = eq_const $ (Free(z',iT)) $ (#1 (rule_concl intr)) |
|
169 in foldr mk_exists (exfrees, fold_bal (app conj) (zeq::prems)) end; |
|
170 |
|
171 val dom_sum = fold_bal (app Su.sum) domts; |
|
172 |
|
173 (*The Part(A,h) terms -- compose injections to make h*) |
|
174 fun mk_Part (Bound 0) = Free(X',iT) (*no mutual rec, no Part needed*) |
|
175 | mk_Part h = Part_const $ Free(X',iT) $ Abs(w',iT,h); |
|
176 |
|
177 (*Access to balanced disjoint sums via injections*) |
|
178 val parts = |
|
179 map mk_Part (accesses_bal (ap Su.inl, ap Su.inr, Bound 0) |
|
180 (length rec_doms)); |
|
181 |
|
182 (*replace each set by the corresponding Part(A,h)*) |
|
183 val part_intrs = map (subst_free (rec_tms ~~ parts) o lfp_part) intr_tms; |
|
184 |
|
185 val lfp_abs = absfree(X', iT, |
|
186 mk_Collect(z', dom_sum, fold_bal (app disj) part_intrs)); |
|
187 |
|
188 val lfp_rhs = Fp.oper $ dom_sum $ lfp_abs |
|
189 |
|
190 val dummy = seq (fn rec_hd => deny (rec_hd occs lfp_rhs) |
|
191 "Illegal occurrence of recursion operator") |
|
192 rec_hds; |
|
193 |
|
194 (*** Make the new theory ***) |
|
195 |
|
196 (*A key definition: |
|
197 If no mutual recursion then it equals the one recursive set. |
|
198 If mutual recursion then it differs from all the recursive sets. *) |
|
199 val big_rec_name = space_implode "_" rec_names; |
49 val big_rec_name = space_implode "_" rec_names; |
200 |
50 |
201 (*Big_rec... is the union of the mutually recursive sets*) |
51 (*fetch fp definitions from the theory*) |
202 val big_rec_tm = list_comb(Const(big_rec_name,recT), rec_params); |
52 val big_rec_def::part_rec_defs = |
|
53 map (get_def thy) |
|
54 (case rec_names of [_] => rec_names | _ => big_rec_name::rec_names); |
203 |
55 |
204 (*The individual sets must already be declared*) |
|
205 val axpairs = map (mk_defpair sign) |
|
206 ((big_rec_tm, lfp_rhs) :: |
|
207 (case parts of |
|
208 [_] => [] (*no mutual recursion*) |
|
209 | _ => rec_tms ~~ (*define the sets as Parts*) |
|
210 map (subst_atomic [(Free(X',iT),big_rec_tm)]) parts)); |
|
211 |
56 |
212 val thy = |
57 val sign = sign_of thy; |
213 Ind.thy |
|
214 |> add_axioms_i axpairs |
|
215 |> add_thyname thy_name; |
|
216 |
|
217 val defs = map (get_axiom thy o #1) axpairs; |
|
218 |
|
219 val big_rec_def::part_rec_defs = defs; |
|
220 |
|
221 val prove = prove_term (sign_of thy); |
|
222 |
58 |
223 (********) |
59 (********) |
224 val dummy = writeln "Proving monotonicity..."; |
60 val _ = writeln " Proving monotonicity..."; |
|
61 |
|
62 val Const("==",_) $ _ $ (_ $ dom_sum $ fp_abs) = |
|
63 big_rec_def |> rep_thm |> #prop |> unvarify; |
225 |
64 |
226 val bnd_mono = |
65 val bnd_mono = |
227 prove [] (mk_tprop (Fp.bnd_mono $ dom_sum $ lfp_abs), |
66 prove_term sign [] (mk_tprop (Fp.bnd_mono $ dom_sum $ fp_abs), |
228 fn _ => |
67 fn _ => |
229 [rtac (Collect_subset RS bnd_monoI) 1, |
68 [rtac (Collect_subset RS bnd_monoI) 1, |
230 REPEAT (ares_tac (basic_monos @ monos) 1)]); |
69 REPEAT (ares_tac (basic_monos @ monos) 1)]); |
231 |
70 |
232 val dom_subset = standard (big_rec_def RS Fp.subs); |
71 val dom_subset = standard (big_rec_def RS Fp.subs); |
233 |
72 |
234 val unfold = standard (bnd_mono RS (big_rec_def RS Fp.Tarski)); |
73 val unfold = standard (bnd_mono RS (big_rec_def RS Fp.Tarski)); |
235 |
74 |
236 (********) |
75 (********) |
237 val dummy = writeln "Proving the introduction rules..."; |
76 val _ = writeln " Proving the introduction rules..."; |
238 |
77 |
239 (*Mutual recursion: Needs subset rules for the individual sets???*) |
78 (*Mutual recursion: Needs subset rules for the individual sets???*) |
240 val rec_typechecks = [dom_subset] RL (asm_rl::monos) RL [subsetD]; |
79 val rec_typechecks = [dom_subset] RL (asm_rl::monos) RL [subsetD]; |
241 |
80 |
242 (*Type-checking is hardest aspect of proof; |
81 (*Type-checking is hardest aspect of proof; |
250 rtac disjIn 2, |
89 rtac disjIn 2, |
251 REPEAT (ares_tac [refl,exI,conjI] 2), |
90 REPEAT (ares_tac [refl,exI,conjI] 2), |
252 rewrite_goals_tac con_defs, |
91 rewrite_goals_tac con_defs, |
253 (*Now can solve the trivial equation*) |
92 (*Now can solve the trivial equation*) |
254 REPEAT (rtac refl 2), |
93 REPEAT (rtac refl 2), |
255 REPEAT (FIRSTGOAL (eresolve_tac (asm_rl::PartE::SigmaE2::type_elims) |
94 REPEAT (FIRSTGOAL ( dresolve_tac rec_typechecks |
256 ORELSE' hyp_subst_tac |
95 ORELSE' eresolve_tac (asm_rl::PartE::SigmaE2::type_elims) |
257 ORELSE' dresolve_tac rec_typechecks)), |
96 ORELSE' hyp_subst_tac)), |
258 DEPTH_SOLVE (swap_res_tac (SigmaI::type_intrs) 1)]; |
97 DEPTH_SOLVE (swap_res_tac (SigmaI::type_intrs) 1)]; |
259 |
98 |
260 (*combines disjI1 and disjI2 to access the corresponding nested disjunct...*) |
99 (*combines disjI1 and disjI2 to access the corresponding nested disjunct...*) |
261 val mk_disj_rls = |
100 val mk_disj_rls = |
262 let fun f rl = rl RS disjI1 |
101 let fun f rl = rl RS disjI1 |
263 and g rl = rl RS disjI2 |
102 and g rl = rl RS disjI2 |
264 in accesses_bal(f, g, asm_rl) end; |
103 in accesses_bal(f, g, asm_rl) end; |
265 |
104 |
266 val intrs = map (prove part_rec_defs) |
105 val intrs = map (prove_term sign part_rec_defs) |
267 (intr_tms ~~ map intro_tacsf (mk_disj_rls(length intr_tms))); |
106 (intr_tms ~~ map intro_tacsf (mk_disj_rls(length intr_tms))); |
268 |
107 |
269 (********) |
108 (********) |
270 val dummy = writeln "Proving the elimination rule..."; |
109 val _ = writeln " Proving the elimination rule..."; |
271 |
110 |
272 (*Includes rules for succ and Pair since they are common constructions*) |
111 (*Includes rules for succ and Pair since they are common constructions*) |
273 val elim_rls = [asm_rl, FalseE, succ_neq_0, sym RS succ_neq_0, |
112 val elim_rls = [asm_rl, FalseE, succ_neq_0, sym RS succ_neq_0, |
274 Pair_neq_0, sym RS Pair_neq_0, make_elim succ_inject, |
113 Pair_neq_0, sym RS Pair_neq_0, make_elim succ_inject, |
275 refl_thin, conjE, exE, disjE]; |
114 refl_thin, conjE, exE, disjE]; |
276 |
115 |
277 val sumprod_free_SEs = |
116 val sumprod_free_SEs = |
278 map (gen_make_elim [conjE,FalseE]) |
117 map (gen_make_elim [conjE,FalseE]) |
279 ([Su.distinct, Su.distinct', Su.inl_iff, Su.inr_iff, Pr.pair_iff] |
118 ([Su.distinct, Su.distinct', Su.inl_iff, Su.inr_iff, Pr.pair_iff] |
280 RL [iffD1]); |
119 RL [iffD1]); |
281 |
120 |
282 (*Breaks down logical connectives in the monotonic function*) |
121 (*Breaks down logical connectives in the monotonic function*) |
283 val basic_elim_tac = |
122 val basic_elim_tac = |
284 REPEAT (SOMEGOAL (eresolve_tac (elim_rls@sumprod_free_SEs) |
123 REPEAT (SOMEGOAL (eresolve_tac (elim_rls@sumprod_free_SEs) |
285 ORELSE' bound_hyp_subst_tac)) |
124 ORELSE' bound_hyp_subst_tac)) |
286 THEN prune_params_tac; |
125 THEN prune_params_tac; |
287 |
126 |
288 val elim = rule_by_tactic basic_elim_tac (unfold RS equals_CollectD); |
127 val elim = rule_by_tactic basic_elim_tac (unfold RS equals_CollectD); |
289 |
128 |
290 (*Applies freeness of the given constructors, which *must* be unfolded by |
129 (*Applies freeness of the given constructors, which *must* be unfolded by |