src/HOL/Nominal/nominal_permeq.ML
author wenzelm
Thu Mar 15 20:07:00 2012 +0100 (2012-03-15)
changeset 46949 94aa7b81bcf6
parent 46219 426ed18eba43
child 51717 9e7d1c139569
permissions -rw-r--r--
prefer formally checked @{keyword} parser;
berghofe@19494
     1
(*  Title:      HOL/Nominal/nominal_permeq.ML
wenzelm@32960
     2
    Author:     Christian Urban, TU Muenchen
wenzelm@32960
     3
    Author:     Julien Narboux, TU Muenchen
berghofe@17870
     4
wenzelm@32960
     5
Methods for simplifying permutations and for analysing equations
wenzelm@32960
     6
involving permutations. 
berghofe@19494
     7
*)
berghofe@17870
     8
urbanc@20431
     9
(*
urbanc@20431
    10
FIXMES:
urbanc@20431
    11
urbanc@20431
    12
 - allow the user to give an explicit set S in the
urbanc@20431
    13
   fresh_guess tactic which is then verified
urbanc@20431
    14
urbanc@20431
    15
 - the perm_compose tactic does not do an "outermost
urbanc@20431
    16
   rewriting" and can therefore not deal with goals
urbanc@20431
    17
   like
urbanc@20431
    18
urbanc@20431
    19
      [(a,b)] o pi1 o pi2 = ....
urbanc@20431
    20
urbanc@20431
    21
   rather it tries to permute pi1 over pi2, which 
urbanc@20431
    22
   results in a failure when used with the 
urbanc@20431
    23
   perm_(full)_simp tactics
urbanc@20431
    24
urbanc@20431
    25
*)
urbanc@20431
    26
urbanc@20431
    27
berghofe@19987
    28
signature NOMINAL_PERMEQ =
berghofe@19987
    29
sig
berghofe@25997
    30
  val perm_simproc_fun : simproc
berghofe@25997
    31
  val perm_simproc_app : simproc
berghofe@25997
    32
berghofe@19987
    33
  val perm_simp_tac : simpset -> int -> tactic
urbanc@28322
    34
  val perm_extend_simp_tac : simpset -> int -> tactic
berghofe@19987
    35
  val supports_tac : simpset -> int -> tactic
berghofe@19987
    36
  val finite_guess_tac : simpset -> int -> tactic
berghofe@19987
    37
  val fresh_guess_tac : simpset -> int -> tactic
berghofe@17870
    38
wenzelm@30549
    39
  val perm_simp_meth : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    40
  val perm_simp_meth_debug : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    41
  val perm_extend_simp_meth : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    42
  val perm_extend_simp_meth_debug : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    43
  val supports_meth : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    44
  val supports_meth_debug : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    45
  val finite_guess_meth : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    46
  val finite_guess_meth_debug : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    47
  val fresh_guess_meth : (Proof.context -> Proof.method) context_parser
wenzelm@30549
    48
  val fresh_guess_meth_debug : (Proof.context -> Proof.method) context_parser
berghofe@19987
    49
end
berghofe@19987
    50
berghofe@19987
    51
structure NominalPermeq : NOMINAL_PERMEQ =
berghofe@19987
    52
struct
berghofe@19987
    53
urbanc@22418
    54
(* some lemmas needed below *)
urbanc@24519
    55
val finite_emptyI = @{thm "finite.emptyI"};
urbanc@24519
    56
val finite_Un     = @{thm "finite_Un"};
urbanc@24519
    57
val conj_absorb   = @{thm "conj_absorb"};
urbanc@24519
    58
val not_false     = @{thm "not_False_eq_True"}
haftmann@44684
    59
val perm_fun_def  = Simpdata.mk_eq @{thm "Nominal.perm_fun_def"};
urbanc@24519
    60
val perm_eq_app   = @{thm "Nominal.pt_fun_app_eq"};
haftmann@44684
    61
val supports_def  = Simpdata.mk_eq @{thm "Nominal.supports_def"};
haftmann@44684
    62
val fresh_def     = Simpdata.mk_eq @{thm "Nominal.fresh_def"};
urbanc@24519
    63
val fresh_prod    = @{thm "Nominal.fresh_prod"};
urbanc@24519
    64
