src/HOL/Tools/BNF/bnf_lfp_tactics.ML
author haftmann
Sat Mar 22 08:37:43 2014 +0100 (2014-03-22)
changeset 56248 67dc9549fa15
parent 56237 69a9dfe71aed
child 56262 251f60be62a7
permissions -rw-r--r--
generalized and strengthened cong rules on compound operators, similar to 1ed737a98198
blanchet@55061
     1
(*  Title:      HOL/Tools/BNF/bnf_lfp_tactics.ML
blanchet@48975
     2
    Author:     Dmitriy Traytel, TU Muenchen
blanchet@48975
     3
    Author:     Andrei Popescu, TU Muenchen
blanchet@48975
     4
    Copyright   2012
blanchet@48975
     5
blanchet@48975
     6
Tactics for the datatype construction.
blanchet@48975
     7
*)
blanchet@48975
     8
blanchet@48975
     9
signature BNF_LFP_TACTICS =
blanchet@48975
    10
sig
blanchet@48975
    11
  val mk_alg_min_alg_tac: int -> thm -> thm list -> thm -> thm -> thm list list -> thm list ->
blanchet@48975
    12
    thm list -> tactic
wenzelm@51798
    13
  val mk_alg_not_empty_tac: Proof.context -> thm -> thm list -> thm list -> tactic
traytel@55197
    14
  val mk_alg_select_tac: Proof.context -> thm -> tactic
blanchet@48975
    15
  val mk_alg_set_tac: thm -> tactic
blanchet@48975
    16
  val mk_bd_card_order_tac: thm list -> tactic
blanchet@48975
    17
  val mk_bd_limit_tac: int -> thm -> tactic
blanchet@48975
    18
  val mk_card_of_min_alg_tac: thm -> thm -> thm -> thm -> thm -> tactic
traytel@56237
    19
  val mk_copy_tac: int -> thm -> thm -> thm list -> thm list list -> tactic
wenzelm@51798
    20
  val mk_ctor_induct_tac: Proof.context -> int -> thm list list -> thm -> thm list -> thm ->
wenzelm@51798
    21
    thm list -> thm list -> thm list -> tactic
traytel@55197
    22
  val mk_ctor_induct2_tac: Proof.context -> ctyp option list -> cterm option list -> thm ->
traytel@55197
    23
    thm list -> tactic
blanchet@49585
    24
  val mk_ctor_set_tac: thm -> thm -> thm list -> tactic
traytel@51893
    25
  val mk_ctor_rel_tac: Proof.context -> thm list -> int -> thm -> thm -> thm -> thm -> thm list ->
wenzelm@51798
    26
    thm -> thm -> thm list -> thm list -> thm list list -> tactic
blanchet@49506
    27
  val mk_dtor_o_ctor_tac: thm -> thm -> thm -> thm -> thm list -> tactic
traytel@56237
    28
  val mk_init_ex_mor_tac: Proof.context -> thm -> thm -> thm list -> thm -> thm -> thm -> thm ->
traytel@55197
    29
    tactic
blanchet@48975
    30
  val mk_init_induct_tac: int -> thm -> thm -> thm list -> thm list -> tactic
blanchet@48975
    31
  val mk_init_unique_mor_tac: int -> thm -> thm -> thm list -> thm list -> thm list -> thm list ->
blanchet@48975
    32
    thm list -> tactic
blanchet@49504
    33
  val mk_fold_unique_mor_tac: thm list -> thm list -> thm list -> thm -> thm -> thm -> tactic
traytel@55197
    34
  val mk_fold_transfer_tac: Proof.context -> int -> thm -> thm list -> thm list -> tactic
blanchet@48975
    35
  val mk_least_min_alg_tac: thm -> thm -> tactic
traytel@55197
    36
  val mk_le_rel_OO_tac: Proof.context -> int -> thm -> thm list -> thm list -> thm list ->
traytel@55197
    37
    thm list -> tactic
blanchet@53287
    38
  val mk_map_comp0_tac: thm list -> thm list -> thm -> int -> tactic
blanchet@53270
    39
  val mk_map_id0_tac: thm list -> thm -> tactic
blanchet@48975
    40
  val mk_map_tac: int -> int -> thm -> thm -> thm -> tactic
traytel@55197
    41
  val mk_ctor_map_unique_tac: Proof.context -> thm -> thm list -> tactic
traytel@55197
    42
  val mk_mcong_tac: Proof.context -> (int -> tactic) -> thm list list list -> thm list ->
traytel@55197
    43
    thm list -> tactic
blanchet@48975
    44
  val mk_min_algs_card_of_tac: ctyp -> cterm -> int -> thm -> thm list -> thm list -> thm -> thm ->
blanchet@51812
    45
    thm -> thm -> thm -> thm -> thm -> tactic
blanchet@48975
    46
  val mk_min_algs_least_tac: ctyp -> cterm -> thm -> thm list -> thm list -> tactic
wenzelm@51798
    47
  val mk_min_algs_mono_tac: Proof.context -> thm -> tactic
blanchet@48975
    48
  val mk_min_algs_tac: thm -> thm list -> tactic
traytel@56237
    49
  val mk_mor_Abs_tac: Proof.context -> cterm option list -> thm list -> thm list -> thm list ->
traytel@56237
    50
    thm list -> tactic
traytel@56237
    51
  val mk_mor_Rep_tac: Proof.context -> int -> thm list -> thm list -> thm list -> thm -> thm list ->
traytel@56237
    52
    thm list list -> tactic
blanchet@48975
    53
  val mk_mor_UNIV_tac: int -> thm list -> thm -> tactic
blanchet@48975
    54
  val mk_mor_comp_tac: thm -> thm list list -> thm list -> tactic
blanchet@48975
    55
  val mk_mor_convol_tac: 'a list -> thm -> tactic
blanchet@48975
    56
  val mk_mor_elim_tac: thm -> tactic
blanchet@48975
    57
  val mk_mor_incl_tac: thm -> thm list -> tactic
blanchet@49504
    58
  val mk_mor_fold_tac: ctyp -> cterm -> thm list -> thm -> thm -> tactic
blanchet@48975
    59
  val mk_mor_select_tac: thm -> thm -> thm -> thm -> thm -> thm -> thm list -> thm list list ->
blanchet@48975
    60
    thm list -> tactic
blanchet@48975
    61
  val mk_mor_str_tac: 'a list -> thm -> tactic
traytel@55197
    62
  val mk_rel_induct_tac: Proof.context -> thm list -> int -> thm -> int list -> thm list ->
traytel@55197
    63
    thm list -> tactic
traytel@55197
    64
  val mk_rec_tac: Proof.context -> thm list -> thm -> thm list -> tactic
traytel@55197
    65
  val mk_rec_unique_mor_tac: Proof.context -> thm list -> thm list -> thm -> tactic
traytel@55197
    66
  val mk_set_bd_tac: Proof.context -> int -> (int -> tactic) -> thm -> thm list list -> thm list ->
traytel@55197
    67
    int -> tactic
traytel@55197
    68
  val mk_set_nat_tac: Proof.context -> int -> (int -> tactic) -> thm list list -> thm list ->
traytel@55197
    69
    cterm list -> thm list -> int -> tactic
blanchet@53289
    70
  val mk_set_map0_tac: thm -> tactic
blanchet@48975
    71
  val mk_set_tac: thm -> tactic
wenzelm@51798
    72
  val mk_wit_tac: Proof.context -> int -> thm list -> thm list -> tactic
blanchet@48975
    73
end;
blanchet@48975
    74
blanchet@48975
    75
structure BNF_LFP_Tactics : BNF_LFP_TACTICS =
blanchet@48975
    76
struct
blanchet@48975
    77
blanchet@48975
    78
open BNF_Tactics
blanchet@48975
    79
open BNF_LFP_Util
blanchet@48975
    80
open BNF_Util
blanchet@48975
    81
blanchet@49306
    82
val fst_snd_convs = @{thms fst_conv snd_conv};
blanchet@49306
    83
val ord_eq_le_trans = @{thm ord_eq_le_trans};
blanchet@49306
    84
val subset_trans = @{thm subset_trans};
blanchet@49306
    85
val trans_fun_cong_image_id_id_apply = @{thm trans[OF fun_cong[OF image_id] id_apply]};
traytel@52659
    86
val rev_bspec = Drule.rotate_prems 1 bspec;
traytel@56114
    87
val Un_cong = @{thm arg_cong2[of _ _ _ _ "op \<union>"]};
traytel@56114
    88
val relChainD = @{thm iffD2[OF meta_eq_to_obj_eq[OF relChain_def]]};
blanchet@49306
    89
blanchet@48975
    90
