src/HOL/Library/BNF_Corec.thy
author traytel
Mon Oct 24 16:53:32 2016 +0200 (2016-10-24)
changeset 64379 71f42dcaa1df
parent 64378 e9eb0b99a44c
child 67091 1393c2340eec
permissions -rw-r--r--
additional user-specified simp (naturality) rules used in friend_of_corec
blanchet@62692
     1
(*  Title:      HOL/Library/BNF_Corec.thy
blanchet@62692
     2
    Author:     Jasmin Blanchette, Inria, LORIA, MPII
blanchet@62692
     3
    Author:     Aymeric Bouzy, Ecole polytechnique
blanchet@62692
     4
    Author:     Dmitriy Traytel, ETH Zurich
blanchet@62692
     5
    Copyright   2015, 2016
blanchet@62692
     6
blanchet@62692
     7
Generalized corecursor sugar ("corec" and friends).
blanchet@62692
     8
*)
blanchet@62692
     9
blanchet@62700
    10
section \<open>Generalized Corecursor Sugar (corec and friends)\<close>
blanchet@62692
    11
blanchet@62692
    12
theory BNF_Corec
blanchet@62692
    13
imports Main
blanchet@62692
    14
keywords
blanchet@62692
    15
  "corec" :: thy_decl and
blanchet@62692
    16
  "corecursive" :: thy_goal and
blanchet@62692
    17
  "friend_of_corec" :: thy_goal and
blanchet@62692
    18
  "coinduction_upto" :: thy_decl
blanchet@62692
    19
begin
blanchet@62692
    20
blanchet@62692
    21
lemma obj_distinct_prems: "P \<longrightarrow> P \<longrightarrow> Q \<Longrightarrow> P \<Longrightarrow> Q"
blanchet@62692
    22
  by auto
blanchet@62692
    23
blanchet@62692
    24
lemma inject_refine: "g (f x) = x \<Longrightarrow> g (f y) = y \<Longrightarrow> f x = f y \<longleftrightarrow> x = y"
blanchet@62692
    25
  by (metis (no_types))
blanchet@62692
    26
blanchet@62692
    27
lemma convol_apply: "BNF_Def.convol f g x = (f x, g x)"
blanchet@62692
    28
  unfolding convol_def ..
blanchet@62692
    29
blanchet@62692
    30
lemma Grp_UNIV_id: "BNF_Def.Grp UNIV id = (op =)"
blanchet@62692
    31
  unfolding BNF_Def.Grp_def by auto
blanchet@62692
    32
blanchet@62692
    33
lemma sum_comp_cases:
blanchet@62692
    34
  assumes "f o Inl = g o Inl" and "f o Inr = g o Inr"
blanchet@62692
    35
  shows "f = g"
blanchet@62692
    36
proof (rule ext)
blanchet@62692
    37
  fix a show "f a = g a"
blanchet@62692
    38
    using assms unfolding comp_def fun_eq_iff by (cases a) auto
blanchet@62692
    39
qed
blanchet@62692
    40
blanchet@62692
    41
