(* Title: HOL/Nominal/nominal_inductive2.ML Author: Stefan Berghofer, TU Muenchen
Infrastructure for proving equivariance and strong induction theorems for inductive predicates involving nominal datatypes. Experimental version that allows to avoid lists of atoms.
*)
signature NOMINAL_INDUCTIVE2 = sig val prove_strong_ind: string -> stringoption -> (string * stringlist) list ->
local_theory -> Proof.state end
fun preds_of ps t = inter (op = o apsnd dest_Free) ps (Term.add_frees t []);
val perm_bool = mk_meta_eq @{thm perm_bool_def}; val perm_boolI = @{thm perm_boolI}; val (_, [perm_boolI_pi, _]) = Drule.strip_comb (Thm.dest_arg
(Drule.strip_imp_concl (Thm.cprop_of perm_boolI)));
fun mk_perm_bool ctxt pi th =
th RS infer_instantiate ctxt [(#1 (dest_Var (Thm.term_of perm_boolI_pi)), pi)] perm_boolI;
fun mk_perm_bool_simproc names =
Simplifier.make_simproc \<^context>
{name = "perm_bool",
kind = Simproc,
lhss = [\<^term>\<open>perm pi x\<close>],
proc = fn _ => fn _ => fn ct =>
(case Thm.term_of ct of Const (\<^const_name>\<open>Nominal.perm\<close>, _) $ _ $ t => if member (op =) names (the_default "" (try (dest_Const_name o head_of) t)) then SOME perm_bool else NONE
| _ => NONE),
identifier = []};
fun transp ([] :: _) = []
| transp xs = map hd xs :: transp (map tl xs);
fun add_binders thy i (t as (_ $ _)) bs = (case strip_comb t of
(Const (s, T), ts) => (case strip_type T of
(Ts, Type (tname, _)) =>
(case NominalDatatype.get_nominal_datatype thy tname of
NONE => fold (add_binders thy i) ts bs
| SOME {descr, index, ...} => (case AList.lookup op =
(#3 (the (AList.lookup op = descr index))) s of
NONE => fold (add_binders thy i) ts bs
| SOME cargs => fst (fold (fn (xs, x) => fn (bs', cargs') => letval (cargs1, (u, _) :: cargs2) = chop (length xs) cargs' in (add_binders thy i u
(fold (fn (u, T) => ifexists (fn j => j < i) (loose_bnos u) then I else AList.map_default op = (T, [])
(insert op aconv (incr_boundvars (~i) u)))
cargs1 bs'), cargs2) end) cargs (bs, ts ~~ Ts))))
| _ => fold (add_binders thy i) ts bs)
| (u, ts) => add_binders thy i u (fold (add_binders thy i) ts bs))
| add_binders thy i (Abs (_, _, t)) bs = add_binders thy (i + 1) t bs
| add_binders thy i _ bs = bs;
fun split_conj f names (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ p $ q) _ = (case head_of p of Const (name, _) => if member (op =) names name then SOME (f p q) else NONE
| _ => NONE)
| split_conj _ _ _ _ = NONE;
fun strip_all [] t = t
| strip_all (_ :: xs) (Const (\<^const_name>\<open>All\<close>, _) $ Abs (s, T, t)) = strip_all xs t;
(*********************************************************************) (* maps R ... & (ALL pi_1 ... pi_n z. P z (pi_1 o ... o pi_n o t)) *) (* or ALL pi_1 ... pi_n z. P z (pi_1 o ... o pi_n o t) *) (* to R ... & id (ALL z. P z (pi_1 o ... o pi_n o t)) *) (* or id (ALL z. P z (pi_1 o ... o pi_n o t)) *) (* *) (* where "id" protects the subformula from simplification *) (*********************************************************************)
fun inst_conj_all names ps pis (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ p $ q) _ =
(case head_of p of Const (name, _) => if member (op =) names name then SOME (HOLogic.mk_conj (p, Const (\<^const_name>\<open>Fun.id\<close>, HOLogic.boolT --> HOLogic.boolT) $
(subst_bounds (pis, strip_all pis q)))) else NONE
| _ => NONE)
| inst_conj_all names ps pis t u = if member (op aconv) ps (head_of u) then
SOME (Const (\<^const_name>\<open>Fun.id\<close>, HOLogic.boolT --> HOLogic.boolT) $
(subst_bounds (pis, strip_all pis t))) else NONE
| inst_conj_all _ _ _ _ _ = NONE;
fun inst_conj_all_tac ctxt k = EVERY
[TRY (EVERY [eresolve_tac ctxt [conjE] 1, resolve_tac ctxt [conjI] 1, assume_tac ctxt 1]),
REPEAT_DETERM_N k (eresolve_tac ctxt [allE] 1),
simp_tac (put_simpset HOL_basic_ss ctxt addsimps [@{thm id_apply}]) 1];
fun map_term f t u = (case f t u of
NONE => map_term' f t u | x => x) and map_term' f (t $ u) (t' $ u') = (case (map_term f t t', map_term f u u') of
(NONE, NONE) => NONE
| (SOME t'', NONE) => SOME (t'' $ u)
| (NONE, SOME u'') => SOME (t $ u'')
| (SOME t'', SOME u'') => SOME (t'' $ u''))
| map_term' f (Abs (s, T, t)) (Abs (s', T', t')) = (case map_term f t t' of
NONE => NONE
| SOME t'' => SOME (Abs (s, T, t'')))
| map_term' _ _ _ = NONE;
(*********************************************************************) (* Prove F[f t] from F[t], where F is monotone *) (*********************************************************************)
fun map_thm ctxt f tac monos opt th = let val prop = Thm.prop_of th; fun prove t =
Goal.prove ctxt [] [] t (fn {context = goal_ctxt, ...} =>
EVERY [cut_facts_tac [th] 1, eresolve_tac goal_ctxt [rev_mp] 1,
REPEAT_DETERM (FIRSTGOAL (resolve_tac goal_ctxt monos)),
REPEAT_DETERM (resolve_tac goal_ctxt [impI] 1 THEN (assume_tac goal_ctxt 1 ORELSE tac))]) inOption.map prove (map_term f prop (the_default prop opt)) end;
fun abs_params params t = letval vs = map (Var o apfst (rpair 0)) (Term.variant_bounds t params) in (Logic.list_all (params, t), (vs, subst_bounds (rev vs, t))) end;
fun inst_params thy (vs, p) th cts = letval env = Pattern.first_order_match thy (p, Thm.prop_of th)
(Vartab.empty, Vartab.empty) in
Thm.instantiate (TVars.empty, Vars.make (map (dest_Var o Envir.subst_term env) vs ~~ cts)) th end;
fun prove_strong_ind s alt_name avoids lthy = let val thy = Proof_Context.theory_of lthy; val ({names, ...}, {raw_induct, intrs, elims, ...}) =
Inductive.the_inductive_global lthy (Sign.intern_const thy s); val ind_params = Inductive.params_of raw_induct; val raw_induct = atomize_induct lthy raw_induct; val elims = map (atomize_induct lthy) elims; val monos = Inductive.get_monos lthy; val eqvt_thms = NominalThmDecls.get_eqvt_thms lthy; val _ = (case subtract (op =) (fold (Term.add_const_names o Thm.prop_of) eqvt_thms []) names of
[] => ()
| xs => error ("Missing equivariance theorem for predicate(s): " ^
commas_quote xs)); val induct_cases = map (fst o fst) (fst (Rule_Cases.get (the
(Induct.lookup_inductP lthy (hd names))))); val induct_cases' = if null induct_cases then replicate (length intrs) "" else induct_cases; val (raw_induct', ctxt') = lthy
|> yield_singleton (Variable.import_terms false) (Thm.prop_of raw_induct); val concls = raw_induct' |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop |>
HOLogic.dest_conj |> map (HOLogic.dest_imp ##> strip_comb); val ps = map (fst o snd) concls;
val _ = (case duplicates (op = o apply2 fst) avoids of
[] => ()
| xs => error ("Duplicate case names: " ^ commas_quote (map fst xs))); val _ = (case subtract (op =) induct_cases (map fst avoids) of
[] => ()
| xs => error ("No such case(s) in inductive definition: " ^ commas_quote xs)); fun mk_avoids params name sets = let val (_, ctxt') = Proof_Context.add_fixes
(map (fn (s, T) => (Binding.name s, SOME T, NoSyn)) params) lthy; fun mk s = let val t = Syntax.read_term ctxt' s; val t' = fold_rev absfree params t |>
funpow (length params) (fn Abs (_, _, t) => t) in (t', HOLogic.dest_setT (fastype_of t)) end handle TERM _ =>
error ("Expression " ^ quote s ^ " to be avoided in case " ^
quote name ^ " is not a set type"); fun add_set p [] = [p]
| add_set (t, T) ((u, U) :: ps) = if T = U then letval S = HOLogic.mk_setT T in (Const (\<^const_name>\<open>sup\<close>, S --> S --> S) $ u $ t, T) :: ps end else (u, U) :: add_set (t, T) ps in
fold (mk #> add_set) sets [] end;
val prems = map (fn (prem, name) => let val prems = map (incr_boundvars 1) (Logic.strip_assums_hyp prem); val concl = incr_boundvars 1 (Logic.strip_assums_concl prem); val params = Logic.strip_params prem in
(params, if null avoids then map (fn (T, ts) => (HOLogic.mk_set T ts, T))
(fold (add_binders thy 0) (prems @ [concl]) []) elsecase AList.lookup op = avoids name of
NONE => []
| SOME sets => map (apfst (incr_boundvars 1)) (mk_avoids params name sets),
prems, strip_comb (HOLogic.dest_Trueprop concl)) end) (Logic.strip_imp_prems raw_induct' ~~ induct_cases');
val atomTs = distinct op = (maps (map snd o #2) prems); val atoms = map dest_Type_name atomTs; val ind_sort = if null atomTs then \<^sort>\<open>type\<close> else Sign.minimize_sort thy (Sign.certify_sort thy (map (fn a => Sign.intern_class thy
("fs_" ^ Long_Name.base_name a)) atoms)); val (fs_ctxt_tyname, _) = Name.variant "'n" (Variable.names_of ctxt'); val ([fs_ctxt_name], ctxt'') = Variable.variant_fixes ["z"] ctxt'; val fsT = TFree (fs_ctxt_tyname, ind_sort);
val inductive_forall_def' = Thm.instantiate'
[SOME (Thm.global_ctyp_of thy fsT)] [] inductive_forall_def;
fun lift_pred' t (Free (s, T)) ts =
list_comb (Free (s, fsT --> T), t :: ts); val lift_pred = lift_pred' (Bound 0);
fun lift_prem (t as (f $ u)) = letval (p, ts) = strip_comb t in if member (op =) ps p then HOLogic.mk_induct_forall fsT $
Abs ("z", fsT, lift_pred p (map (incr_boundvars 1) ts)) else lift_prem f $ lift_prem u end
| lift_prem (Abs (s, T, t)) = Abs (s, T, lift_prem t)
| lift_prem t = t;
fun mk_fresh (x, T) = HOLogic.mk_Trueprop
(NominalDatatype.fresh_star_const T fsT $ x $ Bound 0);
val (prems', prems'') = split_list (map (fn (params, sets, prems, (p, ts)) => let val params' = params @ [("y", fsT)]; val prem = Logic.list_implies
(map mk_fresh sets @ map (fn prem => if null (preds_of ps prem) then prem else lift_prem prem) prems,
HOLogic.mk_Trueprop (lift_pred p ts)); in abs_params params' prem end) prems);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.