fun mk_alg_set_tac alg_def =
traytel@55541
    91
  EVERY' [dtac (alg_def RS iffD1), REPEAT_DETERM o etac conjE, etac bspec, rtac CollectI,
traytel@55541
    92
   REPEAT_DETERM o (rtac (subset_UNIV RS conjI) ORELSE' etac conjI), atac] 1;
blanchet@48975
    93
wenzelm@51798
    94
fun mk_alg_not_empty_tac ctxt alg_set alg_sets wits =
wenzelm@51798
    95
  (EVERY' [rtac notI, hyp_subst_tac ctxt, ftac alg_set] THEN'
blanchet@48975
    96
  REPEAT_DETERM o FIRST'
traytel@55541
    97
    [EVERY' [rtac @{thm subset_emptyI}, eresolve_tac wits],
blanchet@48975
    98
    EVERY' [rtac subsetI, rtac FalseE, eresolve_tac wits],
wenzelm@51798
    99
    EVERY' [rtac subsetI, dresolve_tac wits, hyp_subst_tac ctxt,
blanchet@48975
   100
      FIRST' (map (fn thm => rtac thm THEN' atac) alg_sets)]] THEN'
blanchet@48975
   101
  etac @{thm emptyE}) 1;
blanchet@48975
   102
blanchet@48975
   103
fun mk_mor_elim_tac mor_def =
traytel@56114
   104
  (dtac (mor_def RS iffD1) THEN'
blanchet@48975
   105
  REPEAT o etac conjE THEN'
blanchet@48975
   106
  TRY o rtac @{thm image_subsetI} THEN'
blanchet@48975
   107
  etac bspec THEN'
blanchet@48975
   108
  atac) 1;
blanchet@48975
   109
blanchet@53285
   110
fun mk_mor_incl_tac mor_def map_ids =
traytel@56114
   111
  (rtac (mor_def RS iffD2) THEN'
blanchet@48975
   112
  rtac conjI THEN'
traytel@56114
   113
  CONJ_WRAP' (K (EVERY' [rtac ballI, etac set_mp, etac (id_apply RS @{thm ssubst_mem})]))
traytel@56114
   114
    map_ids THEN'
blanchet@48975
   115
  CONJ_WRAP' (fn thm =>
traytel@56114
   116
    (EVERY' [rtac ballI, rtac trans, rtac id_apply, stac thm, rtac refl])) map_ids) 1;
blanchet@48975
   117
blanchet@53290
   118
fun mk_mor_comp_tac mor_def set_maps map_comp_ids =
blanchet@48975
   119
  let
traytel@56114
   120
    val fbetw_tac =
traytel@56114
   121
      EVERY' [rtac ballI, rtac (o_apply RS @{thm ssubst_mem}), etac bspec, etac bspec, atac];
blanchet@53290
   122
    fun mor_tac (set_map, map_comp_id) =
traytel@56114
   123
      EVERY' [rtac ballI, rtac (o_apply RS trans), rtac trans,
traytel@52659
   124
        rtac trans, dtac rev_bspec, atac, etac arg_cong,
blanchet@48975
   125
         REPEAT o eresolve_tac [CollectE, conjE], etac bspec, rtac CollectI] THEN'
blanchet@48975
   126
      CONJ_WRAP' (fn thm =>
blanchet@49306
   127
        FIRST' [rtac subset_UNIV,
blanchet@49306
   128
          (EVERY' [rtac ord_eq_le_trans, rtac thm, rtac @{thm image_subsetI},
blanchet@53290
   129
            etac bspec, etac set_mp, atac])]) set_map THEN'
blanchet@48975
   130
      rtac (map_comp_id RS arg_cong);
blanchet@48975
   131
  in
traytel@56114
   132
    (dtac (mor_def RS iffD1) THEN' dtac (mor_def RS iffD1) THEN' rtac (mor_def RS iffD2) THEN'
blanchet@48975
   133
    REPEAT o etac conjE THEN'
blanchet@48975
   134
    rtac conjI THEN'
blanchet@53290
   135
    CONJ_WRAP' (K fbetw_tac) set_maps THEN'
blanchet@53290
   136
    CONJ_WRAP' mor_tac (set_maps ~~ map_comp_ids)) 1
blanchet@48975
   137
  end;
blanchet@48975
   138
blanchet@48975
   139
fun mk_mor_str_tac ks mor_def =
traytel@56114
   140
  (rtac (mor_def RS iffD2) THEN' rtac conjI THEN'
blanchet@48975
   141
  CONJ_WRAP' (K (EVERY' [rtac ballI, rtac UNIV_I])) ks THEN'
blanchet@48975
   142
  CONJ_WRAP' (K (EVERY' [rtac ballI, rtac refl])) ks) 1;
blanchet@48975
   143
blanchet@48975
   144
fun mk_mor_convol_tac ks mor_def =
traytel@56114
   145
  (rtac (mor_def RS iffD2) THEN' rtac conjI THEN'
blanchet@48975
   146
  CONJ_WRAP' (K (EVERY' [rtac ballI, rtac UNIV_I])) ks THEN'
blanchet@48975
   147
  CONJ_WRAP' (K (EVERY' [rtac ballI, rtac trans, rtac @{thm fst_convol'}, rtac o_apply])) ks) 1;
blanchet@48975
   148
blanchet@48975
   149
fun mk_mor_UNIV_tac m morEs mor_def =
blanchet@48975
   150
  let
blanchet@48975
   151
    val n = length morEs;
wenzelm@55990
   152
    fun mor_tac morE = EVERY' [rtac @{thm ext}, rtac trans, rtac o_apply, rtac trans, etac morE,
blanchet@49306
   153
      rtac CollectI, CONJ_WRAP' (K (rtac subset_UNIV)) (1 upto m + n),
blanchet@48975
   154
      rtac sym, rtac o_apply];
blanchet@48975
   155
  in
blanchet@48975
   156
    EVERY' [rtac iffI, CONJ_WRAP' mor_tac morEs,
traytel@56114
   157
    rtac (mor_def RS iffD2), rtac conjI, CONJ_WRAP' (K (rtac ballI THEN' rtac UNIV_I)) morEs,
traytel@56114
   158
    REPEAT_DETERM o etac conjE, REPEAT_DETERM_N n o dtac (@{thm fun_eq_iff} RS iffD1),
blanchet@48975
   159
    CONJ_WRAP' (K (EVERY' [rtac ballI, REPEAT_DETERM o etac allE, rtac trans,
traytel@56114
   160
      etac (o_apply RS sym RS trans), rtac o_apply])) morEs] 1
blanchet@48975
   161
  end;
blanchet@48975
   162
traytel@56237
   163
fun mk_copy_tac m alg_def mor_def alg_sets set_mapss =
blanchet@48975
   164
  let
blanchet@48975
   165
    val n = length alg_sets;
traytel@56237
   166
    fun set_tac thm =
traytel@56237
   167
      EVERY' [rtac ord_eq_le_trans, rtac thm, rtac subset_trans, etac @{thm image_mono},
traytel@56237
   168
        rtac equalityD1, etac @{thm bij_betw_imageE}];
traytel@56237
   169
    val alg_tac =
traytel@56237
   170
      CONJ_WRAP' (fn (set_maps, alg_set) =>
blanchet@49306
   171
        EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, conjE], rtac set_mp,
traytel@56237
   172
          rtac equalityD1, etac @{thm bij_betw_imageE[OF bij_betw_the_inv_into]},
traytel@56237
   173
          rtac imageI, etac alg_set, EVERY' (map set_tac (drop m set_maps))])
traytel@56237
   174
      (set_mapss ~~ alg_sets);
blanchet@48975
   175
traytel@56237
   176
    val mor_tac = rtac conjI THEN' CONJ_WRAP' (K (etac @{thm bij_betwE})) alg_sets THEN'
traytel@56237
   177
      CONJ_WRAP' (fn (set_maps, alg_set) =>
traytel@56237
   178
        EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, conjE],
traytel@56237
   179
          etac @{thm f_the_inv_into_f_bij_betw}, etac alg_set,
traytel@56237
   180
          EVERY' (map set_tac (drop m set_maps))])
traytel@56237
   181
      (set_mapss ~~ alg_sets);
blanchet@48975
   182
  in
