diff -r 41137dc935ff -r 8193bbaa07fe Nominal/nominal_eqvt.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal/nominal_eqvt.ML Sun Nov 14 16:34:47 2010 +0000 @@ -0,0 +1,142 @@ +(* Title: nominal_eqvt.ML + Author: Stefan Berghofer (original code) + Author: Christian Urban + + Automatic proofs for equivariance of inductive predicates. +*) + +signature NOMINAL_EQVT = +sig + val eqvt_rel_tac: Proof.context -> string list -> term -> thm -> thm list -> int -> tactic + val eqvt_rel_single_case_tac: Proof.context -> string list -> term -> thm -> int -> tactic + + val equivariance: bool -> term list -> thm -> thm list -> Proof.context -> thm list * local_theory + val equivariance_cmd: string -> Proof.context -> local_theory +end + +structure Nominal_Eqvt : NOMINAL_EQVT = +struct + +open Nominal_Permeq; +open Nominal_ThmDecls; + +val atomize_conv = + MetaSimplifier.rewrite_cterm (true, false, false) (K (K NONE)) + (HOL_basic_ss addsimps @{thms induct_atomize}); +val atomize_intr = Conv.fconv_rule (Conv.prems_conv ~1 atomize_conv); +fun atomize_induct ctxt = Conv.fconv_rule (Conv.prems_conv ~1 + (Conv.params_conv ~1 (K (Conv.prems_conv ~1 atomize_conv)) ctxt)); + + +(** equivariance tactics **) + +val perm_boolE = @{thm permute_boolE} +val perm_cancel = @{thms permute_minus_cancel(2)} + +fun eqvt_rel_single_case_tac ctxt pred_names pi intro = + let + val thy = ProofContext.theory_of ctxt + val cpi = Thm.cterm_of thy (mk_minus pi) + val pi_intro_rule = Drule.instantiate' [] [SOME cpi] perm_boolE + val simps1 = HOL_basic_ss addsimps @{thms permute_fun_def minus_minus split_paired_all} + val simps2 = HOL_basic_ss addsimps @{thms permute_bool_def} + in + eqvt_strict_tac ctxt [] pred_names THEN' + SUBPROOF (fn {prems, context as ctxt, ...} => + let + val prems' = map (transform_prem2 ctxt pred_names) prems + val tac1 = resolve_tac prems' + val tac2 = EVERY' [ rtac pi_intro_rule, + eqvt_strict_tac ctxt perm_cancel pred_names, resolve_tac prems' ] + val tac3 = EVERY' [ rtac pi_intro_rule, + eqvt_strict_tac ctxt perm_cancel pred_names, simp_tac simps1, + simp_tac simps2, resolve_tac prems'] + in + (rtac intro THEN_ALL_NEW FIRST' [tac1, tac2, tac3]) 1 + end) ctxt + end + +fun eqvt_rel_tac ctxt pred_names pi induct intros = + let + val cases = map (eqvt_rel_single_case_tac ctxt pred_names pi) intros + in + EVERY' (rtac induct :: cases) + end + + +(** equivariance procedure *) + +fun prepare_goal pi pred = + let + val (c, xs) = strip_comb pred; + in + HOLogic.mk_imp (pred, list_comb (c, map (mk_perm pi) xs)) + end + +(* stores thm under name.eqvt and adds [eqvt]-attribute *) + +fun note_named_thm (name, thm) ctxt = + let + val thm_name = Binding.qualified_name + (Long_Name.qualify (Long_Name.base_name name) "eqvt") + val attr = Attrib.internal (K eqvt_add) + val ((_, [thm']), ctxt') = Local_Theory.note ((thm_name, [attr]), [thm]) ctxt + in + (thm', ctxt') + end + +fun equivariance note_flag pred_trms raw_induct intrs ctxt = + let + val is_already_eqvt = + filter (is_eqvt ctxt) pred_trms + |> map (Syntax.string_of_term ctxt) + val _ = if null is_already_eqvt then () + else error ("Already equivariant: " ^ commas is_already_eqvt) + + val pred_names = map (fst o dest_Const) pred_trms + val raw_induct' = atomize_induct ctxt raw_induct + val intrs' = map atomize_intr intrs + + val (([raw_concl], [raw_pi]), ctxt') = + ctxt + |> Variable.import_terms false [concl_of raw_induct'] + ||>> Variable.variant_fixes ["p"] + val pi = Free (raw_pi, @{typ perm}) + + val preds = map (fst o HOLogic.dest_imp) + (HOLogic.dest_conj (HOLogic.dest_Trueprop raw_concl)); + + val goal = HOLogic.mk_Trueprop + (foldr1 HOLogic.mk_conj (map (prepare_goal pi) preds)) + + val thms = Goal.prove ctxt' [] [] goal + (fn {context,...} => eqvt_rel_tac context pred_names pi raw_induct' intrs' 1) + |> Datatype_Aux.split_conj_thm + |> ProofContext.export ctxt' ctxt + |> map (fn th => th RS mp) + |> map zero_var_indexes + in + if note_flag + then fold_map note_named_thm (pred_names ~~ thms) ctxt + else (thms, ctxt) + end + +fun equivariance_cmd pred_name ctxt = + let + val thy = ProofContext.theory_of ctxt + val (_, {preds, raw_induct, intrs, ...}) = + Inductive.the_inductive ctxt (Sign.intern_const thy pred_name) + in + equivariance true preds raw_induct intrs ctxt |> snd + end + +local structure P = Parse and K = Keyword in + +val _ = + Outer_Syntax.local_theory "equivariance" + "Proves equivariance for inductive predicate involving nominal datatypes." + K.thy_decl (P.xname >> equivariance_cmd); + +end; + +end (* structure *)