val fresh_unit    = @{thm "Nominal.fresh_unit"};
urbanc@24519
    65
val supports_rule = @{thm "supports_finite"};
urbanc@24519
    66
val supp_prod     = @{thm "supp_prod"};
urbanc@24519
    67
val supp_unit     = @{thm "supp_unit"};
urbanc@24519
    68
val pt_perm_compose_aux = @{thm "pt_perm_compose_aux"};
urbanc@24519
    69
val cp1_aux             = @{thm "cp1_aux"};
urbanc@24519
    70
val perm_aux_fold       = @{thm "perm_aux_fold"}; 
urbanc@24519
    71
val supports_fresh_rule = @{thm "supports_fresh"};
wenzelm@21669
    72
berghofe@19987
    73
(* pulls out dynamically a thm via the proof state *)
wenzelm@39557
    74
fun dynamic_thms st name = Global_Theory.get_thms (theory_of_thm st) name;
wenzelm@39557
    75
fun dynamic_thm  st name = Global_Theory.get_thm  (theory_of_thm st) name;
urbanc@22418
    76
urbanc@18012
    77
urbanc@22418
    78
(* needed in the process of fully simplifying permutations *)
urbanc@24519
    79
val strong_congs = [@{thm "if_cong"}]
urbanc@22418
    80
(* needed to avoid warnings about overwritten congs *)
urbanc@24519
    81
val weak_congs   = [@{thm "if_weak_cong"}]
urbanc@22418
    82
urbanc@22418
    83
(* debugging *)
urbanc@22418
    84
fun DEBUG_tac (msg,tac) = 
urbanc@22418
    85
    CHANGED (EVERY [print_tac ("before "^msg), tac, print_tac ("after "^msg)]); 
urbanc@22418
    86
fun NO_DEBUG_tac (_,tac) = CHANGED tac; 
urbanc@22418
    87
urbanc@19477
    88
urbanc@22418
    89
(* simproc that deals with instances of permutations in front *)
urbanc@22418
    90
(* of applications; just adding this rule to the simplifier   *)
urbanc@22418
    91
(* would loop; it also needs careful tuning with the simproc  *)
urbanc@22418
    92
(* for functions to avoid further possibilities for looping   *)
berghofe@25997
    93
fun perm_simproc_app' sg ss redex =
urbanc@22418
    94
  let 
urbanc@22418
    95
    (* the "application" case is only applicable when the head of f is not a *)
urbanc@22418
    96
    (* constant or when (f x) is a permuation with two or more arguments     *)
urbanc@22418
    97
    fun applicable_app t = 
urbanc@22418
    98
          (case (strip_comb t) of
wenzelm@32960
    99
              (Const ("Nominal.perm",_),ts) => (length ts) >= 2
urbanc@22418
   100
            | (Const _,_) => false
urbanc@22418
   101
            | _ => true)
urbanc@22418
   102
  in
urbanc@22418
   103
    case redex of 
urbanc@19169
   104
        (* case pi o (f x) == (pi o f) (pi o x)          *)
berghofe@19494
   105
        (Const("Nominal.perm",
haftmann@37678
   106
          Type("fun",[Type("List.list",[Type(@{type_name Product_Type.prod},[Type(n,_),_])]),_])) $ pi $ (f $ x)) => 
urbanc@22418
   107
            (if (applicable_app f) then
urbanc@22418
   108
              let
wenzelm@30364
   109
                val name = Long_Name.base_name n
wenzelm@39557
   110
                val at_inst = Global_Theory.get_thm sg ("at_" ^ name ^ "_inst")
wenzelm@39557
   111
                val pt_inst = Global_Theory.get_thm sg ("pt_" ^ name ^ "_inst")
urbanc@22418
   112
              in SOME ((at_inst RS (pt_inst RS perm_eq_app)) RS eq_reflection) end
urbanc@22418
   113
            else NONE)
urbanc@22418
   114
      | _ => NONE
urbanc@22418
   115
  end
urbanc@19139
   116
wenzelm@38715
   117
val perm_simproc_app = Simplifier.simproc_global @{theory} "perm_simproc_app"
berghofe@25997
   118
  ["Nominal.perm pi x"] perm_simproc_app';
berghofe@25997
   119
urbanc@24519
   120
(* a simproc that deals with permutation instances in front of functions  *)
berghofe@25997
   121