traytel@56237
   183
    (REPEAT_DETERM_N n o rtac exI THEN' rtac conjI THEN'
traytel@56237
   184
    rtac (alg_def RS iffD2) THEN' alg_tac THEN' rtac (mor_def RS iffD2) THEN' mor_tac) 1
blanchet@48975
   185
  end;
blanchet@48975
   186
blanchet@48975
   187
fun mk_bd_limit_tac n bd_Cinfinite =
blanchet@48975
   188
  EVERY' [REPEAT_DETERM o etac conjE, rtac rev_mp, rtac @{thm Cinfinite_limit_finite},
blanchet@48975
   189
    REPEAT_DETERM_N n o rtac @{thm finite.insertI}, rtac @{thm finite.emptyI},
blanchet@48975
   190
    REPEAT_DETERM_N n o etac @{thm insert_subsetI}, rtac @{thm empty_subsetI},
blanchet@48975
   191
    rtac bd_Cinfinite, rtac impI, etac bexE, rtac bexI,
blanchet@48975
   192
    CONJ_WRAP' (fn i =>
blanchet@48975
   193
      EVERY' [etac bspec, REPEAT_DETERM_N i o rtac @{thm insertI2}, rtac @{thm insertI1}])
blanchet@48975
   194
      (0 upto n - 1),
blanchet@48975
   195
    atac] 1;
blanchet@48975
   196
blanchet@48975
   197
fun mk_min_algs_tac worel in_congs =
blanchet@48975
   198
  let
haftmann@56248
   199
    val minG_tac = EVERY' [rtac @{thm SUP_cong}, rtac refl, dtac bspec, atac, etac arg_cong];
blanchet@48975
   200
    fun minH_tac thm =
traytel@52659
   201
      EVERY' [rtac Un_cong, minG_tac, rtac @{thm image_cong}, rtac thm,
blanchet@48975
   202
        REPEAT_DETERM_N (length in_congs) o minG_tac, rtac refl];
blanchet@48975
   203
  in
traytel@56114
   204
    (rtac (worel RS (@{thm wo_rel.worec_fixpoint} RS fun_cong)) THEN' rtac iffD2 THEN'
blanchet@48975
   205
    rtac meta_eq_to_obj_eq THEN' rtac (worel RS @{thm wo_rel.adm_wo_def}) THEN'
blanchet@48975
   206
    REPEAT_DETERM_N 3 o rtac allI THEN' rtac impI THEN'
traytel@49488
   207
    CONJ_WRAP_GEN' (EVERY' [rtac Pair_eqI, rtac conjI]) minH_tac in_congs) 1
blanchet@48975
   208
  end;
blanchet@48975
   209
traytel@56114
   210
fun mk_min_algs_mono_tac ctxt min_algs = EVERY' [rtac relChainD, rtac allI, rtac allI, rtac impI,
traytel@56114
   211
  rtac @{thm case_split}, rtac @{thm xt1(3)}, rtac min_algs, etac @{thm FieldI2}, rtac subsetI,
traytel@56114
   212
  rtac UnI1, rtac @{thm UN_I}, etac @{thm underS_I}, atac, atac, rtac equalityD1,
traytel@56114
   213
  dtac @{thm notnotD}, hyp_subst_tac ctxt, rtac refl] 1;
blanchet@48975
   214
blanchet@48975
   215
fun mk_min_algs_card_of_tac cT ct m worel min_algs in_bds bd_Card_order bd_Cnotzero
blanchet@51812
   216
  suc_Card_order suc_Cinfinite suc_Cnotzero suc_Asuc Asuc_Cinfinite =
blanchet@48975
   217
  let
blanchet@48975
   218
    val induct = worel RS
blanchet@48975
   219
      Drule.instantiate' [SOME cT] [NONE, SOME ct] @{thm well_order_induct_imp};
blanchet@48975
   220
    val src = 1 upto m + 1;
blanchet@48975
   221
    val dest = (m + 1) :: (1 upto m);
blanchet@48975
   222
    val absorbAs_tac = if m = 0 then K (all_tac)
blanchet@48975
   223
      else EVERY' [rtac @{thm ordIso_transitive}, rtac @{thm csum_cong1},
blanchet@48975
   224
        rtac @{thm ordIso_transitive},
blanchet@48975
   225
        BNF_Tactics.mk_rotate_eq_tac (rtac @{thm ordIso_refl} THEN'
blanchet@48975
   226
          FIRST' [rtac @{thm card_of_Card_order}, rtac @{thm Card_order_csum},
blanchet@48975
   227
            rtac @{thm Card_order_cexp}])
blanchet@48975
   228
        @{thm ordIso_transitive} @{thm csum_assoc} @{thm csum_com} @{thm csum_cong}
blanchet@48975
   229
        src dest,
blanchet@48975
   230
        rtac @{thm csum_absorb1}, rtac Asuc_Cinfinite, rtac ctrans, rtac @{thm ordLeq_csum1},
blanchet@48975
   231
        FIRST' [rtac @{thm Card_order_csum}, rtac @{thm card_of_Card_order}],
blanchet@48975
   232
        rtac @{thm ordLeq_cexp1}, rtac suc_Cnotzero, rtac @{thm Card_order_csum}];
blanchet@48975
   233
blanchet@48975
   234
    val minG_tac = EVERY' [rtac @{thm UNION_Cinfinite_bound}, rtac @{thm ordLess_imp_ordLeq},
blanchet@48975
   235
      rtac @{thm ordLess_transitive}, rtac @{thm card_of_underS}, rtac suc_Card_order,
blanchet@48975
   236
      atac, rtac suc_Asuc, rtac ballI, etac allE, dtac mp, etac @{thm underS_E},
blanchet@48975
   237
      dtac mp, etac @{thm underS_Field}, REPEAT o etac conjE, atac, rtac Asuc_Cinfinite]
blanchet@48975
   238
blanchet@48975
   239
    fun mk_minH_tac (min_alg, in_bd) = EVERY' [rtac @{thm ordIso_ordLeq_trans},
blanchet@48975
   240
      rtac @{thm card_of_ordIso_subst}, etac min_alg, rtac @{thm Un_Cinfinite_bound},
blanchet@48975
   241
      minG_tac, rtac ctrans, rtac @{thm card_of_image}, rtac ctrans, rtac in_bd, rtac ctrans,
traytel@51782
   242
      rtac @{thm cexp_mono1}, rtac @{thm csum_mono1},
blanchet@48975
   243
      REPEAT_DETERM_N m o rtac @{thm csum_mono2},
blanchet@48975
   244
      CONJ_WRAP_GEN' (rtac @{thm csum_cinfinite_bound}) (K minG_tac) min_algs,
blanchet@48975
   245
      REPEAT_DETERM o FIRST'
traytel@51782
   246
        [rtac @{thm card_of_Card_order}, rtac @{thm Card_order_csum},
traytel@51782
   247
        rtac Asuc_Cinfinite, rtac bd_Card_order],
traytel@51782
   248
      rtac @{thm ordIso_ordLeq_trans}, rtac @{thm cexp_cong1}, absorbAs_tac,
blanchet@48975
   249
      rtac @{thm csum_absorb1}, rtac Asuc_Cinfinite, rtac @{thm ctwo_ordLeq_Cinfinite},
blanchet@48975
   250
      rtac Asuc_Cinfinite, rtac bd_Card_order,
blanchet@48975
   251
      rtac @{thm ordIso_imp_ordLeq}, rtac @{thm cexp_cprod_ordLeq},
traytel@51782
   252
      resolve_tac @{thms Card_order_csum Card_order_ctwo}, rtac suc_Cinfinite,
blanchet@48975
   253
      rtac bd_Cnotzero, rtac @{thm cardSuc_ordLeq}, rtac bd_Card_order, rtac Asuc_Cinfinite];
blanchet@48975
   254
  in
blanchet@48975
   255
    (rtac induct THEN'
blanchet@48975
   256
    rtac impI THEN'
blanchet@48975
   257
    CONJ_WRAP' mk_minH_tac (min_algs ~~ in_bds)) 1
blanchet@48975
   258
  end;
blanchet@48975
   259
blanchet@48975
   260
fun mk_min_algs_least_tac cT ct worel min_algs alg_sets =
blanchet@48975
   261
  let
blanchet@48975
   262
    val induct = worel RS
blanchet@48975
   263
      Drule.instantiate' [SOME cT] [NONE, SOME ct] @{thm well_order_induct_imp};
blanchet@48975
   264
blanchet@48975
   265
    val minG_tac = EVERY' [rtac @{thm UN_least}, etac allE, dtac mp, etac @{thm underS_E},
blanchet@48975
   266
      dtac mp, etac @{thm underS_Field}, REPEAT_DETERM o etac conjE, atac];
blanchet@48975
   267
blanchet@49306
   268
    fun mk_minH_tac (min_alg, alg_set) = EVERY' [rtac ord_eq_le_trans, etac min_alg,
blanchet@48975
   269
      rtac @{thm Un_least}, minG_tac, rtac @{thm image_subsetI},
blanchet@48975
   270
      REPEAT_DETERM o eresolve_tac [CollectE, conjE], etac alg_set,
