simpler (forward) derivation of strong (up-to equality) coinduction properties
authortraytel
Tue, 20 Aug 2013 17:39:07 +0200
changeset 54242ec38e9f4352f
parent 54241 c042b3ad18a0
child 54243 d81211f61a1b
simpler (forward) derivation of strong (up-to equality) coinduction properties
src/HOL/BNF/BNF_FP_Basic.thy
src/HOL/BNF/BNF_GFP.thy
src/HOL/BNF/Tools/bnf_fp_util.ML
src/HOL/BNF/Tools/bnf_gfp.ML
src/HOL/BNF/Tools/bnf_gfp_tactics.ML
     1.1 --- a/src/HOL/BNF/BNF_FP_Basic.thy	Tue Aug 20 16:10:58 2013 +0200
     1.2 +++ b/src/HOL/BNF/BNF_FP_Basic.thy	Tue Aug 20 17:39:07 2013 +0200
     1.3 @@ -147,6 +147,12 @@
     1.4    "(fun_rel R (fun_rel S T)) f g = (\<forall>x y. R x y \<longrightarrow> (fun_rel S T) (f x) (g y))"
     1.5    unfolding fun_rel_def ..
     1.6  
     1.7 +lemma subst_eq_imp: "(\<forall>a b. a = b \<longrightarrow> P a b) \<equiv> (\<forall>a. P a a)"
     1.8 +  by auto
     1.9 +
    1.10 +lemma eq_subset: "op = \<le> (\<lambda>a b. P a b \<or> a = b)"
    1.11 +  by auto
    1.12 +
    1.13  ML_file "Tools/bnf_fp_util.ML"
    1.14  ML_file "Tools/bnf_fp_def_sugar_tactics.ML"
    1.15  ML_file "Tools/bnf_fp_def_sugar.ML"
     2.1 --- a/src/HOL/BNF/BNF_GFP.thy	Tue Aug 20 16:10:58 2013 +0200
     2.2 +++ b/src/HOL/BNF/BNF_GFP.thy	Tue Aug 20 17:39:07 2013 +0200
     2.3 @@ -70,9 +70,6 @@
     2.4  lemma image2_eqI: "\<lbrakk>b = f x; c = g x; x \<in> A\<rbrakk> \<Longrightarrow> (b, c) \<in> image2 A f g"
     2.5  unfolding image2_def by auto
     2.6  
     2.7 -lemma eq_subset: "op = \<le> (\<lambda>a b. P a b \<or> a = b)"
     2.8 -by auto
     2.9 -
    2.10  lemma IdD: "(a, b) \<in> Id \<Longrightarrow> a = b"
    2.11  by auto
    2.12  
     3.1 --- a/src/HOL/BNF/Tools/bnf_fp_util.ML	Tue Aug 20 16:10:58 2013 +0200
     3.2 +++ b/src/HOL/BNF/Tools/bnf_fp_util.ML	Tue Aug 20 17:39:07 2013 +0200
     3.3 @@ -179,6 +179,8 @@
     3.4    val mk_xtor_un_fold_o_map_thms: fp_kind -> bool -> int -> thm -> thm list -> thm list ->
     3.5      thm list -> thm list -> thm list
     3.6  
     3.7 +  val mk_strong_coinduct_thm: int -> thm -> thm list -> thm list -> Proof.context -> thm
     3.8 +
     3.9    val fp_bnf: (binding list -> (string * sort) list -> typ list * typ list list ->
    3.10        BNF_Def.bnf list -> local_theory -> 'a) ->
    3.11      binding list -> (string * sort) list -> ((string * sort) * typ) list -> local_theory ->
    3.12 @@ -552,6 +554,24 @@
    3.13      split_conj_thm (un_fold_unique OF map (fp_case fp I mk_sym) unique_prems)
    3.14    end;
    3.15  
    3.16 +fun mk_strong_coinduct_thm m coind rel_eqs rel_monos ctxt =
    3.17 +  let
    3.18 +    val n = Thm.nprems_of coind;
    3.19 +    fun mk_inst phi = (phi, mk_union (phi, HOLogic.eq_const (fst (dest_pred2T (fastype_of phi)))))
    3.20 +      |> pairself (certify ctxt);
    3.21 +    val insts = Term.add_vars (Thm.prop_of coind) [] |> rev |> take n |> map (mk_inst o Var);
    3.22 +    fun mk_unfold rel_eq rel_mono =
    3.23 +      let
    3.24 +        val eq = iffD2 OF [rel_eq RS @{thm predicate2_eqD}, refl];
    3.25 +        val mono = rel_mono OF (replicate m @{thm order_refl} @ replicate n @{thm eq_subset});
    3.26 +      in eq RS (mono RS @{thm predicate2D}) RS @{thm eqTrueI} end;
    3.27 +    val unfolds = map2 mk_unfold rel_eqs rel_monos @ @{thms sup_fun_def sup_bool_def
    3.28 +      imp_disjL all_conj_distrib subst_eq_imp simp_thms(18,21,35)};
    3.29 +  in
    3.30 +    Thm.instantiate ([], insts) coind
    3.31 +    |> unfold_thms ctxt unfolds
    3.32 +  end;
    3.33 +
    3.34  fun fp_bnf construct_fp bs resBs eqs lthy =
    3.35    let
    3.36      val timer = time (Timer.startRealTimer ());
     4.1 --- a/src/HOL/BNF/Tools/bnf_gfp.ML	Tue Aug 20 16:10:58 2013 +0200
     4.2 +++ b/src/HOL/BNF/Tools/bnf_gfp.ML	Tue Aug 20 17:39:07 2013 +0200
     4.3 @@ -2019,48 +2019,36 @@
     4.4  
     4.5      val timer = time (timer "corec definitions & thms");
     4.6  
     4.7 -    (* TODO: Get rid of strong versions (since these can easily be derived from the weak ones). *)
     4.8 -    val (dtor_map_coinduct_thm, coinduct_params, dtor_coinduct_thm, dtor_strong_coinduct_thm) =
     4.9 +    val (dtor_map_coinduct_thm, coinduct_params, dtor_coinduct_thm) =
    4.10        let
    4.11          val zs = Jzs1 @ Jzs2;
    4.12          val frees = phis @ zs;
    4.13  
    4.14 -        fun mk_phi strong_eq phi z1 z2 = if strong_eq
    4.15 -          then Term.absfree (dest_Free z1) (Term.absfree (dest_Free z2)
    4.16 -            (HOLogic.mk_disj (phi $ z1 $ z2, HOLogic.mk_eq (z1, z2))))
    4.17 -          else phi;
    4.18 -
    4.19 -        fun phi_rels strong_eq =
    4.20 -          map3 (fn phi => fn z1 => fn z2 => mk_phi strong_eq phi z1 z2) phis Jzs1 Jzs2;
    4.21 -
    4.22          val rels = map (Term.subst_atomic_types ((activeAs ~~ Ts) @ (activeBs ~~ Ts))) relsAsBs;
    4.23  
    4.24          fun mk_concl phi z1 z2 = HOLogic.mk_imp (phi $ z1 $ z2, HOLogic.mk_eq (z1, z2));
    4.25          val concl = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
    4.26            (map3 mk_concl phis Jzs1 Jzs2));
    4.27  
    4.28 -        fun mk_rel_prem strong_eq phi dtor rel Jz Jz_copy =
    4.29 +        fun mk_rel_prem phi dtor rel Jz Jz_copy =
    4.30            let
    4.31 -            val concl = Term.list_comb (rel, map HOLogic.eq_const passiveAs @ phi_rels strong_eq) $
    4.32 +            val concl = Term.list_comb (rel, map HOLogic.eq_const passiveAs @ phis) $
    4.33                (dtor $ Jz) $ (dtor $ Jz_copy);
    4.34            in
    4.35              HOLogic.mk_Trueprop
    4.36                (list_all_free [Jz, Jz_copy] (HOLogic.mk_imp (phi $ Jz $ Jz_copy, concl)))
    4.37            end;
    4.38  
    4.39 -        val rel_prems = map5 (mk_rel_prem false) phis dtors rels Jzs Jzs_copy;
    4.40 -        val rel_strong_prems = map5 (mk_rel_prem true) phis dtors rels Jzs Jzs_copy;
    4.41 -
    4.42 +        val rel_prems = map5 mk_rel_prem phis dtors rels Jzs Jzs_copy;
    4.43          val dtor_coinduct_goal =
    4.44            fold_rev Logic.all frees (Logic.list_implies (rel_prems, concl));
    4.45 -        val coinduct_params = rev (Term.add_tfrees dtor_coinduct_goal []);
    4.46  
    4.47          val dtor_coinduct =
    4.48            Goal.prove_sorry lthy [] [] dtor_coinduct_goal
    4.49              (K (mk_dtor_coinduct_tac m raw_coind_thm bis_rel_thm rel_congs))
    4.50            |> Thm.close_derivation;
    4.51  
    4.52 -        fun mk_prem strong_eq phi dtor map_nth sets Jz Jz_copy FJz =
    4.53 +        fun mk_prem phi dtor map_nth sets Jz Jz_copy FJz =
    4.54            let
    4.55              val xs = [Jz, Jz_copy];
    4.56  
    4.57 @@ -2070,7 +2058,7 @@
    4.58              fun mk_set_conjunct set phi z1 z2 =
    4.59                list_all_free [z1, z2]
    4.60                  (HOLogic.mk_imp (HOLogic.mk_mem (HOLogic.mk_prod (z1, z2), set $ FJz),
    4.61 -                  mk_phi strong_eq phi z1 z2 $ z1 $ z2));
    4.62 +                  phi $ z1 $ z2));
    4.63  
    4.64              val concl = list_exists_free [FJz] (HOLogic.mk_conj
    4.65                (Library.foldr1 HOLogic.mk_conj (map2 mk_map_conjunct [fstsTs, sndsTs] xs),
    4.66 @@ -2081,31 +2069,21 @@
    4.67                (HOLogic.mk_Trueprop (Term.list_comb (phi, xs)), HOLogic.mk_Trueprop concl))
    4.68            end;
    4.69  
    4.70 -        fun mk_prems strong_eq =
    4.71 -          map7 (mk_prem strong_eq) phis dtors map_FT_nths prodFT_setss Jzs Jzs_copy FJzs;
    4.72 -
    4.73 -        val prems = mk_prems false;
    4.74 -        val strong_prems = mk_prems true;
    4.75 +        val prems = map7 mk_prem phis dtors map_FT_nths prodFT_setss Jzs Jzs_copy FJzs;
    4.76  
    4.77          val dtor_map_coinduct_goal = fold_rev Logic.all frees (Logic.list_implies (prems, concl));
    4.78          val dtor_map_coinduct =
    4.79            Goal.prove_sorry lthy [] [] dtor_map_coinduct_goal
    4.80              (K (mk_dtor_map_coinduct_tac m ks raw_coind_thm bis_def))
    4.81            |> Thm.close_derivation;
    4.82 -
    4.83 -        val cTs = map (SOME o certifyT lthy o TFree) coinduct_params;
    4.84 -        val cts = map3 (SOME o certify lthy ooo mk_phi true) phis Jzs1 Jzs2;
    4.85 -
    4.86 -        val dtor_strong_coinduct = singleton (Proof_Context.export names_lthy lthy)
    4.87 -          (Goal.prove_sorry lthy [] []
    4.88 -            (fold_rev Logic.all zs (Logic.list_implies (rel_strong_prems, concl)))
    4.89 -            (K (mk_dtor_strong_coinduct_tac lthy m cTs cts dtor_coinduct rel_monos rel_eqs)))
    4.90 -          |> Thm.close_derivation;
    4.91        in
    4.92 -        (dtor_map_coinduct, rev (Term.add_tfrees dtor_map_coinduct_goal []),
    4.93 -         dtor_coinduct, dtor_strong_coinduct)
    4.94 +        (dtor_map_coinduct, rev (Term.add_tfrees dtor_map_coinduct_goal []), dtor_coinduct)
    4.95        end;
    4.96  
    4.97 +    (* TODO: Get rid of strong versions (since these can easily be derived from the weak ones). *)
    4.98 +    val dtor_strong_coinduct_thm =
    4.99 +      mk_strong_coinduct_thm m dtor_coinduct_thm rel_eqs rel_monos lthy;
   4.100 +
   4.101      val timer = time (timer "coinduction");
   4.102  
   4.103      fun mk_dtor_map_DEADID_thm dtor_inject map_id =
     5.1 --- a/src/HOL/BNF/Tools/bnf_gfp_tactics.ML	Tue Aug 20 16:10:58 2013 +0200
     5.2 +++ b/src/HOL/BNF/Tools/bnf_gfp_tactics.ML	Tue Aug 20 17:39:07 2013 +0200
     5.3 @@ -41,8 +41,6 @@
     5.4    val mk_dtor_map_coinduct_tac: int -> int list -> thm -> thm -> tactic
     5.5    val mk_dtor_set_tac: int -> thm -> thm -> thm list -> tactic
     5.6    val mk_dtor_coinduct_tac: int -> thm -> thm -> thm list -> tactic
     5.7 -  val mk_dtor_strong_coinduct_tac: Proof.context -> int -> ctyp option list ->
     5.8 -    cterm option list -> thm -> thm list -> thm list -> tactic
     5.9    val mk_dtor_rel_tac: Proof.context -> thm list -> int -> thm -> thm -> thm -> thm -> thm list ->
    5.10      thm -> thm -> thm list -> thm list -> thm list list -> tactic
    5.11    val mk_dtor_o_ctor_tac: thm -> thm -> thm -> thm -> thm list ->
    5.12 @@ -989,18 +987,6 @@
    5.13      CONJ_WRAP' (K (EVERY' [rtac impI, rtac @{thm IdD}, etac set_mp,
    5.14        rtac CollectI, etac @{thm prod_caseI}])) rel_congs] 1;
    5.15  
    5.16 -fun mk_dtor_strong_coinduct_tac ctxt m cTs cts dtor_coinduct rel_monos rel_eqs =
    5.17 -  EVERY' [rtac rev_mp, rtac (Drule.instantiate' cTs cts dtor_coinduct),
    5.18 -    EVERY' (map2 (fn rel_mono => fn rel_eq =>
    5.19 -      EVERY' [REPEAT_DETERM o resolve_tac [allI, impI], REPEAT_DETERM o etac allE,
    5.20 -        etac disjE, etac mp, atac, hyp_subst_tac ctxt, rtac (rel_mono RS @{thm predicate2D}),
    5.21 -        REPEAT_DETERM_N m o rtac @{thm order_refl},
    5.22 -        REPEAT_DETERM_N (length rel_monos) o rtac @{thm eq_subset},
    5.23 -        rtac (rel_eq RS sym RS @{thm eq_refl} RS @{thm predicate2D}), rtac refl])
    5.24 -    rel_monos rel_eqs),
    5.25 -    rtac impI, REPEAT_DETERM o etac conjE,
    5.26 -    CONJ_WRAP' (K (rtac impI THEN' etac mp THEN' etac disjI1)) rel_eqs] 1;
    5.27 -
    5.28  fun mk_dtor_map_coinduct_tac m ks raw_coind bis_def =
    5.29    let
    5.30      val n = length ks;