lemma case_sum_Inl_Inr_L: "case_sum (f o Inl) (f o Inr) = f"
blanchet@62692
    42
  by (metis case_sum_expand_Inr')
blanchet@62692
    43
blanchet@62692
    44
lemma eq_o_InrI: "\<lbrakk>g o Inl = h; case_sum h f = g\<rbrakk> \<Longrightarrow> f = g o Inr"
blanchet@62692
    45
  by (auto simp: fun_eq_iff split: sum.splits)
blanchet@62692
    46
blanchet@62692
    47
lemma id_bnf_o: "BNF_Composition.id_bnf \<circ> f = f"
blanchet@62692
    48
  unfolding BNF_Composition.id_bnf_def by (rule o_def)
blanchet@62692
    49
blanchet@62692
    50
lemma o_id_bnf: "f \<circ> BNF_Composition.id_bnf = f"
blanchet@62692
    51
  unfolding BNF_Composition.id_bnf_def by (rule o_def)
blanchet@62692
    52
blanchet@62692
    53
lemma if_True_False:
blanchet@62692
    54
  "(if P then True else Q) \<longleftrightarrow> P \<or> Q"
blanchet@62692
    55
  "(if P then False else Q) \<longleftrightarrow> \<not> P \<and> Q"
blanchet@62692
    56
  "(if P then Q else True) \<longleftrightarrow> \<not> P \<or> Q"
blanchet@62692
    57
  "(if P then Q else False) \<longleftrightarrow> P \<and> Q"
blanchet@62692
    58
  by auto
blanchet@62692
    59
blanchet@62692
    60
lemma if_distrib_fun: "(if c then f else g) x = (if c then f x else g x)"
blanchet@62692
    61
  by simp
blanchet@62692
    62
blanchet@62692
    63
blanchet@62700
    64
subsection \<open>Coinduction\<close>
blanchet@62692
    65
blanchet@62692
    66
lemma eq_comp_compI: "a o b = f o x \<Longrightarrow> x o c = id \<Longrightarrow> f = a o (b o c)"
blanchet@62692
    67
  unfolding fun_eq_iff by simp
blanchet@62692
    68
blanchet@62692
    69
lemma self_bounded_weaken_left: "(a :: 'a :: semilattice_inf) \<le> inf a b \<Longrightarrow> a \<le> b"
blanchet@62692
    70
  by (erule le_infE)
blanchet@62692
    71
blanchet@62692
    72
lemma self_bounded_weaken_right: "(a :: 'a :: semilattice_inf) \<le> inf b a \<Longrightarrow> a \<le> b"
blanchet@62692
    73
  by (erule le_infE)
blanchet@62692
    74
blanchet@62692
    75
lemma symp_iff: "symp R \<longleftrightarrow> R = R^--1"
blanchet@62692
    76
  by (metis antisym conversep.cases conversep_le_swap predicate2I symp_def)
blanchet@62692
    77
blanchet@62692
    78
lemma equivp_inf: "\<lbrakk>equivp R; equivp S\<rbrakk> \<Longrightarrow> equivp (inf R S)"
blanchet@62692
    79
  unfolding equivp_def inf_fun_def inf_bool_def by metis
blanchet@62692
    80
blanchet@62692
    81
lemma vimage2p_rel_prod:
blanchet@62692
    82
  "(\<lambda>x y. rel_prod R S (BNF_Def.convol f1 g1 x) (BNF_Def.convol f2 g2 y)) =
blanchet@62692
    83
   (inf (BNF_Def.vimage2p f1 f2 R) (BNF_Def.vimage2p g1 g2 S))"
blanchet@62692
    84
  unfolding vimage2p_def rel_prod.simps convol_def by auto
blanchet@62692
    85
blanchet@62692
    86
lemma predicate2I_obj: "(\<forall>x y. P x y \<longrightarrow> Q x y) \<Longrightarrow> P \<le> Q"
blanchet@62692
    87
  by auto
blanchet@62692
    88
blanchet@62692
    89
lemma predicate2D_obj: "P \<le> Q \<Longrightarrow> P x y \<longrightarrow> Q x y"
blanchet@62692
    90
  by auto
blanchet@62692
    91
blanchet@62692
    92
locale cong =
blanchet@62692
    93
  fixes rel :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> ('b \<Rightarrow> 'b \<Rightarrow> bool)"
blanchet@62692
    94
    and eval :: "'b \<Rightarrow> 'a"
blanchet@62692
    95
    and retr :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a \<Rightarrow> bool)"
blanchet@62692
    96
  assumes rel_mono: "\<And>R S. R \<le> S \<Longrightarrow> rel R \<le> rel S"
blanchet@62692
    97
    and equivp_retr: "\<And>R. equivp R \<Longrightarrow> equivp (retr R)"
blanchet@62692
    98
    and retr_eval: "\<And>R x y. \<lbrakk>(rel_fun (rel R) R) eval eval; rel (inf R (retr R)) x y\<rbrakk> \<Longrightarrow>
blanchet@62692
    99
      retr R (eval x) (eval y)"
blanchet@62692
   100
begin
blanchet@62692
   101
blanchet@62692
   102
definition cong :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> bool" where
blanchet@62692
   103
  "cong R \<equiv> equivp R \<and> (rel_fun (rel R) R) eval eval"
blanchet@62692
   104
blanchet@62692
   105
lemma cong_retr: "cong R \<Longrightarrow> cong (inf R (retr R))"
blanchet@62692
   106
  unfolding cong_def
blanchet@62692
   107
  by (auto simp: rel_fun_def dest: predicate2D[OF rel_mono, rotated]
blanchet@62692
   108
    intro: equivp_inf equivp_retr retr_eval)
blanchet@62692
   109
blanchet@62692
   110
lemma cong_equivp: "cong R \<Longrightarrow> equivp R"
blanchet@62692
   111
  unfolding cong_def by simp
blanchet@62692
   112