traytel@55541
   271
      REPEAT_DETERM o (etac subset_trans THEN' minG_tac)];
blanchet@48975
   272
  in
blanchet@48975
   273
    (rtac induct THEN'
blanchet@48975
   274
    rtac impI THEN'
blanchet@48975
   275
    CONJ_WRAP' mk_minH_tac (min_algs ~~ alg_sets)) 1
blanchet@48975
   276
  end;
blanchet@48975
   277
blanchet@48975
   278
fun mk_alg_min_alg_tac m alg_def min_alg_defs bd_limit bd_Cinfinite
blanchet@48975
   279
    set_bdss min_algs min_alg_monos =
blanchet@48975
   280
  let
blanchet@48975
   281
    val n = length min_algs;
blanchet@48975
   282
    fun mk_cardSuc_UNION_tac set_bds (mono, def) = EVERY'
blanchet@48975
   283
      [rtac bexE, rtac @{thm cardSuc_UNION_Cinfinite}, rtac bd_Cinfinite, rtac mono,
blanchet@48975
   284
       etac (def RSN (2, @{thm subset_trans[OF _ equalityD1]})), resolve_tac set_bds];
blanchet@48975
   285
    fun mk_conjunct_tac (set_bds, (min_alg, min_alg_def)) =
blanchet@48975
   286
      EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, conjE],
blanchet@48975
   287
        EVERY' (map (mk_cardSuc_UNION_tac set_bds) (min_alg_monos ~~ min_alg_defs)), rtac bexE,
blanchet@48975
   288
        rtac bd_limit, REPEAT_DETERM_N (n - 1) o etac conjI, atac,
blanchet@48975
   289
        rtac (min_alg_def RS @{thm set_mp[OF equalityD2]}),
blanchet@49306
   290
        rtac @{thm UN_I}, REPEAT_DETERM_N (m + 3 * n) o etac thin_rl, atac, rtac set_mp,
blanchet@48975
   291
        rtac equalityD2, rtac min_alg, atac, rtac UnI2, rtac @{thm image_eqI}, rtac refl,
blanchet@48975
   292
        rtac CollectI, REPEAT_DETERM_N m o dtac asm_rl, REPEAT_DETERM_N n o etac thin_rl,
blanchet@48975
   293
        REPEAT_DETERM o etac conjE,
blanchet@48975
   294
        CONJ_WRAP' (K (FIRST' [atac,
blanchet@48975
   295
          EVERY' [etac subset_trans, rtac subsetI, rtac @{thm UN_I},
blanchet@48975
   296
            etac @{thm underS_I}, atac, atac]]))
blanchet@48975
   297
          set_bds];
blanchet@48975
   298
  in
traytel@52904
   299
    (rtac (alg_def RS iffD2) THEN'
blanchet@48975
   300
    CONJ_WRAP' mk_conjunct_tac (set_bdss ~~ (min_algs ~~ min_alg_defs))) 1
blanchet@48975
   301
  end;
blanchet@48975
   302
blanchet@48975
   303
fun mk_card_of_min_alg_tac min_alg_def card_of suc_Card_order suc_Asuc Asuc_Cinfinite =
traytel@56114
   304
  EVERY' [rtac @{thm ordIso_ordLeq_trans}, rtac (min_alg_def RS @{thm card_of_ordIso_subst}),
traytel@56114
   305
    rtac @{thm UNION_Cinfinite_bound}, rtac @{thm ordIso_ordLeq_trans},
traytel@56114
   306
    rtac @{thm card_of_Field_ordIso}, rtac suc_Card_order, rtac @{thm ordLess_imp_ordLeq},
traytel@56114
   307
    rtac suc_Asuc, rtac ballI, dtac rev_mp, rtac card_of,  REPEAT_DETERM o etac conjE, atac,
traytel@56114
   308
    rtac Asuc_Cinfinite] 1;
blanchet@48975
   309
blanchet@48975
   310
fun mk_least_min_alg_tac min_alg_def least =
traytel@56114
   311
  EVERY' [rtac (min_alg_def RS ord_eq_le_trans), rtac @{thm UN_least}, dtac least, dtac mp, atac,
blanchet@48975
   312
    REPEAT_DETERM o etac conjE, atac] 1;
blanchet@48975
   313
traytel@55197
   314
fun mk_alg_select_tac ctxt Abs_inverse =
wenzelm@51798
   315
  EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, exE, conjE], hyp_subst_tac ctxt] 1 THEN
blanchet@49504
   316
  unfold_thms_tac ctxt (Abs_inverse :: fst_snd_convs) THEN atac 1;
blanchet@48975
   317
blanchet@53290
   318
fun mk_mor_select_tac mor_def mor_cong mor_comp mor_incl_min_alg alg_def alg_select alg_sets
blanchet@53290
   319
    set_maps str_init_defs =
blanchet@48975
   320
  let
blanchet@48975
   321
    val n = length alg_sets;
blanchet@48975
   322
    val fbetw_tac =
traytel@52659
   323
      CONJ_WRAP' (K (EVERY' [rtac ballI, etac rev_bspec, etac CollectE, atac])) alg_sets;
blanchet@48975
   324
    val mor_tac =
blanchet@48975
   325
      CONJ_WRAP' (fn thm => EVERY' [rtac ballI, rtac thm]) str_init_defs;
blanchet@53290
   326
    fun alg_epi_tac ((alg_set, str_init_def), set_map) =
blanchet@48975
   327
      EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, conjE], rtac CollectI,
traytel@56114
   328
        rtac ballI, ftac (alg_select RS bspec), rtac (str_init_def RS @{thm ssubst_mem}),
traytel@56114
   329
        etac alg_set, REPEAT_DETERM o EVERY' [rtac ord_eq_le_trans, resolve_tac set_map,
traytel@56114
   330
          rtac subset_trans, etac @{thm image_mono}, rtac @{thm image_Collect_subsetI}, etac bspec,
traytel@56114
   331
          atac]];
blanchet@48975
   332
  in
traytel@56114
   333
    EVERY' [rtac mor_cong, REPEAT_DETERM_N n o (rtac sym THEN' rtac @{thm comp_id}),
traytel@56114
   334
      rtac (Thm.permute_prems 0 1 mor_comp), etac (Thm.permute_prems 0 1 mor_comp),
traytel@56114
   335
      rtac (mor_def RS iffD2), rtac conjI, fbetw_tac, mor_tac, rtac mor_incl_min_alg,
traytel@56114
   336
      rtac (alg_def RS iffD2), CONJ_WRAP' alg_epi_tac ((alg_sets ~~ str_init_defs) ~~ set_maps)] 1
blanchet@48975
   337
  end;
blanchet@48975
   338
traytel@56237
   339
fun mk_init_ex_mor_tac ctxt Abs_inverse copy card_of_min_algs mor_Rep mor_comp mor_select mor_incl =
blanchet@48975
   340
  let
blanchet@48975
   341
    val n = length card_of_min_algs;
blanchet@48975
   342
  in
traytel@56237
   343
    EVERY' [Method.insert_tac (map (fn thm => thm RS @{thm ex_bij_betw}) card_of_min_algs),
traytel@56237
   344
      REPEAT_DETERM o etac exE, rtac rev_mp, rtac copy, REPEAT_DETERM_N n o atac,
traytel@56237
   345
      rtac impI, REPEAT_DETERM o eresolve_tac [exE, conjE], REPEAT_DETERM_N n o rtac exI,
traytel@56237
   346
      rtac mor_comp, rtac mor_Rep, rtac mor_select, rtac CollectI, REPEAT_DETERM o rtac exI,
traytel@56237
   347
      rtac conjI, rtac refl, atac,
traytel@56237
   348
      SELECT_GOAL (unfold_thms_tac ctxt (Abs_inverse :: fst_snd_convs)),
traytel@56237
   349
      etac mor_comp, rtac mor_incl, REPEAT_DETERM_N n o rtac subset_UNIV] 1
blanchet@48975
   350
  end;
blanchet@48975
   351
blanchet@48975
   352
fun mk_init_unique_mor_tac m
blanchet@51761
   353
    alg_def alg_min_alg least_min_algs in_monos alg_sets morEs map_cong0s =
blanchet@48975
   354
  let
blanchet@48975
   355
    val n = length least_min_algs;
blanchet@48975
   356
    val ks = (1 upto n);
blanchet@48975
   357
blanchet@49306
   358
    fun mor_tac morE in_mono = EVERY' [etac morE, rtac set_mp, rtac in_mono,
blanchet@48975
   359
      REPEAT_DETERM_N n o rtac @{thm Collect_restrict}, rtac CollectI,