fun perm_simproc_fun' sg ss redex = 
urbanc@22418
   122
   let 
urbanc@22418
   123
     fun applicable_fun t =
urbanc@22418
   124
       (case (strip_comb t) of
urbanc@22418
   125
          (Abs _ ,[]) => true
wenzelm@32960
   126
        | (Const ("Nominal.perm",_),_) => false
urbanc@22418
   127
        | (Const _, _) => true
wenzelm@32960
   128
        | _ => false)
urbanc@22418
   129
   in
urbanc@22418
   130
     case redex of 
urbanc@22418
   131
       (* case pi o f == (%x. pi o (f ((rev pi)o x))) *)     
urbanc@22418
   132
       (Const("Nominal.perm",_) $ pi $ f)  => 
haftmann@44830
   133
          (if applicable_fun f then SOME perm_fun_def else NONE)
urbanc@22418
   134
      | _ => NONE
urbanc@22418
   135
   end
urbanc@19139
   136
wenzelm@38715
   137
val perm_simproc_fun = Simplifier.simproc_global @{theory} "perm_simproc_fun"
berghofe@25997
   138
  ["Nominal.perm pi x"] perm_simproc_fun';
berghofe@25997
   139
urbanc@28322
   140
(* function for simplyfying permutations          *)
urbanc@28322
   141
(* stac contains the simplifiation tactic that is *)
urbanc@28322
   142