blanchet@62692
   113
definition gen_cong :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" where
blanchet@62692
   114
  "gen_cong R j1 j2 \<equiv> \<forall>R'. R \<le> R' \<and> cong R' \<longrightarrow> R' j1 j2"
blanchet@62692
   115
blanchet@62692
   116
lemma gen_cong_reflp[intro, simp]: "x = y \<Longrightarrow> gen_cong R x y"
blanchet@62692
   117
  unfolding gen_cong_def by (auto dest: cong_equivp equivp_reflp)
blanchet@62692
   118
blanchet@62692
   119
lemma gen_cong_symp[intro]: "gen_cong R x y \<Longrightarrow> gen_cong R y x"
blanchet@62692
   120
  unfolding gen_cong_def by (auto dest: cong_equivp equivp_symp)
blanchet@62692
   121
blanchet@62692
   122
lemma gen_cong_transp[intro]: "gen_cong R x y \<Longrightarrow> gen_cong R y z \<Longrightarrow> gen_cong R x z"
blanchet@62692
   123
  unfolding gen_cong_def by (auto dest: cong_equivp equivp_transp)
blanchet@62692
   124
blanchet@62692
   125
lemma equivp_gen_cong: "equivp (gen_cong R)"
blanchet@62692
   126
  by (intro equivpI reflpI sympI transpI) auto
blanchet@62692
   127
blanchet@62692
   128
lemma leq_gen_cong: "R \<le> gen_cong R"
blanchet@62692
   129
  unfolding gen_cong_def[abs_def] by auto
blanchet@62692
   130
blanchet@62692
   131
lemmas imp_gen_cong[intro] = predicate2D[OF leq_gen_cong]
blanchet@62692
   132
blanchet@62692
   133
lemma gen_cong_minimal: "\<lbrakk>R \<le> R'; cong R'\<rbrakk> \<Longrightarrow> gen_cong R \<le> R'"
blanchet@62692
   134
  unfolding gen_cong_def[abs_def] by (rule predicate2I) metis
blanchet@62692
   135
blanchet@62692
   136
lemma congdd_base_gen_congdd_base_aux:
blanchet@62692
   137
  "rel (gen_cong R) x y \<Longrightarrow> R \<le> R' \<Longrightarrow> cong R' \<Longrightarrow> R' (eval x) (eval y)"
blanchet@62692
   138
   by (force simp: rel_fun_def gen_cong_def cong_def dest: spec[of _ R'] predicate2D[OF rel_mono, rotated -1, of _ _ _ R'])
blanchet@62692
   139
blanchet@62692
   140
lemma cong_gen_cong: "cong (gen_cong R)"
blanchet@62692
   141