blanchet@48975
   360
      REPEAT_DETERM_N (m + n) o (TRY o rtac conjI THEN' atac)];
blanchet@51761
   361
    fun cong_tac map_cong0 = EVERY' [rtac (map_cong0 RS arg_cong),
blanchet@48975
   362
      REPEAT_DETERM_N m o rtac refl,
blanchet@48975
   363
      REPEAT_DETERM_N n o (etac @{thm prop_restrict} THEN' atac)];
blanchet@48975
   364
blanchet@51761
   365
    fun mk_alg_tac (alg_set, (in_mono, (morE, map_cong0))) = EVERY' [rtac ballI, rtac CollectI,
blanchet@48975
   366
      REPEAT_DETERM o eresolve_tac [CollectE, conjE], rtac conjI, rtac (alg_min_alg RS alg_set),
blanchet@49306
   367
      REPEAT_DETERM_N n o (etac subset_trans THEN' rtac @{thm Collect_restrict}),
blanchet@48975
   368
      rtac trans, mor_tac morE in_mono,
blanchet@51761
   369
      rtac trans, cong_tac map_cong0,
blanchet@48975
   370
      rtac sym, mor_tac morE in_mono];
blanchet@48975
   371
blanchet@48975
   372
    fun mk_unique_tac (k, least_min_alg) =
blanchet@48975
   373
      select_prem_tac n (etac @{thm prop_restrict}) k THEN' rtac least_min_alg THEN'
traytel@56114
   374
      rtac (alg_def RS iffD2) THEN'
blanchet@51761
   375
      CONJ_WRAP' mk_alg_tac (alg_sets ~~ (in_monos ~~ (morEs ~~ map_cong0s)));
blanchet@48975
   376
  in
blanchet@48975
   377
    CONJ_WRAP' mk_unique_tac (ks ~~ least_min_algs) 1
blanchet@48975
   378
  end;
blanchet@48975
   379
blanchet@48975
   380
fun mk_init_induct_tac m alg_def alg_min_alg least_min_algs alg_sets =
blanchet@48975
   381
  let
blanchet@48975
   382
    val n = length least_min_algs;
blanchet@48975
   383
blanchet@48975
   384
    fun mk_alg_tac alg_set = EVERY' [rtac ballI, rtac CollectI,
blanchet@48975
   385
      REPEAT_DETERM o eresolve_tac [CollectE, conjE], rtac conjI, rtac (alg_min_alg RS alg_set),
blanchet@49306
   386
      REPEAT_DETERM_N n o (etac subset_trans THEN' rtac @{thm Collect_restrict}),
blanchet@48975
   387
      rtac mp, etac bspec, rtac CollectI,
blanchet@48975
   388
      REPEAT_DETERM_N m o (rtac conjI THEN' atac),
blanchet@49306
   389
      CONJ_WRAP' (K (etac subset_trans THEN' rtac @{thm Collect_restrict})) alg_sets,
blanchet@48975
   390
      CONJ_WRAP' (K (rtac ballI THEN' etac @{thm prop_restrict} THEN' atac)) alg_sets];
blanchet@48975
   391
blanchet@48975
   392
    fun mk_induct_tac least_min_alg =
blanchet@48975
   393
      rtac ballI THEN' etac @{thm prop_restrict} THEN' rtac least_min_alg THEN'
traytel@56114
   394
      rtac (alg_def RS iffD2) THEN'
blanchet@48975
   395
      CONJ_WRAP' mk_alg_tac alg_sets;
blanchet@48975
   396
  in
blanchet@48975
   397
    CONJ_WRAP' mk_induct_tac least_min_algs 1
blanchet@48975
   398
  end;
blanchet@48975
   399
traytel@56237
   400
fun mk_mor_Rep_tac ctxt m defs Reps Abs_inverses alg_min_alg alg_sets set_mapss =
traytel@56237
   401
  unfold_thms_tac ctxt (@{thm o_apply} :: defs) THEN
traytel@56237
   402
  EVERY' [rtac conjI,
traytel@56237
   403
    CONJ_WRAP' (fn thm => rtac ballI THEN' rtac thm) Reps,
traytel@56237
   404
    CONJ_WRAP' (fn (Abs_inverse, (set_maps, alg_set)) =>
traytel@56237
   405
      EVERY' [rtac ballI, rtac Abs_inverse, rtac (alg_min_alg RS alg_set),
traytel@56237
   406
        EVERY' (map2 (fn Rep => fn set_map =>
traytel@56237
   407
          EVERY' [rtac (set_map RS ord_eq_le_trans), rtac @{thm image_subsetI}, rtac Rep])
traytel@56237
   408
        Reps (drop m set_maps))])
traytel@56237
   409
    (Abs_inverses ~~ (set_mapss ~~ alg_sets))] 1;
blanchet@48975
   410
traytel@56237
   411
fun mk_mor_Abs_tac ctxt cts defs Abs_inverses map_comp_ids map_congLs =
traytel@56237
   412
  unfold_thms_tac ctxt (@{thm o_apply} :: defs) THEN
traytel@56237
   413
  EVERY' [rtac conjI,
traytel@56237
   414
    CONJ_WRAP' (K (rtac ballI THEN' rtac UNIV_I)) Abs_inverses,
traytel@56237
   415
    CONJ_WRAP' (fn (ct, thm) =>
traytel@56237
   416
      EVERY' [rtac ballI, REPEAT_DETERM o eresolve_tac [CollectE, conjE],
traytel@56237
   417
        rtac (thm RS (cterm_instantiate_pos [NONE, NONE, ct] arg_cong) RS sym),
traytel@56237
   418
        EVERY' (map (fn Abs_inverse =>
traytel@56237
   419
          EVERY' [rtac (o_apply RS trans RS ballI), etac (set_mp RS Abs_inverse), atac])
traytel@56237
   420
        Abs_inverses)])
traytel@56237
   421
    (cts ~~ map2 mk_trans map_comp_ids map_congLs)] 1;;
blanchet@48975
   422
blanchet@49504
   423
fun mk_mor_fold_tac cT ct fold_defs ex_mor mor =
blanchet@49504
   424
  (EVERY' (map stac fold_defs) THEN' EVERY' [rtac rev_mp, rtac ex_mor, rtac impI] THEN'
blanchet@49504
   425
  REPEAT_DETERM_N (length fold_defs) o etac exE THEN'
blanchet@48975
   426
  rtac (Drule.instantiate' [SOME cT] [SOME ct] @{thm someI}) THEN' etac mor) 1;
blanchet@48975
   427
blanchet@49504
   428
fun mk_fold_unique_mor_tac type_defs init_unique_mors Reps mor_comp mor_Abs mor_fold =
blanchet@48975
   429
  let
blanchet@48975
   430
    fun mk_unique type_def =
blanchet@48975
   431
      EVERY' [rtac @{thm surj_fun_eq}, rtac (type_def RS @{thm type_definition.Abs_image}),
traytel@49227
   432
        rtac ballI, resolve_tac init_unique_mors,
traytel@49227
   433
        EVERY' (map (fn thm => atac ORELSE' rtac thm) Reps),
blanchet@48975
   434
        rtac mor_comp, rtac mor_Abs, atac,
blanchet@49504
   435
        rtac mor_comp, rtac mor_Abs, rtac mor_fold];
blanchet@48975
   436
  in
blanchet@48975
   437
    CONJ_WRAP' mk_unique type_defs 1
blanchet@48975
   438
  end;
blanchet@48975
   439
blanchet@51761
   440
fun mk_dtor_o_ctor_tac dtor_def foldx map_comp_id map_cong0L ctor_o_folds =
traytel@56114
   441
  EVERY' [rtac @{thm ext}, rtac trans, rtac o_apply, rtac (dtor_def RS fun_cong RS trans),
traytel@56114
   442
    rtac trans, rtac foldx, rtac trans, rtac map_comp_id, rtac trans, rtac map_cong0L,
blanchet@49306
   443
    EVERY' (map (fn thm => rtac ballI THEN' rtac (trans OF [thm RS fun_cong, id_apply]))
blanchet@49504
   444
      ctor_o_folds),
blanchet@49306
   445
    rtac sym, rtac id_apply] 1;
blanchet@48975
   446
traytel@55197
   447
fun mk_rec_tac ctxt rec_defs foldx fst_recs =
blanchet@49504
   448
  unfold_thms_tac ctxt
blanchet@48975
   449
    (rec_defs @ map (fn thm => thm RS @{thm convol_expand_snd}) fst_recs) THEN
blanchet@49504
   450
  EVERY' [rtac trans, rtac o_apply, rtac trans, rtac (foldx RS @{thm arg_cong[of _ _ snd]}),
