22 |
22 |
23 open Quotient_Info; |
23 open Quotient_Info; |
24 |
24 |
25 exception LIFT_MATCH of string |
25 exception LIFT_MATCH of string |
26 |
26 |
27 (* simplifies a term according to the id_rules *) |
27 |
28 fun id_simplify ctxt trm = |
28 |
29 let |
29 (*** Aggregate Rep/Abs Function ***) |
30 val thy = ProofContext.theory_of ctxt |
30 |
31 val id_thms = id_simps_get ctxt |
31 |
32 in |
32 (* The flag repF is for types in negative position; absF is for types |
33 MetaSimplifier.rewrite_term thy id_thms [] trm |
33 in positive position. Because of this, function types need to be |
34 end |
34 treated specially, since there the polarity changes. |
35 |
35 *) |
36 (******************************) |
|
37 (* Aggregate Rep/Abs Function *) |
|
38 (******************************) |
|
39 |
|
40 (* The flag repF is for types in negative position; absF is for types *) |
|
41 (* in positive position. Because of this, function types need to be *) |
|
42 (* treated specially, since there the polarity changes. *) |
|
43 |
36 |
44 datatype flag = absF | repF |
37 datatype flag = absF | repF |
45 |
38 |
46 fun negF absF = repF |
39 fun negF absF = repF |
47 | negF repF = absF |
40 | negF repF = absF |
|
41 |
|
42 fun is_identity (Const (@{const_name "id"}, _)) = true |
|
43 | is_identity _ = false |
48 |
44 |
49 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty) |
45 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty) |
50 |
46 |
51 fun mk_fun_compose flag (trm1, trm2) = |
47 fun mk_fun_compose flag (trm1, trm2) = |
52 case flag of |
48 case flag of |
63 end |
59 end |
64 |
60 |
65 (* makes a Free out of a TVar *) |
61 (* makes a Free out of a TVar *) |
66 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT) |
62 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT) |
67 |
63 |
68 (* produces an aggregate map function for the *) |
64 (* produces an aggregate map function for the |
69 (* rty-part of a quotient definition; abstracts *) |
65 rty-part of a quotient definition; abstracts |
70 (* over all variables listed in vs (these variables *) |
66 over all variables listed in vs (these variables |
71 (* correspond to the type variables in rty) *) |
67 correspond to the type variables in rty) |
72 (* *) |
68 |
73 (* for example for: (?'a list * ?'b) *) |
69 for example for: (?'a list * ?'b) |
74 (* it produces: %a b. prod_map (map a) b *) |
70 it produces: %a b. prod_map (map a) b |
|
71 *) |
75 fun mk_mapfun ctxt vs rty = |
72 fun mk_mapfun ctxt vs rty = |
76 let |
73 let |
77 val vs' = map (mk_Free) vs |
74 val vs' = map (mk_Free) vs |
78 |
75 |
79 fun mk_mapfun_aux rty = |
76 fun mk_mapfun_aux rty = |
84 | _ => raise LIFT_MATCH ("mk_mapfun (default)") |
81 | _ => raise LIFT_MATCH ("mk_mapfun (default)") |
85 in |
82 in |
86 fold_rev Term.lambda vs' (mk_mapfun_aux rty) |
83 fold_rev Term.lambda vs' (mk_mapfun_aux rty) |
87 end |
84 end |
88 |
85 |
89 (* looks up the (varified) rty and qty for *) |
86 (* looks up the (varified) rty and qty for |
90 (* a quotient definition *) |
87 a quotient definition |
|
88 *) |
91 fun get_rty_qty ctxt s = |
89 fun get_rty_qty ctxt s = |
92 let |
90 let |
93 val thy = ProofContext.theory_of ctxt |
91 val thy = ProofContext.theory_of ctxt |
94 val exc = LIFT_MATCH ("No quotient type " ^ (quote s) ^ " found.") |
92 val exc = LIFT_MATCH ("No quotient type " ^ (quote s) ^ " found.") |
95 val qdata = (quotdata_lookup thy s) handle NotFound => raise exc |
93 val qdata = (quotdata_lookup thy s) handle NotFound => raise exc |
96 in |
94 in |
97 (#rtyp qdata, #qtyp qdata) |
95 (#rtyp qdata, #qtyp qdata) |
98 end |
96 end |
99 |
97 |
100 (* takes two type-environments and looks *) |
98 (* takes two type-environments and looks |
101 (* up in both of them the variable v, which *) |
99 up in both of them the variable v, which |
102 (* must be listed in the environment *) |
100 must be listed in the environment |
|
101 *) |
103 fun double_lookup rtyenv qtyenv v = |
102 fun double_lookup rtyenv qtyenv v = |
104 let |
103 let |
105 val v' = fst (dest_TVar v) |
104 val v' = fst (dest_TVar v) |
106 in |
105 in |
107 (snd (the (Vartab.lookup rtyenv v')), snd (the (Vartab.lookup qtyenv v'))) |
106 (snd (the (Vartab.lookup rtyenv v')), snd (the (Vartab.lookup qtyenv v'))) |
134 in |
133 in |
135 raise LIFT_MATCH (space_implode " " |
134 raise LIFT_MATCH (space_implode " " |
136 ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
135 ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
137 end |
136 end |
138 |
137 |
139 (* produces an aggregate absrep function *) |
138 |
140 (* *) |
139 (** generation of an aggregate absrep function **) |
141 (* - In case of equal types we just return the identity. *) |
140 |
142 (* *) |
141 (* - In case of equal types we just return the identity. |
143 (* - In case of function types and TFrees, we recurse, taking in *) |
142 |
144 (* the first case the polarity change into account. *) |
143 - In case of TFrees we also return the identity. |
145 (* *) |
144 |
146 (* - If the type constructors are equal, we recurse for the *) |
145 - In case of function types we recurse taking |
147 (* arguments and build the appropriate map function. *) |
146 the polarity change into account. |
148 (* *) |
147 |
149 (* - If the type constructors are unequal, there must be an *) |
148 - If the type constructors are equal, we recurse for the |
150 (* instance of quotient types: *) |
149 arguments and build the appropriate map function. |
151 (* - we first look up the corresponding rty_pat and qty_pat *) |
150 |
152 (* from the quotient definition; the arguments of qty_pat *) |
151 - If the type constructors are unequal, there must be an |
153 (* must be some distinct TVars *) |
152 instance of quotient types: |
154 (* - we then match the rty_pat with rty and qty_pat with qty; *) |
153 |
155 (* if matching fails the types do not match *) |
154 - we first look up the corresponding rty_pat and qty_pat |
156 (* - the matching produces two environments; we look up the *) |
155 from the quotient definition; the arguments of qty_pat |
157 (* assignments for the qty_pat variables and recurse on the *) |
156 must be some distinct TVars |
158 (* assignments *) |
157 - we then match the rty_pat with rty and qty_pat with qty; |
159 (* - we prefix the aggregate map function for the rty_pat, *) |
158 if matching fails the types do not correspond -> error |
160 (* which is an abstraction over all type variables *) |
159 - the matching produces two environments; we look up the |
161 (* - finally we compose the result with the appropriate *) |
160 assignments for the qty_pat variables and recurse on the |
162 (* absrep function *) |
161 assignments |
163 (* *) |
162 - we prefix the aggregate map function for the rty_pat, |
164 (* The composition is necessary for types like *) |
163 which is an abstraction over all type variables |
165 (* *) |
164 - finally we compose the result with the appropriate |
166 (* ('a list) list / ('a foo) foo *) |
165 absrep function in case at least one argument produced |
167 (* *) |
166 a non-identity function / |
168 (* The matching is necessary for types like *) |
167 otherwise we just return the appropriate absrep |
169 (* *) |
168 function |
170 (* ('a * 'a) list / 'a bar *) |
169 |
|
170 The composition is necessary for types like |
|
171 |
|
172 ('a list) list / ('a foo) foo |
|
173 |
|
174 The matching is necessary for types like |
|
175 |
|
176 ('a * 'a) list / 'a bar |
|
177 |
|
178 The test is necessary in order to eliminate superflous |
|
179 identity maps. |
|
180 *) |
171 |
181 |
172 fun absrep_fun flag ctxt (rty, qty) = |
182 fun absrep_fun flag ctxt (rty, qty) = |
173 if rty = qty |
183 if rty = qty |
174 then mk_identity rty |
184 then mk_identity rty |
175 else |
185 else |
192 else |
202 else |
193 let |
203 let |
194 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
204 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
195 val rtyenv = match ctxt absrep_match_err rty_pat rty |
205 val rtyenv = match ctxt absrep_match_err rty_pat rty |
196 val qtyenv = match ctxt absrep_match_err qty_pat qty |
206 val qtyenv = match ctxt absrep_match_err qty_pat qty |
197 val args_aux = map (double_lookup rtyenv qtyenv) vs |
207 val args_aux = map (double_lookup rtyenv qtyenv) vs |
198 val args = map (absrep_fun flag ctxt) args_aux |
208 val args = map (absrep_fun flag ctxt) args_aux |
199 val map_fun = mk_mapfun ctxt vs rty_pat |
209 val map_fun = mk_mapfun ctxt vs rty_pat |
200 val result = list_comb (map_fun, args) |
210 val result = list_comb (map_fun, args) |
201 in |
211 in |
202 mk_fun_compose flag (absrep_const flag ctxt s', result) |
212 if forall is_identity args |
|
213 then absrep_const flag ctxt s' |
|
214 else mk_fun_compose flag (absrep_const flag ctxt s', result) |
203 end |
215 end |
204 | (TFree x, TFree x') => |
216 | (TFree x, TFree x') => |
205 if x = x' |
217 if x = x' |
206 then mk_identity rty |
218 then mk_identity rty |
207 else raise (LIFT_MATCH "absrep_fun (frees)") |
219 else raise (LIFT_MATCH "absrep_fun (frees)") |
209 | _ => raise (LIFT_MATCH "absrep_fun (default)") |
221 | _ => raise (LIFT_MATCH "absrep_fun (default)") |
210 |
222 |
211 fun absrep_fun_chk flag ctxt (rty, qty) = |
223 fun absrep_fun_chk flag ctxt (rty, qty) = |
212 absrep_fun flag ctxt (rty, qty) |
224 absrep_fun flag ctxt (rty, qty) |
213 |> Syntax.check_term ctxt |
225 |> Syntax.check_term ctxt |
214 |> id_simplify ctxt |
226 |
215 |
227 |
216 (**********************************) |
228 |
217 (* Aggregate Equivalence Relation *) |
229 |
218 (**********************************) |
230 (*** Aggregate Equivalence Relation ***) |
|
231 |
|
232 |
|
233 (* works very similar to the absrep generation, |
|
234 except there is no need for polarities |
|
235 *) |
219 |
236 |
220 (* instantiates TVars so that the term is of type ty *) |
237 (* instantiates TVars so that the term is of type ty *) |
221 fun force_typ ctxt trm ty = |
238 fun force_typ ctxt trm ty = |
222 let |
239 let |
223 val thy = ProofContext.theory_of ctxt |
240 val thy = ProofContext.theory_of ctxt |
225 val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty |
242 val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty |
226 in |
243 in |
227 map_types (Envir.subst_type ty_inst) trm |
244 map_types (Envir.subst_type ty_inst) trm |
228 end |
245 end |
229 |
246 |
|
247 fun is_eq (Const (@{const_name "op ="}, _)) = true |
|
248 | is_eq _ = false |
|
249 |
230 fun mk_rel_compose (trm1, trm2) = |
250 fun mk_rel_compose (trm1, trm2) = |
231 Const (@{const_name "pred_comp"}, dummyT) $ trm1 $ |
251 Const (@{const_name "rel_conj"}, dummyT) $ trm1 $ trm2 |
232 (Const (@{const_name "pred_comp"}, dummyT) $ trm2 $ trm1) |
|
233 |
252 |
234 fun get_relmap ctxt s = |
253 fun get_relmap ctxt s = |
235 let |
254 let |
236 val thy = ProofContext.theory_of ctxt |
255 val thy = ProofContext.theory_of ctxt |
237 val exc = LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")") |
256 val exc = LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")") |
269 in |
288 in |
270 raise LIFT_MATCH (space_implode " " |
289 raise LIFT_MATCH (space_implode " " |
271 ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
290 ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
272 end |
291 end |
273 |
292 |
274 (* builds the aggregate equivalence relation *) |
293 (* builds the aggregate equivalence relation |
275 (* that will be the argument of Respects *) |
294 that will be the argument of Respects |
|
295 *) |
276 fun equiv_relation ctxt (rty, qty) = |
296 fun equiv_relation ctxt (rty, qty) = |
277 if rty = qty |
297 if rty = qty |
278 then HOLogic.eq_const rty |
298 then HOLogic.eq_const rty |
279 else |
299 else |
280 case (rty, qty) of |
300 case (rty, qty) of |
296 val rel_map = mk_relmap ctxt vs rty_pat |
316 val rel_map = mk_relmap ctxt vs rty_pat |
297 val result = list_comb (rel_map, args) |
317 val result = list_comb (rel_map, args) |
298 val eqv_rel = get_equiv_rel ctxt s' |
318 val eqv_rel = get_equiv_rel ctxt s' |
299 val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool}) |
319 val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool}) |
300 in |
320 in |
301 mk_rel_compose (result, eqv_rel') |
321 if forall is_eq args |
|
322 then eqv_rel' |
|
323 else mk_rel_compose (result, eqv_rel') |
302 end |
324 end |
303 | _ => HOLogic.eq_const rty |
325 | _ => HOLogic.eq_const rty |
304 |
326 |
305 fun equiv_relation_chk ctxt (rty, qty) = |
327 fun equiv_relation_chk ctxt (rty, qty) = |
306 equiv_relation ctxt (rty, qty) |
328 equiv_relation ctxt (rty, qty) |
307 |> Syntax.check_term ctxt |
329 |> Syntax.check_term ctxt |
308 |> id_simplify ctxt |
330 |
309 |
331 |
310 |
332 |
311 (******************) |
333 (*** Regularization ***) |
312 (* Regularization *) |
|
313 (******************) |
|
314 |
334 |
315 (* Regularizing an rtrm means: |
335 (* Regularizing an rtrm means: |
316 |
336 |
317 - Quantifiers over types that need lifting are replaced |
337 - Quantifiers over types that need lifting are replaced |
318 by bounded quantifiers, for example: |
338 by bounded quantifiers, for example: |
342 val mk_babs = Const (@{const_name Babs}, dummyT) |
362 val mk_babs = Const (@{const_name Babs}, dummyT) |
343 val mk_ball = Const (@{const_name Ball}, dummyT) |
363 val mk_ball = Const (@{const_name Ball}, dummyT) |
344 val mk_bex = Const (@{const_name Bex}, dummyT) |
364 val mk_bex = Const (@{const_name Bex}, dummyT) |
345 val mk_resp = Const (@{const_name Respects}, dummyT) |
365 val mk_resp = Const (@{const_name Respects}, dummyT) |
346 |
366 |
347 (* - applies f to the subterm of an abstraction, *) |
367 (* - applies f to the subterm of an abstraction, |
348 (* otherwise to the given term, *) |
368 otherwise to the given term, |
349 (* - used by regularize, therefore abstracted *) |
369 - used by regularize, therefore abstracted |
350 (* variables do not have to be treated specially *) |
370 variables do not have to be treated specially |
|
371 *) |
351 fun apply_subt f (trm1, trm2) = |
372 fun apply_subt f (trm1, trm2) = |
352 case (trm1, trm2) of |
373 case (trm1, trm2) of |
353 (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t')) |
374 (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t')) |
354 | _ => f (trm1, trm2) |
375 | _ => f (trm1, trm2) |
355 |
376 |
356 (* the major type of All and Ex quantifiers *) |
377 (* the major type of All and Ex quantifiers *) |
357 fun qnt_typ ty = domain_type (domain_type ty) |
378 fun qnt_typ ty = domain_type (domain_type ty) |
358 |
379 |
359 |
380 (* produces a regularized version of rtrm |
360 (* produces a regularized version of rtrm *) |
381 |
361 (* *) |
382 - the result might contain dummyTs |
362 (* - the result might contain dummyTs *) |
383 |
363 (* *) |
384 - for regularisation we do not need any |
364 (* - for regularisation we do not need any *) |
385 special treatment of bound variables |
365 (* special treatment of bound variables *) |
386 *) |
366 |
|
367 fun regularize_trm ctxt (rtrm, qtrm) = |
387 fun regularize_trm ctxt (rtrm, qtrm) = |
368 case (rtrm, qtrm) of |
388 case (rtrm, qtrm) of |
369 (Abs (x, ty, t), Abs (_, ty', t')) => |
389 (Abs (x, ty, t), Abs (_, ty', t')) => |
370 let |
390 let |
371 val subtrm = Abs(x, ty, regularize_trm ctxt (t, t')) |
391 val subtrm = Abs(x, ty, regularize_trm ctxt (t, t')) |