proof -
blanchet@62692
   142
  { fix R' x y
blanchet@62692
   143
    have "rel (gen_cong R) x y \<Longrightarrow> R \<le> R' \<Longrightarrow> cong R' \<Longrightarrow> R' (eval x) (eval y)"
blanchet@62692
   144
      by (force simp: rel_fun_def gen_cong_def cong_def dest: spec[of _ R']
blanchet@62692
   145
        predicate2D[OF rel_mono, rotated -1, of _ _ _ R'])
blanchet@62692
   146
  }
blanchet@62692
   147
  then show "cong (gen_cong R)" by (auto simp: equivp_gen_cong rel_fun_def gen_cong_def cong_def)
blanchet@62692
   148
qed
blanchet@62692
   149
blanchet@62692
   150
lemma gen_cong_eval_rel_fun:
blanchet@62692
   151
  "(rel_fun (rel (gen_cong R)) (gen_cong R)) eval eval"
blanchet@62692
   152
  using cong_gen_cong[of R] unfolding cong_def by simp
blanchet@62692
   153
blanchet@62692
   154
lemma gen_cong_eval:
blanchet@62692
   155
  "rel (gen_cong R) x y \<Longrightarrow> gen_cong R (eval x) (eval y)"
blanchet@62692
   156
  by (erule rel_funD[OF gen_cong_eval_rel_fun])
blanchet@62692
   157
blanchet@62692
   158
lemma gen_cong_idem: "gen_cong (gen_cong R) = gen_cong R"
blanchet@62692
   159
  by (simp add: antisym cong_gen_cong gen_cong_minimal leq_gen_cong)
blanchet@62692
   160
blanchet@62692
   161
lemma gen_cong_rho:
blanchet@62692
   162
  "\<rho> = eval o f \<Longrightarrow> rel (gen_cong R) (f x) (f y) \<Longrightarrow> gen_cong R (\<rho> x) (\<rho> y)"
blanchet@62692
   163
  by (simp add: gen_cong_eval)
blanchet@62692
   164
lemma coinduction:
blanchet@62692
   165
  assumes coind: "\<forall>R. R \<le> retr R \<longrightarrow> R \<le> op ="
blanchet@62692
   166
  assumes cih: "R \<le> retr (gen_cong R)"
blanchet@62692
   167
  shows "R \<le> op ="
blanchet@62692
   168
  apply (rule order_trans[OF leq_gen_cong mp[OF spec[OF coind]]])
blanchet@62692
   169
  apply (rule self_bounded_weaken_left[OF gen_cong_minimal])
blanchet@62692
   170
   apply (rule inf_greatest[OF leq_gen_cong cih])
blanchet@62692
   171
  apply (rule cong_retr[OF cong_gen_cong])
blanchet@62692
   172
  done
blanchet@62692
   173
blanchet@62692
   174
end
blanchet@62692
   175
blanchet@62692
   176
lemma rel_sum_case_sum:
blanchet@62692
   177
  "rel_fun (rel_sum R S) T (case_sum f1 g1) (case_sum f2 g2) = (rel_fun R T f1 f2 \<and> rel_fun S T g1 g2)"
blanchet@62692
   178
  by (auto simp: rel_fun_def rel_sum.simps split: sum.splits)
blanchet@62692
   179
blanchet@62692
   180
context
blanchet@62692
   181
  fixes rel eval rel' eval' retr emb
blanchet@62692
   182
  assumes base: "cong rel eval retr"
blanchet@62692
   183
  and step: "cong rel' eval' retr"
blanchet@62692
   184
  and emb: "eval' o emb = eval"
blanchet@62692
   185
  and emb_transfer: "rel_fun (rel R) (rel' R) emb emb"
blanchet@62692
   186
begin
blanchet@62692
   187
blanchet@62692
   188
interpretation base: cong rel eval retr by (rule base)
blanchet@62692
   189
interpretation step: cong rel' eval' retr by (rule step)
blanchet@62692
   190
blanchet@62692
   191
lemma gen_cong_emb: "base.gen_cong R \<le> step.gen_cong R"
blanchet@62692
   192
proof (rule base.gen_cong_minimal[OF step.leq_gen_cong])
blanchet@62692
   193
  note step.gen_cong_eval_rel_fun[transfer_rule] emb_transfer[transfer_rule]
blanchet@62692
   194
  have "(rel_fun (rel (step.gen_cong R)) (step.gen_cong R)) eval eval"
blanchet@62692
   195
    unfolding emb[symmetric] by transfer_prover
blanchet@62692
   196
  then show "base.cong (step.gen_cong R)"
blanchet@62692
   197
    by (auto simp: base.cong_def step.equivp_gen_cong)
blanchet@62692
   198
qed
blanchet@62692
   199
blanchet@62692
   200
end
blanchet@62692
   201
traytel@64379
   202
named_theorems friend_of_corec_simps
traytel@64379
   203
blanchet@62692
   204
ML_file "../Tools/BNF/bnf_gfp_grec_tactics.ML"
blanchet@62692
   205
ML_file "../Tools/BNF/bnf_gfp_grec.ML"
blanchet@62692
   206
ML_file "../Tools/BNF/bnf_gfp_grec_sugar_util.ML"
blanchet@62692
   207
ML_file "../Tools/BNF/bnf_gfp_grec_sugar_tactics.ML"
blanchet@62692
   208
ML_file "../Tools/BNF/bnf_gfp_grec_sugar.ML"
blanchet@62692
   209
ML_file "../Tools/BNF/bnf_gfp_grec_unique_sugar.ML"
blanchet@62692
   210
traytel@64378
   211
method_setup transfer_prover_eq = \<open>
traytel@64378
   212
  Scan.succeed (SIMPLE_METHOD' o BNF_GFP_Grec_Tactics.transfer_prover_eq_tac)
traytel@64378
   213
\<close> "apply transfer_prover after folding relator_eq"
traytel@64378
   214
blanchet@62692
   215
method_setup corec_unique = \<open>
blanchet@62692
   216
  Scan.succeed (SIMPLE_METHOD' o BNF_GFP_Grec_Unique_Sugar.corec_unique_tac)
blanchet@62692
   217
\<close> "prove uniqueness of corecursive equation"
blanchet@62692
   218
blanchet@62692
   219
end