blanchet@48975
   451
    rtac @{thm snd_convol'}] 1;
blanchet@48975
   452
traytel@55197
   453
fun mk_rec_unique_mor_tac ctxt rec_defs fst_recs fold_unique_mor =
traytel@51739
   454
  unfold_thms_tac ctxt
traytel@51739
   455
    (rec_defs @ map (fn thm => thm RS @{thm convol_expand_snd'}) fst_recs) THEN
traytel@51739
   456
  etac fold_unique_mor 1;
traytel@51739
   457
blanchet@53290
   458
fun mk_ctor_induct_tac ctxt m set_mapss init_induct morEs mor_Abs Rep_invs Abs_invs Reps =
blanchet@48975
   459
  let
blanchet@53290
   460
    val n = length set_mapss;
blanchet@48975
   461
    val ks = 1 upto n;
blanchet@48975
   462
blanchet@53290
   463
    fun mk_IH_tac Rep_inv Abs_inv set_map =
traytel@56114
   464
      DETERM o EVERY' [dtac meta_mp, rtac (Rep_inv RS arg_cong RS iffD1), etac bspec,
blanchet@53290
   465
        dtac set_rev_mp, rtac equalityD1, rtac set_map, etac imageE,
traytel@56114
   466
        hyp_subst_tac ctxt, rtac (Abs_inv RS @{thm ssubst_mem}), etac set_mp, atac, atac];
blanchet@48975
   467
blanchet@53290
   468
    fun mk_closed_tac (k, (morE, set_maps)) =
blanchet@48975
   469
      EVERY' [select_prem_tac n (dtac asm_rl) k, rtac ballI, rtac impI,
traytel@56114
   470
        rtac (mor_Abs RS morE RS arg_cong RS iffD2), atac,
blanchet@48975
   471
        REPEAT_DETERM o eresolve_tac [CollectE, conjE], dtac @{thm meta_spec},
blanchet@53290
   472
        EVERY' (map3 mk_IH_tac Rep_invs Abs_invs (drop m set_maps)), atac];
blanchet@48975
   473
traytel@49227
   474
    fun mk_induct_tac (Rep, Rep_inv) =
traytel@56114
   475
      EVERY' [rtac (Rep_inv RS arg_cong RS iffD1), etac (Rep RSN (2, bspec))];
blanchet@48975
   476
  in
blanchet@48975
   477
    (rtac mp THEN' rtac impI THEN'
traytel@49227
   478
    DETERM o CONJ_WRAP_GEN' (etac conjE THEN' rtac conjI) mk_induct_tac (Reps ~~ Rep_invs) THEN'
blanchet@48975
   479
    rtac init_induct THEN'
blanchet@53290
   480
    DETERM o CONJ_WRAP' mk_closed_tac (ks ~~ (morEs ~~ set_mapss))) 1
blanchet@48975
   481
  end;
blanchet@48975
   482
traytel@55197
   483
fun mk_ctor_induct2_tac ctxt cTs cts ctor_induct weak_ctor_inducts =
blanchet@48975
   484
  let
blanchet@49501
   485
    val n = length weak_ctor_inducts;
blanchet@48975
   486
    val ks = 1 upto n;
blanchet@48975
   487
    fun mk_inner_induct_tac induct i =
blanchet@48975
   488
      EVERY' [rtac allI, fo_rtac induct ctxt,
blanchet@48975
   489
        select_prem_tac n (dtac @{thm meta_spec2}) i,
blanchet@48975
   490
        REPEAT_DETERM_N n o
wenzelm@54742
   491
          EVERY' [dtac meta_mp THEN_ALL_NEW Goal.norm_hhf_tac ctxt,
blanchet@49306
   492
            REPEAT_DETERM o dtac @{thm meta_spec}, etac (spec RS meta_mp), atac],
blanchet@48975
   493
        atac];
blanchet@48975
   494
  in
blanchet@49501
   495
    EVERY' [rtac rev_mp, rtac (Drule.instantiate' cTs cts ctor_induct),
blanchet@49501
   496
      EVERY' (map2 mk_inner_induct_tac weak_ctor_inducts ks), rtac impI,
blanchet@48975
   497
      REPEAT_DETERM o eresolve_tac [conjE, allE],
blanchet@48975
   498
      CONJ_WRAP' (K atac) ks] 1
blanchet@48975
   499
  end;
blanchet@48975
   500
blanchet@51761
   501
fun mk_map_tac m n foldx map_comp_id map_cong0 =
wenzelm@55990
   502
  EVERY' [rtac @{thm ext}, rtac trans, rtac o_apply, rtac trans, rtac foldx, rtac trans,
wenzelm@55990
   503
    rtac o_apply,
blanchet@51761
   504
    rtac trans, rtac (map_comp_id RS arg_cong), rtac trans, rtac (map_cong0 RS arg_cong),
blanchet@48975
   505
    REPEAT_DETERM_N m o rtac refl,
blanchet@49306
   506
    REPEAT_DETERM_N n o (EVERY' (map rtac [trans, o_apply, id_apply])),
blanchet@48975
   507
    rtac sym, rtac o_apply] 1;
blanchet@48975
   508
traytel@55197
   509
fun mk_ctor_map_unique_tac ctxt fold_unique sym_map_comps =
traytel@52911
   510
  rtac fold_unique 1 THEN
blanchet@55067
   511
  unfold_thms_tac ctxt (sym_map_comps @ @{thms comp_assoc id_comp comp_id}) THEN
traytel@52911
   512
  ALLGOALS atac;
blanchet@48975
   513
wenzelm@55990
   514
fun mk_set_tac foldx = EVERY' [rtac @{thm ext}, rtac trans, rtac o_apply,
blanchet@49504
   515
  rtac trans, rtac foldx, rtac sym, rtac o_apply] 1;
blanchet@48975
   516
blanchet@53290
   517
fun mk_ctor_set_tac set set_map set_maps =
blanchet@48975
   518
  let
blanchet@53290
   519
    val n = length set_maps;
blanchet@48975
   520
    fun mk_UN thm = rtac (thm RS @{thm arg_cong[of _ _ Union]} RS trans) THEN'
blanchet@48975
   521
      rtac @{thm Union_image_eq};
blanchet@48975
   522
  in
traytel@52659
   523
    EVERY' [rtac (set RS @{thm comp_eq_dest} RS trans), rtac Un_cong,
blanchet@53290
   524
      rtac (trans OF [set_map, trans_fun_cong_image_id_id_apply]),
traytel@52659
   525
      REPEAT_DETERM_N (n - 1) o rtac Un_cong,
blanchet@53290
   526
      EVERY' (map mk_UN set_maps)] 1
blanchet@48975
   527
  end;
blanchet@48975
   528
traytel@55197
   529
fun mk_set_nat_tac ctxt m induct_tac set_mapss ctor_maps csets ctor_sets i =
blanchet@48975
   530
  let
blanchet@49541
   531
    val n = length ctor_maps;
blanchet@48975
   532
haftmann@56248
   533
    fun useIH set_nat = EVERY' [rtac trans, rtac @{thm image_UN}, rtac trans, rtac @{thm SUP_cong},
haftmann@56248
   534
      rtac refl, Goal.assume_rule_tac ctxt, rtac sym, rtac trans, rtac @{thm SUP_cong},
blanchet@48975
   535
      rtac set_nat, rtac refl, rtac @{thm UN_simps(10)}];
blanchet@48975
   536
blanchet@49585
   537
    fun mk_set_nat cset ctor_map ctor_set set_nats =
blanchet@49585
   538
      EVERY' [rtac trans, rtac @{thm image_cong}, rtac ctor_set, rtac refl,
blanchet@49585
   539
        rtac sym, rtac (trans OF [ctor_map RS HOL_arg_cong cset, ctor_set RS trans]),
traytel@52659
   540
        rtac sym, EVERY' (map rtac [trans, @{thm image_Un}, Un_cong]),
blanchet@48975
   541
        rtac sym, rtac (nth set_nats (i - 1)),
traytel@52659
   542
        REPEAT_DETERM_N (n - 1) o EVERY' (map rtac [trans, @{thm image_Un}, Un_cong]),
blanchet@48975
   543
        EVERY' (map useIH (drop m set_nats))];
blanchet@48975
   544
  in
blanchet@53290
   545
    (induct_tac THEN' EVERY' (map4 mk_set_nat csets ctor_maps ctor_sets set_mapss)) 1
blanchet@48975
   546
  end;
blanchet@48975
   547
traytel@55197
   548
fun mk_set_bd_tac ctxt m induct_tac bd_Cinfinite set_bdss ctor_sets i =
blanchet@48975
   549
  let
blanchet@49542
   550
    val n = length ctor_sets;
blanchet@48975
   551