(* applied (see (no_asm) options below            *)
urbanc@28322
   143
fun perm_simp_gen stac dyn_thms eqvt_thms ss i = 
urbanc@22418
   144
    ("general simplification of permutations", fn st =>
urbanc@22418
   145
    let
wenzelm@35232
   146
       val ss' = Simplifier.global_context (theory_of_thm st) ss
wenzelm@26343
   147
         addsimps (maps (dynamic_thms st) dyn_thms @ eqvt_thms)
berghofe@25997
   148
         addsimprocs [perm_simproc_fun, perm_simproc_app]
wenzelm@45620
   149
         |> fold Simplifier.del_cong weak_congs
wenzelm@45620
   150
         |> fold Simplifier.add_cong strong_congs
urbanc@19477
   151
    in
urbanc@28322
   152
      stac ss' i st
berghofe@19987
   153
    end);
urbanc@19477
   154
urbanc@22418
   155
(* general simplification of permutations and permutation that arose from eqvt-problems *)
urbanc@28322
   156
fun perm_simp stac ss = 
urbanc@22610
   157
    let val simps = ["perm_swap","perm_fresh_fresh","perm_bij","perm_pi_simp","swap_simps"]
urbanc@22610
   158
    in 
wenzelm@32960
   159
        perm_simp_gen stac simps [] ss
urbanc@22610
   160
    end;
urbanc@22610
   161
urbanc@28322
   162
fun eqvt_simp stac ss = 
urbanc@22610
   163
    let val simps = ["perm_swap","perm_fresh_fresh","perm_pi_simp"]
wenzelm@32960
   164
        val eqvts_thms = NominalThmDecls.get_eqvt_thms (Simplifier.the_context ss);
urbanc@22610
   165
    in 
wenzelm@32960
   166
        perm_simp_gen stac simps eqvts_thms ss
urbanc@22610
   167
    end;
narboux@22562
   168
urbanc@22418
   169
urbanc@22418
   170
(* main simplification tactics for permutations *)
urbanc@28322
   171
fun perm_simp_tac_gen_i stac tactical ss i = DETERM (tactical (perm_simp stac ss i));
urbanc@28322
   172
fun eqvt_simp_tac_gen_i stac tactical ss i = DETERM (tactical (eqvt_simp stac ss i)); 
urbanc@22418
   173
urbanc@28322
   174
val perm_simp_tac_i          = perm_simp_tac_gen_i simp_tac
urbanc@28322
   175
val perm_asm_simp_tac_i      = perm_simp_tac_gen_i asm_simp_tac
urbanc@28322
   176
val perm_full_simp_tac_i     = perm_simp_tac_gen_i full_simp_tac
urbanc@28322
   177
val perm_asm_lr_simp_tac_i   = perm_simp_tac_gen_i asm_lr_simp_tac
urbanc@28322
   178
val perm_asm_full_simp_tac_i = perm_simp_tac_gen_i asm_full_simp_tac
urbanc@28322
   179
val eqvt_asm_full_simp_tac_i = eqvt_simp_tac_gen_i asm_full_simp_tac
urbanc@22418
   180
urbanc@19477
   181
(* applies the perm_compose rule such that                             *)
urbanc@19477
   182
(*   pi o (pi' o lhs) = rhs                                            *)
urbanc@19477
   183
(* is transformed to                                                   *) 
urbanc@19477
   184
(*  (pi o pi') o (pi' o lhs) = rhs                                     *)
urbanc@19477
   185
(*                                                                     *)
urbanc@19477
   186
(* this rule would loop in the simplifier, so some trick is used with  *)
urbanc@19477
   187
(* generating perm_aux'es for the outermost permutation and then un-   *)
urbanc@19477
   188
(* folding the definition                                              *)
berghofe@25997
   189
berghofe@25997
   190
fun perm_compose_simproc' sg ss redex =
berghofe@25997
   191
  (case redex of
berghofe@25997
   192
     (Const ("Nominal.perm", Type ("fun", [Type ("List.list", 
haftmann@37678
   193
       [Type (@{type_name Product_Type.prod}, [T as Type (tname,_),_])]),_])) $ pi1 $ (Const ("Nominal.perm", 
haftmann@37678
   194
         Type ("fun", [Type ("List.list", [Type (@{type_name Product_Type.prod}, [U as Type (uname,_),_])]),_])) $ 
berghofe@25997
   195
          pi2 $ t)) =>
urbanc@19477
   196
    let
wenzelm@30364
   197
      val tname' = Long_Name.base_name tname
wenzelm@30364
   198
      val uname' = Long_Name.base_name uname
berghofe@25997
   199
    in
berghofe@25997
   200
      if pi1 <> pi2 then  (* only apply the composition rule in this case *)
berghofe@25997
   201
        if T = U then    
berghofe@25997
   202
          SOME (Drule.instantiate'
berghofe@25997
   203
            [SOME (ctyp_of sg (fastype_of t))]
berghofe@25997
   204
            [SOME (cterm_of sg pi1), SOME (cterm_of sg pi2), SOME (cterm_of sg t)]
wenzelm@39557
   205
            (mk_meta_eq ([Global_Theory.get_thm sg ("pt_"^tname'^"_inst"),
wenzelm@39557
   206
             Global_Theory.get_thm sg ("at_"^tname'^"_inst")] MRS pt_perm_compose_aux)))
berghofe@25997
   207
        else
berghofe@25997
   208
          SOME (Drule.instantiate'
berghofe@25997
   209
            [SOME (ctyp_of sg (fastype_of t))]
berghofe@25997
   210
            [SOME (cterm_of sg pi1), SOME (cterm_of sg pi2), SOME (cterm_of sg t)]
wenzelm@39557
   211
            (mk_meta_eq (Global_Theory.get_thm sg ("cp_"^tname'^"_"^uname'^"_inst") RS 
berghofe@25997
   212
             cp1_aux)))
berghofe@25997
   213
      else NONE
berghofe@25997
   214
    end
berghofe@25997
   215
  | _ => NONE);
urbanc@19477
   216
wenzelm@38715
   217
val perm_compose_simproc = Simplifier.simproc_global @{theory} "perm_compose"
berghofe@25997
   218
  ["Nominal.perm pi1 (Nominal.perm pi2 t)"] perm_compose_simproc';
urbanc@19477
   219
berghofe@25997
   220
fun perm_compose_tac ss i = 
berghofe@25997
   221
  ("analysing permutation compositions on the lhs",
berghofe@25997
   222
   fn st => EVERY
berghofe@25997
   223
     [rtac trans i,
wenzelm@35232
   224
      asm_full_simp_tac (Simplifier.global_context (theory_of_thm st) empty_ss
berghofe@25997
   225
        addsimprocs [perm_compose_simproc]) i,
berghofe@25997
   226
      asm_full_simp_tac (HOL_basic_ss addsimps [perm_aux_fold]) i] st);
urbanc@18012
   227
wenzelm@32733
   228
fun apply_cong_tac i = ("application of congruence", cong_tac i);
berghofe@17870
   229
urbanc@22418
   230
urbanc@19477
   231
(* unfolds the definition of permutations     *)
urbanc@19477
   232
(* applied to functions such that             *)
urbanc@22418
   233
(*     pi o f = rhs                           *)  
urbanc@19477
   234
(* is transformed to                          *)
urbanc@22418
   235
(*     %x. pi o (f ((rev pi) o x)) = rhs      *)
urbanc@24519
   236
fun unfold_perm_fun_def_tac i =
urbanc@24519
   237
    ("unfolding of permutations on functions", 
urbanc@24519
   238
      rtac (perm_fun_def RS meta_eq_to_obj_eq RS trans) i)
berghofe@17870
   239
urbanc@19477
   240
(* applies the ext-rule such that      *)
urbanc@19477
   241
(*                                     *)
urbanc@22418
   242
(*    f = g   goes to  /\x. f x = g x  *)
urbanc@19477
   243
fun ext_fun_tac i = ("extensionality expansion of functions", rtac ext i);
berghofe@17870
   244
berghofe@17870
   245
urbanc@28322
   246
(* perm_extend_simp_tac_i is perm_simp plus additional tactics        *)
urbanc@19477
   247
(* to decide equation that come from support problems             *)
urbanc@19477
   248
(* since it contains looping rules the "recursion" - depth is set *)
urbanc@19477
   249
(* to 10 - this seems to be sufficient in most cases              *)
urbanc@28322
   250
fun perm_extend_simp_tac_i tactical ss =
urbanc@28322
   251
  let fun perm_extend_simp_tac_aux tactical ss n = 
wenzelm@32960
   252
          if n=0 then K all_tac
wenzelm@32960
   253
          else DETERM o 
wenzelm@32960
   254
               (FIRST'[fn i => tactical ("splitting conjunctions on the rhs", rtac conjI i),
urbanc@28322
   255
                       fn i => tactical (perm_simp asm_full_simp_tac ss i),
wenzelm@32960
   256
                       fn i => tactical (perm_compose_tac ss i),
wenzelm@32960
   257
                       fn i => tactical (apply_cong_tac i), 
urbanc@19477
   258
                       fn i => tactical (unfold_perm_fun_def_tac i),
urbanc@22418
   259
                       fn i => tactical (ext_fun_tac i)]
wenzelm@32960
   260
                      THEN_ALL_NEW (TRY o (perm_extend_simp_tac_aux tactical ss (n-1))))
urbanc@28322
   261
  in perm_extend_simp_tac_aux tactical ss 10 end;
urbanc@19151
   262
urbanc@22418
   263
urbanc@22418
   264
(* tactic that tries to solve "supports"-goals; first it *)
urbanc@22418
   265
(* unfolds the support definition and strips off the     *)
urbanc@22418
   266
(* intros, then applies eqvt_simp_tac                    *)
urbanc@28322
   267
fun supports_tac_i tactical ss i =
urbanc@18012
   268
  let 
wenzelm@36945
   269
     val simps        = [supports_def, Thm.symmetric fresh_def, fresh_prod]
berghofe@17870
   270
  in
urbanc@19477
   271
      EVERY [tactical ("unfolding of supports   ", simp_tac (HOL_basic_ss addsimps simps) i),
urbanc@19477
   272
             tactical ("stripping of foralls    ", REPEAT_DETERM (rtac allI i)),
urbanc@19477
   273
             tactical ("geting rid of the imps  ", rtac impI i),
urbanc@19477
   274
             tactical ("eliminating conjuncts   ", REPEAT_DETERM (etac  conjE i)),
urbanc@28322
   275
             tactical ("applying eqvt_simp      ", eqvt_simp_tac_gen_i asm_full_simp_tac tactical ss i )]
berghofe@17870
   276
  end;
berghofe@17870
   277
urbanc@19151
   278
urbanc@22418
   279
(* tactic that guesses the finite-support of a goal        *)
urbanc@22418
   280
(* it first collects all free variables and tries to show  *)
urbanc@22418
   281
(* that the support of these free variables (op supports)  *)
urbanc@22418
   282
(* the goal                                                *)
haftmann@20854
   283
fun collect_vars i (Bound j) vs = if j < i then vs else insert (op =) (Bound (j - i)) vs
haftmann@20854
   284
  | collect_vars i (v as Free _) vs = insert (op =) v vs
haftmann@20854
   285
  | collect_vars i (v as Var _) vs = insert (op =) v vs
urbanc@19151
   286
  | collect_vars i (Const _) vs = vs
urbanc@19151
   287
  | collect_vars i (Abs (_, _, t)) vs = collect_vars (i+1) t vs
urbanc@19151
   288
  | collect_vars i (t $ u) vs = collect_vars i u (collect_vars i t vs);
urbanc@19151
   289
wenzelm@43278
   290
(* FIXME proper SUBGOAL/CSUBGOAL instead of cprems_of etc. *)
urbanc@28322
   291
fun finite_guess_tac_i tactical ss i st =
wenzelm@42364
   292
    let val goal = nth (cprems_of st) (i - 1)
urbanc@19151
   293
    in
berghofe@26806
   294
      case Envir.eta_contract (Logic.strip_assums_concl (term_of goal)) of
berghofe@22274
   295
          _ $ (Const ("Finite_Set.finite", _) $ (Const ("Nominal.supp", T) $ x)) =>
urbanc@19151
   296
          let
wenzelm@22578
   297
            val cert = Thm.cterm_of (Thm.theory_of_thm st);
urbanc@19151
   298
            val ps = Logic.strip_params (term_of goal);
urbanc@19151
   299
            val Ts = rev (map snd ps);
urbanc@19151
   300
            val vs = collect_vars 0 x [];
wenzelm@33244
   301
            val s = fold_rev (fn v => fn s =>
urbanc@19151
   302
                HOLogic.pair_const (fastype_of1 (Ts, v)) (fastype_of1 (Ts, s)) $ v $ s)
wenzelm@33244
   303
              vs HOLogic.unit;
wenzelm@46219
   304
            val s' = fold_rev Term.abs ps
wenzelm@46219
   305
              (Const ("Nominal.supp", fastype_of1 (Ts, s) -->
huffman@44692
   306
                Term.range_type T) $ s);
urbanc@19151
   307
            val supports_rule' = Thm.lift_rule goal supports_rule;
urbanc@19151
   308
            val _ $ (_ $ S $ _) =
urbanc@19151
   309
              Logic.strip_assums_concl (hd (prems_of supports_rule'));
urbanc@19151
   310
            val supports_rule'' = Drule.cterm_instantiate
urbanc@19151
   311
              [(cert (head_of S), cert s')] supports_rule'
wenzelm@26343
   312
            val fin_supp = dynamic_thms st ("fin_supp")
urbanc@22418
   313
            val ss' = ss addsimps [supp_prod,supp_unit,finite_Un,finite_emptyI,conj_absorb]@fin_supp
urbanc@19151
   314
          in
urbanc@19151
   315
            (tactical ("guessing of the right supports-set",
urbanc@19151
   316
                      EVERY [compose_tac (false, supports_rule'', 2) i,
berghofe@19987
   317
                             asm_full_simp_tac ss' (i+1),
urbanc@28322
   318
                             supports_tac_i tactical ss i])) st
urbanc@19151
   319
          end
urbanc@19151
   320
        | _ => Seq.empty
urbanc@19151
   321
    end
wenzelm@43278
   322
    handle General.Subscript => Seq.empty
wenzelm@43278
   323
(* FIXME proper SUBGOAL/CSUBGOAL instead of cprems_of etc. *)
urbanc@19151
   324
narboux@22595
   325
urbanc@22418
   326
(* tactic that guesses whether an atom is fresh for an expression  *)
urbanc@22418
   327
(* it first collects all free variables and tries to show that the *) 
urbanc@22418
   328
(* support of these free variables (op supports) the goal          *)
wenzelm@43278
   329
(* FIXME proper SUBGOAL/CSUBGOAL instead of cprems_of etc. *)
urbanc@28322
   330
fun fresh_guess_tac_i tactical ss i st =
berghofe@19857
   331
    let 
wenzelm@42364
   332
        val goal = nth (cprems_of st) (i - 1)
wenzelm@26343
   333
        val fin_supp = dynamic_thms st ("fin_supp")
wenzelm@26343
   334
        val fresh_atm = dynamic_thms st ("fresh_atm")
wenzelm@36945
   335
        val ss1 = ss addsimps [Thm.symmetric fresh_def,fresh_prod,fresh_unit,conj_absorb,not_false]@fresh_atm
urbanc@22418
   336
        val ss2 = ss addsimps [supp_prod,supp_unit,finite_Un,finite_emptyI,conj_absorb]@fin_supp
berghofe@19857
   337
    in
berghofe@19857
   338
      case Logic.strip_assums_concl (term_of goal) of
berghofe@19857
   339
          _ $ (Const ("Nominal.fresh", Type ("fun", [T, _])) $ _ $ t) => 
berghofe@19857
   340
          let
wenzelm@22578
   341
            val cert = Thm.cterm_of (Thm.theory_of_thm st);
berghofe@19857
   342
            val ps = Logic.strip_params (term_of goal);
berghofe@19857
   343
            val Ts = rev (map snd ps);
berghofe@19857
   344
            val vs = collect_vars 0 t [];
wenzelm@33244
   345
            val s = fold_rev (fn v => fn s =>
berghofe@19857
   346
                HOLogic.pair_const (fastype_of1 (Ts, v)) (fastype_of1 (Ts, s)) $ v $ s)
wenzelm@33244
   347
              vs HOLogic.unit;
wenzelm@46219
   348
            val s' =
wenzelm@46219
   349
              fold_rev Term.abs ps
wenzelm@46219
   350
                (Const ("Nominal.supp", fastype_of1 (Ts, s) --> HOLogic.mk_setT T) $ s);
berghofe@19857
   351
            val supports_fresh_rule' = Thm.lift_rule goal supports_fresh_rule;
berghofe@19857
   352
            val _ $ (_ $ S $ _) =
berghofe@19857
   353
              Logic.strip_assums_concl (hd (prems_of supports_fresh_rule'));
berghofe@19857
   354
            val supports_fresh_rule'' = Drule.cterm_instantiate
berghofe@19857
   355
              [(cert (head_of S), cert s')] supports_fresh_rule'
berghofe@19857
   356
          in
urbanc@22418
   357
            (tactical ("guessing of the right set that supports the goal", 
urbanc@22418
   358
                      (EVERY [compose_tac (false, supports_fresh_rule'', 3) i,
urbanc@19993
   359
                             asm_full_simp_tac ss1 (i+2),
urbanc@19993
   360
                             asm_full_simp_tac ss2 (i+1), 
urbanc@28322
   361
                             supports_tac_i tactical ss i]))) st
berghofe@19857
   362
          end
urbanc@22418
   363
          (* when a term-constructor contains more than one binder, it is useful    *) 
urbanc@22418
   364
          (* in nominal_primrecs to try whether the goal can be solved by an hammer *)
urbanc@22418
   365
        | _ => (tactical ("if it is not of the form _\<sharp>_, then try the simplifier",   
urbanc@22418
   366
                          (asm_full_simp_tac (HOL_ss addsimps [fresh_prod]@fresh_atm) i))) st
berghofe@19857
   367
    end
wenzelm@43278
   368
    handle General.Subscript => Seq.empty;
wenzelm@43278
   369
(* FIXME proper SUBGOAL/CSUBGOAL instead of cprems_of etc. *)
urbanc@22418
   370
urbanc@28322
   371
val eqvt_simp_tac        = eqvt_asm_full_simp_tac_i NO_DEBUG_tac;
urbanc@28322
   372
urbanc@28322
   373
val perm_simp_tac        = perm_asm_full_simp_tac_i NO_DEBUG_tac;
urbanc@28322
   374
val perm_extend_simp_tac = perm_extend_simp_tac_i NO_DEBUG_tac;
urbanc@28322
   375
val supports_tac         = supports_tac_i NO_DEBUG_tac;
urbanc@28322
   376
val finite_guess_tac     = finite_guess_tac_i NO_DEBUG_tac;
urbanc@28322
   377
val fresh_guess_tac      = fresh_guess_tac_i NO_DEBUG_tac;
urbanc@28322
   378
urbanc@28322
   379
val dperm_simp_tac        = perm_asm_full_simp_tac_i DEBUG_tac;
urbanc@28322
   380
val dperm_extend_simp_tac = perm_extend_simp_tac_i DEBUG_tac;
urbanc@28322
   381
val dsupports_tac         = supports_tac_i DEBUG_tac;
urbanc@28322
   382
val dfinite_guess_tac     = finite_guess_tac_i DEBUG_tac;
urbanc@28322
   383
val dfresh_guess_tac      = fresh_guess_tac_i DEBUG_tac;
urbanc@28322
   384
urbanc@28322
   385
(* Code opied from the Simplifer for setting up the perm_simp method   *)
urbanc@28322
   386
(* behaves nearly identical to the simp-method, for example can handle *)
urbanc@28322
   387
(* options like (no_asm) etc.                                          *) 
urbanc@28322
   388
val no_asmN = "no_asm";
urbanc@28322
   389
val no_asm_useN = "no_asm_use";
urbanc@28322
   390
val no_asm_simpN = "no_asm_simp";
urbanc@28322
   391
val asm_lrN = "asm_lr";
urbanc@28322
   392
urbanc@28322
   393
val perm_simp_options =
urbanc@28322
   394
 (Args.parens (Args.$$$ no_asmN) >> K (perm_simp_tac_i NO_DEBUG_tac) ||
urbanc@28322
   395
  Args.parens (Args.$$$ no_asm_simpN) >> K (perm_asm_simp_tac_i NO_DEBUG_tac) ||
urbanc@28322
   396
  Args.parens (Args.$$$ no_asm_useN) >> K (perm_full_simp_tac_i NO_DEBUG_tac) ||
urbanc@28322
   397
  Args.parens (Args.$$$ asm_lrN) >> K (perm_asm_lr_simp_tac_i NO_DEBUG_tac) ||
urbanc@28322
   398
  Scan.succeed (perm_asm_full_simp_tac_i NO_DEBUG_tac));
urbanc@28322
   399
wenzelm@30549
   400
val perm_simp_meth =
wenzelm@33554
   401
  Scan.lift perm_simp_options --| Method.sections (Simplifier.simp_modifiers') >>
wenzelm@33554
   402
  (fn tac => fn ctxt => SIMPLE_METHOD' (CHANGED_PROP o tac (simpset_of ctxt)));
urbanc@28322
   403
urbanc@22418
   404
(* setup so that the simpset is used which is active at the moment when the tactic is called *)
urbanc@22418
   405
fun local_simp_meth_setup tac =
wenzelm@30549
   406
  Method.sections (Simplifier.simp_modifiers' @ Splitter.split_modifiers) >>
wenzelm@32149
   407
  (K (SIMPLE_METHOD' o tac o simpset_of));
berghofe@17870
   408
narboux@22595
   409
(* uses HOL_basic_ss only and fails if the tactic does not solve the subgoal *)
narboux@22595
   410
narboux@22656
   411
fun basic_simp_meth_setup debug tac =
wenzelm@30549
   412
  Scan.depend (fn ctxt => Scan.succeed (Simplifier.map_ss (fn _ => HOL_basic_ss) ctxt, ())) --
wenzelm@30549
   413
  Method.sections (Simplifier.simp_modifiers' @ Splitter.split_modifiers) >>
wenzelm@34885
   414
  (K (SIMPLE_METHOD' o (if debug then tac else SOLVED' o tac) o simpset_of));
urbanc@22418
   415
urbanc@28322
   416
val perm_simp_meth_debug        = local_simp_meth_setup dperm_simp_tac;
urbanc@28322
   417
val perm_extend_simp_meth       = local_simp_meth_setup perm_extend_simp_tac;
urbanc@28322
   418
val perm_extend_simp_meth_debug = local_simp_meth_setup dperm_extend_simp_tac;
urbanc@28322
   419
val supports_meth               = local_simp_meth_setup supports_tac;
urbanc@28322
   420
val supports_meth_debug         = local_simp_meth_setup dsupports_tac;
urbanc@24571
   421
urbanc@28322
   422
val finite_guess_meth         = basic_simp_meth_setup false finite_guess_tac;
urbanc@28322
   423
val finite_guess_meth_debug   = basic_simp_meth_setup true  dfinite_guess_tac;
urbanc@28322
   424
val fresh_guess_meth          = basic_simp_meth_setup false fresh_guess_tac;
urbanc@28322
   425
val fresh_guess_meth_debug    = basic_simp_meth_setup true  dfresh_guess_tac;
berghofe@17870
   426
wenzelm@20289
   427
end