226 ((T11, SOME T12), (T2, NONE)) |
226 ((T11, SOME T12), (T2, NONE)) |
227 | factor_out_types T1 (Type (@{type_name prod}, [T21, T22])) = |
227 | factor_out_types T1 (Type (@{type_name prod}, [T21, T22])) = |
228 ((T1, NONE), (T21, SOME T22)) |
228 ((T1, NONE), (T21, SOME T22)) |
229 | factor_out_types T1 T2 = ((T1, NONE), (T2, NONE)) |
229 | factor_out_types T1 T2 = ((T1, NONE), (T2, NONE)) |
230 |
230 |
|
231 (* Term-encoded data structure for holding key-value pairs as well as an "opt" |
|
232 flag indicating whether the function is approximated. *) |
231 fun make_plain_fun maybe_opt T1 T2 = |
233 fun make_plain_fun maybe_opt T1 T2 = |
232 let |
234 let |
233 fun aux T1 T2 [] = |
235 fun aux T1 T2 [] = |
234 Const (if maybe_opt then opt_flag else non_opt_flag, T1 --> T2) |
236 Const (if maybe_opt then opt_flag else non_opt_flag, T1 --> T2) |
235 | aux T1 T2 ((t1, t2) :: tps) = |
237 | aux T1 T2 ((t1, t2) :: tps) = |
266 if T1 = T1' then HOLogic.mk_prod (t1, t2) |
268 if T1 = T1' then HOLogic.mk_prod (t1, t2) |
267 else HOLogic.mk_prod (t11, pair_up T2' t12 t2) |
269 else HOLogic.mk_prod (t11, pair_up T2' t12 t2) |
268 | pair_up _ t1 t2 = HOLogic.mk_prod (t1, t2) |
270 | pair_up _ t1 t2 = HOLogic.mk_prod (t1, t2) |
269 fun multi_pair_up T1 t1 (ts2, ts3) = map2 (pair o pair_up T1 t1) ts2 ts3 |
271 fun multi_pair_up T1 t1 (ts2, ts3) = map2 (pair o pair_up T1 t1) ts2 ts3 |
270 |
272 |
271 fun typecast_fun (Type (@{type_name fun}, [T1', T2'])) T1 T2 t = |
273 fun format_fun T' T1 T2 t = |
272 let |
274 let |
273 fun do_curry T1 T1a T1b T2 t = |
275 val T1' = pseudo_domain_type T' |
274 let |
276 val T2' = pseudo_range_type T' |
275 val (maybe_opt, tsp) = dest_plain_fun t |
277 fun do_curry T1 T1a T1b T2 t = |
276 val tps = |
278 let |
277 tsp |>> map (break_in_two T1 T1a T1b) |
279 val (maybe_opt, tsp) = dest_plain_fun t |
278 |> uncurry (map2 (fn (t1a, t1b) => fn t2 => (t1a, (t1b, t2)))) |
280 val tps = |
279 |> AList.coalesce (op =) |
281 tsp |>> map (break_in_two T1 T1a T1b) |
280 |> map (apsnd (make_plain_fun maybe_opt T1b T2)) |
282 |> uncurry (map2 (fn (t1a, t1b) => fn t2 => (t1a, (t1b, t2)))) |
281 in make_plain_fun maybe_opt T1a (T1b --> T2) tps end |
283 |> AList.coalesce (op =) |
282 and do_uncurry T1 T2 t = |
284 |> map (apsnd (make_plain_fun maybe_opt T1b T2)) |
283 let |
285 in make_plain_fun maybe_opt T1a (T1b --> T2) tps end |
284 val (maybe_opt, tsp) = dest_plain_fun t |
286 and do_uncurry T1 T2 t = |
285 val tps = |
287 let |
286 tsp |> op ~~ |
288 val (maybe_opt, tsp) = dest_plain_fun t |
287 |> maps (fn (t1, t2) => |
289 val tps = |
288 multi_pair_up T1 t1 (snd (dest_plain_fun t2))) |
290 tsp |> op ~~ |
289 in make_plain_fun maybe_opt T1 T2 tps end |
291 |> maps (fn (t1, t2) => |
290 and do_arrow T1' T2' _ _ (Const (s, _)) = Const (s, T1' --> T2') |
292 multi_pair_up T1 t1 (snd (dest_plain_fun t2))) |
291 | do_arrow T1' T2' T1 T2 |
293 in make_plain_fun maybe_opt T1 T2 tps end |
292 (Const (@{const_name fun_upd}, _) $ t0 $ t1 $ t2) = |
294 and do_arrow T1' T2' _ _ (Const (s, _)) = Const (s, T1' --> T2') |
293 Const (@{const_name fun_upd}, |
295 | do_arrow T1' T2' T1 T2 |
294 (T1' --> T2') --> T1' --> T2' --> T1' --> T2') |
296 (Const (@{const_name fun_upd}, _) $ t0 $ t1 $ t2) = |
295 $ do_arrow T1' T2' T1 T2 t0 $ do_term T1' T1 t1 $ do_term T2' T2 t2 |
297 Const (@{const_name fun_upd}, |
296 | do_arrow _ _ _ _ t = |
298 (T1' --> T2') --> T1' --> T2' --> T1' --> T2') |
297 raise TERM ("Nitpick_Model.typecast_fun.do_arrow", [t]) |
299 $ do_arrow T1' T2' T1 T2 t0 $ do_term T1' T1 t1 $ do_term T2' T2 t2 |
298 and do_fun T1' T2' T1 T2 t = |
300 | do_arrow _ _ _ _ t = |
299 case factor_out_types T1' T1 of |
301 raise TERM ("Nitpick_Model.format_fun.do_arrow", [t]) |
300 ((_, NONE), (_, NONE)) => t |> do_arrow T1' T2' T1 T2 |
302 and do_fun T1' T2' T1 T2 t = |
301 | ((_, NONE), (T1a, SOME T1b)) => |
303 case factor_out_types T1' T1 of |
302 t |> do_curry T1 T1a T1b T2 |> do_arrow T1' T2' T1a (T1b --> T2) |
304 ((_, NONE), (_, NONE)) => t |> do_arrow T1' T2' T1 T2 |
303 | ((T1a', SOME T1b'), (_, NONE)) => |
305 | ((_, NONE), (T1a, SOME T1b)) => |
304 t |> do_arrow T1a' (T1b' --> T2') T1 T2 |> do_uncurry T1' T2' |
306 t |> do_curry T1 T1a T1b T2 |> do_arrow T1' T2' T1a (T1b --> T2) |
305 | _ => raise TYPE ("Nitpick_Model.typecast_fun.do_fun", [T1, T1'], []) |
307 | ((T1a', SOME T1b'), (_, NONE)) => |
306 and do_term (Type (@{type_name fun}, [T1', T2'])) |
308 t |> do_arrow T1a' (T1b' --> T2') T1 T2 |> do_uncurry T1' T2' |
307 (Type (@{type_name fun}, [T1, T2])) t = |
309 | _ => raise TYPE ("Nitpick_Model.format_fun.do_fun", [T1, T1'], []) |
308 do_fun T1' T2' T1 T2 t |
310 and do_term (Type (@{type_name fun}, [T1', T2'])) |
309 | do_term (T' as Type (@{type_name prod}, Ts' as [T1', T2'])) |
311 (Type (@{type_name fun}, [T1, T2])) t = |
310 (Type (@{type_name prod}, [T1, T2])) |
312 do_fun T1' T2' T1 T2 t |
311 (Const (@{const_name Pair}, _) $ t1 $ t2) = |
313 | do_term (T' as Type (@{type_name prod}, Ts' as [T1', T2'])) |
312 Const (@{const_name Pair}, Ts' ---> T') |
314 (Type (@{type_name prod}, [T1, T2])) |
313 $ do_term T1' T1 t1 $ do_term T2' T2 t2 |
315 (Const (@{const_name Pair}, _) $ t1 $ t2) = |
314 | do_term T' T t = |
316 Const (@{const_name Pair}, Ts' ---> T') |
315 if T = T' then t |
317 $ do_term T1' T1 t1 $ do_term T2' T2 t2 |
316 else raise TYPE ("Nitpick_Model.typecast_fun.do_term", [T, T'], []) |
318 | do_term T' T t = |
317 in if T1' = T1 andalso T2' = T2 then t else do_fun T1' T2' T1 T2 t end |
319 if T = T' then t |
318 | typecast_fun T' _ _ _ = |
320 else raise TYPE ("Nitpick_Model.format_fun.do_term", [T, T'], []) |
319 raise TYPE ("Nitpick_Model.typecast_fun", [T'], []) |
321 in if T1' = T1 andalso T2' = T2 then t else do_fun T1' T2' T1 T2 t end |
320 |
322 |
321 fun truth_const_sort_key @{const True} = "0" |
323 fun truth_const_sort_key @{const True} = "0" |
322 | truth_const_sort_key @{const False} = "2" |
324 | truth_const_sort_key @{const False} = "2" |
323 | truth_const_sort_key _ = "1" |
325 | truth_const_sort_key _ = "1" |
324 |
326 |
383 postprocess_term (fastype_of1 (Ts, t)) t |
385 postprocess_term (fastype_of1 (Ts, t)) t |
384 end |
386 end |
385 | postprocess_subterms Ts (Abs (s, T, t')) = |
387 | postprocess_subterms Ts (Abs (s, T, t')) = |
386 Abs (s, T, postprocess_subterms (T :: Ts) t') |
388 Abs (s, T, postprocess_subterms (T :: Ts) t') |
387 | postprocess_subterms Ts t = postprocess_term (fastype_of1 (Ts, t)) t |
389 | postprocess_subterms Ts t = postprocess_term (fastype_of1 (Ts, t)) t |
388 fun make_set maybe_opt T1 T2 tps = |
390 fun make_set maybe_opt T tps = |
389 let |
391 let |
390 val empty_const = Const (@{const_abbrev Set.empty}, T1 --> T2) |
392 val empty_const = Const (@{const_abbrev Set.empty}, T --> bool_T) |
391 val insert_const = Const (@{const_name insert}, |
393 val insert_const = |
392 T1 --> (T1 --> T2) --> T1 --> T2) |
394 Const (@{const_name insert}, T --> (T --> bool_T) --> T --> bool_T) |
393 fun aux [] = |
395 fun aux [] = |
394 if maybe_opt andalso not (is_complete_type datatypes false T1) then |
396 if maybe_opt andalso not (is_complete_type datatypes false T) then |
395 insert_const $ Const (unrep (), T1) $ empty_const |
397 insert_const $ Const (unrep (), T) $ empty_const |
396 else |
398 else |
397 empty_const |
399 empty_const |
398 | aux ((t1, t2) :: zs) = |
400 | aux ((t1, t2) :: zs) = |
399 aux zs |
401 aux zs |
400 |> t2 <> @{const False} |
402 |> t2 <> @{const False} |
401 ? curry (op $) |
403 ? curry (op $) |
402 (insert_const |
404 (insert_const |
403 $ (t1 |> t2 <> @{const True} |
405 $ (t1 |> t2 <> @{const True} |
404 ? curry (op $) |
406 ? curry (op $) |
405 (Const (maybe_name, T1 --> T1)))) |
407 (Const (maybe_name, T --> T)))) |
406 in |
408 in |
407 if forall (fn (_, t) => t <> @{const True} andalso t <> @{const False}) |
409 if forall (fn (_, t) => t <> @{const True} andalso t <> @{const False}) |
408 tps then |
410 tps then |
409 Const (unknown, T1 --> T2) |
411 Const (unknown, T --> bool_T) |
410 else |
412 else |
411 aux tps |
413 aux tps |
412 end |
414 end |
413 fun make_map maybe_opt T1 T2 T2' = |
415 fun make_map maybe_opt T1 T2 T2' = |
414 let |
416 let |
619 in |
624 in |
620 list_comb (HOLogic.pair_const T1 T2, |
625 list_comb (HOLogic.pair_const T1 T2, |
621 map3 (fn T => term_for_rep true seen T T) [T1, T2] [R1, R2] |
626 map3 (fn T => term_for_rep true seen T T) [T1, T2] [R1, R2] |
622 [[js1], [js2]]) |
627 [[js1], [js2]]) |
623 end |
628 end |
624 | term_for_rep _ seen (Type (@{type_name fun}, [T1, T2])) T' |
629 | term_for_rep _ seen T T' (Vect (k, R')) [js] = |
625 (Vect (k, R')) [js] = |
630 term_for_vect seen k R' T T' js |
626 term_for_vect seen k R' T1 T2 T' js |
631 | term_for_rep maybe_opt seen T T' (Func (R1, Formula Neut)) jss = |
627 | term_for_rep maybe_opt seen (Type (@{type_name fun}, [T1, T2])) T' |
|
628 (Func (R1, Formula Neut)) jss = |
|
629 let |
632 let |
|
633 val T1 = pseudo_domain_type T |
|
634 val T2 = pseudo_range_type T |
630 val jss1 = all_combinations_for_rep R1 |
635 val jss1 = all_combinations_for_rep R1 |
631 val ts1 = map (term_for_rep true seen T1 T1 R1 o single) jss1 |
636 val ts1 = map (term_for_rep true seen T1 T1 R1 o single) jss1 |
632 val ts2 = |
637 val ts2 = |
633 map (fn js => term_for_rep true seen T2 T2 (Atom (2, 0)) |
638 map (fn js => term_for_rep true seen T2 T2 (Atom (2, 0)) |
634 [[int_from_bool (member (op =) jss js)]]) |
639 [[int_from_bool (member (op =) jss js)]]) |
635 jss1 |
640 jss1 |
636 in make_fun maybe_opt T1 T2 T' ts1 ts2 end |
641 in make_fun_or_set maybe_opt T T1 T2 T' ts1 ts2 end |
637 | term_for_rep maybe_opt seen (Type (@{type_name fun}, [T1, T2])) T' |
642 | term_for_rep maybe_opt seen T T' (Func (R1, R2)) jss = |
638 (Func (R1, R2)) jss = |
|
639 let |
643 let |
|
644 val T1 = pseudo_domain_type T |
|
645 val T2 = pseudo_range_type T |
640 val arity1 = arity_of_rep R1 |
646 val arity1 = arity_of_rep R1 |
641 val jss1 = all_combinations_for_rep R1 |
647 val jss1 = all_combinations_for_rep R1 |
642 val ts1 = map (term_for_rep false seen T1 T1 R1 o single) jss1 |
648 val ts1 = map (term_for_rep false seen T1 T1 R1 o single) jss1 |
643 val grouped_jss2 = AList.group (op =) (map (chop arity1) jss) |
649 val grouped_jss2 = AList.group (op =) (map (chop arity1) jss) |
644 val ts2 = map (term_for_rep false seen T2 T2 R2 o the_default [] |
650 val ts2 = map (term_for_rep false seen T2 T2 R2 o the_default [] |
645 o AList.lookup (op =) grouped_jss2) jss1 |
651 o AList.lookup (op =) grouped_jss2) jss1 |
646 in make_fun maybe_opt T1 T2 T' ts1 ts2 end |
652 in make_fun_or_set maybe_opt T T1 T2 T' ts1 ts2 end |
647 | term_for_rep _ seen T T' (Opt R) jss = |
653 | term_for_rep _ seen T T' (Opt R) jss = |
648 if null jss then Const (unknown, T) |
654 if null jss then Const (unknown, T) |
649 else term_for_rep true seen T T' R jss |
655 else term_for_rep true seen T T' R jss |
650 | term_for_rep _ _ T _ R jss = |
656 | term_for_rep _ _ T _ R jss = |
651 raise ARG ("Nitpick_Model.reconstruct_term.term_for_rep", |
657 raise ARG ("Nitpick_Model.reconstruct_term.term_for_rep", |