blanchet@48975
   552
    fun useIH set_bd = EVERY' [rtac @{thm UNION_Cinfinite_bound}, rtac set_bd, rtac ballI,
blanchet@48975
   553
      Goal.assume_rule_tac ctxt, rtac bd_Cinfinite];
blanchet@48975
   554
blanchet@49585
   555
    fun mk_set_nat ctor_set set_bds =
blanchet@49585
   556
      EVERY' [rtac @{thm ordIso_ordLeq_trans}, rtac @{thm card_of_ordIso_subst}, rtac ctor_set,
blanchet@48975
   557
        rtac (bd_Cinfinite RSN (3, @{thm Un_Cinfinite_bound})), rtac (nth set_bds (i - 1)),
blanchet@48975
   558
        REPEAT_DETERM_N (n - 1) o rtac (bd_Cinfinite RSN (3, @{thm Un_Cinfinite_bound})),
blanchet@48975
   559
        EVERY' (map useIH (drop m set_bds))];
blanchet@48975
   560
  in
blanchet@49542
   561
    (induct_tac THEN' EVERY' (map2 mk_set_nat ctor_sets set_bdss)) 1
blanchet@48975
   562
  end;
blanchet@48975
   563
traytel@55197
   564
fun mk_mcong_tac ctxt induct_tac set_setsss map_cong0s ctor_maps =
blanchet@48975
   565
  let
blanchet@49306
   566
    fun use_asm thm = EVERY' [etac bspec, etac set_rev_mp, rtac thm];
blanchet@48975
   567
blanchet@48975
   568
    fun useIH set_sets = EVERY' [rtac mp, Goal.assume_rule_tac ctxt,
blanchet@48975
   569
      CONJ_WRAP' (fn thm =>
blanchet@49306
   570
        EVERY' [rtac ballI, etac bspec, etac set_rev_mp, etac thm]) set_sets];
blanchet@48975
   571
blanchet@51761
   572
    fun mk_map_cong0 ctor_map map_cong0 set_setss =
blanchet@48975
   573
      EVERY' [rtac impI, REPEAT_DETERM o etac conjE,
blanchet@51761
   574
        rtac trans, rtac ctor_map, rtac trans, rtac (map_cong0 RS arg_cong),
blanchet@48975
   575
        EVERY' (map use_asm (map hd set_setss)),
blanchet@48975
   576
        EVERY' (map useIH (transpose (map tl set_setss))),
blanchet@49541
   577
        rtac sym, rtac ctor_map];
blanchet@48975
   578
  in
blanchet@51761
   579
    (induct_tac THEN' EVERY' (map3 mk_map_cong0 ctor_maps map_cong0s set_setsss)) 1
blanchet@48975
   580
  end;
blanchet@48975
   581
traytel@55197
   582
fun mk_le_rel_OO_tac ctxt m induct ctor_nchotomys ctor_Irels rel_mono_strongs rel_OOs =
traytel@54841
   583
  EVERY' (rtac induct ::
traytel@54841
   584
  map4 (fn nchotomy => fn Irel => fn rel_mono => fn rel_OO =>
traytel@54841
   585
    EVERY' [rtac impI, etac (nchotomy RS @{thm nchotomy_relcomppE}),
traytel@54841
   586
      REPEAT_DETERM_N 2 o dtac (Irel RS iffD1), rtac (Irel RS iffD2),
traytel@54841
   587
      rtac rel_mono, rtac (rel_OO RS @{thm predicate2_eqD} RS iffD2),
traytel@54841
   588
      rtac @{thm relcomppI}, atac, atac,
traytel@54841
   589
      REPEAT_DETERM_N m o EVERY' [rtac ballI, rtac ballI, rtac impI, atac],
traytel@54841
   590
      REPEAT_DETERM_N (length rel_OOs) o
traytel@54841
   591
        EVERY' [rtac ballI, rtac ballI, Goal.assume_rule_tac ctxt]])
traytel@54841
   592
  ctor_nchotomys ctor_Irels rel_mono_strongs rel_OOs) 1;
blanchet@48975
   593
blanchet@48975
   594
(* BNF tactics *)
blanchet@48975
   595
blanchet@53270
   596
fun mk_map_id0_tac map_id0s unique =
blanchet@48975
   597
  (rtac sym THEN' rtac unique THEN'
blanchet@48975
   598
  EVERY' (map (fn thm =>
blanchet@55067
   599
    EVERY' [rtac trans, rtac @{thm id_comp}, rtac trans, rtac sym, rtac @{thm comp_id},
blanchet@53270
   600
      rtac (thm RS sym RS arg_cong)]) map_id0s)) 1;
blanchet@48975
   601
blanchet@53287
   602
fun mk_map_comp0_tac map_comp0s ctor_maps unique iplus1 =
blanchet@48975
   603
  let
blanchet@48975
   604
    val i = iplus1 - 1;
blanchet@48975
   605
    val unique' = Thm.permute_prems 0 i unique;
blanchet@53288
   606
    val map_comp0s' = drop i map_comp0s @ take i map_comp0s;
blanchet@49541
   607
    val ctor_maps' = drop i ctor_maps @ take i ctor_maps;
blanchet@48975
   608
    fun mk_comp comp simp =
wenzelm@55990
   609
      EVERY' [rtac @{thm ext}, rtac trans, rtac o_apply, rtac trans, rtac o_apply,
blanchet@48975
   610
        rtac trans, rtac (simp RS arg_cong), rtac trans, rtac simp,
blanchet@48975
   611
        rtac trans, rtac (comp RS arg_cong), rtac sym, rtac o_apply];
blanchet@48975
   612
  in
blanchet@53288
   613
    (rtac sym THEN' rtac unique' THEN' EVERY' (map2 mk_comp map_comp0s' ctor_maps')) 1
blanchet@48975
   614
  end;
blanchet@48975
   615
blanchet@53289
   616
fun mk_set_map0_tac set_nat =
wenzelm@55990
   617
  EVERY' (map rtac [@{thm ext}, trans, o_apply, sym, trans, o_apply, set_nat]) 1;
blanchet@48975
   618
blanchet@48975
   619
fun mk_bd_card_order_tac bd_card_orders =
traytel@54793
   620
  CONJ_WRAP_GEN' (rtac @{thm card_order_csum}) rtac bd_card_orders 1;
blanchet@48975
   621
wenzelm@51798
   622
fun mk_wit_tac ctxt n ctor_set wit =
blanchet@48975
   623
  REPEAT_DETERM (atac 1 ORELSE
blanchet@49585
   624
    EVERY' [dtac set_rev_mp, rtac equalityD1, resolve_tac ctor_set,
blanchet@48975
   625
    REPEAT_DETERM o
blanchet@48975
   626
      (TRY o REPEAT_DETERM o etac UnE THEN' TRY o etac @{thm UN_E} THEN'
blanchet@48975
   627
        (eresolve_tac wit ORELSE'
blanchet@48975
   628
        (dresolve_tac wit THEN'
blanchet@48975
   629
          (etac FalseE ORELSE'
wenzelm@51798
   630
          EVERY' [hyp_subst_tac ctxt, dtac set_rev_mp, rtac equalityD1, resolve_tac ctor_set,
blanchet@48975
   631
            REPEAT_DETERM_N n o etac UnE]))))] 1);
blanchet@48975
   632
blanchet@53287
   633
fun mk_ctor_rel_tac ctxt in_Irels i in_rel map_comp0 map_cong0 ctor_map ctor_sets ctor_inject
blanchet@53289
   634
  ctor_dtor set_map0s ctor_set_incls ctor_set_set_inclss =
blanchet@48975
   635
  let
blanchet@49544
   636
    val m = length ctor_set_incls;
blanchet@49544
   637
    val n = length ctor_set_set_inclss;
blanchet@48975
   638
blanchet@53289
   639
    val (passive_set_map0s, active_set_map0s) = chop m set_map0s;
traytel@51893
   640
    val in_Irel = nth in_Irels (i - 1);
blanchet@49501
   641
    val le_arg_cong_ctor_dtor = ctor_dtor RS arg_cong RS ord_eq_le_trans;
blanchet@49501
   642
    val eq_arg_cong_ctor_dtor = ctor_dtor RS arg_cong RS trans;
blanchet@48975
   643
    val if_tac =
traytel@51893
   644
      EVERY' [dtac (in_Irel RS iffD1), REPEAT_DETERM o eresolve_tac [exE, conjE, CollectE],
traytel@51893
   645
        rtac (in_rel RS iffD2), rtac exI, rtac conjI, rtac CollectI,
blanchet@53289
   646
        EVERY' (map2 (fn set_map0 => fn ctor_set_incl =>
blanchet@53289
   647
          EVERY' [rtac conjI, rtac ord_eq_le_trans, rtac set_map0,
blanchet@49306
   648
            rtac ord_eq_le_trans, rtac trans_fun_cong_image_id_id_apply,
blanchet@49544
   649
            rtac (ctor_set_incl RS subset_trans), etac le_arg_cong_ctor_dtor])
blanchet@53289
   650
        passive_set_map0s ctor_set_incls),
blanchet@53289
   651
        CONJ_WRAP' (fn (in_Irel, (set_map0, ctor_set_set_incls)) =>
blanchet@53289
   652
          EVERY' [rtac ord_eq_le_trans, rtac set_map0, rtac @{thm image_subsetI}, rtac CollectI,
blanchet@55414
   653
            rtac @{thm case_prodI}, rtac (in_Irel RS iffD2), rtac exI, rtac conjI, rtac CollectI,
blanchet@48975
   654
            CONJ_WRAP' (fn thm =>
blanchet@49501
   655
              EVERY' (map etac [thm RS subset_trans, le_arg_cong_ctor_dtor]))
blanchet@49544
   656
            ctor_set_set_incls,
blanchet@48975
   657
            rtac conjI, rtac refl, rtac refl])
blanchet@53289
   658
        (in_Irels ~~ (active_set_map0s ~~ ctor_set_set_inclss)),
blanchet@48975
   659
        CONJ_WRAP' (fn conv =>
blanchet@53287
   660
          EVERY' [rtac trans, rtac map_comp0, rtac trans, rtac map_cong0,
blanchet@55067
   661
          REPEAT_DETERM_N m o rtac @{thm fun_cong[OF comp_id]},
blanchet@48975
   662
          REPEAT_DETERM_N n o EVERY' (map rtac [trans, o_apply, conv]),
blanchet@49541
   663
          rtac (ctor_inject RS iffD1), rtac trans, rtac sym, rtac ctor_map,
blanchet@49501
   664
          etac eq_arg_cong_ctor_dtor])
blanchet@49306
   665
        fst_snd_convs];
blanchet@48975
   666
    val only_if_tac =
traytel@51893
   667
      EVERY' [dtac (in_rel RS iffD1), REPEAT_DETERM o eresolve_tac [exE, conjE, CollectE],
traytel@51893
   668
        rtac (in_Irel RS iffD2), rtac exI, rtac conjI, rtac CollectI,
blanchet@53289
   669
        CONJ_WRAP' (fn (ctor_set, passive_set_map0) =>
blanchet@49585
   670
          EVERY' [rtac ord_eq_le_trans, rtac ctor_set, rtac @{thm Un_least},
blanchet@49306
   671
            rtac ord_eq_le_trans, rtac @{thm box_equals[OF _ refl]},
blanchet@53289
   672
            rtac passive_set_map0, rtac trans_fun_cong_image_id_id_apply, atac,
blanchet@48975
   673
            CONJ_WRAP_GEN' (rtac (Thm.permute_prems 0 1 @{thm Un_least}))
blanchet@53289
   674
              (fn (active_set_map0, in_Irel) => EVERY' [rtac ord_eq_le_trans,
haftmann@56248
   675
                rtac @{thm SUP_cong[OF _ refl]}, rtac active_set_map0, rtac @{thm UN_least},
blanchet@49306
   676
                dtac set_rev_mp, etac @{thm image_mono}, etac imageE,
traytel@51893
   677
                dtac @{thm ssubst_mem[OF pair_collapse]},
traytel@51893
   678
                REPEAT_DETERM o eresolve_tac (CollectE :: conjE ::
blanchet@55414
   679
                  @{thms case_prodE iffD1[OF Pair_eq, elim_format]}),
traytel@51893
   680
                hyp_subst_tac ctxt,
traytel@51893
   681
                dtac (in_Irel RS iffD1), dtac @{thm someI_ex}, REPEAT_DETERM o etac conjE,
traytel@51893
   682
                TRY o
traytel@51893
   683
                  EVERY' [dtac (Thm.permute_prems 0 1 @{thm ssubst_mem}), atac, hyp_subst_tac ctxt],
traytel@51893
   684
                REPEAT_DETERM o eresolve_tac [CollectE, conjE], atac])
blanchet@53289
   685
            (rev (active_set_map0s ~~ in_Irels))])
blanchet@53289
   686
        (ctor_sets ~~ passive_set_map0s),
blanchet@48975
   687
        rtac conjI,
blanchet@49541
   688
        REPEAT_DETERM_N 2 o EVERY' [rtac trans, rtac ctor_map, rtac (ctor_inject RS iffD2),
blanchet@53287
   689
          rtac trans, rtac map_comp0, rtac trans, rtac map_cong0,
blanchet@55067
   690
          REPEAT_DETERM_N m o rtac @{thm fun_cong[OF comp_id]},
traytel@51893
   691
          EVERY' (map (fn in_Irel => EVERY' [rtac trans, rtac o_apply, dtac set_rev_mp, atac,
traytel@51893
   692
            dtac @{thm ssubst_mem[OF pair_collapse]},
traytel@51893
   693
            REPEAT_DETERM o
blanchet@55414
   694
              eresolve_tac (CollectE :: conjE :: @{thms case_prodE iffD1[OF Pair_eq, elim_format]}),
traytel@51893
   695
            hyp_subst_tac ctxt,
traytel@51893
   696
            dtac (in_Irel RS iffD1), dtac @{thm someI_ex}, REPEAT_DETERM o etac conjE, atac])
traytel@51893
   697
          in_Irels),
blanchet@48975
   698
          atac]]
blanchet@48975
   699
  in
blanchet@48975
   700
    EVERY' [rtac iffI, if_tac, only_if_tac] 1
blanchet@48975
   701
  end;
blanchet@48975
   702
traytel@55197
   703
fun mk_rel_induct_tac ctxt IHs m ctor_induct2 ks ctor_rels rel_mono_strongs =
traytel@51918
   704
  let val n = length ks;
traytel@51918
   705
  in
wenzelm@54998
   706
    unfold_tac ctxt @{thms le_fun_def le_bool_def all_simps(1,2)[symmetric]} THEN
traytel@51918
   707
    EVERY' [REPEAT_DETERM o rtac allI, rtac ctor_induct2,
traytel@52506
   708
      EVERY' (map3 (fn IH => fn ctor_rel => fn rel_mono_strong =>
traytel@52506
   709
        EVERY' [rtac impI, dtac (ctor_rel RS iffD1), rtac (IH RS @{thm spec2} RS mp),
traytel@52506
   710
          etac rel_mono_strong,
traytel@51918
   711
          REPEAT_DETERM_N m o rtac @{thm ballI[OF ballI[OF imp_refl]]},
traytel@51918
   712
          EVERY' (map (fn j =>
traytel@51918
   713
            EVERY' [select_prem_tac n (dtac asm_rl) j, rtac @{thm ballI[OF ballI]},
traytel@51918
   714
              Goal.assume_rule_tac ctxt]) ks)])
traytel@52506
   715
      IHs ctor_rels rel_mono_strongs)] 1
traytel@51918
   716
  end;
traytel@51918
   717
blanchet@55901
   718
fun mk_fold_transfer_tac ctxt m ctor_rel_induct map_transfers folds =
traytel@52731
   719
  let
traytel@52731
   720
    val n = length map_transfers;
traytel@52731
   721
  in
traytel@52731
   722
    unfold_thms_tac ctxt
blanchet@55945
   723
      @{thms rel_fun_def_butlast all_conj_distrib[symmetric] imp_conjR[symmetric]} THEN
blanchet@55945
   724
    unfold_thms_tac ctxt @{thms rel_fun_iff_leq_vimage2p} THEN
traytel@52731
   725
    HEADGOAL (EVERY'
blanchet@55901
   726
      [REPEAT_DETERM o resolve_tac [allI, impI], rtac ctor_rel_induct,
traytel@52731
   727
      EVERY' (map (fn map_transfer => EVERY'
traytel@52731
   728
        [REPEAT_DETERM o resolve_tac [allI, impI, @{thm vimage2pI}],
traytel@52731
   729
        SELECT_GOAL (unfold_thms_tac ctxt folds),
traytel@52731
   730
        etac @{thm predicate2D_vimage2p},
blanchet@55945
   731
        rtac (funpow (m + n + 1) (fn thm => thm RS @{thm rel_funD}) map_transfer),
traytel@52731
   732
        REPEAT_DETERM_N m o rtac @{thm id_transfer},
blanchet@55945
   733
        REPEAT_DETERM_N n o rtac @{thm vimage2p_rel_fun},
traytel@52731
   734
        atac])
traytel@52731
   735
      map_transfers)])
traytel@52731
   736
  end;
traytel@52731
   737
blanchet@48975
   738
end;